1use std::os::raw::c_void;
185#[cfg(any(doc, feature = "pa_v15"))]
186use std::os::raw::c_char;
187use std::ffi::{CStr, CString};
188use std::borrow::Cow;
189use std::ptr::null_mut;
190use num_traits::FromPrimitive;
191use capi::pa_sink_port_info as SinkPortInfoInternal;
192use capi::pa_sink_info as SinkInfoInternal;
193use capi::pa_source_port_info as SourcePortInfoInternal;
194use capi::pa_source_info as SourceInfoInternal;
195use capi::pa_server_info as ServerInfoInternal;
196use capi::pa_module_info as ModuleInfoInternal;
197use capi::pa_client_info as ClientInfoInternal;
198use capi::pa_card_profile_info2 as CardProfileInfoInternal;
199use capi::pa_card_port_info as CardPortInfoInternal;
200use capi::pa_card_info as CardInfoInternal;
201use capi::pa_sink_input_info as SinkInputInfoInternal;
202use capi::pa_source_output_info as SourceOutputInfoInternal;
203use capi::pa_sample_info as SampleInfoInternal;
204use super::{Context, ContextInternal};
205use crate::{def, sample, channelmap, format, direction};
206use crate::time::MicroSeconds;
207use crate::callbacks::{
208 ListResult, box_closure_get_capi_ptr, callback_for_list_instance, get_su_capi_params,
209 get_su_callback
210};
211use crate::volume::{ChannelVolumes, Volume};
212use crate::{operation::Operation, proplist::Proplist};
213#[cfg(any(doc, feature = "pa_v14"))]
214use crate::def::DevicePortType;
215
216pub use capi::pa_stat_info as StatInfo;
217
218pub struct Introspector {
220 context: *mut super::ContextInternal,
221}
222
223unsafe impl Send for Introspector {}
224unsafe impl Sync for Introspector {}
225
226impl Context {
227 #[inline]
232 pub fn introspect(&self) -> Introspector {
233 unsafe { capi::pa_context_ref(self.ptr) };
234 Introspector::from_raw(self.ptr)
235 }
236}
237
238impl Introspector {
239 #[inline(always)]
241 fn from_raw(context: *mut ContextInternal) -> Self {
242 Self { context: context }
243 }
244}
245
246impl Drop for Introspector {
247 fn drop(&mut self) {
248 unsafe { capi::pa_context_unref(self.context) };
249 self.context = null_mut::<super::ContextInternal>();
250 }
251}
252
253#[derive(Debug)]
262pub struct SinkPortInfo<'a> {
263 pub name: Option<Cow<'a, str>>,
265 pub description: Option<Cow<'a, str>>,
267 pub priority: u32,
269 pub available: def::PortAvailable,
271 #[cfg(any(doc, feature = "pa_v14"))]
293 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
294 pub availability_group: Option<Cow<'a, str>>,
295 #[cfg(any(doc, feature = "pa_v14"))]
297 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
298 pub r#type: DevicePortType,
299}
300
301impl SinkPortInfo<'_> {
302 fn new_from_raw(p: *const SinkPortInfoInternal) -> Self {
303 assert!(!p.is_null());
304 let src = unsafe { &*p };
305 unsafe {
306 SinkPortInfo {
307 name: match src.name.is_null() {
308 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
309 true => None,
310 },
311 description: match src.description.is_null() {
312 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
313 true => None,
314 },
315 priority: src.priority,
316 available: def::PortAvailable::from_i32(src.available).unwrap(),
317 #[cfg(any(doc, feature = "pa_v14"))]
318 availability_group: match src.availability_group.is_null() {
319 false => Some(CStr::from_ptr(src.availability_group).to_string_lossy()),
320 true => None,
321 },
322 #[cfg(any(doc, feature = "pa_v14"))]
323 r#type: DevicePortType::from_u32(src.r#type).unwrap(),
324 }
325 }
326 }
327
328 pub fn to_owned(&self) -> SinkPortInfo<'static> {
330 SinkPortInfo {
331 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
332 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
333 #[cfg(any(doc, feature = "pa_v14"))]
334 availability_group: self.availability_group.clone().map(|o| Cow::Owned(o.into_owned())),
335 ..*self
336 }
337 }
338}
339
340#[derive(Debug)]
345pub struct SinkInfo<'a> {
346 pub name: Option<Cow<'a, str>>,
348 pub index: u32,
350 pub description: Option<Cow<'a, str>>,
352 pub sample_spec: sample::Spec,
354 pub channel_map: channelmap::Map,
356 pub owner_module: Option<u32>,
358 pub volume: ChannelVolumes,
360 pub mute: bool,
362 pub monitor_source: u32,
364 pub monitor_source_name: Option<Cow<'a, str>>,
366 pub latency: MicroSeconds,
368 pub driver: Option<Cow<'a, str>>,
370 pub flags: def::SinkFlagSet,
372 pub proplist: Proplist,
374 pub configured_latency: MicroSeconds,
376 pub base_volume: Volume,
379 pub state: def::SinkState,
381 pub n_volume_steps: u32,
383 pub card: Option<u32>,
385 pub ports: Vec<SinkPortInfo<'a>>,
387 pub active_port: Option<Box<SinkPortInfo<'a>>>,
389 pub formats: Vec<format::Info>,
391}
392
393impl SinkInfo<'_> {
394 fn new_from_raw(p: *const SinkInfoInternal) -> Self {
395 assert!(!p.is_null());
396 let src = unsafe { &*p };
397
398 let mut port_vec = Vec::with_capacity(src.n_ports as usize);
399 assert!(src.n_ports == 0 || !src.ports.is_null());
400 for i in 0..src.n_ports as isize {
401 let indexed_ptr = unsafe { (*src.ports.offset(i)) as *mut SinkPortInfoInternal };
402 if !indexed_ptr.is_null() {
403 port_vec.push(SinkPortInfo::new_from_raw(indexed_ptr));
404 }
405 }
406 let mut formats_vec = Vec::with_capacity(src.n_formats as usize);
407 assert!(src.n_formats == 0 || !src.formats.is_null());
408 for i in 0..src.n_formats as isize {
409 let indexed_ptr = unsafe { (*src.formats.offset(i)) as *mut format::InfoInternal };
410 if !indexed_ptr.is_null() {
411 formats_vec.push(format::Info::from_raw_weak(indexed_ptr));
412 }
413 }
414
415 unsafe {
416 SinkInfo {
417 name: match src.name.is_null() {
418 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
419 true => None,
420 },
421 index: src.index,
422 description: match src.description.is_null() {
423 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
424 true => None,
425 },
426 sample_spec: src.sample_spec.into(),
427 channel_map: src.channel_map.into(),
428 owner_module: match src.owner_module {
429 def::INVALID_INDEX => None,
430 i => Some(i),
431 },
432 volume: src.volume.into(),
433 mute: match src.mute {
434 0 => false,
435 _ => true,
436 },
437 monitor_source: src.monitor_source,
438 monitor_source_name: match src.monitor_source_name.is_null() {
439 false => Some(CStr::from_ptr(src.monitor_source_name).to_string_lossy()),
440 true => None,
441 },
442 latency: MicroSeconds(src.latency),
443 driver: match src.driver.is_null() {
444 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
445 true => None,
446 },
447 flags: def::SinkFlagSet::from_bits_truncate(src.flags),
448 proplist: Proplist::from_raw_weak(src.proplist),
449 configured_latency: MicroSeconds(src.configured_latency),
450 base_volume: Volume(src.base_volume),
451 state: src.state.into(),
452 n_volume_steps: src.n_volume_steps,
453 card: match src.card {
454 def::INVALID_INDEX => None,
455 i => Some(i),
456 },
457 ports: port_vec,
458 active_port: match src.active_port.is_null() {
459 true => None,
460 false => Some(Box::new(SinkPortInfo::new_from_raw(src.active_port))),
461 },
462 formats: formats_vec,
463 }
464 }
465 }
466
467 pub fn to_owned(&self) -> SinkInfo<'static> {
469 SinkInfo {
470 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
471 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
472 monitor_source_name: self.monitor_source_name.clone().map(|o| Cow::Owned(o.into_owned())),
473 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
474 proplist: self.proplist.to_owned(),
475 ports: self.ports.iter().map(SinkPortInfo::to_owned).collect(),
476 active_port: self.active_port.as_ref().map(|ap| Box::new(ap.as_ref().to_owned())),
477 formats: self.formats.iter().map(format::Info::to_owned).collect(),
478 ..*self
479 }
480 }
481}
482
483impl Introspector {
484 pub fn get_sink_info_by_name<F>(&self, name: &str, callback: F)
488 -> Operation<dyn FnMut(ListResult<&SinkInfo>)>
489 where F: FnMut(ListResult<&SinkInfo>) + 'static
490 {
491 let c_name = CString::new(name).unwrap();
494
495 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SinkInfo>)>(Box::new(callback));
496 let ptr = unsafe { capi::pa_context_get_sink_info_by_name(self.context, c_name.as_ptr(),
497 Some(get_sink_info_list_cb_proxy), cb_data) };
498 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SinkInfo>)>)
499 }
500
501 pub fn get_sink_info_by_index<F>(&self, index: u32, callback: F)
505 -> Operation<dyn FnMut(ListResult<&SinkInfo>)>
506 where F: FnMut(ListResult<&SinkInfo>) + 'static
507 {
508 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SinkInfo>)>(Box::new(callback));
509 let ptr = unsafe { capi::pa_context_get_sink_info_by_index(self.context, index,
510 Some(get_sink_info_list_cb_proxy), cb_data) };
511 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SinkInfo>)>)
512 }
513
514 pub fn get_sink_info_list<F>(&self, callback: F) -> Operation<dyn FnMut(ListResult<&SinkInfo>)>
518 where F: FnMut(ListResult<&SinkInfo>) + 'static
519 {
520 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SinkInfo>)>(Box::new(callback));
521 let ptr = unsafe { capi::pa_context_get_sink_info_list(self.context,
522 Some(get_sink_info_list_cb_proxy), cb_data) };
523 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SinkInfo>)>)
524 }
525
526 pub fn set_sink_volume_by_index(&mut self, index: u32, volume: &ChannelVolumes,
532 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
533 {
534 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
535 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
536 let ptr = unsafe { capi::pa_context_set_sink_volume_by_index(self.context, index,
537 volume.as_ref(), cb_fn, cb_data) };
538 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
539 }
540
541 pub fn set_sink_volume_by_name(&mut self, name: &str, volume: &ChannelVolumes,
547 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
548 {
549 let c_name = CString::new(name).unwrap();
552
553 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
554 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
555 let ptr = unsafe { capi::pa_context_set_sink_volume_by_name(self.context, c_name.as_ptr(),
556 volume.as_ref(), cb_fn, cb_data) };
557 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
558 }
559
560 pub fn set_sink_mute_by_index(&mut self, index: u32, mute: bool,
566 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
567 {
568 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
569 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
570 let ptr = unsafe { capi::pa_context_set_sink_mute_by_index(self.context, index, mute as i32,
571 cb_fn, cb_data) };
572 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
573 }
574
575 pub fn set_sink_mute_by_name(&mut self, name: &str, mute: bool,
581 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
582 {
583 let c_name = CString::new(name).unwrap();
586
587 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
588 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
589 let ptr = unsafe { capi::pa_context_set_sink_mute_by_name(self.context, c_name.as_ptr(),
590 mute as i32, cb_fn, cb_data) };
591 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
592 }
593
594 pub fn suspend_sink_by_name(&mut self, sink_name: &str, suspend: bool,
600 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
601 {
602 let c_name = CString::new(sink_name).unwrap();
605
606 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
607 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
608 let ptr = unsafe { capi::pa_context_suspend_sink_by_name(self.context, c_name.as_ptr(),
609 suspend as i32, cb_fn, cb_data) };
610 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
611 }
612
613 pub fn suspend_sink_by_index(&mut self, index: u32, suspend: bool,
620 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
621 {
622 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
623 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
624 let ptr = unsafe { capi::pa_context_suspend_sink_by_index(self.context, index,
625 suspend as i32, cb_fn, cb_data) };
626 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
627 }
628
629 pub fn set_sink_port_by_index(&mut self, index: u32, port: &str,
635 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
636 {
637 let c_port = CString::new(port).unwrap();
640
641 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
642 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
643 let ptr = unsafe { capi::pa_context_set_sink_port_by_index(self.context, index,
644 c_port.as_ptr(), cb_fn, cb_data) };
645 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
646 }
647
648 pub fn set_sink_port_by_name(&mut self, name: &str, port: &str,
654 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
655 {
656 let c_name = CString::new(name).unwrap();
659 let c_port = CString::new(port).unwrap();
660
661 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
662 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
663 let ptr = unsafe { capi::pa_context_set_sink_port_by_name(self.context, c_name.as_ptr(),
664 c_port.as_ptr(), cb_fn, cb_data) };
665 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
666 }
667}
668
669extern "C"
672fn get_sink_info_list_cb_proxy(_: *mut ContextInternal, i: *const SinkInfoInternal, eol: i32,
673 userdata: *mut c_void)
674{
675 let _ = std::panic::catch_unwind(|| {
676 callback_for_list_instance(i, eol, userdata, SinkInfo::new_from_raw);
677 });
678}
679
680#[derive(Debug)]
689pub struct SourcePortInfo<'a> {
690 pub name: Option<Cow<'a, str>>,
692 pub description: Option<Cow<'a, str>>,
694 pub priority: u32,
696 pub available: def::PortAvailable,
698 #[cfg(any(doc, feature = "pa_v14"))]
720 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
721 pub availability_group: Option<Cow<'a, str>>,
722 #[cfg(any(doc, feature = "pa_v14"))]
724 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
725 pub r#type: DevicePortType,
726}
727
728impl SourcePortInfo<'_> {
729 fn new_from_raw(p: *const SourcePortInfoInternal) -> Self {
730 assert!(!p.is_null());
731 let src = unsafe { &*p };
732 unsafe {
733 SourcePortInfo {
734 name: match src.name.is_null() {
735 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
736 true => None,
737 },
738 description: match src.description.is_null() {
739 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
740 true => None,
741 },
742 priority: src.priority,
743 available: def::PortAvailable::from_i32(src.available).unwrap(),
744 #[cfg(any(doc, feature = "pa_v14"))]
745 availability_group: match src.availability_group.is_null() {
746 false => Some(CStr::from_ptr(src.availability_group).to_string_lossy()),
747 true => None,
748 },
749 #[cfg(any(doc, feature = "pa_v14"))]
750 r#type: DevicePortType::from_u32(src.r#type).unwrap(),
751 }
752 }
753 }
754
755 pub fn to_owned(&self) -> SourcePortInfo<'static> {
757 SourcePortInfo {
758 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
759 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
760 #[cfg(any(doc, feature = "pa_v14"))]
761 availability_group: self.availability_group.clone().map(|o| Cow::Owned(o.into_owned())),
762 ..*self
763 }
764 }
765}
766
767#[derive(Debug)]
772pub struct SourceInfo<'a> {
773 pub name: Option<Cow<'a, str>>,
775 pub index: u32,
777 pub description: Option<Cow<'a, str>>,
779 pub sample_spec: sample::Spec,
781 pub channel_map: channelmap::Map,
783 pub owner_module: Option<u32>,
785 pub volume: ChannelVolumes,
787 pub mute: bool,
789 pub monitor_of_sink: Option<u32>,
791 pub monitor_of_sink_name: Option<Cow<'a, str>>,
793 pub latency: MicroSeconds,
795 pub driver: Option<Cow<'a, str>>,
797 pub flags: def::SourceFlagSet,
799 pub proplist: Proplist,
801 pub configured_latency: MicroSeconds,
803 pub base_volume: Volume,
806 pub state: def::SourceState,
808 pub n_volume_steps: u32,
810 pub card: Option<u32>,
812 pub ports: Vec<SourcePortInfo<'a>>,
814 pub active_port: Option<Box<SourcePortInfo<'a>>>,
816 pub formats: Vec<format::Info>,
818}
819
820impl SourceInfo<'_> {
821 fn new_from_raw(p: *const SourceInfoInternal) -> Self {
822 assert!(!p.is_null());
823 let src = unsafe { &*p };
824
825 let mut port_vec = Vec::with_capacity(src.n_ports as usize);
826 assert!(src.n_ports == 0 || !src.ports.is_null());
827 for i in 0..src.n_ports as isize {
828 let indexed_ptr = unsafe { (*src.ports.offset(i)) as *mut SourcePortInfoInternal };
829 if !indexed_ptr.is_null() {
830 port_vec.push(SourcePortInfo::new_from_raw(indexed_ptr));
831 }
832 }
833 let mut formats_vec = Vec::with_capacity(src.n_formats as usize);
834 assert!(src.n_formats == 0 || !src.formats.is_null());
835 for i in 0..src.n_formats as isize {
836 let indexed_ptr = unsafe { (*src.formats.offset(i)) as *mut format::InfoInternal };
837 if !indexed_ptr.is_null() {
838 formats_vec.push(format::Info::from_raw_weak(indexed_ptr));
839 }
840 }
841
842 unsafe {
843 SourceInfo {
844 name: match src.name.is_null() {
845 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
846 true => None,
847 },
848 index: src.index,
849 description: match src.description.is_null() {
850 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
851 true => None,
852 },
853 sample_spec: src.sample_spec.into(),
854 channel_map: src.channel_map.into(),
855 owner_module: match src.owner_module {
856 def::INVALID_INDEX => None,
857 i => Some(i),
858 },
859 volume: src.volume.into(),
860 mute: match src.mute {
861 0 => false,
862 _ => true,
863 },
864 monitor_of_sink: match src.monitor_of_sink {
865 def::INVALID_INDEX => None,
866 i => Some(i),
867 },
868 monitor_of_sink_name: match src.monitor_of_sink_name.is_null() {
869 false => Some(CStr::from_ptr(src.monitor_of_sink_name).to_string_lossy()),
870 true => None,
871 },
872 latency: MicroSeconds(src.latency),
873 driver: match src.driver.is_null() {
874 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
875 true => None,
876 },
877 flags: def::SourceFlagSet::from_bits_truncate(src.flags),
878 proplist: Proplist::from_raw_weak(src.proplist),
879 configured_latency: MicroSeconds(src.configured_latency),
880 base_volume: Volume(src.base_volume),
881 state: src.state.into(),
882 n_volume_steps: src.n_volume_steps,
883 card: match src.card {
884 def::INVALID_INDEX => None,
885 i => Some(i),
886 },
887 ports: port_vec,
888 active_port: match src.active_port.is_null() {
889 true => None,
890 false => Some(Box::new(SourcePortInfo::new_from_raw(src.active_port))),
891 },
892 formats: formats_vec,
893 }
894 }
895 }
896
897 pub fn to_owned(&self) -> SourceInfo<'static> {
899 SourceInfo {
900 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
901 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
902 monitor_of_sink_name: self.monitor_of_sink_name.clone().map(|o| Cow::Owned(o.into_owned())),
903 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
904 proplist: self.proplist.to_owned(),
905 ports: self.ports.iter().map(SourcePortInfo::to_owned).collect(),
906 active_port: self.active_port.as_ref().map(|ap| Box::new(ap.as_ref().to_owned())),
907 formats: self.formats.iter().map(format::Info::to_owned).collect(),
908 ..*self
909 }
910 }
911}
912
913impl Introspector {
914 pub fn get_source_info_by_name<F>(&self, name: &str, callback: F)
918 -> Operation<dyn FnMut(ListResult<&SourceInfo>)>
919 where F: FnMut(ListResult<&SourceInfo>) + 'static
920 {
921 let c_name = CString::new(name).unwrap();
924
925 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SourceInfo>)>(Box::new(callback));
926 let ptr = unsafe { capi::pa_context_get_source_info_by_name(self.context, c_name.as_ptr(),
927 Some(get_source_info_list_cb_proxy), cb_data) };
928 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SourceInfo>)>)
929 }
930
931 pub fn get_source_info_by_index<F>(&self, index: u32, callback: F)
935 -> Operation<dyn FnMut(ListResult<&SourceInfo>)>
936 where F: FnMut(ListResult<&SourceInfo>) + 'static
937 {
938 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SourceInfo>)>(Box::new(callback));
939 let ptr = unsafe { capi::pa_context_get_source_info_by_index(self.context, index,
940 Some(get_source_info_list_cb_proxy), cb_data) };
941 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SourceInfo>)>)
942 }
943
944 pub fn get_source_info_list<F>(&self, callback: F)
948 -> Operation<dyn FnMut(ListResult<&SourceInfo>)>
949 where F: FnMut(ListResult<&SourceInfo>) + 'static
950 {
951 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SourceInfo>)>(Box::new(callback));
952 let ptr = unsafe { capi::pa_context_get_source_info_list(self.context,
953 Some(get_source_info_list_cb_proxy), cb_data) };
954 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SourceInfo>)>)
955 }
956
957 pub fn set_source_volume_by_index(&mut self, index: u32, volume: &ChannelVolumes,
963 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
964 {
965 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
966 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
967 let ptr = unsafe { capi::pa_context_set_source_volume_by_index(self.context, index,
968 volume.as_ref(), cb_fn, cb_data) };
969 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
970 }
971
972 pub fn set_source_volume_by_name(&mut self, name: &str, volume: &ChannelVolumes,
978 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
979 {
980 let c_name = CString::new(name).unwrap();
983
984 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
985 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
986 let ptr = unsafe { capi::pa_context_set_source_volume_by_name(self.context,
987 c_name.as_ptr(), volume.as_ref(), cb_fn, cb_data) };
988 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
989 }
990
991 pub fn set_source_mute_by_index(&mut self, index: u32, mute: bool,
997 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
998 {
999 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1000 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1001 let ptr = unsafe { capi::pa_context_set_source_mute_by_index(self.context, index,
1002 mute as i32, cb_fn, cb_data) };
1003 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1004 }
1005
1006 pub fn set_source_mute_by_name(&mut self, name: &str, mute: bool,
1012 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1013 {
1014 let c_name = CString::new(name).unwrap();
1017
1018 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1019 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1020 let ptr = unsafe { capi::pa_context_set_source_mute_by_name(self.context, c_name.as_ptr(),
1021 mute as i32, cb_fn, cb_data) };
1022 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1023 }
1024
1025 pub fn suspend_source_by_name(&mut self, name: &str, suspend: bool,
1031 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1032 {
1033 let c_name = CString::new(name).unwrap();
1036
1037 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1038 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1039 let ptr = unsafe { capi::pa_context_suspend_source_by_name(self.context, c_name.as_ptr(),
1040 suspend as i32, cb_fn, cb_data) };
1041 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1042 }
1043
1044 pub fn suspend_source_by_index(&mut self, index: u32, suspend: bool,
1051 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1052 {
1053 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1054 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1055 let ptr = unsafe { capi::pa_context_suspend_source_by_index(self.context, index,
1056 suspend as i32, cb_fn, cb_data) };
1057 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1058 }
1059
1060 pub fn set_source_port_by_index(&mut self, index: u32, port: &str,
1066 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1067 {
1068 let c_port = CString::new(port).unwrap();
1071
1072 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1073 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1074 let ptr = unsafe { capi::pa_context_set_source_port_by_index(self.context, index,
1075 c_port.as_ptr(), cb_fn, cb_data) };
1076 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1077 }
1078
1079 pub fn set_source_port_by_name(&mut self, name: &str, port: &str,
1085 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1086 {
1087 let c_name = CString::new(name).unwrap();
1090 let c_port = CString::new(port).unwrap();
1091
1092 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1093 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1094 let ptr = unsafe { capi::pa_context_set_source_port_by_name(self.context, c_name.as_ptr(),
1095 c_port.as_ptr(), cb_fn, cb_data) };
1096 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1097 }
1098}
1099
1100extern "C"
1104fn get_source_info_list_cb_proxy(_: *mut ContextInternal, i: *const SourceInfoInternal, eol: i32,
1105 userdata: *mut c_void)
1106{
1107 let _ = std::panic::catch_unwind(|| {
1108 callback_for_list_instance(i, eol, userdata, SourceInfo::new_from_raw);
1109 });
1110}
1111
1112#[derive(Debug)]
1121pub struct ServerInfo<'a> {
1122 pub user_name: Option<Cow<'a, str>>,
1124 pub host_name: Option<Cow<'a, str>>,
1126 pub server_version: Option<Cow<'a, str>>,
1128 pub server_name: Option<Cow<'a, str>>,
1130 pub sample_spec: sample::Spec,
1132 pub default_sink_name: Option<Cow<'a, str>>,
1134 pub default_source_name: Option<Cow<'a, str>>,
1136 pub cookie: u32,
1138 pub channel_map: channelmap::Map,
1140}
1141
1142impl ServerInfo<'_> {
1143 fn new_from_raw(p: *const ServerInfoInternal) -> Self {
1144 assert!(!p.is_null());
1145 let src = unsafe { &*p };
1146 unsafe {
1147 ServerInfo {
1148 user_name: match src.user_name.is_null() {
1149 false => Some(CStr::from_ptr(src.user_name).to_string_lossy()),
1150 true => None,
1151 },
1152 host_name: match src.host_name.is_null() {
1153 false => Some(CStr::from_ptr(src.host_name).to_string_lossy()),
1154 true => None,
1155 },
1156 server_version: match src.server_version.is_null() {
1157 false => Some(CStr::from_ptr(src.server_version).to_string_lossy()),
1158 true => None,
1159 },
1160 server_name: match src.server_name.is_null() {
1161 false => Some(CStr::from_ptr(src.server_name).to_string_lossy()),
1162 true => None,
1163 },
1164 sample_spec: src.sample_spec.into(),
1165 default_sink_name: match src.default_sink_name.is_null() {
1166 false => Some(CStr::from_ptr(src.default_sink_name).to_string_lossy()),
1167 true => None,
1168 },
1169 default_source_name: match src.default_source_name.is_null() {
1170 false => Some(CStr::from_ptr(src.default_source_name).to_string_lossy()),
1171 true => None,
1172 },
1173 cookie: src.cookie,
1174 channel_map: src.channel_map.into(),
1175 }
1176 }
1177 }
1178
1179 pub fn to_owned(&self) -> ServerInfo<'static> {
1181 ServerInfo {
1182 user_name: self.user_name.clone().map(|o| Cow::Owned(o.into_owned())),
1183 host_name: self.host_name.clone().map(|o| Cow::Owned(o.into_owned())),
1184 server_version: self.server_version.clone().map(|o| Cow::Owned(o.into_owned())),
1185 server_name: self.server_name.clone().map(|o| Cow::Owned(o.into_owned())),
1186 default_sink_name: self.default_sink_name.clone().map(|o| Cow::Owned(o.into_owned())),
1187 default_source_name: self.default_source_name.clone().map(|o| Cow::Owned(o.into_owned())),
1188 ..*self
1189 }
1190 }
1191}
1192
1193impl Introspector {
1194 pub fn get_server_info<F>(&self, callback: F) -> Operation<dyn FnMut(&ServerInfo)>
1198 where F: FnMut(&ServerInfo) + 'static
1199 {
1200 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(&ServerInfo)>(Box::new(callback));
1201 let ptr = unsafe { capi::pa_context_get_server_info(self.context,
1202 Some(get_server_info_cb_proxy), cb_data) };
1203 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(&ServerInfo)>)
1204 }
1205}
1206
1207extern "C"
1210fn get_server_info_cb_proxy(_: *mut ContextInternal, i: *const ServerInfoInternal,
1211 userdata: *mut c_void)
1212{
1213 let _ = std::panic::catch_unwind(|| {
1214 assert!(!i.is_null());
1215 let obj = ServerInfo::new_from_raw(i);
1216
1217 let mut callback = get_su_callback::<dyn FnMut(&ServerInfo)>(userdata);
1219 (callback)(&obj);
1220 });
1221}
1222
1223#[derive(Debug)]
1232pub struct ModuleInfo<'a> {
1233 pub index: u32,
1235 pub name: Option<Cow<'a, str>>,
1237 pub argument: Option<Cow<'a, str>>,
1239 pub n_used: Option<u32>,
1241 pub proplist: Proplist,
1243}
1244
1245impl ModuleInfo<'_> {
1246 fn new_from_raw(p: *const ModuleInfoInternal) -> Self {
1247 assert!(!p.is_null());
1248 let src = unsafe { &*p };
1249 unsafe {
1250 ModuleInfo {
1251 index: src.index,
1252 name: match src.name.is_null() {
1253 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1254 true => None,
1255 },
1256 argument: match src.argument.is_null() {
1257 false => Some(CStr::from_ptr(src.argument).to_string_lossy()),
1258 true => None,
1259 },
1260 n_used: match src.n_used {
1261 def::INVALID_INDEX => None,
1262 i => Some(i),
1263 },
1264 proplist: Proplist::from_raw_weak(src.proplist),
1265 }
1266 }
1267 }
1268
1269 pub fn to_owned(&self) -> ModuleInfo<'static> {
1271 ModuleInfo {
1272 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
1273 argument: self.argument.clone().map(|o| Cow::Owned(o.into_owned())),
1274 proplist: self.proplist.to_owned(),
1275 ..*self
1276 }
1277 }
1278}
1279
1280impl Introspector {
1281 pub fn get_module_info<F>(&self, index: u32, callback: F)
1285 -> Operation<dyn FnMut(ListResult<&ModuleInfo>)>
1286 where F: FnMut(ListResult<&ModuleInfo>) + 'static
1287 {
1288 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&ModuleInfo>)>(Box::new(callback));
1289 let ptr = unsafe { capi::pa_context_get_module_info(self.context, index,
1290 Some(mod_info_list_cb_proxy), cb_data) };
1291 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&ModuleInfo>)>)
1292 }
1293
1294 pub fn get_module_info_list<F>(&self, callback: F)
1298 -> Operation<dyn FnMut(ListResult<&ModuleInfo>)>
1299 where F: FnMut(ListResult<&ModuleInfo>) + 'static
1300 {
1301 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&ModuleInfo>)>(Box::new(callback));
1302 let ptr = unsafe { capi::pa_context_get_module_info_list(self.context,
1303 Some(mod_info_list_cb_proxy), cb_data) };
1304 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&ModuleInfo>)>)
1305 }
1306
1307 pub fn load_module<F>(&mut self, name: &str, argument: &str, callback: F)
1312 -> Operation<dyn FnMut(u32)>
1313 where F: FnMut(u32) + 'static
1314 {
1315 let c_name = CString::new(name).unwrap();
1318 let c_arg = CString::new(argument).unwrap();
1319
1320 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(u32)>(Box::new(callback));
1321 let ptr = unsafe { capi::pa_context_load_module(self.context, c_name.as_ptr(),
1322 c_arg.as_ptr(), Some(context_index_cb_proxy), cb_data) };
1323 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(u32)>)
1324 }
1325
1326 pub fn unload_module<F>(&mut self, index: u32, callback: F) -> Operation<dyn FnMut(bool)>
1332 where F: FnMut(bool) + 'static
1333 {
1334 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1335 let ptr = unsafe { capi::pa_context_unload_module(self.context, index,
1336 Some(super::success_cb_proxy), cb_data) };
1337 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1338 }
1339}
1340
1341extern "C"
1345fn mod_info_list_cb_proxy(_: *mut ContextInternal, i: *const ModuleInfoInternal, eol: i32,
1346 userdata: *mut c_void)
1347{
1348 let _ = std::panic::catch_unwind(|| {
1349 callback_for_list_instance(i, eol, userdata, ModuleInfo::new_from_raw);
1350 });
1351}
1352
1353extern "C"
1357fn context_index_cb_proxy(_: *mut ContextInternal, index: u32, userdata: *mut c_void) {
1358 let _ = std::panic::catch_unwind(|| {
1359 let mut callback = get_su_callback::<dyn FnMut(u32)>(userdata);
1361 (callback)(index);
1362 });
1363}
1364
1365impl Introspector {
1370 #[cfg(any(doc, feature = "pa_v15"))]
1380 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v15")))]
1381 pub fn send_message_to_object<F>(&mut self, recipient_name: &str, message: &str,
1382 message_parameters: &str, callback: F) -> Operation<dyn FnMut(bool, Option<String>)>
1383 where F: FnMut(bool, Option<String>) + 'static
1384 {
1385 let c_recipient_name = CString::new(recipient_name.clone()).unwrap();
1388 let c_message = CString::new(message.clone()).unwrap();
1389 let c_message_parameters = CString::new(message_parameters.clone()).unwrap();
1390
1391 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool, Option<String>)>(Box::new(callback));
1392 let ptr = unsafe { capi::pa_context_send_message_to_object(self.context,
1393 c_recipient_name.as_ptr(), c_message.as_ptr(), c_message_parameters.as_ptr(),
1394 Some(send_message_to_object_cb_proxy), cb_data) };
1395 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool, Option<String>)>)
1396 }
1397}
1398
1399#[cfg(any(doc, feature = "pa_v15"))]
1403extern "C"
1404fn send_message_to_object_cb_proxy(_: *mut ContextInternal, success: i32, response: *const c_char,
1405 userdata: *mut c_void)
1406{
1407 let success_actual = match success {
1408 0 => false,
1409 _ => true,
1410 };
1411 let _ = std::panic::catch_unwind(|| {
1412 let r = response.is_null().then(|| {
1413 unsafe { CStr::from_ptr(response) }.to_string_lossy().into_owned()
1414 });
1415 let mut callback = get_su_callback::<dyn FnMut(bool, Option<String>)>(userdata);
1417 (callback)(success_actual, r);
1418 });
1419}
1420
1421#[derive(Debug)]
1430pub struct ClientInfo<'a> {
1431 pub index: u32,
1433 pub name: Option<Cow<'a, str>>,
1435 pub owner_module: Option<u32>,
1437 pub driver: Option<Cow<'a, str>>,
1439 pub proplist: Proplist,
1441}
1442
1443impl ClientInfo<'_> {
1444 fn new_from_raw(p: *const ClientInfoInternal) -> Self {
1445 assert!(!p.is_null());
1446 let src = unsafe { &*p };
1447 unsafe {
1448 ClientInfo {
1449 index: src.index,
1450 name: match src.name.is_null() {
1451 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1452 true => None,
1453 },
1454 owner_module: match src.owner_module {
1455 def::INVALID_INDEX => None,
1456 i => Some(i),
1457 },
1458 driver: match src.driver.is_null() {
1459 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
1460 true => None,
1461 },
1462 proplist: Proplist::from_raw_weak(src.proplist),
1463 }
1464 }
1465 }
1466
1467 pub fn to_owned(&self) -> ClientInfo<'static> {
1469 ClientInfo {
1470 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
1471 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
1472 proplist: self.proplist.to_owned(),
1473 ..*self
1474 }
1475 }
1476}
1477
1478impl Introspector {
1479 pub fn get_client_info<F>(&self, index: u32, callback: F)
1483 -> Operation<dyn FnMut(ListResult<&ClientInfo>)>
1484 where F: FnMut(ListResult<&ClientInfo>) + 'static
1485 {
1486 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&ClientInfo>)>(Box::new(callback));
1487 let ptr = unsafe { capi::pa_context_get_client_info(self.context, index,
1488 Some(get_client_info_list_cb_proxy), cb_data) };
1489 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&ClientInfo>)>)
1490 }
1491
1492 pub fn get_client_info_list<F>(&self, callback: F)
1496 -> Operation<dyn FnMut(ListResult<&ClientInfo>)>
1497 where F: FnMut(ListResult<&ClientInfo>) + 'static
1498 {
1499 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&ClientInfo>)>(Box::new(callback));
1500 let ptr = unsafe { capi::pa_context_get_client_info_list(self.context,
1501 Some(get_client_info_list_cb_proxy), cb_data) };
1502 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&ClientInfo>)>)
1503 }
1504
1505 pub fn kill_client<F>(&mut self, index: u32, callback: F) -> Operation<dyn FnMut(bool)>
1511 where F: FnMut(bool) + 'static
1512 {
1513 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
1514 let ptr = unsafe { capi::pa_context_kill_client(self.context, index,
1515 Some(super::success_cb_proxy), cb_data) };
1516 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1517 }
1518}
1519
1520extern "C"
1524fn get_client_info_list_cb_proxy(_: *mut ContextInternal, i: *const ClientInfoInternal, eol: i32,
1525 userdata: *mut c_void)
1526{
1527 let _ = std::panic::catch_unwind(|| {
1528 callback_for_list_instance(i, eol, userdata, ClientInfo::new_from_raw);
1529 });
1530}
1531
1532#[derive(Debug)]
1541pub struct CardProfileInfo<'a> {
1542 pub name: Option<Cow<'a, str>>,
1544 pub description: Option<Cow<'a, str>>,
1546 pub n_sinks: u32,
1548 pub n_sources: u32,
1550 pub priority: u32,
1552 pub available: bool,
1557}
1558
1559impl CardProfileInfo<'_> {
1560 fn new_from_raw(p: *const CardProfileInfoInternal) -> Self {
1561 assert!(!p.is_null());
1562 let src = unsafe { &*p };
1563 unsafe {
1564 CardProfileInfo {
1565 name: match src.name.is_null() {
1566 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1567 true => None,
1568 },
1569 description: match src.description.is_null() {
1570 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
1571 true => None,
1572 },
1573 n_sinks: src.n_sinks,
1574 n_sources: src.n_sources,
1575 priority: src.priority,
1576 available: match src.available {
1577 0 => false,
1578 _ => true,
1579 },
1580 }
1581 }
1582 }
1583
1584 pub fn to_owned(&self) -> CardProfileInfo<'static> {
1586 CardProfileInfo {
1587 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
1588 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
1589 ..*self
1590 }
1591 }
1592}
1593
1594#[derive(Debug)]
1599pub struct CardPortInfo<'a> {
1600 pub name: Option<Cow<'a, str>>,
1602 pub description: Option<Cow<'a, str>>,
1604 pub priority: u32,
1606 pub available: def::PortAvailable,
1608 pub direction: direction::FlagSet,
1610 pub proplist: Proplist,
1612 pub latency_offset: i64,
1615 pub profiles: Vec<CardProfileInfo<'a>>,
1617 #[cfg(any(doc, feature = "pa_v14"))]
1635 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
1636 pub availability_group: Option<Cow<'a, str>>,
1637 #[cfg(any(doc, feature = "pa_v14"))]
1639 #[cfg_attr(docsrs, doc(cfg(feature = "pa_v14")))]
1640 pub r#type: DevicePortType,
1641}
1642
1643impl CardPortInfo<'_> {
1644 fn new_from_raw(p: *const CardPortInfoInternal) -> Self {
1645 assert!(!p.is_null());
1646 let src = unsafe { &*p };
1647
1648 let mut profiles_vec = Vec::with_capacity(src.n_profiles as usize);
1649
1650 assert!(src.n_profiles == 0 || !src.profiles2.is_null());
1651 for i in 0..src.n_profiles as isize {
1652 let indexed_ptr =
1653 unsafe { (*src.profiles2.offset(i)) as *mut CardProfileInfoInternal };
1654 if !indexed_ptr.is_null() {
1655 profiles_vec.push(CardProfileInfo::new_from_raw(indexed_ptr));
1656 }
1657 }
1658
1659 unsafe {
1660 CardPortInfo {
1661 name: match src.name.is_null() {
1662 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1663 true => None,
1664 },
1665 description: match src.description.is_null() {
1666 false => Some(CStr::from_ptr(src.description).to_string_lossy()),
1667 true => None,
1668 },
1669 priority: src.priority,
1670 available: def::PortAvailable::from_i32(src.available).unwrap(),
1671 direction: direction::FlagSet::from_bits_truncate(src.direction),
1672 proplist: Proplist::from_raw_weak(src.proplist),
1673 latency_offset: src.latency_offset,
1674 profiles: profiles_vec,
1675 #[cfg(any(doc, feature = "pa_v14"))]
1676 availability_group: match src.availability_group.is_null() {
1677 false => Some(CStr::from_ptr(src.availability_group).to_string_lossy()),
1678 true => None,
1679 },
1680 #[cfg(any(doc, feature = "pa_v14"))]
1681 r#type: DevicePortType::from_u32(src.r#type).unwrap(),
1682 }
1683 }
1684 }
1685
1686 pub fn to_owned(&self) -> CardPortInfo<'static> {
1688 CardPortInfo {
1689 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
1690 description: self.description.clone().map(|o| Cow::Owned(o.into_owned())),
1691 proplist: self.proplist.to_owned(),
1692 profiles: self.profiles.iter().map(CardProfileInfo::to_owned).collect(),
1693 #[cfg(any(doc, feature = "pa_v14"))]
1694 availability_group: self.availability_group.clone().map(|o| Cow::Owned(o.into_owned())),
1695 ..*self
1696 }
1697 }
1698}
1699
1700#[derive(Debug)]
1705pub struct CardInfo<'a> {
1706 pub index: u32,
1708 pub name: Option<Cow<'a, str>>,
1710 pub owner_module: Option<u32>,
1712 pub driver: Option<Cow<'a, str>>,
1714 pub proplist: Proplist,
1716 pub ports: Vec<CardPortInfo<'a>>,
1718 pub profiles: Vec<CardProfileInfo<'a>>,
1720 pub active_profile: Option<Box<CardProfileInfo<'a>>>,
1722}
1723
1724impl CardInfo<'_> {
1725 fn new_from_raw(p: *const CardInfoInternal) -> Self {
1726 assert!(!p.is_null());
1727 let src = unsafe { &*p };
1728
1729 let mut ports_vec = Vec::with_capacity(src.n_ports as usize);
1730 assert!(src.n_ports == 0 || !src.ports.is_null());
1731 for i in 0..src.n_ports as isize {
1732 let indexed_ptr = unsafe { (*src.ports.offset(i)) as *mut CardPortInfoInternal };
1733 if !indexed_ptr.is_null() {
1734 ports_vec.push(CardPortInfo::new_from_raw(indexed_ptr));
1735 }
1736 }
1737 let mut profiles_vec = Vec::with_capacity(src.n_profiles as usize);
1738
1739 assert!(src.n_profiles == 0 || !src.profiles2.is_null());
1740 for i in 0..src.n_profiles as isize {
1741 let indexed_ptr =
1742 unsafe { (*src.profiles2.offset(i)) as *mut CardProfileInfoInternal };
1743 if !indexed_ptr.is_null() {
1744 profiles_vec.push(CardProfileInfo::new_from_raw(indexed_ptr));
1745 }
1746 }
1747
1748 unsafe {
1749 CardInfo {
1750 index: src.index,
1751 name: match src.name.is_null() {
1752 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1753 true => None,
1754 },
1755 owner_module: match src.owner_module {
1756 def::INVALID_INDEX => None,
1757 i => Some(i),
1758 },
1759 driver: match src.driver.is_null() {
1760 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
1761 true => None,
1762 },
1763 proplist: Proplist::from_raw_weak(src.proplist),
1764 ports: ports_vec,
1765 profiles: profiles_vec,
1766 active_profile: match src.active_profile2.is_null() {
1767 true => None,
1768 false => Some(Box::new(CardProfileInfo::new_from_raw(src.active_profile2))),
1769 },
1770 }
1771 }
1772 }
1773
1774 pub fn to_owned(&self) -> CardInfo<'static> {
1776 CardInfo {
1777 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
1778 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
1779 proplist: self.proplist.to_owned(),
1780 ports: self.ports.iter().map(CardPortInfo::to_owned).collect(),
1781 profiles: self.profiles.iter().map(CardProfileInfo::to_owned).collect(),
1782 active_profile: self.active_profile.as_ref().map(|ap| Box::new(ap.as_ref().to_owned())),
1783 ..*self
1784 }
1785 }
1786}
1787
1788impl Introspector {
1789 pub fn get_card_info_by_index<F>(&self, index: u32, callback: F)
1793 -> Operation<dyn FnMut(ListResult<&CardInfo>)>
1794 where F: FnMut(ListResult<&CardInfo>) + 'static
1795 {
1796 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&CardInfo>)>(Box::new(callback));
1797 let ptr = unsafe { capi::pa_context_get_card_info_by_index(self.context, index,
1798 Some(get_card_info_list_cb_proxy), cb_data) };
1799 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&CardInfo>)>)
1800 }
1801
1802 pub fn get_card_info_by_name<F>(&self, name: &str, callback: F)
1806 -> Operation<dyn FnMut(ListResult<&CardInfo>)>
1807 where F: FnMut(ListResult<&CardInfo>) + 'static
1808 {
1809 let c_name = CString::new(name).unwrap();
1812
1813 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&CardInfo>)>(Box::new(callback));
1814 let ptr = unsafe { capi::pa_context_get_card_info_by_name(self.context, c_name.as_ptr(),
1815 Some(get_card_info_list_cb_proxy), cb_data) };
1816 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&CardInfo>)>)
1817 }
1818
1819 pub fn get_card_info_list<F>(&self, callback: F) -> Operation<dyn FnMut(ListResult<&CardInfo>)>
1823 where F: FnMut(ListResult<&CardInfo>) + 'static
1824 {
1825 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&CardInfo>)>(Box::new(callback));
1826 let ptr = unsafe { capi::pa_context_get_card_info_list(self.context,
1827 Some(get_card_info_list_cb_proxy), cb_data) };
1828 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&CardInfo>)>)
1829 }
1830
1831 pub fn set_card_profile_by_index(&mut self, index: u32, profile: &str,
1837 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1838 {
1839 let c_profile = CString::new(profile).unwrap();
1842
1843 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1844 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1845 let ptr = unsafe { capi::pa_context_set_card_profile_by_index(self.context, index,
1846 c_profile.as_ptr(), cb_fn, cb_data) };
1847 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1848 }
1849
1850 pub fn set_card_profile_by_name(&mut self, name: &str, profile: &str,
1856 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1857 {
1858 let c_name = CString::new(name).unwrap();
1861 let c_profile = CString::new(profile).unwrap();
1862
1863 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1864 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1865 let ptr = unsafe { capi::pa_context_set_card_profile_by_name(self.context, c_name.as_ptr(),
1866 c_profile.as_ptr(), cb_fn, cb_data) };
1867 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1868 }
1869
1870 pub fn set_port_latency_offset(&mut self, card_name: &str, port_name: &str, offset: i64,
1876 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
1877 {
1878 let c_name = CString::new(card_name).unwrap();
1881 let c_port = CString::new(port_name).unwrap();
1882
1883 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
1884 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
1885 let ptr = unsafe { capi::pa_context_set_port_latency_offset(self.context, c_name.as_ptr(),
1886 c_port.as_ptr(), offset, cb_fn, cb_data) };
1887 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
1888 }
1889}
1890
1891extern "C"
1895fn get_card_info_list_cb_proxy(_: *mut ContextInternal, i: *const CardInfoInternal, eol: i32,
1896 userdata: *mut c_void)
1897{
1898 let _ = std::panic::catch_unwind(|| {
1899 callback_for_list_instance(i, eol, userdata, CardInfo::new_from_raw);
1900 });
1901}
1902
1903#[derive(Debug)]
1912pub struct SinkInputInfo<'a> {
1913 pub index: u32,
1915 pub name: Option<Cow<'a, str>>,
1917 pub owner_module: Option<u32>,
1920 pub client: Option<u32>,
1923 pub sink: u32,
1925 pub sample_spec: sample::Spec,
1927 pub channel_map: channelmap::Map,
1929 pub volume: ChannelVolumes,
1931 pub buffer_usec: MicroSeconds,
1934 pub sink_usec: MicroSeconds,
1936 pub resample_method: Option<Cow<'a, str>>,
1938 pub driver: Option<Cow<'a, str>>,
1940 pub mute: bool,
1942 pub proplist: Proplist,
1944 pub corked: bool,
1946 pub has_volume: bool,
1949 pub volume_writable: bool,
1952 pub format: format::Info,
1954}
1955
1956impl SinkInputInfo<'_> {
1957 fn new_from_raw(p: *const SinkInputInfoInternal) -> Self {
1958 assert!(!p.is_null());
1959 let src = unsafe { &*p };
1960 unsafe {
1961 SinkInputInfo {
1962 index: src.index,
1963 name: match src.name.is_null() {
1964 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
1965 true => None,
1966 },
1967 owner_module: match src.owner_module {
1968 def::INVALID_INDEX => None,
1969 i => Some(i),
1970 },
1971 client: match src.client {
1972 def::INVALID_INDEX => None,
1973 i => Some(i),
1974 },
1975 sink: src.sink,
1976 sample_spec: src.sample_spec.into(),
1977 channel_map: src.channel_map.into(),
1978 volume: src.volume.into(),
1979 buffer_usec: MicroSeconds(src.buffer_usec),
1980 sink_usec: MicroSeconds(src.sink_usec),
1981 resample_method: match src.resample_method.is_null() {
1982 false => Some(CStr::from_ptr(src.resample_method).to_string_lossy()),
1983 true => None,
1984 },
1985 driver: match src.driver.is_null() {
1986 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
1987 true => None,
1988 },
1989 mute: match src.mute {
1990 0 => false,
1991 _ => true,
1992 },
1993 proplist: Proplist::from_raw_weak(src.proplist),
1994 corked: match src.corked {
1995 0 => false,
1996 _ => true,
1997 },
1998 has_volume: match src.has_volume {
1999 0 => false,
2000 _ => true,
2001 },
2002 volume_writable: match src.volume_writable {
2003 0 => false,
2004 _ => true,
2005 },
2006 format: format::Info::from_raw_weak(src.format as *mut format::InfoInternal),
2007 }
2008 }
2009 }
2010
2011 pub fn to_owned(&self) -> SinkInputInfo<'static> {
2013 SinkInputInfo {
2014 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
2015 resample_method: self.resample_method.clone().map(|o| Cow::Owned(o.into_owned())),
2016 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
2017 proplist: self.proplist.to_owned(),
2018 format: self.format.to_owned(),
2019 ..*self
2020 }
2021 }
2022}
2023
2024impl Introspector {
2025 pub fn get_sink_input_info<F>(&self, index: u32, callback: F)
2029 -> Operation<dyn FnMut(ListResult<&SinkInputInfo>)>
2030 where F: FnMut(ListResult<&SinkInputInfo>) + 'static
2031 {
2032 let cb_data =
2033 box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SinkInputInfo>)>(Box::new(callback));
2034 let ptr = unsafe { capi::pa_context_get_sink_input_info(self.context, index,
2035 Some(get_sink_input_info_list_cb_proxy), cb_data) };
2036 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SinkInputInfo>)>)
2037 }
2038
2039 pub fn get_sink_input_info_list<F>(&self, callback: F)
2043 -> Operation<dyn FnMut(ListResult<&SinkInputInfo>)>
2044 where F: FnMut(ListResult<&SinkInputInfo>) + 'static
2045 {
2046 let cb_data =
2047 box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SinkInputInfo>)>(Box::new(callback));
2048 let ptr = unsafe { capi::pa_context_get_sink_input_info_list(self.context,
2049 Some(get_sink_input_info_list_cb_proxy), cb_data) };
2050 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SinkInputInfo>)>)
2051 }
2052
2053 pub fn move_sink_input_by_name(&mut self, index: u32, sink_name: &str,
2059 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2060 {
2061 let c_name = CString::new(sink_name).unwrap();
2064
2065 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2066 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2067 let ptr = unsafe { capi::pa_context_move_sink_input_by_name(self.context, index,
2068 c_name.as_ptr(), cb_fn, cb_data) };
2069 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2070 }
2071
2072 pub fn move_sink_input_by_index(&mut self, index: u32, sink_index: u32,
2078 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2079 {
2080 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2081 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2082 let ptr = unsafe { capi::pa_context_move_sink_input_by_index(self.context, index,
2083 sink_index, cb_fn, cb_data) };
2084 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2085 }
2086
2087 pub fn set_sink_input_volume(&mut self, index: u32, volume: &ChannelVolumes,
2093 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2094 {
2095 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2096 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2097 let ptr = unsafe { capi::pa_context_set_sink_input_volume(self.context, index,
2098 volume.as_ref(), cb_fn, cb_data) };
2099 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2100 }
2101
2102 pub fn set_sink_input_mute(&mut self, index: u32, mute: bool,
2108 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2109 {
2110 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2111 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2112 let ptr = unsafe { capi::pa_context_set_sink_input_mute(self.context, index, mute as i32,
2113 cb_fn, cb_data) };
2114 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2115 }
2116
2117 pub fn kill_sink_input<F>(&mut self, index: u32, callback: F) -> Operation<dyn FnMut(bool)>
2123 where F: FnMut(bool) + 'static
2124 {
2125 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
2126 let ptr = unsafe { capi::pa_context_kill_sink_input(self.context, index,
2127 Some(super::success_cb_proxy), cb_data) };
2128 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2129 }
2130}
2131
2132extern "C"
2136fn get_sink_input_info_list_cb_proxy(_: *mut ContextInternal, i: *const SinkInputInfoInternal,
2137 eol: i32, userdata: *mut c_void)
2138{
2139 let _ = std::panic::catch_unwind(|| {
2140 callback_for_list_instance(i, eol, userdata, SinkInputInfo::new_from_raw);
2141 });
2142}
2143
2144#[derive(Debug)]
2153pub struct SourceOutputInfo<'a> {
2154 pub index: u32,
2156 pub name: Option<Cow<'a, str>>,
2158 pub owner_module: Option<u32>,
2161 pub client: Option<u32>,
2164 pub source: u32,
2166 pub sample_spec: sample::Spec,
2168 pub channel_map: channelmap::Map,
2170 pub buffer_usec: MicroSeconds,
2173 pub source_usec: MicroSeconds,
2175 pub resample_method: Option<Cow<'a, str>>,
2177 pub driver: Option<Cow<'a, str>>,
2179 pub proplist: Proplist,
2181 pub corked: bool,
2183 pub volume: ChannelVolumes,
2185 pub mute: bool,
2187 pub has_volume: bool,
2190 pub volume_writable: bool,
2193 pub format: format::Info,
2195}
2196
2197impl SourceOutputInfo<'_> {
2198 fn new_from_raw(p: *const SourceOutputInfoInternal) -> Self {
2199 assert!(!p.is_null());
2200 let src = unsafe { &*p };
2201 unsafe {
2202 SourceOutputInfo {
2203 index: src.index,
2204 name: match src.name.is_null() {
2205 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
2206 true => None,
2207 },
2208 owner_module: match src.owner_module {
2209 def::INVALID_INDEX => None,
2210 i => Some(i),
2211 },
2212 client: match src.client {
2213 def::INVALID_INDEX => None,
2214 i => Some(i),
2215 },
2216 source: src.source,
2217 sample_spec: src.sample_spec.into(),
2218 channel_map: src.channel_map.into(),
2219 buffer_usec: MicroSeconds(src.buffer_usec),
2220 source_usec: MicroSeconds(src.source_usec),
2221 resample_method: match src.resample_method.is_null() {
2222 false => Some(CStr::from_ptr(src.resample_method).to_string_lossy()),
2223 true => None,
2224 },
2225 driver: match src.driver.is_null() {
2226 false => Some(CStr::from_ptr(src.driver).to_string_lossy()),
2227 true => None,
2228 },
2229 proplist: Proplist::from_raw_weak(src.proplist),
2230 corked: match src.corked {
2231 0 => false,
2232 _ => true,
2233 },
2234 volume: src.volume.into(),
2235 mute: match src.mute {
2236 0 => false,
2237 _ => true,
2238 },
2239 has_volume: match src.has_volume {
2240 0 => false,
2241 _ => true,
2242 },
2243 volume_writable: match src.volume_writable {
2244 0 => false,
2245 _ => true,
2246 },
2247 format: format::Info::from_raw_weak(src.format as *mut format::InfoInternal),
2248 }
2249 }
2250 }
2251
2252 pub fn to_owned(&self) -> SourceOutputInfo<'static> {
2254 SourceOutputInfo {
2255 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
2256 resample_method: self.resample_method.clone().map(|o| Cow::Owned(o.into_owned())),
2257 driver: self.driver.clone().map(|o| Cow::Owned(o.into_owned())),
2258 proplist: self.proplist.to_owned(),
2259 format: self.format.to_owned(),
2260 ..*self
2261 }
2262 }
2263}
2264
2265impl Introspector {
2266 pub fn get_source_output_info<F>(&self, index: u32, callback: F)
2270 -> Operation<dyn FnMut(ListResult<&SourceOutputInfo>)>
2271 where F: FnMut(ListResult<&SourceOutputInfo>) + 'static
2272 {
2273 let cb_data =
2274 box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SourceOutputInfo>)>(Box::new(callback));
2275 let ptr = unsafe { capi::pa_context_get_source_output_info(self.context, index,
2276 Some(get_source_output_info_list_cb_proxy), cb_data) };
2277 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SourceOutputInfo>)>)
2278 }
2279
2280 pub fn get_source_output_info_list<F>(&self, callback: F)
2284 -> Operation<dyn FnMut(ListResult<&SourceOutputInfo>)>
2285 where F: FnMut(ListResult<&SourceOutputInfo>) + 'static
2286 {
2287 let cb_data =
2288 box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SourceOutputInfo>)>(Box::new(callback));
2289 let ptr = unsafe { capi::pa_context_get_source_output_info_list(self.context,
2290 Some(get_source_output_info_list_cb_proxy), cb_data) };
2291 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SourceOutputInfo>)>)
2292 }
2293
2294 pub fn move_source_output_by_name(&mut self, index: u32, source_name: &str,
2300 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2301 {
2302 let c_name = CString::new(source_name).unwrap();
2305
2306 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2307 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2308 let ptr = unsafe { capi::pa_context_move_source_output_by_name(self.context, index,
2309 c_name.as_ptr(), cb_fn, cb_data) };
2310 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2311 }
2312
2313 pub fn move_source_output_by_index(&mut self, index: u32, source_index: u32,
2319 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2320 {
2321 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2322 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2323 let ptr = unsafe { capi::pa_context_move_source_output_by_index(self.context, index,
2324 source_index, cb_fn, cb_data) };
2325 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2326 }
2327
2328 pub fn set_source_output_volume(&mut self, index: u32, volume: &ChannelVolumes,
2334 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2335 {
2336 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2337 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2338 let ptr = unsafe { capi::pa_context_set_source_output_volume(self.context, index,
2339 volume.as_ref(), cb_fn, cb_data) };
2340 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2341 }
2342
2343 pub fn set_source_output_mute(&mut self, index: u32, mute: bool,
2349 callback: Option<Box<dyn FnMut(bool) + 'static>>) -> Operation<dyn FnMut(bool)>
2350 {
2351 let (cb_fn, cb_data): (Option<extern "C" fn(_, _, _)>, _) =
2352 get_su_capi_params::<_, _>(callback, super::success_cb_proxy);
2353 let ptr = unsafe { capi::pa_context_set_source_output_mute(self.context, index, mute as i32,
2354 cb_fn, cb_data) };
2355 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2356 }
2357
2358 pub fn kill_source_output<F>(&mut self, index: u32, callback: F) -> Operation<dyn FnMut(bool)>
2364 where F: FnMut(bool) + 'static
2365 {
2366 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(bool)>(Box::new(callback));
2367 let ptr = unsafe { capi::pa_context_kill_source_output(self.context, index,
2368 Some(super::success_cb_proxy), cb_data) };
2369 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(bool)>)
2370 }
2371}
2372
2373extern "C"
2377fn get_source_output_info_list_cb_proxy(_: *mut ContextInternal, i: *const SourceOutputInfoInternal,
2378 eol: i32, userdata: *mut c_void)
2379{
2380 let _ = std::panic::catch_unwind(|| {
2381 callback_for_list_instance(i, eol, userdata, SourceOutputInfo::new_from_raw);
2382 });
2383}
2384
2385impl Introspector {
2390 pub fn stat<F>(&self, callback: F) -> Operation<dyn FnMut(&StatInfo)>
2394 where F: FnMut(&StatInfo) + 'static
2395 {
2396 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(&StatInfo)>(Box::new(callback));
2397 let ptr =
2398 unsafe { capi::pa_context_stat(self.context, Some(get_stat_info_cb_proxy), cb_data) };
2399 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(&StatInfo)>)
2400 }
2401}
2402
2403extern "C"
2407fn get_stat_info_cb_proxy(_: *mut ContextInternal, i: *const StatInfo, userdata: *mut c_void) {
2408 let _ = std::panic::catch_unwind(|| {
2409 assert!(!i.is_null());
2410 let mut callback = get_su_callback::<dyn FnMut(&StatInfo)>(userdata);
2412 (callback)(unsafe { &*i });
2413 });
2414}
2415
2416#[derive(Debug)]
2425pub struct SampleInfo<'a> {
2426 pub index: u32,
2428 pub name: Option<Cow<'a, str>>,
2430 pub volume: ChannelVolumes,
2432 pub sample_spec: sample::Spec,
2434 pub channel_map: channelmap::Map,
2436 pub duration: MicroSeconds,
2438 pub bytes: u32,
2440 pub lazy: bool,
2442 pub filename: Option<Cow<'a, str>>,
2444 pub proplist: Proplist,
2446}
2447
2448impl SampleInfo<'_> {
2449 fn new_from_raw(p: *const SampleInfoInternal) -> Self {
2450 assert!(!p.is_null());
2451 let src = unsafe { &*p };
2452 unsafe {
2453 SampleInfo {
2454 index: src.index,
2455 name: match src.name.is_null() {
2456 false => Some(CStr::from_ptr(src.name).to_string_lossy()),
2457 true => None,
2458 },
2459 volume: src.volume.into(),
2460 sample_spec: src.sample_spec.into(),
2461 channel_map: src.channel_map.into(),
2462 duration: MicroSeconds(src.duration),
2463 bytes: src.bytes,
2464 lazy: match src.lazy {
2465 0 => false,
2466 _ => true,
2467 },
2468 filename: match src.filename.is_null() {
2469 false => Some(CStr::from_ptr(src.filename).to_string_lossy()),
2470 true => None,
2471 },
2472 proplist: Proplist::from_raw_weak(src.proplist),
2473 }
2474 }
2475 }
2476
2477 pub fn to_owned(&self) -> SampleInfo<'static> {
2479 SampleInfo {
2480 name: self.name.clone().map(|o| Cow::Owned(o.into_owned())),
2481 filename: self.filename.clone().map(|o| Cow::Owned(o.into_owned())),
2482 proplist: self.proplist.to_owned(),
2483 ..*self
2484 }
2485 }
2486}
2487
2488impl Introspector {
2489 pub fn get_sample_info_by_name<F>(&self, name: &str, callback: F)
2493 -> Operation<dyn FnMut(ListResult<&SampleInfo>)>
2494 where F: FnMut(ListResult<&SampleInfo>) + 'static
2495 {
2496 let c_name = CString::new(name).unwrap();
2499
2500 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SampleInfo>)>(Box::new(callback));
2501 let ptr = unsafe { capi::pa_context_get_sample_info_by_name(self.context, c_name.as_ptr(),
2502 Some(get_sample_info_list_cb_proxy), cb_data) };
2503 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SampleInfo>)>)
2504 }
2505
2506 pub fn get_sample_info_by_index<F>(&self, index: u32, callback: F)
2510 -> Operation<dyn FnMut(ListResult<&SampleInfo>)>
2511 where F: FnMut(ListResult<&SampleInfo>) + 'static
2512 {
2513 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SampleInfo>)>(Box::new(callback));
2514 let ptr = unsafe { capi::pa_context_get_sample_info_by_index(self.context, index,
2515 Some(get_sample_info_list_cb_proxy), cb_data) };
2516 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SampleInfo>)>)
2517 }
2518
2519 pub fn get_sample_info_list<F>(&self, callback: F)
2523 -> Operation<dyn FnMut(ListResult<&SampleInfo>)>
2524 where F: FnMut(ListResult<&SampleInfo>) + 'static
2525 {
2526 let cb_data = box_closure_get_capi_ptr::<dyn FnMut(ListResult<&SampleInfo>)>(Box::new(callback));
2527 let ptr = unsafe { capi::pa_context_get_sample_info_list(self.context,
2528 Some(get_sample_info_list_cb_proxy), cb_data) };
2529 Operation::from_raw(ptr, cb_data as *mut Box<dyn FnMut(ListResult<&SampleInfo>)>)
2530 }
2531}
2532
2533extern "C"
2537fn get_sample_info_list_cb_proxy(_: *mut ContextInternal, i: *const SampleInfoInternal, eol: i32,
2538 userdata: *mut c_void)
2539{
2540 let _ = std::panic::catch_unwind(|| {
2541 callback_for_list_instance(i, eol, userdata, SampleInfo::new_from_raw);
2542 });
2543}