1pub(crate) mod error;
7pub mod types;
8
9use pulse::{
10 callbacks::ListResult,
11 context::introspect,
12 volume::{ChannelVolumes, Volume},
13};
14
15use std::cell::RefCell;
16use std::clone::Clone;
17use std::rc::Rc;
18
19use self::error::ControllerError;
20use self::types::{ApplicationInfo, DeviceInfo, ServerInfo};
21use crate::Handler;
22
23pub trait DeviceControl<T> {
24 fn get_default_device(&mut self) -> Result<T, ControllerError>;
25 fn set_default_device(&mut self, name: &str) -> Result<bool, ControllerError>;
26
27 fn list_devices(&mut self) -> Result<Vec<T>, ControllerError>;
28 fn get_device_by_index(&mut self, index: u32) -> Result<T, ControllerError>;
29 fn get_device_by_name(&mut self, name: &str) -> Result<T, ControllerError>;
30 fn set_device_volume_by_index(&mut self, index: u32, volume: &ChannelVolumes);
31 fn set_device_volume_by_name(&mut self, name: &str, volume: &ChannelVolumes);
32 fn set_device_mute_by_index(&mut self, index: u32, mute: bool);
33 fn set_device_mute_by_name(&mut self, name: &str, mute: bool);
34 fn increase_device_volume_by_percent(&mut self, index: u32, delta: f64);
35 fn decrease_device_volume_by_percent(&mut self, index: u32, delta: f64);
36}
37
38pub trait AppControl<T> {
39 fn list_applications(&mut self) -> Result<Vec<T>, ControllerError>;
40
41 fn get_app_by_index(&mut self, index: u32) -> Result<T, ControllerError>;
42 fn increase_app_volume_by_percent(&mut self, index: u32, delta: f64);
43 fn decrease_app_volume_by_percent(&mut self, index: u32, delta: f64);
44
45 fn move_app_by_index(
46 &mut self,
47 stream_index: u32,
48 device_index: u32,
49 ) -> Result<bool, ControllerError>;
50 fn move_app_by_name(
51 &mut self,
52 stream_index: u32,
53 device_name: &str,
54 ) -> Result<bool, ControllerError>;
55 fn set_app_mute(&mut self, index: u32, mute: bool) -> Result<bool, ControllerError>;
56}
57
58fn volume_from_percent(volume: f64) -> f64 {
59 (volume * 100.0) * (f64::from(pulse::volume::Volume::NORMAL.0) / 100.0)
60}
61
62pub struct SinkController {
65 pub handler: Handler,
66}
67
68impl SinkController {
69 pub fn create() -> Result<Self, ControllerError> {
70 let handler = Handler::connect("SinkController")?;
71 Ok(SinkController { handler })
72 }
73
74 pub fn get_server_info(&mut self) -> Result<ServerInfo, ControllerError> {
75 let server = Rc::new(RefCell::new(Some(None)));
76 let server_ref = server.clone();
77
78 let op = self.handler.introspect.get_server_info(move |res| {
79 server_ref
80 .borrow_mut()
81 .as_mut()
82 .unwrap()
83 .replace(res.into());
84 });
85 self.handler.wait_for_operation(op)?;
86 let mut result = server.borrow_mut();
87 result.take().unwrap().ok_or_else(|| {
88 ControllerError::GetInfo("Error getting information about the server".to_string())
89 })
90 }
91}
92
93impl DeviceControl<DeviceInfo> for SinkController {
94 fn get_default_device(&mut self) -> Result<DeviceInfo, ControllerError> {
95 let server_info = self.get_server_info();
96 match server_info {
97 Ok(info) => self.get_device_by_name(info.default_sink_name.unwrap().as_ref()),
98 Err(e) => Err(e),
99 }
100 }
101 fn set_default_device(&mut self, name: &str) -> Result<bool, ControllerError> {
102 let success = Rc::new(RefCell::new(false));
103 let success_ref = success.clone();
104
105 let op = self
106 .handler
107 .context
108 .borrow_mut()
109 .set_default_sink(name, move |res| success_ref.borrow_mut().clone_from(&res));
110 self.handler.wait_for_operation(op)?;
111 let result = *success.borrow_mut();
112 Ok(result)
113 }
114
115 fn list_devices(&mut self) -> Result<Vec<DeviceInfo>, ControllerError> {
116 let list = Rc::new(RefCell::new(Some(Vec::new())));
117 let list_ref = list.clone();
118
119 let op = self.handler.introspect.get_sink_info_list(
120 move |sink_list: ListResult<&introspect::SinkInfo>| {
121 if let ListResult::Item(item) = sink_list {
122 list_ref.borrow_mut().as_mut().unwrap().push(item.into());
123 }
124 },
125 );
126 self.handler.wait_for_operation(op)?;
127 let mut result = list.borrow_mut();
128 result
129 .take()
130 .ok_or_else(|| ControllerError::GetInfo("Error getting device list".to_string()))
131 }
132 fn get_device_by_index(&mut self, index: u32) -> Result<DeviceInfo, ControllerError> {
133 let device = Rc::new(RefCell::new(Some(None)));
134 let dev_ref = device.clone();
135 let op = self.handler.introspect.get_sink_info_by_index(
136 index,
137 move |sink_list: ListResult<&introspect::SinkInfo>| {
138 if let ListResult::Item(item) = sink_list {
139 dev_ref.borrow_mut().as_mut().unwrap().replace(item.into());
140 }
141 },
142 );
143 self.handler.wait_for_operation(op)?;
144 let mut result = device.borrow_mut();
145 result
146 .take()
147 .unwrap()
148 .ok_or_else(|| ControllerError::GetInfo("Error getting requested device".to_string()))
149 }
150 fn get_device_by_name(&mut self, name: &str) -> Result<DeviceInfo, ControllerError> {
151 let device = Rc::new(RefCell::new(Some(None)));
152 let dev_ref = device.clone();
153 let op = self.handler.introspect.get_sink_info_by_name(
154 name,
155 move |sink_list: ListResult<&introspect::SinkInfo>| {
156 if let ListResult::Item(item) = sink_list {
157 dev_ref.borrow_mut().as_mut().unwrap().replace(item.into());
158 }
159 },
160 );
161 self.handler.wait_for_operation(op)?;
162 let mut result = device.borrow_mut();
163 result
164 .take()
165 .unwrap()
166 .ok_or_else(|| ControllerError::GetInfo("Error getting requested device".to_string()))
167 }
168
169 fn set_device_volume_by_index(&mut self, index: u32, volume: &ChannelVolumes) {
170 let op = self
171 .handler
172 .introspect
173 .set_sink_volume_by_index(index, volume, None);
174 self.handler.wait_for_operation(op).ok();
175 }
176 fn set_device_volume_by_name(&mut self, name: &str, volume: &ChannelVolumes) {
177 let op = self
178 .handler
179 .introspect
180 .set_sink_volume_by_name(name, volume, None);
181 self.handler.wait_for_operation(op).ok();
182 }
183 fn set_device_mute_by_index(&mut self, index: u32, mute: bool) {
184 let op = self
185 .handler
186 .introspect
187 .set_sink_mute_by_index(index, mute, None);
188 self.handler.wait_for_operation(op).ok();
189 }
190 fn set_device_mute_by_name(&mut self, name: &str, mute: bool) {
191 let op = self
192 .handler
193 .introspect
194 .set_sink_mute_by_name(name, mute, None);
195 self.handler.wait_for_operation(op).ok();
196 }
197 fn increase_device_volume_by_percent(&mut self, index: u32, delta: f64) {
198 if let Ok(mut dev_ref) = self.get_device_by_index(index) {
199 let new_vol = Volume(volume_from_percent(delta) as u32);
200 if let Some(volumes) = dev_ref.volume.increase(new_vol) {
201 let op = self
202 .handler
203 .introspect
204 .set_sink_volume_by_index(index, volumes, None);
205 self.handler.wait_for_operation(op).ok();
206 }
207 }
208 }
209 fn decrease_device_volume_by_percent(&mut self, index: u32, delta: f64) {
210 if let Ok(mut dev_ref) = self.get_device_by_index(index) {
211 let new_vol = Volume(volume_from_percent(delta) as u32);
212 if let Some(volumes) = dev_ref.volume.decrease(new_vol) {
213 let op = self
214 .handler
215 .introspect
216 .set_sink_volume_by_index(index, volumes, None);
217 self.handler.wait_for_operation(op).ok();
218 }
219 }
220 }
221}
222
223impl AppControl<ApplicationInfo> for SinkController {
224 fn list_applications(&mut self) -> Result<Vec<ApplicationInfo>, ControllerError> {
225 let list = Rc::new(RefCell::new(Some(Vec::new())));
226 let list_ref = list.clone();
227
228 let op = self.handler.introspect.get_sink_input_info_list(
229 move |sink_list: ListResult<&introspect::SinkInputInfo>| {
230 if let ListResult::Item(item) = sink_list {
231 list_ref.borrow_mut().as_mut().unwrap().push(item.into());
232 }
233 },
234 );
235 self.handler.wait_for_operation(op)?;
236 let mut result = list.borrow_mut();
237 result
238 .take()
239 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
240 }
241
242 fn get_app_by_index(&mut self, index: u32) -> Result<ApplicationInfo, ControllerError> {
243 let app = Rc::new(RefCell::new(Some(None)));
244 let app_ref = app.clone();
245 let op = self.handler.introspect.get_sink_input_info(
246 index,
247 move |sink_list: ListResult<&introspect::SinkInputInfo>| {
248 if let ListResult::Item(item) = sink_list {
249 app_ref.borrow_mut().as_mut().unwrap().replace(item.into());
250 }
251 },
252 );
253 self.handler.wait_for_operation(op)?;
254 let mut result = app.borrow_mut();
255 result
256 .take()
257 .unwrap()
258 .ok_or_else(|| ControllerError::GetInfo("Error getting requested app".to_string()))
259 }
260
261 fn increase_app_volume_by_percent(&mut self, index: u32, delta: f64) {
262 if let Ok(mut app_ref) = self.get_app_by_index(index) {
263 let new_vol = Volume(volume_from_percent(delta) as u32);
264 if let Some(volumes) = app_ref.volume.increase(new_vol) {
265 let op = self
266 .handler
267 .introspect
268 .set_sink_input_volume(index, volumes, None);
269 self.handler.wait_for_operation(op).ok();
270 }
271 }
272 }
273
274 fn decrease_app_volume_by_percent(&mut self, index: u32, delta: f64) {
275 if let Ok(mut app_ref) = self.get_app_by_index(index) {
276 let new_vol = Volume(volume_from_percent(delta) as u32);
277 if let Some(volumes) = app_ref.volume.decrease(new_vol) {
278 let op = self
279 .handler
280 .introspect
281 .set_sink_input_volume(index, volumes, None);
282 self.handler.wait_for_operation(op).ok();
283 }
284 }
285 }
286
287 fn move_app_by_index(
288 &mut self,
289 stream_index: u32,
290 device_index: u32,
291 ) -> Result<bool, ControllerError> {
292 let success = Rc::new(RefCell::new(false));
293 let success_ref = success.clone();
294 let op = self.handler.introspect.move_sink_input_by_index(
295 stream_index,
296 device_index,
297 Some(Box::new(move |res| {
298 success_ref.borrow_mut().clone_from(&res)
299 })),
300 );
301 self.handler.wait_for_operation(op)?;
302 let result = *success.borrow_mut();
303 Ok(result)
304 }
305
306 fn move_app_by_name(
307 &mut self,
308 stream_index: u32,
309 device_name: &str,
310 ) -> Result<bool, ControllerError> {
311 let success = Rc::new(RefCell::new(false));
312 let success_ref = success.clone();
313 let op = self.handler.introspect.move_sink_input_by_name(
314 stream_index,
315 device_name,
316 Some(Box::new(move |res| {
317 success_ref.borrow_mut().clone_from(&res)
318 })),
319 );
320 self.handler.wait_for_operation(op)?;
321 let result = *success.borrow_mut();
322 Ok(result)
323 }
324
325 fn set_app_mute(&mut self, index: u32, mute: bool) -> Result<bool, ControllerError> {
326 let success = Rc::new(RefCell::new(false));
327 let success_ref = success.clone();
328 let op = self.handler.introspect.set_sink_input_mute(
329 index,
330 mute,
331 Some(Box::new(move |res| {
332 success_ref.borrow_mut().clone_from(&res)
333 })),
334 );
335 self.handler.wait_for_operation(op)?;
336 let result = *success.borrow_mut();
337 Ok(result)
338 }
339}
340
341pub struct SourceController {
344 pub handler: Handler,
345}
346
347impl SourceController {
348 pub fn create() -> Result<Self, ControllerError> {
349 let handler = Handler::connect("SourceController")?;
350 Ok(SourceController { handler })
351 }
352
353 pub fn get_server_info(&mut self) -> Result<ServerInfo, ControllerError> {
354 let server = Rc::new(RefCell::new(Some(None)));
355 let server_ref = server.clone();
356
357 let op = self.handler.introspect.get_server_info(move |res| {
358 server_ref
359 .borrow_mut()
360 .as_mut()
361 .unwrap()
362 .replace(res.into());
363 });
364 self.handler.wait_for_operation(op)?;
365 let mut result = server.borrow_mut();
366 result
367 .take()
368 .unwrap()
369 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
370 }
371}
372
373impl DeviceControl<DeviceInfo> for SourceController {
374 fn get_default_device(&mut self) -> Result<DeviceInfo, ControllerError> {
375 let server_info = self.get_server_info();
376 match server_info {
377 Ok(info) => self.get_device_by_name(info.default_sink_name.unwrap().as_ref()),
378 Err(e) => Err(e),
379 }
380 }
381 fn set_default_device(&mut self, name: &str) -> Result<bool, ControllerError> {
382 let success = Rc::new(RefCell::new(false));
383 let success_ref = success.clone();
384
385 let op = self
386 .handler
387 .context
388 .borrow_mut()
389 .set_default_source(name, move |res| success_ref.borrow_mut().clone_from(&res));
390 self.handler.wait_for_operation(op)?;
391 let result = *success.borrow_mut();
392 Ok(result)
393 }
394
395 fn list_devices(&mut self) -> Result<Vec<DeviceInfo>, ControllerError> {
396 let list = Rc::new(RefCell::new(Some(Vec::new())));
397 let list_ref = list.clone();
398
399 let op = self.handler.introspect.get_source_info_list(
400 move |sink_list: ListResult<&introspect::SourceInfo>| {
401 if let ListResult::Item(item) = sink_list {
402 list_ref.borrow_mut().as_mut().unwrap().push(item.into());
403 }
404 },
405 );
406 self.handler.wait_for_operation(op)?;
407 let mut result = list.borrow_mut();
408 result
409 .take()
410 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
411 }
412 fn get_device_by_index(&mut self, index: u32) -> Result<DeviceInfo, ControllerError> {
413 let device = Rc::new(RefCell::new(Some(None)));
414 let dev_ref = device.clone();
415 let op = self.handler.introspect.get_source_info_by_index(
416 index,
417 move |sink_list: ListResult<&introspect::SourceInfo>| {
418 if let ListResult::Item(item) = sink_list {
419 dev_ref.borrow_mut().as_mut().unwrap().replace(item.into());
420 }
421 },
422 );
423 self.handler.wait_for_operation(op)?;
424 let mut result = device.borrow_mut();
425 result
426 .take()
427 .unwrap()
428 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
429 }
430 fn get_device_by_name(&mut self, name: &str) -> Result<DeviceInfo, ControllerError> {
431 let device = Rc::new(RefCell::new(Some(None)));
432 let dev_ref = device.clone();
433 let op = self.handler.introspect.get_source_info_by_name(
434 name,
435 move |sink_list: ListResult<&introspect::SourceInfo>| {
436 if let ListResult::Item(item) = sink_list {
437 dev_ref.borrow_mut().as_mut().unwrap().replace(item.into());
438 }
439 },
440 );
441 self.handler.wait_for_operation(op)?;
442 let mut result = device.borrow_mut();
443 result
444 .take()
445 .unwrap()
446 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
447 }
448
449 fn set_device_volume_by_index(&mut self, index: u32, volume: &ChannelVolumes) {
450 let op = self
451 .handler
452 .introspect
453 .set_source_volume_by_index(index, volume, None);
454 self.handler.wait_for_operation(op).ok();
455 }
456 fn set_device_volume_by_name(&mut self, name: &str, volume: &ChannelVolumes) {
457 let op = self
458 .handler
459 .introspect
460 .set_source_volume_by_name(name, volume, None);
461 self.handler.wait_for_operation(op).ok();
462 }
463 fn increase_device_volume_by_percent(&mut self, index: u32, delta: f64) {
464 if let Ok(mut dev_ref) = self.get_device_by_index(index) {
465 let new_vol = Volume(volume_from_percent(delta) as u32);
466 if let Some(volumes) = dev_ref.volume.increase(new_vol) {
467 let op = self
468 .handler
469 .introspect
470 .set_source_volume_by_index(index, volumes, None);
471 self.handler.wait_for_operation(op).ok();
472 }
473 }
474 }
475 fn set_device_mute_by_index(&mut self, index: u32, mute: bool) {
476 let op = self
477 .handler
478 .introspect
479 .set_sink_mute_by_index(index, mute, None);
480 self.handler.wait_for_operation(op).ok();
481 }
482 fn set_device_mute_by_name(&mut self, name: &str, mute: bool) {
483 let op = self
484 .handler
485 .introspect
486 .set_sink_mute_by_name(name, mute, None);
487 self.handler.wait_for_operation(op).ok();
488 }
489 fn decrease_device_volume_by_percent(&mut self, index: u32, delta: f64) {
490 if let Ok(mut dev_ref) = self.get_device_by_index(index) {
491 let new_vol = Volume(volume_from_percent(delta) as u32);
492 if let Some(volumes) = dev_ref.volume.decrease(new_vol) {
493 let op = self
494 .handler
495 .introspect
496 .set_source_volume_by_index(index, volumes, None);
497 self.handler.wait_for_operation(op).ok();
498 }
499 }
500 }
501}
502
503impl AppControl<ApplicationInfo> for SourceController {
504 fn list_applications(&mut self) -> Result<Vec<ApplicationInfo>, ControllerError> {
505 let list = Rc::new(RefCell::new(Some(Vec::new())));
506 let list_ref = list.clone();
507
508 let op = self.handler.introspect.get_source_output_info_list(
509 move |sink_list: ListResult<&introspect::SourceOutputInfo>| {
510 if let ListResult::Item(item) = sink_list {
511 list_ref.borrow_mut().as_mut().unwrap().push(item.into());
512 }
513 },
514 );
515 self.handler.wait_for_operation(op)?;
516 let mut result = list.borrow_mut();
517 result
518 .take()
519 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
520 }
521
522 fn get_app_by_index(&mut self, index: u32) -> Result<ApplicationInfo, ControllerError> {
523 let app = Rc::new(RefCell::new(Some(None)));
524 let app_ref = app.clone();
525 let op = self.handler.introspect.get_source_output_info(
526 index,
527 move |sink_list: ListResult<&introspect::SourceOutputInfo>| {
528 if let ListResult::Item(item) = sink_list {
529 app_ref.borrow_mut().as_mut().unwrap().replace(item.into());
530 }
531 },
532 );
533 self.handler.wait_for_operation(op)?;
534 let mut result = app.borrow_mut();
535 result
536 .take()
537 .unwrap()
538 .ok_or_else(|| ControllerError::GetInfo("Error getting application list".to_string()))
539 }
540
541 fn increase_app_volume_by_percent(&mut self, index: u32, delta: f64) {
542 if let Ok(mut app_ref) = self.get_app_by_index(index) {
543 let new_vol = Volume(volume_from_percent(delta) as u32);
544 if let Some(volumes) = app_ref.volume.increase(new_vol) {
545 let op = self
546 .handler
547 .introspect
548 .set_source_output_volume(index, volumes, None);
549 self.handler.wait_for_operation(op).ok();
550 }
551 }
552 }
553
554 fn decrease_app_volume_by_percent(&mut self, index: u32, delta: f64) {
555 if let Ok(mut app_ref) = self.get_app_by_index(index) {
556 let new_vol = Volume(volume_from_percent(delta) as u32);
557 if let Some(volumes) = app_ref.volume.decrease(new_vol) {
558 let op = self
559 .handler
560 .introspect
561 .set_source_output_volume(index, volumes, None);
562 self.handler.wait_for_operation(op).ok();
563 }
564 }
565 }
566
567 fn move_app_by_index(
568 &mut self,
569 stream_index: u32,
570 device_index: u32,
571 ) -> Result<bool, ControllerError> {
572 let success = Rc::new(RefCell::new(false));
573 let success_ref = success.clone();
574 let op = self.handler.introspect.move_source_output_by_index(
575 stream_index,
576 device_index,
577 Some(Box::new(move |res| {
578 success_ref.borrow_mut().clone_from(&res)
579 })),
580 );
581 self.handler.wait_for_operation(op)?;
582 let result = *success.borrow_mut();
583 Ok(result)
584 }
585
586 fn move_app_by_name(
587 &mut self,
588 stream_index: u32,
589 device_name: &str,
590 ) -> Result<bool, ControllerError> {
591 let success = Rc::new(RefCell::new(false));
592 let success_ref = success.clone();
593 let op = self.handler.introspect.move_source_output_by_name(
594 stream_index,
595 device_name,
596 Some(Box::new(move |res| {
597 success_ref.borrow_mut().clone_from(&res)
598 })),
599 );
600 self.handler.wait_for_operation(op)?;
601 let result = *success.borrow_mut();
602 Ok(result)
603 }
604
605 fn set_app_mute(&mut self, index: u32, mute: bool) -> Result<bool, ControllerError> {
606 let success = Rc::new(RefCell::new(false));
607 let success_ref = success.clone();
608 let op = self.handler.introspect.set_source_mute_by_index(
609 index,
610 mute,
611 Some(Box::new(move |res| {
612 success_ref.borrow_mut().clone_from(&res)
613 })),
614 );
615 self.handler.wait_for_operation(op)?;
616 let result = *success.borrow_mut();
617 Ok(result)
618 }
619}