pipewire/stream/
rc.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use std::{
5    ffi::{CStr, CString},
6    ops::Deref,
7    ptr,
8    rc::{Rc, Weak},
9};
10
11use crate::{
12    core::CoreRc,
13    properties::PropertiesBox,
14    stream::{Stream, StreamBox},
15    Error,
16};
17
18#[derive(Debug)]
19struct StreamRcInner {
20    stream: StreamBox<'static>,
21    // Store the core here, so that the core is not dropped before the stream,
22    // which may lead to undefined behaviour. Rusts drop order of struct fields
23    // (from top to bottom) ensures that this is always destroyed _after_ the context.
24    _core: CoreRc,
25}
26
27/// Reference counting smart pointer providing shared ownership of a PipeWire [stream](super).
28///
29/// For the non-owning variant, see [`StreamWeak`].
30/// For unique ownership, see [`StreamBox`].
31///
32/// For an explanation of these, see [Smart pointers to PipeWire objects](crate#smart-pointers-to-pipewire-objects).
33#[derive(Clone, Debug)]
34pub struct StreamRc {
35    inner: Rc<StreamRcInner>,
36}
37
38impl StreamRc {
39    pub fn new(core: CoreRc, name: &str, properties: PropertiesBox) -> Result<StreamRc, Error> {
40        let name = CString::new(name).expect("Invalid byte in stream name");
41
42        let c_str = name.as_c_str();
43        StreamRc::new_cstr(core, c_str, properties)
44    }
45
46    /// Initialises a new stream with the given `name` as C String and `properties`.
47    pub fn new_cstr(
48        core: CoreRc,
49        name: &CStr,
50        properties: PropertiesBox,
51    ) -> Result<StreamRc, Error> {
52        unsafe {
53            let stream =
54                pw_sys::pw_stream_new(core.as_raw_ptr(), name.as_ptr(), properties.into_raw());
55            let stream = ptr::NonNull::new(stream).ok_or(Error::CreationFailed)?;
56
57            let stream: StreamBox<'static> = StreamBox::from_raw(stream);
58
59            Ok(Self {
60                inner: Rc::new(StreamRcInner {
61                    stream,
62                    _core: core,
63                }),
64            })
65        }
66    }
67
68    pub fn downgrade(&self) -> StreamWeak {
69        let weak = Rc::downgrade(&self.inner);
70        StreamWeak { weak }
71    }
72}
73
74impl std::ops::Deref for StreamRc {
75    type Target = Stream;
76
77    fn deref(&self) -> &Self::Target {
78        self.inner.stream.deref()
79    }
80}
81
82impl std::convert::AsRef<Stream> for StreamRc {
83    fn as_ref(&self) -> &Stream {
84        self.deref()
85    }
86}
87
88/// Non-owning reference to a [stream](super) managed by [`StreamRc`].
89///
90/// The stream can be accessed by calling [`upgrade`](Self::upgrade).
91pub struct StreamWeak {
92    weak: Weak<StreamRcInner>,
93}
94
95impl StreamWeak {
96    pub fn upgrade(&self) -> Option<StreamRc> {
97        self.weak.upgrade().map(|inner| StreamRc { inner })
98    }
99}