pipewire_native/proxy/
client.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, permission,
13 properties::Properties,
14 protocol,
15 proxy::{HasProxy, Proxy},
16 proxy_object_invoke, refcounted, types, HookId, Id, Refcounted,
17};
18
19refcounted! {
20 pub struct Client {
22 proxy: RwLock<Option<Proxy<Client>>>,
23 methods: Arc<Mutex<ClientMethods<Client>>>,
24 hooks: Arc<Mutex<spa::hook::HookList<ClientEvents>>>,
25 }
26}
27
28#[allow(clippy::type_complexity)]
29pub(crate) struct ClientMethods<T: HasProxy + Refcounted> {
30 pub(crate) error: Box<dyn FnMut(&Proxy<T>, u32, u32, &str) -> std::io::Result<()>>,
31 pub(crate) update_properties: Box<dyn FnMut(&Proxy<T>, &Properties) -> std::io::Result<()>>,
32 pub(crate) get_permissions: Box<dyn FnMut(&Proxy<T>, u32, u32) -> std::io::Result<()>>,
33 pub(crate) update_permissions:
34 Box<dyn FnMut(&Proxy<T>, &[permission::Permission]) -> std::io::Result<()>>,
35}
36
37bitflags! {
38 #[repr(C)]
40 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
41 pub struct ClientChangeMask : u32 {
42 const PROPS = (1 << 0);
44 }
45}
46
47pub struct ClientInfo<'a> {
49 pub id: Id,
51 pub mask: ClientChangeMask,
53 pub props: &'a Properties,
55}
56
57#[allow(clippy::type_complexity)]
59#[derive(Default)]
60pub struct ClientEvents {
61 pub info: Option<Box<dyn FnMut(&ClientInfo<'_>) + Send>>,
63 pub permissions: Option<Box<dyn FnMut(u32, &[permission::Permission]) + Send>>,
65}
66
67impl HasProxy for Client {
68 fn type_(&self) -> types::ObjectType {
69 types::interface::CLIENT
70 }
71
72 fn version(&self) -> u32 {
73 3
74 }
75
76 fn proxy(&self) -> Proxy<Self> {
77 self.inner
78 .proxy
79 .read()
80 .unwrap()
81 .as_ref()
82 .expect("Client proxy should be initialised on creation")
83 .clone()
84 }
85}
86
87impl Client {
88 pub(crate) fn new(core: &Core) -> Self {
89 let this = Self {
90 inner: new_refcounted(InnerClient::new(core)),
91 };
92
93 let id = core.next_proxy_id();
94 this.inner
95 .proxy
96 .write()
97 .unwrap()
98 .replace(Proxy::new(id, &this));
99 core.add_proxy(&this, id);
100
101 this
102 }
103
104 pub fn add_listener(&self, events: ClientEvents) -> HookId {
106 self.inner.hooks.lock().unwrap().append(events)
107 }
108
109 pub fn remove_listener(&self, hook_id: HookId) {
111 self.inner.hooks.lock().unwrap().remove(hook_id);
112 }
113
114 pub fn error(&self, id: u32, res: u32, message: &str) -> std::io::Result<()> {
116 let proxy = self.proxy();
117 proxy_object_invoke!(proxy, error, id, res, message)
118 }
119
120 pub fn permissions(&self, index: u32, num: u32) -> std::io::Result<()> {
122 let proxy = self.proxy();
123 proxy_object_invoke!(proxy, get_permissions, index, num)
124 }
125
126 pub fn update_permissions(
128 &self,
129 permissions: &[permission::Permission],
130 ) -> std::io::Result<()> {
131 let proxy = self.proxy();
132 proxy_object_invoke!(proxy, update_permissions, permissions)
133 }
134
135 pub(crate) fn methods(&self) -> Arc<Mutex<ClientMethods<Client>>> {
136 self.inner.methods.clone()
137 }
138
139 pub(crate) fn events(&self) -> Arc<Mutex<spa::hook::HookList<ClientEvents>>> {
140 self.inner.hooks.clone()
141 }
142}
143
144impl InnerClient {
145 fn new(core: &Core) -> Self {
146 Self {
147 proxy: RwLock::new(None),
148 methods: Arc::new(Mutex::new(protocol::marshal::client::Methods::marshal(
149 core.connection(),
150 ))),
151 hooks: spa::hook::HookList::new(),
152 }
153 }
154}