libpulse_binding/mainloop/api.rs
1// Copyright 2017 Lyndon Brown
2//
3// This file is part of the PulseAudio Rust language binding.
4//
5// Licensed under the MIT license or the Apache license (version 2.0), at your option. You may not
6// copy, modify, or distribute this file except in compliance with said license. You can find copies
7// of these licenses either in the LICENSE-MIT and LICENSE-APACHE files, or alternatively at
8// <http://opensource.org/licenses/MIT> and <http://www.apache.org/licenses/LICENSE-2.0>
9// respectively.
10//
11// Portions of documentation are copied from the LGPL 2.1+ licensed PulseAudio C headers on a
12// fair-use basis, as discussed in the overall project readme (available in the git repository).
13
14//! Main loop abstraction layer API.
15
16use std::os::raw::c_void;
17use std::rc::Rc;
18use libc::timeval;
19use crate::def;
20use super::events;
21use super::events::io::{IoEvent, IoEventRef, IoEventInternal, FlagSet as IoEventFlagSet};
22use super::events::timer::{TimeEvent, TimeEventRef, TimeEventInternal};
23use super::events::deferred::{DeferEvent, DeferEventRef, DeferEventInternal};
24use crate::time::{UnixTs, MonotonicTs, Timeval, MicroSeconds};
25use crate::callbacks::{get_su_capi_params, get_su_callback};
26
27pub(crate) use capi::pa_mainloop_api as ApiInternal;
28
29/// This enables generic type enforcement with the opaque C objects.
30pub trait MainloopInternalType {}
31
32/// This enables generic type enforcement with MainloopInner objects, and describes mandatory
33/// accessors for the internal pointers, allowing access to these pointers across the generic
34/// implementations to work.
35pub trait MainloopInnerType {
36 /// Internal mainloop type.
37 type I: MainloopInternalType;
38
39 /// Create a new instance
40 #[inline(always)]
41 unsafe fn new(ptr: *mut Self::I, api: *const MainloopApi,
42 dropfn: fn(&mut MainloopInner<Self::I>), supports_rtclock: bool)
43 -> MainloopInner::<Self::I>
44 {
45 MainloopInner::<Self::I> { ptr, api, dropfn, supports_rtclock }
46 }
47
48 /// Return opaque main loop object pointer.
49 ///
50 /// **Warning**: The pointer is only valid for the lifetime of this object.
51 fn get_ptr(&self) -> *mut Self::I;
52
53 /// Return raw API object pointer.
54 ///
55 /// **Warning**: The pointer is only valid for the lifetime of this object.
56 fn get_api_ptr(&self) -> *const MainloopApi;
57
58 /// Return main loop API object pointer.
59 fn get_api(&self) -> &MainloopApi;
60
61 /// Returns `true` if the mainloop implementation supports monotonic based time events.
62 fn supports_rtclock(&self) -> bool;
63}
64
65/// Mainloop inner wrapper.
66///
67/// This contains the actual main loop object pointers, holding both the pointer to the actual
68/// opaque main loop C object, and the pointer to the associated API vtable.
69///
70/// An instance of this type will be held, in an `Rc` ref counted wrapper both in an outer Mainloop
71/// wrapper, and by all event objects. With event objects holding a ref-counted copy, this both
72/// gives event objects access to the API pointer, which they need, and also it allows us to ensure
73/// that event objects do not outlive the main loop object (which internally owns the API object),
74/// and thus ensures correct destruction order of event and main loop objects.
75pub struct MainloopInner<T>
76 where T: MainloopInternalType
77{
78 /// An opaque main loop object.
79 ptr: *mut T,
80
81 /// The abstract main loop API vtable for the GLIB main loop object. No need to free this API as
82 /// it is owned by the loop and is destroyed when the loop is freed.
83 api: *const MainloopApi,
84
85 /// All implementations must provide a drop method, to be called from an actual drop call, which
86 /// should free the mainloop object.
87 dropfn: fn(&mut MainloopInner<T>),
88
89 /// Whether or not the implementation supports monotonic based time events. (`true` if so).
90 supports_rtclock: bool,
91}
92
93impl<T> Drop for MainloopInner<T>
94 where T: MainloopInternalType
95{
96 fn drop(&mut self) {
97 (self.dropfn)(self);
98 self.ptr = std::ptr::null_mut::<<MainloopInner<T> as MainloopInnerType>::I>();
99 self.api = std::ptr::null::<MainloopApi>();
100 }
101}
102
103/// This is the actual implementation of the ‘inner type’ trait.
104///
105/// It is not possible to replace this with ‘default’ method implementations within the trait itself
106/// since the trait does not know about the existence of the struct attributes being accessed.
107impl<T> MainloopInnerType for MainloopInner<T>
108 where T: MainloopInternalType
109{
110 type I = T;
111
112 /// Gets opaque main loop object pointer.
113 ///
114 /// **Warning**: The pointer is only valid for the lifetime of this object.
115 #[inline(always)]
116 fn get_ptr(&self) -> *mut T {
117 self.ptr
118 }
119
120 /// Gets raw API object pointer.
121 ///
122 /// **Warning**: The pointer is only valid for the lifetime of this object.
123 #[inline(always)]
124 fn get_api_ptr(&self) -> *const MainloopApi {
125 self.api
126 }
127
128 /// Gets main loop API object pointer.
129 #[inline(always)]
130 fn get_api(&self) -> &MainloopApi {
131 assert!(!self.api.is_null());
132 unsafe { &*self.api }
133 }
134
135 #[inline(always)]
136 fn supports_rtclock(&self) -> bool {
137 self.supports_rtclock
138 }
139}
140
141/// Mainloop trait, to be implemented by the different types of mainloops.
142pub trait Mainloop {
143 /// Inner mainloop type.
144 type MI: MainloopInnerType;
145
146 /// Get inner mainloop.
147 fn inner(&self) -> Rc<Self::MI>;
148
149 /// Creates a new IO event.
150 ///
151 /// **Note**: You must ensure that the returned event object lives for as long as you want its
152 /// event(s) to fire, as its `Drop` implementation destroys the event source. I.e. if you create
153 /// a new event, but then immediately drop the object returned here, no event will fire!
154 ///
155 /// The given callback must accept three parameters, an [`IoEventRef`] object, a copy of the
156 /// given file descriptor, and an event flag set, indicating the event(s) that occurred. The
157 /// [`DeferEventRef`] object gives you some opportunity to manage the event source from within
158 /// it’s callback execution.
159 fn new_io_event(&mut self, fd: i32, events: IoEventFlagSet,
160 mut callback: Box<dyn FnMut(IoEventRef<Self::MI>, i32, IoEventFlagSet) + 'static>)
161 -> Option<IoEvent<Self::MI>>
162 {
163 let inner_for_wrapper = self.inner();
164 let wrapper_cb = Box::new(move |ptr, fd, flags| {
165 let ref_obj = IoEventRef::<Self::MI>::from_raw(ptr, Rc::clone(&inner_for_wrapper));
166 callback(ref_obj, fd, flags);
167 });
168
169 let to_save = events::io::EventCb::new(Some(wrapper_cb));
170 let (cb_fn, cb_data) = to_save.get_capi_params(events::io::event_cb_proxy);
171
172 let inner = self.inner();
173 let api = inner.get_api();
174 let fn_ptr = api.io_new.unwrap();
175 let ptr = fn_ptr(api, fd, events, cb_fn, cb_data);
176 match ptr.is_null() {
177 false => Some(IoEvent::<Self::MI>::from_raw(ptr, Rc::clone(&inner), to_save)),
178 true => None,
179 }
180 }
181
182 /// Creates a new timer event.
183 ///
184 /// **Note**: You must ensure that the returned event object lives for as long as you want its
185 /// event(s) to fire, as its `Drop` implementation destroys the event source. I.e. if you create
186 /// a new event, but then immediately drop the object returned here, no event will fire!
187 ///
188 /// The callback must take a [`TimeEventRef`] object, which gives you some opportunity to
189 /// manage the event source from within it’s callback execution.
190 ///
191 /// Example event set to fire in five seconds time:
192 ///
193 /// ```rust,ignore
194 /// use libpulse_binding::time::{UnixTs, MicroSeconds};
195 /// let _t_event = mainloop.new_timer_event(
196 /// &(UnixTs::now() + MicroSeconds::from_secs(5).unwrap()),
197 /// Box::new(|_| { println!("Timer event fired!"); }));
198 /// ```
199 fn new_timer_event(&mut self, tv: &UnixTs,
200 mut callback: Box<dyn FnMut(TimeEventRef<Self::MI>) + 'static>)
201 -> Option<TimeEvent<Self::MI>>
202 {
203 let inner_for_wrapper = self.inner();
204 let wrapper_cb = Box::new(move |ptr| {
205 let ref_obj = TimeEventRef::<Self::MI>::from_raw(ptr, Rc::clone(&inner_for_wrapper));
206 callback(ref_obj);
207 });
208
209 let to_save = events::timer::EventCb::new(Some(wrapper_cb));
210 let (cb_fn, cb_data) = to_save.get_capi_params(events::timer::event_cb_proxy);
211
212 let inner = self.inner();
213 let api = inner.get_api();
214 let fn_ptr = api.time_new.unwrap();
215 let ptr = fn_ptr(api, &(tv.0).0, cb_fn, cb_data);
216 match ptr.is_null() {
217 false => Some(TimeEvent::<Self::MI>::from_raw(ptr, Rc::clone(&inner), to_save)),
218 true => None,
219 }
220 }
221
222 /// Creates a new monotonic-based timer event.
223 ///
224 /// Asserts that `t` is not `MicroSeconds::INVALID`.
225 ///
226 /// This is an alternative to the `new_timer_event` method, taking a monotonic based time value.
227 ///
228 /// **Note**: You must ensure that the returned event object lives for as long as you want its
229 /// event(s) to fire, as its `Drop` implementation destroys the event source. I.e. if you create
230 /// a new event, but then immediately drop the object returned here, no event will fire!
231 ///
232 /// The callback must take a [`TimeEventRef`] object, which gives you some opportunity to
233 /// manage the event source from within it’s callback execution.
234 ///
235 /// Example event set to fire in five seconds time:
236 ///
237 /// ```rust,ignore
238 /// use libpulse_binding::time::{MonotonicTs, MicroSeconds};
239 /// let _t_event = mainloop.new_timer_event_rt(
240 /// MonotonicTs::now() + MicroSeconds::from_secs(5).unwrap(),
241 /// Box::new(|_| { println!("Timer event fired!"); }));
242 /// ```
243 fn new_timer_event_rt(&mut self, t: MonotonicTs,
244 mut callback: Box<dyn FnMut(TimeEventRef<Self::MI>) + 'static>)
245 -> Option<TimeEvent<Self::MI>>
246 {
247 assert_ne!(t.0, MicroSeconds::INVALID);
248
249 let inner_for_wrapper = self.inner();
250 let wrapper_cb = Box::new(move |ptr| {
251 let ref_obj = TimeEventRef::<Self::MI>::from_raw(ptr, Rc::clone(&inner_for_wrapper));
252 callback(ref_obj);
253 });
254
255 let to_save = events::timer::EventCb::new(Some(wrapper_cb));
256 let (cb_fn, cb_data) = to_save.get_capi_params(events::timer::event_cb_proxy);
257
258 let inner = self.inner();
259
260 let mut tv = Timeval::new_zero();
261 tv.set_rt(t.0, inner.supports_rtclock());
262
263 let api = inner.get_api();
264 let fn_ptr = api.time_new.unwrap();
265 let ptr = fn_ptr(api, &tv.0, cb_fn, cb_data);
266 match ptr.is_null() {
267 false => Some(TimeEvent::<Self::MI>::from_raw(ptr, Rc::clone(&inner), to_save)),
268 true => None,
269 }
270 }
271
272 /// Creates a new deferred event.
273 ///
274 /// **Note**: You must ensure that the returned event object lives for as long as you want its
275 /// event(s) to fire, as its `Drop` implementation destroys the event source. I.e. if you create
276 /// a new event, but then immediately drop the object returned here, no event will fire!
277 ///
278 /// The callback must take a [`DeferEventRef`] object, which gives you some opportunity to
279 /// manage the event source from within it’s callback execution.
280 fn new_deferred_event(&mut self,
281 mut callback: Box<dyn FnMut(DeferEventRef<Self::MI>) + 'static>)
282 -> Option<DeferEvent<Self::MI>>
283 {
284 let inner_for_wrapper = self.inner();
285 let wrapper_cb = Box::new(move |ptr| {
286 let ref_obj = DeferEventRef::<Self::MI>::from_raw(ptr, Rc::clone(&inner_for_wrapper));
287 callback(ref_obj);
288 });
289
290 let to_save = events::deferred::EventCb::new(Some(wrapper_cb));
291 let (cb_fn, cb_data) = to_save.get_capi_params(events::deferred::event_cb_proxy);
292
293 let inner = self.inner();
294 let api = inner.get_api();
295 let fn_ptr = api.defer_new.unwrap();
296 let ptr = fn_ptr(api, cb_fn, cb_data);
297 match ptr.is_null() {
298 false => Some(DeferEvent::<Self::MI>::from_raw(ptr, Rc::clone(&inner), to_save)),
299 true => None,
300 }
301 }
302
303 /// Runs the specified callback once from the main loop using an anonymous defer event.
304 ///
305 /// If the mainloop runs in a different thread, you need to follow the mainloop implementation’s
306 /// rules regarding how to safely create defer events. In particular, if you’re using
307 /// [`mainloop::threaded`](mod@crate::mainloop::threaded), you must lock the mainloop before
308 /// calling this function.
309 fn once_event(&mut self, callback: Box<dyn FnMut() + 'static>) {
310 let (cb_fn, cb_data): (Option<extern "C" fn(_, _)>, _) =
311 get_su_capi_params::<_, _>(Some(callback), once_cb_proxy);
312
313 let inner = self.inner();
314 let api = inner.get_api();
315 unsafe { capi::pa_mainloop_api_once(api.as_ref(), cb_fn, cb_data) };
316 }
317
318 /// Calls quit
319 fn quit(&mut self, retval: def::Retval) {
320 let inner = self.inner();
321 let api = inner.get_api();
322 let fn_ptr = api.quit.unwrap();
323 fn_ptr(api, retval.0);
324 }
325}
326
327/// An IO event callback prototype.
328pub type IoEventCb = extern "C" fn(a: *const MainloopApi, e: *mut IoEventInternal, fd: i32,
329 events: IoEventFlagSet, userdata: *mut c_void);
330/// A IO event destroy callback prototype.
331pub type IoEventDestroyCb = extern "C" fn(a: *const MainloopApi, e: *mut IoEventInternal,
332 userdata: *mut c_void);
333
334/// A time event callback prototype.
335pub type TimeEventCb = extern "C" fn(a: *const MainloopApi, e: *mut TimeEventInternal,
336 tv: *const timeval, userdata: *mut c_void);
337/// A time event destroy callback prototype.
338pub type TimeEventDestroyCb = extern "C" fn(a: *const MainloopApi, e: *mut TimeEventInternal,
339 userdata: *mut c_void);
340
341/// A defer event callback prototype.
342pub type DeferEventCb = extern "C" fn(a: *const MainloopApi, e: *mut DeferEventInternal,
343 userdata: *mut c_void);
344/// A defer event destroy callback prototype.
345pub type DeferEventDestroyCb = extern "C" fn(a: *const MainloopApi, e: *mut DeferEventInternal,
346 userdata: *mut c_void);
347
348/// An abstract mainloop API vtable
349#[repr(C)]
350pub struct MainloopApi {
351 /* NOTE: This struct must be directly usable by the C API, thus same attributes/layout/etc */
352
353 /// A pointer to some private, arbitrary data of the main loop implementation.
354 pub userdata: *mut c_void,
355
356 /// Creates a new IO event source object.
357 pub io_new: Option<extern "C" fn(a: *const MainloopApi, fd: i32, events: IoEventFlagSet,
358 cb: Option<IoEventCb>, userdata: *mut c_void) -> *mut IoEventInternal>,
359 /// Enables or disables IO events on this object.
360 pub io_enable: Option<extern "C" fn(e: *mut IoEventInternal, events: IoEventFlagSet)>,
361 /// Frees a IO event source object.
362 pub io_free: Option<extern "C" fn(e: *mut IoEventInternal)>,
363 /// Sets a function that is called when the IO event source is destroyed. Use this to free the
364 /// `userdata` argument if required.
365 pub io_set_destroy: Option<extern "C" fn(e: *mut IoEventInternal, cb: Option<IoEventDestroyCb>)>,
366
367 /// Creates a new timer event source object for the specified Unix time.
368 pub time_new: Option<extern "C" fn(a: *const MainloopApi, tv: *const timeval,
369 cb: Option<TimeEventCb>, userdata: *mut c_void) -> *mut TimeEventInternal>,
370 /// Restarts a running or expired timer event source with a new Unix time.
371 pub time_restart: Option<extern "C" fn(e: *mut TimeEventInternal, tv: *const timeval)>,
372 /// Frees a deferred timer event source object.
373 pub time_free: Option<extern "C" fn(e: *mut TimeEventInternal)>,
374 /// Sets a function that is called when the timer event source is destroyed. Use this to free
375 /// the `userdata` argument if required.
376 pub time_set_destroy: Option<extern "C" fn(e: *mut TimeEventInternal,
377 cb: Option<TimeEventDestroyCb>)>,
378
379 /// Creates a new deferred event source object.
380 pub defer_new: Option<extern "C" fn(a: *const MainloopApi, cb: Option<DeferEventCb>,
381 userdata: *mut c_void) -> *mut DeferEventInternal>,
382 /// Enables or disables a deferred event source temporarily.
383 pub defer_enable: Option<extern "C" fn(e: *mut DeferEventInternal, b: i32)>,
384 /// Frees a deferred event source object.
385 pub defer_free: Option<extern "C" fn(e: *mut DeferEventInternal)>,
386 /// Sets a function that is called when the deferred event source is
387 /// destroyed. Use this to free the `userdata` argument if required.
388 pub defer_set_destroy: Option<extern "C" fn(e: *mut DeferEventInternal,
389 cb: Option<DeferEventDestroyCb>)>,
390
391 /// Exits the main loop and return the specified retval.
392 pub quit: Option<extern "C" fn(a: *const MainloopApi, retval: def::RetvalActual)>,
393}
394
395/// Test size is equal to `sys` equivalent (duplicated here for different documentation)
396#[test]
397fn api_compare_capi() {
398 assert_eq!(std::mem::size_of::<ApiInternal>(), std::mem::size_of::<capi::pa_mainloop_api>());
399 assert_eq!(std::mem::align_of::<ApiInternal>(), std::mem::align_of::<capi::pa_mainloop_api>());
400}
401
402impl AsRef<capi::pa_mainloop_api> for MainloopApi {
403 #[inline]
404 fn as_ref(&self) -> &capi::pa_mainloop_api {
405 unsafe { &*(self as *const Self as *const capi::pa_mainloop_api) }
406 }
407}
408
409impl<'a> From<*const ApiInternal> for &'a MainloopApi {
410 #[inline]
411 fn from(a: *const ApiInternal) -> Self {
412 unsafe { std::mem::transmute(a) }
413 }
414}
415impl<'a> From<&'a MainloopApi> for *const ApiInternal {
416 #[inline]
417 fn from(a: &'a MainloopApi) -> Self {
418 unsafe { std::mem::transmute(a) }
419 }
420}
421
422/// Proxy for anonymous ‘once’ deferred event callbacks.
423///
424/// Warning: This is for single-use cases only! It destroys the actual closure callback.
425extern "C"
426fn once_cb_proxy(_: *const ApiInternal, userdata: *mut c_void) {
427 let _ = std::panic::catch_unwind(|| {
428 // Note, destroys closure callback after use - restoring outer box means it gets dropped
429 let mut callback = get_su_callback::<dyn FnMut()>(userdata);
430 (callback)();
431 });
432}