pipewire_native/proxy/
device.rs1use std::sync::{Arc, Mutex, RwLock};
6
7use bitflags::bitflags;
8use pipewire_native_spa as spa;
9
10use crate::{
11 core::Core,
12 new_refcounted,
13 properties::Properties,
14 protocol,
15 proxy::{HasProxy, Proxy},
16 proxy_object_invoke, refcounted,
17 types::{self, params::ParamBuilder},
18 HookId, Id, Refcounted,
19};
20
21refcounted! {
22 pub struct Device {
24 proxy: RwLock<Option<Proxy<Device>>>,
25 methods: Arc<Mutex<DeviceMethods<Device>>>,
26 hooks: Arc<Mutex<spa::hook::HookList<DeviceEvents>>>,
27 }
28}
29
30#[allow(clippy::type_complexity)]
31pub(crate) struct DeviceMethods<T: HasProxy + Refcounted> {
32 pub(crate) subscribe_params:
33 Box<dyn FnMut(&Proxy<T>, &[spa::param::ParamType]) -> std::io::Result<()>>,
34 pub(crate) enum_params: Box<
35 dyn FnMut(
36 &Proxy<T>,
37 u32,
38 Option<spa::param::ParamType>,
39 u32,
40 u32,
41 Option<ParamBuilder>,
42 ) -> std::io::Result<()>,
43 >,
44 pub(crate) set_param: Box<
45 dyn FnMut(
46 &Proxy<T>,
47 spa::param::ParamType,
48 spa::pod::types::ObjectType,
49 u32,
50 Box<dyn FnOnce(spa::pod::builder::ObjectBuilder) -> spa::pod::builder::ObjectBuilder>,
51 ) -> std::io::Result<()>,
52 >,
53}
54
55bitflags! {
56 #[repr(C)]
58 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
59 pub struct DeviceChangeMask : u32 {
60 const PROPS = (1 << 0);
62 const PARAMS = (1 << 1);
64 }
65}
66
67pub struct DeviceInfo<'a> {
69 pub id: Id,
71 pub mask: DeviceChangeMask,
73 pub props: &'a Properties,
75 pub params: &'a [(spa::param::ParamType, spa::param::ParamInfoFlags)],
77}
78
79#[allow(clippy::type_complexity)]
81#[derive(Default)]
82pub struct DeviceEvents {
83 pub info: Option<Box<dyn FnMut(&DeviceInfo<'_>) + Send>>,
85 pub param:
88 Option<Box<dyn FnMut(u32, spa::param::ParamType, u32, u32, &spa::pod::RawPodOwned) + Send>>,
89}
90
91impl HasProxy for Device {
92 fn type_(&self) -> types::ObjectType {
93 types::interface::DEVICE
94 }
95
96 fn version(&self) -> u32 {
97 3
98 }
99
100 fn proxy(&self) -> Proxy<Self> {
101 self.inner
102 .proxy
103 .read()
104 .unwrap()
105 .as_ref()
106 .expect("Device proxy should be initialised on creation")
107 .clone()
108 }
109}
110
111impl Device {
112 pub(crate) fn new(core: &Core) -> Self {
113 let this = Self {
114 inner: new_refcounted(InnerDevice::new(core)),
115 };
116
117 let id = core.next_proxy_id();
118 this.inner
119 .proxy
120 .write()
121 .unwrap()
122 .replace(Proxy::new(id, &this));
123 core.add_proxy(&this, id);
124
125 this
126 }
127
128 pub fn add_listener(&self, events: DeviceEvents) -> HookId {
130 self.inner.hooks.lock().unwrap().append(events)
131 }
132
133 pub fn remove_listener(&self, hook_id: HookId) {
135 self.inner.hooks.lock().unwrap().remove(hook_id);
136 }
137
138 pub fn subscribe_params(&self, ids: &[spa::param::ParamType]) -> std::io::Result<()> {
140 let proxy = self.proxy();
141 proxy_object_invoke!(proxy, subscribe_params, ids)
142 }
143
144 pub fn enum_params(
146 &self,
147 seq: u32,
148 id: Option<spa::param::ParamType>,
149 start: u32,
150 num: u32,
151 filter: Option<ParamBuilder>,
152 ) -> std::io::Result<()> {
153 let proxy = self.proxy();
154 proxy_object_invoke!(proxy, enum_params, seq, id, start, num, filter)
155 }
156
157 pub fn set_param(
159 &self,
160 param_id: spa::param::ParamType,
161 object_type: spa::pod::types::ObjectType,
162 flags: u32,
163 builder: Box<
164 dyn FnOnce(spa::pod::builder::ObjectBuilder) -> spa::pod::builder::ObjectBuilder,
165 >,
166 ) -> std::io::Result<()> {
167 let proxy = self.proxy();
168 proxy_object_invoke!(proxy, set_param, param_id, object_type, flags, builder)
169 }
170
171 pub(crate) fn methods(&self) -> Arc<Mutex<DeviceMethods<Device>>> {
172 self.inner.methods.clone()
173 }
174
175 pub(crate) fn events(&self) -> Arc<Mutex<spa::hook::HookList<DeviceEvents>>> {
176 self.inner.hooks.clone()
177 }
178}
179
180impl InnerDevice {
181 fn new(core: &Core) -> Self {
182 Self {
183 proxy: RwLock::new(None),
184 methods: Arc::new(Mutex::new(protocol::marshal::device::Methods::marshal(
185 core.connection(),
186 ))),
187 hooks: spa::hook::HookList::new(),
188 }
189 }
190}