pipewire/main_loop/
rc.rs

1// Copyright The pipewire-rs Contributors.
2// SPDX-License-Identifier: MIT
3
4use std::{
5    ops::Deref,
6    ptr,
7    rc::{Rc, Weak},
8};
9
10use crate::{
11    loop_::{IsLoopRc, Loop},
12    Error,
13};
14
15use super::{MainLoop, MainLoopBox};
16
17#[derive(Debug)]
18struct MainLoopRcInner {
19    main_loop: MainLoopBox,
20}
21
22/// Reference counting smart pointer providing shared ownership of a PipeWire [main loop](super).
23///
24/// For the non-owning variant, see [`MainLoopWeak`].
25/// For unique ownership, see [`MainLoopBox`].
26///
27/// For an explanation of these, see [Smart pointers to PipeWire objects](crate#smart-pointers-to-pipewire-objects).
28#[derive(Debug, Clone)]
29pub struct MainLoopRc {
30    inner: Rc<MainLoopRcInner>,
31}
32
33impl MainLoopRc {
34    /// Initialize Pipewire and create a new [`MainLoopRc`]
35    pub fn new(properties: Option<&spa::utils::dict::DictRef>) -> Result<Self, Error> {
36        let main_loop = MainLoopBox::new(properties)?;
37
38        Ok(Self {
39            inner: Rc::new(MainLoopRcInner { main_loop }),
40        })
41    }
42
43    /// Create a new main loop from a raw [`pw_main_loop`](`pw_sys::pw_main_loop`), taking ownership of it.
44    ///
45    /// # Safety
46    /// The provided pointer must point to a valid, well aligned [`pw_main_loop`](`pw_sys::pw_main_loop`).
47    ///
48    /// The raw loop should not be manually destroyed or moved, as the new [`MainLoopRc`] takes ownership of it.
49    pub unsafe fn from_raw(ptr: ptr::NonNull<pw_sys::pw_main_loop>) -> Self {
50        let main_loop = MainLoopBox::from_raw(ptr);
51
52        Self {
53            inner: Rc::new(MainLoopRcInner { main_loop }),
54        }
55    }
56
57    pub fn downgrade(&self) -> MainLoopWeak {
58        let weak = Rc::downgrade(&self.inner);
59        MainLoopWeak { weak }
60    }
61}
62
63// Safety: The pw_loop is guaranteed to remain valid while any clone of the `MainLoop` is held,
64//         because we use an internal Rc to keep the pw_main_loop containing the pw_loop alive.
65unsafe impl IsLoopRc for MainLoopRc {}
66
67impl std::ops::Deref for MainLoopRc {
68    type Target = MainLoop;
69
70    fn deref(&self) -> &Self::Target {
71        self.inner.main_loop.deref()
72    }
73}
74
75impl std::convert::AsRef<MainLoop> for MainLoopRc {
76    fn as_ref(&self) -> &MainLoop {
77        self.deref()
78    }
79}
80
81impl std::convert::AsRef<Loop> for MainLoopRc {
82    fn as_ref(&self) -> &Loop {
83        self.loop_()
84    }
85}
86
87/// Non-owning reference to a [main loop](super) managed by [`MainLoopRc`].
88///
89/// The main loop can be accessed by calling [`upgrade`](Self::upgrade).
90pub struct MainLoopWeak {
91    weak: Weak<MainLoopRcInner>,
92}
93
94impl MainLoopWeak {
95    pub fn upgrade(&self) -> Option<MainLoopRc> {
96        self.weak.upgrade().map(|inner| MainLoopRc { inner })
97    }
98}