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}