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)]
38pub struct ContextRc {
39 inner: Rc<ContextRcInner>,
40}
41
42impl ContextRc {
43 pub fn new<T: IsLoopRc>(loop_: &T, properties: Option<PropertiesBox>) -> Result<Self, Error> {
44 let loop_: Box<dyn AsRef<Loop>> = Box::new(loop_.clone());
45 let props = properties
46 .map_or(ptr::null(), |props| props.into_raw())
47 .cast_mut();
48
49 unsafe {
50 let raw = ptr::NonNull::new(pw_sys::pw_context_new(
51 (*loop_).as_ref().as_raw_ptr(),
52 props,
53 0,
54 ))
55 .ok_or(Error::CreationFailed)?;
56
57 let context: ContextBox<'static> = ContextBox::from_raw(raw);
58
59 Ok(ContextRc {
60 inner: Rc::new(ContextRcInner {
61 context,
62 _loop: loop_,
63 }),
64 })
65 }
66 }
67
68 pub fn downgrade(&self) -> ContextWeak {
71 let weak = Rc::downgrade(&self.inner);
72 ContextWeak { weak }
73 }
74
75 pub fn connect_rc(&self, properties: Option<PropertiesBox>) -> Result<CoreRc, Error> {
76 let properties = properties.map_or(ptr::null_mut(), |p| p.into_raw());
77
78 unsafe {
79 let core = pw_sys::pw_context_connect(self.as_raw_ptr(), properties, 0);
80 let ptr = ptr::NonNull::new(core).ok_or(Error::CreationFailed)?;
81
82 Ok(CoreRc::from_raw(ptr, self.clone()))
83 }
84 }
85
86 pub fn connect_fd_rc(
87 &self,
88 fd: OwnedFd,
89 properties: Option<PropertiesBox>,
90 ) -> Result<CoreRc, Error> {
91 let properties = properties.map_or(ptr::null_mut(), |p| p.into_raw());
92
93 unsafe {
94 let raw_fd = fd.into_raw_fd();
95 let core = pw_sys::pw_context_connect_fd(self.as_raw_ptr(), raw_fd, properties, 0);
96 let ptr = ptr::NonNull::new(core).ok_or(Error::CreationFailed)?;
97
98 Ok(CoreRc::from_raw(ptr, self.clone()))
99 }
100 }
101}
102
103impl std::ops::Deref for ContextRc {
104 type Target = Context;
105
106 fn deref(&self) -> &Self::Target {
107 self.inner.context.deref()
108 }
109}
110
111impl std::convert::AsRef<Context> for ContextRc {
112 fn as_ref(&self) -> &Context {
113 self.deref()
114 }
115}
116
117pub struct ContextWeak {
118 weak: Weak<ContextRcInner>,
119}
120
121impl ContextWeak {
122 pub fn upgrade(&self) -> Option<ContextRc> {
123 self.weak.upgrade().map(|inner| ContextRc { inner })
124 }
125}