pipewire/core/
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 spa::spa_interface_call_method;
11
12use crate::{registry::RegistryRc, Error};
13
14use super::{Core, CoreBox};
15
16#[derive(Debug)]
17struct CoreRcInner {
18    core: CoreBox<'static>,
19    // Store the context here, so that the context is not dropped before the core,
20    // which may lead to undefined behaviour. Rusts drop order of struct fields
21    // (from top to bottom) ensures that this is always destroyed _after_ the core.
22    _context: crate::context::ContextRc,
23}
24
25#[derive(Debug, Clone)]
26pub struct CoreRc {
27    inner: Rc<CoreRcInner>,
28}
29
30impl CoreRc {
31    pub fn from_raw(
32        ptr: ptr::NonNull<pw_sys::pw_core>,
33        context: crate::context::ContextRc,
34    ) -> Self {
35        let core = unsafe { CoreBox::from_raw(ptr) };
36
37        Self {
38            inner: Rc::new(CoreRcInner {
39                core,
40                _context: context,
41            }),
42        }
43    }
44
45    pub fn downgrade(&self) -> CoreWeak {
46        let weak = Rc::downgrade(&self.inner);
47        CoreWeak { weak }
48    }
49
50    pub fn get_registry_rc(&self) -> Result<RegistryRc, Error> {
51        unsafe {
52            let registry = spa_interface_call_method!(
53                self.as_raw_ptr(),
54                pw_sys::pw_core_methods,
55                get_registry,
56                pw_sys::PW_VERSION_REGISTRY,
57                0
58            );
59            let registry = ptr::NonNull::new(registry).ok_or(Error::CreationFailed)?;
60            Ok(RegistryRc::from_raw(registry, self.clone()))
61        }
62    }
63}
64
65impl Deref for CoreRc {
66    type Target = Core;
67
68    fn deref(&self) -> &Self::Target {
69        self.inner.core.deref()
70    }
71}
72
73impl AsRef<Core> for CoreRc {
74    fn as_ref(&self) -> &Core {
75        self.deref()
76    }
77}
78
79pub struct CoreWeak {
80    weak: Weak<CoreRcInner>,
81}
82
83impl CoreWeak {
84    pub fn upgrade(&self) -> Option<CoreRc> {
85        self.weak.upgrade().map(|inner| CoreRc { inner })
86    }
87}