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#[derive(Clone, Debug)]
28pub struct StreamRc {
29    inner: Rc<StreamRcInner>,
30}
31
32impl StreamRc {
33    pub fn new(core: CoreRc, name: &str, properties: PropertiesBox) -> Result<StreamRc, Error> {
34        let name = CString::new(name).expect("Invalid byte in stream name");
35
36        let c_str = name.as_c_str();
37        StreamRc::new_cstr(core, c_str, properties)
38    }
39
40    /// Initialises a new stream with the given `name` as C String and `properties`.
41    pub fn new_cstr(
42        core: CoreRc,
43        name: &CStr,
44        properties: PropertiesBox,
45    ) -> Result<StreamRc, Error> {
46        unsafe {
47            let stream =
48                pw_sys::pw_stream_new(core.as_raw_ptr(), name.as_ptr(), properties.into_raw());
49            let stream = ptr::NonNull::new(stream).ok_or(Error::CreationFailed)?;
50
51            let stream: StreamBox<'static> = StreamBox::from_raw(stream);
52
53            Ok(Self {
54                inner: Rc::new(StreamRcInner {
55                    stream,
56                    _core: core,
57                }),
58            })
59        }
60    }
61
62    pub fn downgrade(&self) -> StreamWeak {
63        let weak = Rc::downgrade(&self.inner);
64        StreamWeak { weak }
65    }
66}
67
68impl std::ops::Deref for StreamRc {
69    type Target = Stream;
70
71    fn deref(&self) -> &Self::Target {
72        self.inner.stream.deref()
73    }
74}
75
76impl std::convert::AsRef<Stream> for StreamRc {
77    fn as_ref(&self) -> &Stream {
78        self.deref()
79    }
80}
81
82pub struct StreamWeak {
83    weak: Weak<StreamRcInner>,
84}
85
86impl StreamWeak {
87    pub fn upgrade(&self) -> Option<StreamRc> {
88        self.weak.upgrade().map(|inner| StreamRc { inner })
89    }
90}