libpulse_binding/context/
ext_stream_restore.rs1use std::os::raw::{c_char, c_void};
17use std::ffi::{CStr, CString};
18use std::borrow::Cow;
19use std::ptr::{null, null_mut};
20use std::mem;
21use capi::pa_ext_stream_restore_info as InfoInternal;
22use super::{ContextInternal, Context};
23use crate::{channelmap, proplist};
24use crate::callbacks::{ListResult, box_closure_get_capi_ptr, callback_for_list_instance};
25use crate::{operation::Operation, volume::ChannelVolumes};
26
27#[derive(Debug)]
30pub struct Info<'a> {
31 pub name: Option<Cow<'a, str>>,
34 pub channel_map: channelmap::Map,
36 pub volume: ChannelVolumes,
38 pub device: Option<Cow<'a, str>>,
40 pub mute: bool,
42}
43
44impl Info<'_> {
45 fn new_from_raw(p: *const InfoInternal) -> Self {
46 assert!(!p.is_null());
47 let src = unsafe { p.as_ref().unwrap() };
48 unsafe {
49 Info {
50 name: match src.name.is_null() {
51 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
52 true => None,
53 },
54 channel_map: src.channel_map.into(),
55 volume: src.volume.into(),
56 device: match src.device.is_null() {
57 false => Some(CStr::from_ptr(src.device).to_string_lossy()),
58 true => None,
59 },
60 mute: match src.mute {
61 0 => false,
62 _ => true,
63 },
64 }
65 }
66 }
67
68 pub fn to_owned(&self) -> Info<'static> {
70 Info {
71 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
72 device: self.device.clone().map(|o| Cow::Owned(o.into_owned())),
73 ..*self
74 }
75 }
76}
77
78pub struct StreamRestore {
82 context: *mut ContextInternal,
83 cb_ptrs: CallbackPointers,
85}
86
87unsafe impl Send for StreamRestore {}
88unsafe impl Sync for StreamRestore {}
89
90#[derive(Default)]
93struct CallbackPointers {
94 subscribe: super::ExtSubscribeCb,
95}
96
97impl Context {
98 pub fn stream_restore(&self) -> StreamRestore {
103 unsafe { capi::pa_context_ref(self.ptr) };
104 StreamRestore::from_raw(self.ptr)
105 }
106}
107
108impl StreamRestore {
109 fn from_raw(context: *mut ContextInternal) -> Self {
111 Self { context: context, cb_ptrs: Default::default() }
112 }
113
114 pub fn test<F>(&mut self, callback: F) -> Operation<dyn FnMut(u32)>
118 where F: FnMut(u32) + 'static
119 {
120 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(u32)>(Box::new(callback));
121 let ptr = unsafe { capi::pa_ext_stream_restore_test(self.context,
122 Some(super::ext_test_cb_proxy), cb_data) };
123 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(u32)>)
124 }
125
126 pub fn read<F>(&mut self, callback: F) -> Operation<dyn FnMut(ListResult<&Info>)>
130 where F: FnMut(ListResult<&Info>) + 'static
131 {
132 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
133 let ptr = unsafe { capi::pa_ext_stream_restore_read(self.context, Some(read_list_cb_proxy),
134 cb_data) };
135 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
136 }
137
138 pub fn write<F>(&mut self, mode: proplist::UpdateMode, data: &[&Info],
145 apply_immediately: bool, callback: F) -> Operation<dyn FnMut(bool)>
146 where F: FnMut(bool) + 'static
147 {
148 assert!(data.len() <= u32::MAX as usize);
149 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
150 let ptr = unsafe {
151 capi::pa_ext_stream_restore_write(self.context, mode, mem::transmute(data.as_ptr()),
152 data.len() as u32, apply_immediately as i32, Some(super::success_cb_proxy),
153 cb_data)
154 };
155 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
156 }
157
158 pub fn delete<F>(&mut self, streams: &[&str], callback: F) -> Operation<dyn FnMut(bool)>
164 where F: FnMut(bool) + 'static
165 {
166 let mut c_streams: Vec<CString> = Vec::with_capacity(streams.len());
169 for stream in streams {
170 c_streams.push(CString::new(*stream).unwrap());
171 }
172
173 let mut c_stream_ptrs: Vec<*const c_char> = Vec::with_capacity(c_streams.len() + 1);
176 for c_stream in &c_streams {
177 c_stream_ptrs.push(c_stream.as_ptr());
178 }
179 c_stream_ptrs.push(null());
180
181 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
182 let ptr = unsafe { capi::pa_ext_stream_restore_delete(self.context, c_stream_ptrs.as_ptr(),
183 Some(super::success_cb_proxy), cb_data) };
184 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
185 }
186
187 pub fn subscribe<F>(&mut self, enable: bool, callback: F) -> Operation<dyn FnMut(bool)>
193 where F: FnMut(bool) + 'static
194 {
195 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
196 let ptr = unsafe { capi::pa_ext_stream_restore_subscribe(self.context, enable as i32,
197 Some(super::success_cb_proxy), cb_data) };
198 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
199 }
200
201 pub fn set_subscribe_cb<F>(&mut self, callback: F)
204 where F: FnMut() + 'static
205 {
206 let saved = &mut self.cb_ptrs.subscribe;
207 *saved = super::ExtSubscribeCb::new(Some(Box::new(callback)));
208 let (cb_fn, cb_data) = saved.get_capi_params(super::ext_subscribe_cb_proxy);
209 unsafe { capi::pa_ext_stream_restore_set_subscribe_cb(self.context, cb_fn, cb_data); }
210 }
211}
212
213impl Drop for StreamRestore {
214 fn drop(&mut self) {
215 unsafe { capi::pa_context_unref(self.context) };
216 self.context = null_mut::<ContextInternal>();
217 }
218}
219
220extern "C"
224fn read_list_cb_proxy(_: *mut ContextInternal, i: *const InfoInternal, eol: i32,
225 userdata: *mut c_void)
226{
227 let _ = std::panic::catch_unwind(|| {
228 callback_for_list_instance(i, eol, userdata, Info::new_from_raw);
229 });
230}