pipewire/stream/
box_.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use crate::{core::Core, error::Error, properties::PropertiesBox};
5use std::{
6    ffi::{CStr, CString},
7    marker::PhantomData,
8    ptr,
9};
10
11use super::Stream;
12
13pub struct StreamBox<'c> {
14    ptr: ptr::NonNull<pw_sys::pw_stream>,
15    core: PhantomData<&'c Core>,
16}
17
18impl<'c> StreamBox<'c> {
19    /// Create a [`StreamBox`]
20    ///
21    /// Initialises a new stream with the given `name` and `properties`.
22    pub fn new(
23        core: &'c Core,
24        name: &str,
25        properties: PropertiesBox,
26    ) -> Result<StreamBox<'c>, Error> {
27        let name = CString::new(name).expect("Invalid byte in stream name");
28
29        let c_str = name.as_c_str();
30        StreamBox::new_cstr(core, c_str, properties)
31    }
32
33    /// Initialises a new stream with the given `name` as C String and `properties`.
34    pub fn new_cstr(
35        core: &'c Core,
36        name: &CStr,
37        properties: PropertiesBox,
38    ) -> Result<StreamBox<'c>, Error> {
39        unsafe {
40            let stream =
41                pw_sys::pw_stream_new(core.as_raw_ptr(), name.as_ptr(), properties.into_raw());
42            let stream = ptr::NonNull::new(stream).ok_or(Error::CreationFailed)?;
43
44            Ok(Self::from_raw(stream))
45        }
46    }
47
48    /// Create a [`StreamBox`] by taking ownership of a raw [`pw_stream`](`pw_sys::pw_stream`).
49    ///
50    /// # Safety
51    /// The provided pointer must point to a valid, well aligned [`pw_stream`](`pw_sys::pw_stream`).
52    ///
53    /// The raw stream must not be manually destroyed or moved, as the new [`StreamBox`] takes
54    /// ownership of it.
55    ///
56    /// The lifetime of the returned box is unbounded. The caller is responsible to make sure
57    /// that the `core` used with this stream outlives the stream.
58    pub unsafe fn from_raw(raw: ptr::NonNull<pw_sys::pw_stream>) -> StreamBox<'c> {
59        Self {
60            ptr: raw,
61            core: PhantomData,
62        }
63    }
64
65    pub fn into_raw(self) -> ptr::NonNull<pw_sys::pw_stream> {
66        std::mem::ManuallyDrop::new(self).ptr
67    }
68}
69
70impl<'c> std::ops::Deref for StreamBox<'c> {
71    type Target = Stream;
72
73    fn deref(&self) -> &Self::Target {
74        unsafe { self.ptr.cast().as_ref() }
75    }
76}
77
78impl<'c> std::fmt::Debug for StreamBox<'c> {
79    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80        f.debug_struct("StreamBox")
81            .field("name", &self.name())
82            .field("state", &self.state())
83            .field("node-id", &self.node_id())
84            .field("properties", &self.properties())
85            .finish()
86    }
87}
88
89impl<'c> std::ops::Drop for StreamBox<'c> {
90    fn drop(&mut self) {
91        unsafe { pw_sys::pw_stream_destroy(self.as_raw_ptr()) }
92    }
93}