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<'a> Info<'a> {
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
69pub struct StreamRestore {
73 context: *mut ContextInternal,
74 cb_ptrs: CallbackPointers,
76}
77
78unsafe impl Send for StreamRestore {}
79unsafe impl Sync for StreamRestore {}
80
81#[derive(Default)]
84struct CallbackPointers {
85 subscribe: super::ExtSubscribeCb,
86}
87
88impl Context {
89 pub fn stream_restore(&self) -> StreamRestore {
94 unsafe { capi::pa_context_ref(self.ptr) };
95 StreamRestore::from_raw(self.ptr)
96 }
97}
98
99impl StreamRestore {
100 fn from_raw(context: *mut ContextInternal) -> Self {
102 Self { context: context, cb_ptrs: Default::default() }
103 }
104
105 pub fn test<F>(&mut self, callback: F) -> Operation<dyn FnMut(u32)>
109 where F: FnMut(u32) + 'static
110 {
111 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(u32)>(Box::new(callback));
112 let ptr = unsafe { capi::pa_ext_stream_restore_test(self.context,
113 Some(super::ext_test_cb_proxy), cb_data) };
114 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(u32)>)
115 }
116
117 pub fn read<F>(&mut self, callback: F) -> Operation<dyn FnMut(ListResult<&Info>)>
121 where F: FnMut(ListResult<&Info>) + 'static
122 {
123 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&Info>)>(Box::new(callback));
124 let ptr = unsafe { capi::pa_ext_stream_restore_read(self.context, Some(read_list_cb_proxy),
125 cb_data) };
126 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&Info>)>)
127 }
128
129 pub fn write<F>(&mut self, mode: proplist::UpdateMode, data: &[&Info],
135 apply_immediately: bool, callback: F) -> Operation<dyn FnMut(bool)>
136 where F: FnMut(bool) + 'static
137 {
138 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
139 let ptr = unsafe {
140 capi::pa_ext_stream_restore_write(self.context, mode, mem::transmute(data.as_ptr()),
141 data.len() as u32, apply_immediately as i32, Some(super::success_cb_proxy),
142 cb_data)
143 };
144 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
145 }
146
147 pub fn delete<F>(&mut self, streams: &[&str], callback: F) -> Operation<dyn FnMut(bool)>
153 where F: FnMut(bool) + 'static
154 {
155 let mut c_streams: Vec<CString> = Vec::with_capacity(streams.len());
158 for stream in streams {
159 c_streams.push(CString::new(*stream).unwrap());
160 }
161
162 let mut c_stream_ptrs: Vec<*const c_char> = Vec::with_capacity(c_streams.len() + 1);
165 for c_stream in &c_streams {
166 c_stream_ptrs.push(c_stream.as_ptr());
167 }
168 c_stream_ptrs.push(null());
169
170 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
171 let ptr = unsafe { capi::pa_ext_stream_restore_delete(self.context, c_stream_ptrs.as_ptr(),
172 Some(super::success_cb_proxy), cb_data) };
173 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
174 }
175
176 pub fn subscribe<F>(&mut self, enable: bool, callback: F) -> Operation<dyn FnMut(bool)>
182 where F: FnMut(bool) + 'static
183 {
184 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
185 let ptr = unsafe { capi::pa_ext_stream_restore_subscribe(self.context, enable as i32,
186 Some(super::success_cb_proxy), cb_data) };
187 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
188 }
189
190 pub fn set_subscribe_cb<F>(&mut self, callback: F)
193 where F: FnMut() + 'static
194 {
195 let saved = &mut self.cb_ptrs.subscribe;
196 *saved = super::ExtSubscribeCb::new(Some(Box::new(callback)));
197 let (cb_fn, cb_data) = saved.get_capi_params(super::ext_subscribe_cb_proxy);
198 unsafe { capi::pa_ext_stream_restore_set_subscribe_cb(self.context, cb_fn, cb_data); }
199 }
200}
201
202impl Drop for StreamRestore {
203 fn drop(&mut self) {
204 unsafe { capi::pa_context_unref(self.context) };
205 self.context = null_mut::<ContextInternal>();
206 }
207}
208
209extern "C"
213fn read_list_cb_proxy(_: *mut ContextInternal, i: *const InfoInternal, eol: i32,
214 userdata: *mut c_void)
215{
216 let _ = std::panic::catch_unwind(|| {
217 callback_for_list_instance(i, eol, userdata, Info::new_from_raw);
218 });
219}