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 pub fn to_owned(&self) -> Self {
58 Info {
59 formats: self.formats.iter().map(format::Info::to_owned).collect(),
60 ..*self
61 }
62 }
63}
64
65pub struct DeviceRestore {
69 context: *mut ContextInternal,
70 cb_ptrs: CallbackPointers,
72}
73
74unsafe impl Send for DeviceRestore {}
75unsafe impl Sync for DeviceRestore {}
76
77#[derive(Default)]
80struct CallbackPointers {
81 subscribe: SubscribeCb,
82}
83
84type SubscribeCb = MultiUseCallback<dyn FnMut(def::Device, u32),
85 extern "C" fn(*mut ContextInternal, def::Device, u32, *mut c_void)>;
86
87impl Context {
88 pub fn device_restore(&self) -> DeviceRestore {
93 unsafe { capi::pa_context_ref(self.ptr) };
94 DeviceRestore::from_raw(self.ptr)
95 }
96}
97
98impl DeviceRestore {
99 fn from_raw(context: *mut ContextInternal) -> Self {
101 Self { context: context, cb_ptrs: Default::default() }
102 }
103
104 pub fn test<F>(&mut self, callback: F) -> Operation<dyn FnMut(u32)>
110 where F: FnMut(u32) + 'static
111 {
112 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(u32)>(Box::new(callback));
113 let ptr = unsafe { capi::pa_ext_device_restore_test(self.context,
114 Some(super::ext_test_cb_proxy), cb_data) };
115 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(u32)>)
116 }
117
118 pub fn subscribe<F>(&mut self, enable: bool, callback: F) -> Operation<dyn FnMut(bool)>
124 where F: FnMut(bool) + 'static
125 {
126 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
127 let ptr = unsafe { capi::pa_ext_device_restore_subscribe(self.context, enable as i32,
128 Some(super::success_cb_proxy), cb_data) };
129 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
130 }
131
132 pub fn set_subscribe_cb<F>(&mut self, callback: F)
140 where F: FnMut(def::Device, u32) + 'static
141 {
142 let saved = &mut self.cb_ptrs.subscribe;
143 *saved = SubscribeCb::new(Some(Box::new(callback)));
144 let (cb_fn, cb_data) = saved.get_capi_params(ext_subscribe_cb_proxy);
145 unsafe { capi::pa_ext_device_restore_set_subscribe_cb(self.context, cb_fn, cb_data); }
146 }
147
148 pub fn read_formats_all<F>(&mut self, callback: F) -> Operation<dyn FnMut(ListResult<&Info>)>
152 where F: FnMut(ListResult<&Info>) + 'static
153 {
154 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
155 let ptr = unsafe { capi::pa_ext_device_restore_read_formats_all(self.context,
156 Some(read_list_cb_proxy), cb_data) };
157 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
158 }
159
160 pub fn read_formats<F>(&mut self, type_: def::Device, index: u32, callback: F)
164 -> Operation<dyn FnMut(ListResult<&Info>)>
165 where F: FnMut(ListResult<&Info>) + 'static
166 {
167 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
168 let ptr = unsafe { capi::pa_ext_device_restore_read_formats(self.context, type_, index,
169 Some(read_list_cb_proxy), cb_data) };
170 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
171 }
172
173 pub fn save_formats<F>(&mut self, type_: def::Device, index: u32,
179 formats: &mut [&mut format::Info], callback: F) -> Operation<dyn FnMut(bool)>
180 where F: FnMut(bool) + 'static
181 {
182 let mut format_ptrs: Vec<*mut capi::pa_format_info> = Vec::with_capacity(formats.len());
184 for format in formats {
185 format_ptrs.push(unsafe { mem::transmute(&format.ptr) });
186 }
187
188 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
189 let ptr = unsafe {
190 capi::pa_ext_device_restore_save_formats(self.context, type_, index,
191 format_ptrs.len() as u8, format_ptrs.as_ptr(), Some(super::success_cb_proxy),
192 cb_data)
193 };
194 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
195 }
196}
197
198impl Drop for DeviceRestore {
199 fn drop(&mut self) {
200 unsafe { capi::pa_context_unref(self.context) };
201 self.context = null_mut::<ContextInternal>();
202 }
203}
204
205extern "C"
210fn ext_subscribe_cb_proxy(_: *mut ContextInternal, type_: def::Device, index: u32,
211 userdata: *mut c_void)
212{
213 let _ = std::panic::catch_unwind(|| {
214 let callback = SubscribeCb::get_callback(userdata);
215 (callback)(type_, index);
216 });
217}
218
219extern "C"
223fn read_list_cb_proxy(_: *mut ContextInternal, i: *const InfoInternal, eol: i32,
224 userdata: *mut c_void)
225{
226 let _ = std::panic::catch_unwind(|| {
227 callback_for_list_instance(i, eol, userdata, Info::new_from_raw);
228 });
229}