pipewire_native_spa/interface/
mod.rs1use std::{
6 collections::HashMap,
7 ffi::{c_void, CStr, CString},
8 pin::Pin,
9 sync::Arc,
10};
11
12use cpu::CpuImpl;
13use ffi::{CInterface, CSupport};
14use log::LogImpl;
15use r#loop::{LoopControlImpl, LoopImpl, LoopUtilsImpl};
16use system::SystemImpl;
17use thread::ThreadUtilsImpl;
18
19use crate::support;
20
21pub mod cpu;
22pub mod ffi;
23pub mod log;
24pub mod r#loop;
25pub mod plugin;
26pub mod system;
27pub mod thread;
28
29pub const CPU: &str = "Spa:Pointer:Interface:CPU";
31pub const LOG: &str = "Spa:Pointer:Interface:Log";
32pub const LOOP: &str = "Spa:Pointer:Interface:Loop";
33pub const LOOP_CONTROL: &str = "Spa:Pointer:Interface:LoopControl";
34pub const LOOP_UTILS: &str = "Spa:Pointer:Interface:LoopUtils";
35pub const SYSTEM: &str = "Spa:Pointer:Interface:System";
36pub const THREAD_UTILS: &str = "Spa:Pointer:Interface:ThreadUtils";
37
38pub struct Support {
39 supports: HashMap<&'static str, Arc<Pin<Box<dyn plugin::Interface>>>>,
40 c_supports: Vec<CSupport>,
43}
44
45unsafe impl Send for Support {}
46unsafe impl Sync for Support {}
47
48impl Default for Support {
49 fn default() -> Self {
50 Support {
51 supports: HashMap::new(),
52 c_supports: Vec::with_capacity(16),
54 }
55 }
56}
57
58impl Support {
59 pub fn new() -> Support {
60 Support::default()
61 }
62
63 pub fn c_support(&self) -> &Vec<CSupport> {
64 &self.c_supports
65 }
66
67 fn add_or_update_c(&mut self, name: &str, data: *mut CInterface) {
68 for s in self.c_supports.iter_mut() {
69 let type_ = unsafe { CStr::from_ptr(s.type_).to_str() };
70 if type_ == Ok(name) {
71 s.data = data as *mut c_void;
72 return;
73 }
74 }
75
76 self.c_supports.push(CSupport {
77 type_: support::ffi::c_string(name).into_raw(),
78 data: data as *mut c_void,
79 });
80 }
81
82 pub fn add_interface(&mut self, name: &'static str, iface: Box<dyn plugin::Interface>) {
83 let pin = Box::into_pin(iface);
84 let data = unsafe { pin.make_native() };
85
86 #[allow(clippy::arc_with_non_send_sync)]
87 self.supports.insert(name, Arc::new(pin));
88 self.add_or_update_c(name, data);
89 }
90
91 pub fn get_interface<T>(&self, name: &str) -> Option<Arc<Pin<Box<T>>>>
92 where
93 T: plugin::Interface + 'static,
94 {
95 let iface = self.supports.get(name).cloned();
96
97 iface.and_then(|iface| iface.downcast_arc_pin_box::<T>().ok())
98 }
99}
100
101impl Drop for Support {
102 fn drop(&mut self) {
103 for s in self.c_supports.iter_mut() {
104 unsafe {
105 let type_ = CString::from_raw(s.type_);
106 match type_.to_str().unwrap() {
107 CPU => <CpuImpl as plugin::Interface>::free_native(s.data as *mut CInterface),
108 LOOP => <LoopImpl as plugin::Interface>::free_native(s.data as *mut CInterface),
109 LOOP_CONTROL => <LoopControlImpl as plugin::Interface>::free_native(
110 s.data as *mut CInterface,
111 ),
112 LOOP_UTILS => {
113 <LoopUtilsImpl as plugin::Interface>::free_native(s.data as *mut CInterface)
114 }
115 LOG => <LogImpl as plugin::Interface>::free_native(s.data as *mut CInterface),
116 SYSTEM => {
117 <SystemImpl as plugin::Interface>::free_native(s.data as *mut CInterface)
118 }
119 THREAD_UTILS => <ThreadUtilsImpl as plugin::Interface>::free_native(
120 s.data as *mut CInterface,
121 ),
122 _ => unreachable!(),
123 }
124 }
125 }
126 }
127}