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