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