libpulse_binding/mainloop/events/
deferred.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 deferred events.
15
16use std::os::raw::c_void;
17use std::rc::Rc;
18use crate::mainloop::api::{MainloopApi, MainloopInnerType};
19use crate::callbacks::MultiUseCallback;
20
21pub use capi::pa_defer_event as DeferEventInternal;
22
23/// A deferred event source.
24pub struct DeferEvent<T>
25    where T: MainloopInnerType
26{
27    /// Internal object pointer
28    ptr: *mut DeferEventInternal,
29    /// Source mainloop.
30    owner: Rc<T>,
31    /// Saved callback closure, for later destruction.
32    _saved_cb: EventCb,
33}
34
35/// A reference to a deferred event source, provided to the callback, allowing modification within
36/// the callback itself.
37pub struct DeferEventRef<T: 'static>
38    where T: MainloopInnerType
39{
40    /// Internal object pointer
41    ptr: *mut DeferEventInternal,
42    /// Source mainloop.
43    owner: Rc<T>,
44}
45
46pub(crate) type EventCb = MultiUseCallback<dyn FnMut(*mut DeferEventInternal),
47    extern "C" fn(a: *const MainloopApi, e: *mut DeferEventInternal, userdata: *mut c_void)>;
48
49impl<T> DeferEvent<T>
50    where T: MainloopInnerType
51{
52    #[inline]
53    pub(crate) fn from_raw(ptr: *mut DeferEventInternal, mainloop_inner: Rc<T>, callback: EventCb)
54        -> Self
55    {
56        assert_eq!(false, ptr.is_null());
57        Self { ptr: ptr, owner: mainloop_inner, _saved_cb: callback }
58    }
59
60    /// Enables this event source temporarily.
61    #[inline]
62    pub fn enable(&mut self) {
63        let fn_ptr = (*self.owner).get_api().defer_enable.unwrap();
64        fn_ptr(self.ptr, 1);
65    }
66
67    /// Disables this event source temporarily.
68    #[inline]
69    pub fn disable(&mut self) {
70        let fn_ptr = (*self.owner).get_api().defer_enable.unwrap();
71        fn_ptr(self.ptr, 0);
72    }
73}
74
75impl<T> DeferEventRef<T>
76    where T: MainloopInnerType
77{
78    #[inline]
79    pub(crate) fn from_raw(ptr: *mut DeferEventInternal, mainloop_inner: Rc<T>) -> Self {
80        assert_eq!(false, ptr.is_null());
81        Self { ptr: ptr, owner: mainloop_inner }
82    }
83
84    /// Enables this event source temporarily.
85    #[inline]
86    pub fn enable(&mut self) {
87        let fn_ptr = (*self.owner).get_api().defer_enable.unwrap();
88        fn_ptr(self.ptr, 1);
89    }
90
91    /// Disables this event source temporarily.
92    #[inline]
93    pub fn disable(&mut self) {
94        let fn_ptr = (*self.owner).get_api().defer_enable.unwrap();
95        fn_ptr(self.ptr, 0);
96    }
97}
98
99impl<T> Drop for DeferEvent<T>
100    where T: MainloopInnerType
101{
102    fn drop(&mut self) {
103        let fn_ptr = (*self.owner).get_api().defer_free.unwrap();
104        fn_ptr(self.ptr);
105    }
106}
107
108/// Proxy for the event callback.
109///
110/// Warning: This is for multi-use cases! It does **not** destroy the actual closure callback, which
111/// must be accomplished separately to avoid a memory leak.
112pub(crate)
113extern "C"
114fn event_cb_proxy(_: *const MainloopApi, e: *mut DeferEventInternal, userdata: *mut c_void) {
115    let _ = std::panic::catch_unwind(|| {
116        let callback = EventCb::get_callback(userdata);
117        (callback)(e);
118    });
119}