1use dbus::{
2 arg::{self, Append, Arg, ArgType, Get},
3 Signature,
4};
5use pulse::context::introspect::{
6 CardInfo, CardProfileInfo, SinkInfo, SinkInputInfo, SourceInfo, SourceOutputInfo,
7};
8
9use crate::network::connection::Enum;
10
11#[derive(Debug)]
12pub struct PulseError(pub &'static str);
13
14#[derive(Debug, Clone, Default)]
15pub enum DeviceState {
16 #[default]
17 Idle,
18 Invalid,
19 Suspended,
20 Running,
21}
22
23impl Enum for DeviceState {
24 fn from_i32(num: i32) -> Self {
25 match num {
26 0 => DeviceState::Idle,
27 1 => DeviceState::Invalid,
28 2 => DeviceState::Suspended,
29 _ => DeviceState::Running,
30 }
31 }
32
33 fn to_i32(&self) -> i32 {
34 match self {
35 DeviceState::Idle => 0,
36 DeviceState::Invalid => 1,
37 DeviceState::Suspended => 2,
38 DeviceState::Running => 3,
39 }
40 }
41}
42
43#[derive(Debug, Clone, Default)]
44pub struct Source {
45 pub index: u32,
46 pub name: String,
47 pub alias: String,
48 pub channels: u16,
49 pub volume: Vec<u32>,
50 pub muted: bool,
51 pub active: i32,
52}
53
54unsafe impl Send for Source {}
55unsafe impl Sync for Source {}
56
57impl Append for Source {
58 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
59 iter.append_struct(|i| {
60 i.append(self.index);
61 i.append(&self.name);
62 i.append(&self.alias);
63 i.append(self.channels);
64 i.append(&self.volume);
65 i.append(self.muted);
66 i.append(self.active);
67 });
68 }
69}
70
71impl<'a> Get<'a> for Source {
72 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
73 let (index, name, alias, channels, volume, muted, active) =
74 <(u32, String, String, u16, Vec<u32>, bool, i32)>::get(i)?;
75 Some(Self {
76 index,
77 name,
78 alias,
79 channels,
80 volume,
81 muted,
82 active,
83 })
84 }
85}
86
87impl Arg for Source {
88 const ARG_TYPE: arg::ArgType = ArgType::Struct;
89 fn signature() -> Signature<'static> {
90 unsafe { Signature::from_slice_unchecked("(ussqaubi)\0") }
91 }
92}
93
94impl From<&SourceInfo<'_>> for Source {
95 fn from(value: &SourceInfo<'_>) -> Self {
96 let name_opt = &value.name;
97 let alias_opt = &value.description;
98 let name: String;
99 let alias: String;
100 if name_opt.is_none() {
101 name = String::from("");
102 } else {
103 name = String::from(name_opt.clone().unwrap());
104 }
105 if alias_opt.is_none() {
106 alias = String::from("");
107 } else {
108 alias = String::from(alias_opt.clone().unwrap());
109 }
110 let index = value.index;
111 let channels = value.channel_map.len() as u16;
112 let mut volume = vec![0; channels as usize];
113 for i in 0..channels as usize {
114 unsafe { *volume.get_unchecked_mut(i) = value.volume.get()[i].0 };
115 }
116 let muted = value.mute;
117 let active = value.state as i32;
118 Self {
119 index,
120 name,
121 alias,
122 channels,
123 volume,
124 muted,
125 active,
126 }
127 }
128}
129
130#[derive(Debug, Clone, Default)]
131pub struct Sink {
132 pub index: u32,
133 pub name: String,
134 pub alias: String,
135 pub channels: u16,
136 pub volume: Vec<u32>,
137 pub muted: bool,
138 pub active: i32,
139}
140
141unsafe impl Send for Sink {}
142unsafe impl Sync for Sink {}
143
144impl Append for Sink {
145 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
146 iter.append_struct(|i| {
147 i.append(self.index);
148 i.append(&self.name);
149 i.append(&self.alias);
150 i.append(self.channels);
151 i.append(&self.volume);
152 i.append(self.muted);
153 i.append(self.active);
154 });
155 }
156}
157
158impl<'a> Get<'a> for Sink {
159 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
160 let (index, name, alias, channels, volume, muted, active) =
161 <(u32, String, String, u16, Vec<u32>, bool, i32)>::get(i)?;
162 Some(Self {
163 index,
164 name,
165 alias,
166 channels,
167 volume,
168 muted,
169 active,
170 })
171 }
172}
173
174impl Arg for Sink {
175 const ARG_TYPE: arg::ArgType = ArgType::Struct;
176 fn signature() -> Signature<'static> {
177 unsafe { Signature::from_slice_unchecked("(ussqaubi)\0") }
178 }
179}
180
181impl From<&SinkInfo<'_>> for Sink {
182 fn from(value: &SinkInfo<'_>) -> Self {
183 let name_opt = &value.name;
184 let alias_opt = &value.description;
185 let name: String;
186 let alias: String;
187 if name_opt.is_none() {
188 name = String::from("");
189 } else {
190 name = String::from(name_opt.clone().unwrap());
191 }
192 if alias_opt.is_none() {
193 alias = String::from("");
194 } else {
195 alias = String::from(alias_opt.clone().unwrap());
196 }
197 let index = value.index;
198 let channels = value.channel_map.len() as u16;
199 let mut volume = vec![0; channels as usize];
200 for i in 0..channels as usize {
201 unsafe { *volume.get_unchecked_mut(i) = value.volume.get()[i].0 };
202 }
203 let muted = value.mute;
204 let active = value.mute as i32;
205 Self {
206 index,
207 name,
208 alias,
209 channels,
210 volume,
211 muted,
212 active,
213 }
214 }
215}
216
217#[derive(Debug, Clone, Default)]
218pub struct InputStream {
219 pub index: u32,
220 pub name: String,
221 pub application_name: String,
222 pub sink_index: u32,
223 pub channels: u16,
224 pub volume: Vec<u32>,
225 pub muted: bool,
226 pub corked: bool,
227}
228
229impl Append for InputStream {
230 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
231 iter.append_struct(|i| {
232 i.append(self.index);
233 i.append(&self.name);
234 i.append(&self.application_name);
235 i.append(self.sink_index);
236 i.append(self.channels);
237 i.append(&self.volume);
238 i.append(self.muted);
239 i.append(self.corked);
240 });
241 }
242}
243
244impl<'a> Get<'a> for InputStream {
245 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
246 let (index, name, application_name, sink_index, channels, volume, muted, corked) =
247 <(u32, String, String, u32, u16, Vec<u32>, bool, bool)>::get(i)?;
248 Some(Self {
249 index,
250 name,
251 application_name,
252 sink_index,
253 channels,
254 volume,
255 muted,
256 corked,
257 })
258 }
259}
260
261impl Arg for InputStream {
262 const ARG_TYPE: arg::ArgType = ArgType::Struct;
263 fn signature() -> Signature<'static> {
264 unsafe { Signature::from_slice_unchecked("(ussuqaubb)\0") }
265 }
266}
267
268impl From<&SinkInputInfo<'_>> for InputStream {
269 fn from(value: &SinkInputInfo<'_>) -> Self {
270 let name_opt = &value.name;
271 let name: String;
272 if name_opt.is_none() {
273 name = String::from("");
274 } else {
275 name = String::from(name_opt.clone().unwrap());
276 }
277 let application_name = value
278 .proplist
279 .get_str("application.name")
280 .unwrap_or_default();
281 let sink_index = value.sink;
282 let index = value.index;
283 let channels = value.channel_map.len() as u16;
284 let mut volume = vec![0; channels as usize];
285 for i in 0..channels as usize {
286 unsafe { *volume.get_unchecked_mut(i) = value.volume.get()[i].0 };
287 }
288 let muted = value.mute;
289 let corked = value.corked;
290 Self {
291 index,
292 name,
293 application_name,
294 sink_index,
295 channels,
296 volume,
297 muted,
298 corked,
299 }
300 }
301}
302
303#[derive(Debug, Clone, Default)]
304pub struct OutputStream {
305 pub index: u32,
306 pub name: String,
307 pub application_name: String,
308 pub source_index: u32,
309 pub channels: u16,
310 pub volume: Vec<u32>,
311 pub muted: bool,
312 pub corked: bool,
313}
314
315impl Append for OutputStream {
316 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
317 iter.append_struct(|i| {
318 i.append(self.index);
319 i.append(&self.name);
320 i.append(&self.application_name);
321 i.append(self.source_index);
322 i.append(self.channels);
323 i.append(&self.volume);
324 i.append(self.muted);
325 i.append(self.corked);
326 });
327 }
328}
329
330impl<'a> Get<'a> for OutputStream {
331 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
332 let (index, name, application_name, source_index, channels, volume, muted, corked) =
333 <(u32, String, String, u32, u16, Vec<u32>, bool, bool)>::get(i)?;
334 Some(Self {
335 index,
336 name,
337 application_name,
338 source_index,
339 channels,
340 volume,
341 muted,
342 corked,
343 })
344 }
345}
346
347impl Arg for OutputStream {
348 const ARG_TYPE: arg::ArgType = ArgType::Struct;
349 fn signature() -> Signature<'static> {
350 unsafe { Signature::from_slice_unchecked("(ussuqaubb)\0") }
351 }
352}
353
354impl From<&SourceOutputInfo<'_>> for OutputStream {
355 fn from(value: &SourceOutputInfo<'_>) -> Self {
356 let name_opt = &value.name;
357 let name: String;
358 if name_opt.is_none() {
359 name = String::from("");
360 } else {
361 name = String::from(name_opt.clone().unwrap());
362 }
363 let application_name = value
364 .proplist
365 .get_str("application.name")
366 .unwrap_or_default();
367 let source_index = value.source;
368 let index = value.index;
369 let channels = value.channel_map.len() as u16;
370 let mut volume = vec![0; channels as usize];
371 for i in 0..channels as usize {
372 unsafe { *volume.get_unchecked_mut(i) = value.volume.get()[i].0 };
373 }
374 let muted = value.mute;
375 let corked = value.corked;
376 Self {
377 index,
378 name,
379 application_name,
380 source_index,
381 channels,
382 volume,
383 muted,
384 corked,
385 }
386 }
387}
388
389#[derive(Debug, Clone, Default)]
390pub struct Card {
391 pub index: u32,
392 pub name: String,
393 pub profiles: Vec<CardProfile>,
394 pub active_profile: String,
395}
396
397impl Append for Card {
398 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
399 iter.append_struct(|i| {
400 i.append(self.index);
401 i.append(&self.name);
402 i.append(&self.profiles);
403 i.append(&self.active_profile);
404 });
405 }
406}
407
408impl<'a> Get<'a> for Card {
409 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
410 let (index, name, profiles, active_profile) =
411 <(u32, String, Vec<CardProfile>, String)>::get(i)?;
412 Some(Self {
413 index,
414 name,
415 profiles,
416 active_profile,
417 })
418 }
419}
420
421impl Arg for Card {
422 const ARG_TYPE: arg::ArgType = ArgType::Struct;
423 fn signature() -> Signature<'static> {
424 unsafe { Signature::from_slice_unchecked("(usa(ssb)s)\0") }
425 }
426}
427
428impl From<&CardInfo<'_>> for Card {
429 fn from(value: &CardInfo<'_>) -> Self {
430 let name_opt = &value.proplist.get_str("alsa.card_name");
431 let name: String;
432 if name_opt.is_none() {
433 name = String::from("Unnamed");
434 } else {
435 name = name_opt.clone().unwrap();
436 }
437 let index = value.index;
438 let mut profiles = Vec::new();
439 for profile in value.profiles.iter() {
440 profiles.push(CardProfile::from(profile));
441 }
442 let profile_opt = value.active_profile.as_ref();
443 let active_profile: String;
444 if profile_opt.is_none() {
445 active_profile = String::from("Off");
446 } else {
447 active_profile = profile_opt.unwrap().name.clone().unwrap().to_string();
448 }
449 Self {
450 index,
451 name,
452 profiles,
453 active_profile,
454 }
455 }
456}
457
458#[derive(Debug, Clone, Default)]
459pub struct CardProfile {
460 pub name: String,
461 pub description: String,
462 pub available: bool,
463}
464
465impl Append for CardProfile {
466 fn append_by_ref(&self, iter: &mut arg::IterAppend) {
467 iter.append_struct(|i| {
468 i.append(&self.name);
469 i.append(&self.description);
470 i.append(self.available);
471 });
472 }
473}
474
475impl<'a> Get<'a> for CardProfile {
476 fn get(i: &mut arg::Iter<'a>) -> Option<Self> {
477 let (name, description, available) = <(String, String, bool)>::get(i)?;
478 Some(Self {
479 name,
480 description,
481 available,
482 })
483 }
484}
485
486impl Arg for CardProfile {
487 const ARG_TYPE: arg::ArgType = ArgType::Struct;
488 fn signature() -> Signature<'static> {
489 unsafe { Signature::from_slice_unchecked("(ssb)\0") }
490 }
491}
492
493impl From<&CardProfileInfo<'_>> for CardProfile {
494 fn from(value: &CardProfileInfo<'_>) -> Self {
495 let name_opt = &value.name;
496 let name: String;
497 if name_opt.is_none() {
498 name = String::from("");
499 } else {
500 name = String::from(name_opt.clone().unwrap());
501 }
502 let description_opt = &value.description;
503 let description: String;
504 if description_opt.is_none() {
505 description = String::from("");
506 } else {
507 description = String::from(description_opt.clone().unwrap());
508 }
509 let available = value.available;
510 Self {
511 name,
512 description,
513 available,
514 }
515 }
516}