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