libpulse_binding/context/
ext_device_restore.rs1use std::os::raw::c_void;
17use std::ptr::null_mut;
18use std::mem;
19use capi::pa_ext_device_restore_info as InfoInternal;
20use super::{ContextInternal, Context};
21use crate::{def, format};
22use crate::callbacks::{
23 ListResult, box_closure_get_capi_ptr, callback_for_list_instance, MultiUseCallback
24};
25use crate::operation::Operation;
26
27#[derive(Debug)]
30pub struct Info {
31 pub dtype: def::Device,
33 pub index: u32,
35 pub formats: Vec<format::Info>,
37}
38
39impl Info {
40 fn new_from_raw(p: *const InfoInternal) -> Self {
41 assert!(!p.is_null());
42 let src = unsafe { p.as_ref().unwrap() };
43
44 let mut formats_vec = Vec::with_capacity(src.n_formats as usize);
45 assert!(src.n_formats == 0 || !src.formats.is_null());
46 for i in 0..src.n_formats as isize {
47 let indexed_ptr = unsafe { (*src.formats.offset(i)) as *mut format::InfoInternal };
48 if !indexed_ptr.is_null() {
49 formats_vec.push(format::Info::from_raw_weak(indexed_ptr));
50 }
51 }
52
53 Info { dtype: src.dtype, index: src.index, formats: formats_vec }
54 }
55}
56
57pub struct DeviceRestore {
61 context: *mut ContextInternal,
62 cb_ptrs: CallbackPointers,
64}
65
66unsafe impl Send for DeviceRestore {}
67unsafe impl Sync for DeviceRestore {}
68
69#[derive(Default)]
72struct CallbackPointers {
73 subscribe: SubscribeCb,
74}
75
76type SubscribeCb = MultiUseCallback<dyn FnMut(def::Device, u32),
77 extern "C" fn(*mut ContextInternal, def::Device, u32, *mut c_void)>;
78
79impl Context {
80 pub fn device_restore(&self) -> DeviceRestore {
85 unsafe { capi::pa_context_ref(self.ptr) };
86 DeviceRestore::from_raw(self.ptr)
87 }
88}
89
90impl DeviceRestore {
91 fn from_raw(context: *mut ContextInternal) -> Self {
93 Self { context: context, cb_ptrs: Default::default() }
94 }
95
96 pub fn test<F>(&mut self, callback: F) -> Operation<dyn FnMut(u32)>
102 where F: FnMut(u32) + 'static
103 {
104 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(u32)>(Box::new(callback));
105 let ptr = unsafe { capi::pa_ext_device_restore_test(self.context,
106 Some(super::ext_test_cb_proxy), cb_data) };
107 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(u32)>)
108 }
109
110 pub fn subscribe<F>(&mut self, enable: bool, callback: F) -> Operation<dyn FnMut(bool)>
116 where F: FnMut(bool) + 'static
117 {
118 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
119 let ptr = unsafe { capi::pa_ext_device_restore_subscribe(self.context, enable as i32,
120 Some(super::success_cb_proxy), cb_data) };
121 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
122 }
123
124 pub fn set_subscribe_cb<F>(&mut self, callback: F)
132 where F: FnMut(def::Device, u32) + 'static
133 {
134 let saved = &mut self.cb_ptrs.subscribe;
135 *saved = SubscribeCb::new(Some(Box::new(callback)));
136 let (cb_fn, cb_data) = saved.get_capi_params(ext_subscribe_cb_proxy);
137 unsafe { capi::pa_ext_device_restore_set_subscribe_cb(self.context, cb_fn, cb_data); }
138 }
139
140 pub fn read_formats_all<F>(&mut self, callback: F) -> Operation<dyn FnMut(ListResult<&Info>)>
144 where F: FnMut(ListResult<&Info>) + 'static
145 {
146 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
147 let ptr = unsafe { capi::pa_ext_device_restore_read_formats_all(self.context,
148 Some(read_list_cb_proxy), cb_data) };
149 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
150 }
151
152 pub fn read_formats<F>(&mut self, type_: def::Device, index: u32, callback: F)
156 -> Operation<dyn FnMut(ListResult<&Info>)>
157 where F: FnMut(ListResult<&Info>) + 'static
158 {
159 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
160 let ptr = unsafe { capi::pa_ext_device_restore_read_formats(self.context, type_, index,
161 Some(read_list_cb_proxy), cb_data) };
162 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
163 }
164
165 pub fn save_formats<F>(&mut self, type_: def::Device, index: u32,
171 formats: &mut [&mut format::Info], callback: F) -> Operation<dyn FnMut(bool)>
172 where F: FnMut(bool) + 'static
173 {
174 let mut format_ptrs: Vec<*mut capi::pa_format_info> = Vec::with_capacity(formats.len());
176 for format in formats {
177 format_ptrs.push(unsafe { mem::transmute(&format.ptr) });
178 }
179
180 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
181 let ptr = unsafe {
182 capi::pa_ext_device_restore_save_formats(self.context, type_, index,
183 format_ptrs.len() as u8, format_ptrs.as_ptr(), Some(super::success_cb_proxy),
184 cb_data)
185 };
186 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
187 }
188}
189
190impl Drop for DeviceRestore {
191 fn drop(&mut self) {
192 unsafe { capi::pa_context_unref(self.context) };
193 self.context = null_mut::<ContextInternal>();
194 }
195}
196
197extern "C"
202fn ext_subscribe_cb_proxy(_: *mut ContextInternal, type_: def::Device, index: u32,
203 userdata: *mut c_void)
204{
205 let _ = std::panic::catch_unwind(|| {
206 let callback = SubscribeCb::get_callback(userdata);
207 (callback)(type_, index);
208 });
209}
210
211extern "C"
215fn read_list_cb_proxy(_: *mut ContextInternal, i: *const InfoInternal, eol: i32,
216 userdata: *mut c_void)
217{
218 let _ = std::panic::catch_unwind(|| {
219 callback_for_list_instance(i, eol, userdata, Info::new_from_raw);
220 });
221}