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#[derive(Debug, Clone)]
23pub struct MainLoopRc {
24    inner: Rc<MainLoopRcInner>,
25}
26
27impl MainLoopRc {
28    /// Initialize Pipewire and create a new [`MainLoopRc`]
29    pub fn new(properties: Option<&spa::utils::dict::DictRef>) -> Result<Self, Error> {
30        let main_loop = MainLoopBox::new(properties)?;
31
32        Ok(Self {
33            inner: Rc::new(MainLoopRcInner { main_loop }),
34        })
35    }
36
37    /// Create a new main loop from a raw [`pw_main_loop`](`pw_sys::pw_main_loop`), taking ownership of it.
38    ///
39    /// # Safety
40    /// The provided pointer must point to a valid, well aligned [`pw_main_loop`](`pw_sys::pw_main_loop`).
41    ///
42    /// The raw loop should not be manually destroyed or moved, as the new [`MainLoopRc`] takes ownership of it.
43    pub unsafe fn from_raw(ptr: ptr::NonNull<pw_sys::pw_main_loop>) -> Self {
44        let main_loop = MainLoopBox::from_raw(ptr);
45
46        Self {
47            inner: Rc::new(MainLoopRcInner { main_loop }),
48        }
49    }
50
51    pub fn downgrade(&self) -> MainLoopWeak {
52        let weak = Rc::downgrade(&self.inner);
53        MainLoopWeak { weak }
54    }
55}
56
57// Safety: The pw_loop is guaranteed to remain valid while any clone of the `MainLoop` is held,
58//         because we use an internal Rc to keep the pw_main_loop containing the pw_loop alive.
59unsafe impl IsLoopRc for MainLoopRc {}
60
61impl std::ops::Deref for MainLoopRc {
62    type Target = MainLoop;
63
64    fn deref(&self) -> &Self::Target {
65        self.inner.main_loop.deref()
66    }
67}
68
69impl std::convert::AsRef<MainLoop> for MainLoopRc {
70    fn as_ref(&self) -> &MainLoop {
71        self.deref()
72    }
73}
74
75impl std::convert::AsRef<Loop> for MainLoopRc {
76    fn as_ref(&self) -> &Loop {
77        self.loop_()
78    }
79}
80
81pub struct MainLoopWeak {
82    weak: Weak<MainLoopRcInner>,
83}
84
85impl MainLoopWeak {
86    pub fn upgrade(&self) -> Option<MainLoopRc> {
87        self.weak.upgrade().map(|inner| MainLoopRc { inner })
88    }
89}