1use std::{
5 fmt,
6 ops::Deref,
7 os::fd::{IntoRawFd, OwnedFd},
8 ptr,
9 rc::{Rc, Weak},
10};
11
12use crate::{
13 core::CoreRc,
14 loop_::{IsLoopRc, Loop},
15 properties::PropertiesBox,
16 Error,
17};
18
19use super::{Context, ContextBox};
20
21struct ContextRcInner {
22 context: ContextBox<'static>,
23 _loop: Box<dyn AsRef<Loop>>,
27}
28
29impl fmt::Debug for ContextRcInner {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("ContextRcInner")
32 .field("context", &self.context)
33 .finish()
34 }
35}
36
37#[derive(Clone, Debug)]
43pub struct ContextRc {
44 inner: Rc<ContextRcInner>,
45}
46
47impl ContextRc {
48 pub fn new<T: IsLoopRc>(loop_: &T, properties: Option<PropertiesBox>) -> Result<Self, Error> {
49 let loop_: Box<dyn AsRef<Loop>> = Box::new(loop_.clone());
50 let props = properties
51 .map_or(ptr::null(), |props| props.into_raw())
52 .cast_mut();
53
54 unsafe {
55 let raw = ptr::NonNull::new(pw_sys::pw_context_new(
56 (*loop_).as_ref().as_raw_ptr(),
57 props,
58 0,
59 ))
60 .ok_or(Error::CreationFailed)?;
61
62 let context: ContextBox<'static> = ContextBox::from_raw(raw);
63
64 Ok(ContextRc {
65 inner: Rc::new(ContextRcInner {
66 context,
67 _loop: loop_,
68 }),
69 })
70 }
71 }
72
73 pub fn downgrade(&self) -> ContextWeak {
76 let weak = Rc::downgrade(&self.inner);
77 ContextWeak { weak }
78 }
79
80 pub fn connect_rc(&self, properties: Option<PropertiesBox>) -> Result<CoreRc, Error> {
81 let properties = properties.map_or(ptr::null_mut(), |p| p.into_raw());
82
83 unsafe {
84 let core = pw_sys::pw_context_connect(self.as_raw_ptr(), properties, 0);
85 let ptr = ptr::NonNull::new(core).ok_or(Error::CreationFailed)?;
86
87 Ok(CoreRc::from_raw(ptr, self.clone()))
88 }
89 }
90
91 pub fn connect_fd_rc(
92 &self,
93 fd: OwnedFd,
94 properties: Option<PropertiesBox>,
95 ) -> Result<CoreRc, Error> {
96 let properties = properties.map_or(ptr::null_mut(), |p| p.into_raw());
97
98 unsafe {
99 let raw_fd = fd.into_raw_fd();
100 let core = pw_sys::pw_context_connect_fd(self.as_raw_ptr(), raw_fd, properties, 0);
101 let ptr = ptr::NonNull::new(core).ok_or(Error::CreationFailed)?;
102
103 Ok(CoreRc::from_raw(ptr, self.clone()))
104 }
105 }
106}
107
108impl std::ops::Deref for ContextRc {
109 type Target = Context;
110
111 fn deref(&self) -> &Self::Target {
112 self.inner.context.deref()
113 }
114}
115
116impl std::convert::AsRef<Context> for ContextRc {
117 fn as_ref(&self) -> &Context {
118 self.deref()
119 }
120}
121
122pub struct ContextWeak {
126 weak: Weak<ContextRcInner>,
127}
128
129impl ContextWeak {
130 pub fn upgrade(&self) -> Option<ContextRc> {
131 self.weak.upgrade().map(|inner| ContextRc { inner })
132 }
133}