pipewire_native_spa/interface/
loop.rs

1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: Copyright (c) 2025 Asymptotic Inc.
3// SPDX-FileCopyrightText: Copyright (c) 2025 Arun Raghavan
4
5use super::plugin::Interface;
6use crate::{flags, hook::HookId};
7use std::{any::Any, os::fd::RawFd, pin::Pin, time::Duration};
8
9#[derive(Copy, Clone, Debug)]
10pub struct Source {
11    pub fd: RawFd,
12    pub mask: u32,
13    pub rmask: u32,
14}
15
16pub type SourceFn = dyn FnMut(&Source) + Send + 'static;
17pub type InvokeFn = dyn FnMut(bool, u32, &[u8]) -> i32 + Send + 'static;
18
19pub struct LoopImpl {
20    pub inner: Pin<Box<dyn Any>>,
21
22    pub add_source: fn(&mut LoopImpl, source: &Source, func: Box<SourceFn>) -> std::io::Result<i32>,
23    pub update_source: fn(&mut LoopImpl, source: &Source) -> std::io::Result<i32>,
24    pub remove_source: fn(&mut LoopImpl, fd: RawFd) -> std::io::Result<i32>,
25    #[allow(clippy::type_complexity)]
26    pub invoke: fn(
27        this: &LoopImpl,
28        seq: u32,
29        data: &[u8],
30        block: bool,
31        func: Box<InvokeFn>,
32    ) -> std::io::Result<i32>,
33}
34
35unsafe impl Send for LoopImpl {}
36unsafe impl Sync for LoopImpl {}
37
38impl LoopImpl {
39    pub fn add_source(&mut self, source: &Source, func: Box<SourceFn>) -> std::io::Result<i32> {
40        (self.add_source)(self, source, func)
41    }
42
43    pub fn update_source(&mut self, source: &Source) -> std::io::Result<i32> {
44        (self.update_source)(self, source)
45    }
46
47    pub fn remove_source(&mut self, fd: RawFd) -> std::io::Result<i32> {
48        (self.remove_source)(self, fd)
49    }
50
51    pub fn invoke(
52        &self,
53        seq: u32,
54        data: &[u8],
55        block: bool,
56        func: Box<InvokeFn>,
57    ) -> std::io::Result<i32> {
58        (self.invoke)(self, seq, data, block, func)
59    }
60}
61
62impl Interface for LoopImpl {
63    unsafe fn make_native(&self) -> *mut super::ffi::CInterface {
64        crate::support::ffi::r#loop::make_native(self)
65    }
66
67    unsafe fn free_native(loop_: *mut super::ffi::CInterface) {
68        crate::support::ffi::r#loop::free_native(loop_)
69    }
70}
71
72pub struct LoopControlHooks {
73    pub before: Option<Box<dyn FnMut()>>,
74    pub after: Option<Box<dyn FnMut()>>,
75}
76
77pub struct LoopControlImpl {
78    pub inner: Pin<Box<dyn Any>>,
79
80    pub get_fd: fn(&LoopControlImpl) -> u32,
81    pub add_hook: fn(&LoopControlImpl, hooks: LoopControlHooks) -> HookId,
82    pub remove_hook: fn(&LoopControlImpl, hook: HookId),
83    pub enter: fn(&LoopControlImpl),
84    pub leave: fn(&LoopControlImpl),
85    pub iterate: fn(&LoopControlImpl, timeout: Option<Duration>) -> std::io::Result<i32>,
86    pub check: fn(&LoopControlImpl) -> std::io::Result<i32>,
87    pub lock: fn(&LoopControlImpl) -> std::io::Result<i32>,
88    pub unlock: fn(&LoopControlImpl) -> std::io::Result<i32>,
89    pub get_time: fn(&LoopControlImpl, timeout: Duration) -> std::io::Result<libc::timespec>,
90    pub wait: fn(&LoopControlImpl, abstime: &libc::timespec) -> std::io::Result<i32>,
91    pub signal: fn(&LoopControlImpl, wait_for_accept: bool) -> std::io::Result<i32>,
92    pub accept: fn(&LoopControlImpl) -> std::io::Result<i32>,
93}
94
95unsafe impl Send for LoopControlImpl {}
96unsafe impl Sync for LoopControlImpl {}
97
98impl LoopControlImpl {
99    pub fn get_fd(&self) -> u32 {
100        (self.get_fd)(self)
101    }
102
103    pub fn add_hook(&self, hooks: LoopControlHooks) -> HookId {
104        (self.add_hook)(self, hooks)
105    }
106
107    pub fn remove_hook(&self, hook: HookId) {
108        (self.remove_hook)(self, hook)
109    }
110
111    pub fn enter(&self) {
112        (self.enter)(self)
113    }
114
115    pub fn leave(&self) {
116        (self.leave)(self)
117    }
118
119    pub fn iterate(&self, timeout: Option<Duration>) -> std::io::Result<i32> {
120        (self.iterate)(self, timeout)
121    }
122
123    pub fn check(&self) -> std::io::Result<i32> {
124        (self.check)(self)
125    }
126
127    pub fn lock(&self) -> std::io::Result<i32> {
128        (self.lock)(self)
129    }
130
131    pub fn unlock(&self) -> std::io::Result<i32> {
132        (self.unlock)(self)
133    }
134
135    pub fn get_time(&self, timeout: Duration) -> std::io::Result<libc::timespec> {
136        (self.get_time)(self, timeout)
137    }
138
139    pub fn wait(&self, abstime: &libc::timespec) -> std::io::Result<i32> {
140        (self.wait)(self, abstime)
141    }
142
143    pub fn signal(&self, wait_for_accept: bool) -> std::io::Result<i32> {
144        (self.signal)(self, wait_for_accept)
145    }
146
147    pub fn accept(&self) -> std::io::Result<i32> {
148        (self.accept)(self)
149    }
150}
151
152impl Interface for LoopControlImpl {
153    unsafe fn make_native(&self) -> *mut super::ffi::CInterface {
154        crate::support::ffi::r#loop::control::make_native(self)
155    }
156
157    unsafe fn free_native(loop_: *mut super::ffi::CInterface) {
158        crate::support::ffi::r#loop::control::free_native(loop_)
159    }
160}
161
162pub type SourceIoFn = dyn FnMut(RawFd, u32) + Send + 'static;
163pub type SourceIdleFn = dyn FnMut() + Send + 'static;
164pub type SourceEventFn = dyn FnMut(u64) + Send + 'static;
165pub type SourceTimerFn = dyn FnMut(u64) + Send + 'static;
166pub type SourceSignalFn = dyn FnMut(i32) + Send + 'static;
167
168pub enum LoopUtilsSourceCb {
169    Io(Box<SourceIoFn>),
170    Idle(Box<SourceIdleFn>),
171    Event(Box<SourceEventFn>),
172    Timer(Box<SourceTimerFn>),
173    Signal(Box<SourceSignalFn>),
174}
175
176pub struct LoopUtilsSource {
177    pub cb: LoopUtilsSourceCb,
178    pub mask: flags::Io,
179    pub inner: Box<dyn Any>,
180}
181
182#[allow(clippy::type_complexity)]
183pub struct LoopUtilsImpl {
184    pub inner: Pin<Box<dyn Any>>,
185
186    pub add_io: fn(
187        &LoopUtilsImpl,
188        fd: RawFd,
189        mask: flags::Io,
190        close: bool,
191        func: Box<SourceIoFn>,
192    ) -> Option<Pin<Box<LoopUtilsSource>>>,
193    pub update_io: fn(
194        &LoopUtilsImpl,
195        source: &mut Pin<Box<LoopUtilsSource>>,
196        mask: flags::Io,
197    ) -> std::io::Result<i32>,
198    pub add_idle: fn(
199        &LoopUtilsImpl,
200        enabled: bool,
201        func: Box<SourceIdleFn>,
202    ) -> Option<Pin<Box<LoopUtilsSource>>>,
203    pub enable_idle: fn(
204        &LoopUtilsImpl,
205        source: &mut Pin<Box<LoopUtilsSource>>,
206        enabled: bool,
207    ) -> std::io::Result<i32>,
208    pub add_event:
209        fn(&LoopUtilsImpl, func: Box<SourceEventFn>) -> Option<Pin<Box<LoopUtilsSource>>>,
210    pub signal_event:
211        fn(&LoopUtilsImpl, source: &mut Pin<Box<LoopUtilsSource>>) -> std::io::Result<i32>,
212    pub add_timer:
213        fn(&LoopUtilsImpl, func: Box<SourceTimerFn>) -> Option<Pin<Box<LoopUtilsSource>>>,
214    pub update_timer: fn(
215        &LoopUtilsImpl,
216        source: &mut Pin<Box<LoopUtilsSource>>,
217        value: &libc::timespec,
218        interval: Option<&libc::timespec>,
219        absolute: bool,
220    ) -> std::io::Result<i32>,
221    pub add_signal: fn(
222        &LoopUtilsImpl,
223        signal_number: i32,
224        func: Box<SourceSignalFn>,
225    ) -> Option<Pin<Box<LoopUtilsSource>>>,
226    pub destroy_source: fn(&LoopUtilsImpl, source: Pin<Box<LoopUtilsSource>>),
227}
228
229unsafe impl Send for LoopUtilsImpl {}
230unsafe impl Sync for LoopUtilsImpl {}
231
232impl LoopUtilsImpl {
233    pub fn add_io(
234        &self,
235        fd: RawFd,
236        mask: flags::Io,
237        close: bool,
238        func: Box<SourceIoFn>,
239    ) -> Option<Pin<Box<LoopUtilsSource>>> {
240        (self.add_io)(self, fd, mask, close, func)
241    }
242
243    pub fn update_io(
244        &self,
245        source: &mut Pin<Box<LoopUtilsSource>>,
246        mask: flags::Io,
247    ) -> std::io::Result<i32> {
248        (self.update_io)(self, source, mask)
249    }
250
251    pub fn add_idle(
252        &self,
253        enabled: bool,
254        func: Box<SourceIdleFn>,
255    ) -> Option<Pin<Box<LoopUtilsSource>>> {
256        (self.add_idle)(self, enabled, func)
257    }
258
259    pub fn enable_idle(
260        &self,
261        source: &mut Pin<Box<LoopUtilsSource>>,
262        enabled: bool,
263    ) -> std::io::Result<i32> {
264        (self.enable_idle)(self, source, enabled)
265    }
266
267    pub fn add_event(&self, func: Box<SourceEventFn>) -> Option<Pin<Box<LoopUtilsSource>>> {
268        (self.add_event)(self, func)
269    }
270
271    pub fn signal_event(&self, source: &mut Pin<Box<LoopUtilsSource>>) -> std::io::Result<i32> {
272        (self.signal_event)(self, source)
273    }
274
275    pub fn add_timer(&self, func: Box<SourceTimerFn>) -> Option<Pin<Box<LoopUtilsSource>>> {
276        (self.add_timer)(self, func)
277    }
278
279    pub fn update_timer(
280        &self,
281        source: &mut Pin<Box<LoopUtilsSource>>,
282        value: &libc::timespec,
283        interval: Option<&libc::timespec>,
284        absolute: bool,
285    ) -> std::io::Result<i32> {
286        (self.update_timer)(self, source, value, interval, absolute)
287    }
288
289    pub fn add_signal(
290        &self,
291        signal_number: i32,
292        func: Box<SourceSignalFn>,
293    ) -> Option<Pin<Box<LoopUtilsSource>>> {
294        (self.add_signal)(self, signal_number, func)
295    }
296
297    pub fn destroy_source(&self, source: Pin<Box<LoopUtilsSource>>) {
298        (self.destroy_source)(self, source)
299    }
300}
301
302impl Interface for LoopUtilsImpl {
303    unsafe fn make_native(&self) -> *mut super::ffi::CInterface {
304        crate::support::ffi::r#loop::utils::make_native(self)
305    }
306
307    unsafe fn free_native(loop_: *mut super::ffi::CInterface) {
308        crate::support::ffi::r#loop::utils::free_native(loop_)
309    }
310}