aboutsummaryrefslogtreecommitdiff
path: root/pulse/src/runnable/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'pulse/src/runnable/mod.rs')
-rw-r--r--pulse/src/runnable/mod.rs106
1 files changed, 104 insertions, 2 deletions
diff --git a/pulse/src/runnable/mod.rs b/pulse/src/runnable/mod.rs
index 149e994..7286c31 100644
--- a/pulse/src/runnable/mod.rs
+++ b/pulse/src/runnable/mod.rs
@@ -2,9 +2,10 @@ use std::sync::mpsc::*;
use crate::config::*;
use swaystatus_plugin::*;
use crate::communication::*;
+use std::convert::TryFrom;
pub mod pulse;
-use pulse::{Pulse,MainLoopCreationError};
+use pulse::{Pulse,MainLoopCreationError, PulseContext, PaContextState, SinkHandle};
pub struct PulseVolumeRunnable<'p> {
config : &'p PulseVolumeConfig,
@@ -25,10 +26,111 @@ impl<'p : 's, 's> PulseVolumeRunnable<'p> {
let sender = SenderForMain::new(s, result.pulse.as_ref().map_or(None,|x| Some(x.get_wake_up())));
(result, sender)
}
+ fn send_error_to_main<E>(&self, err : E) where E : std::error::Error {
+ self.to_main.send_update(Err(PluginError::ShowInsteadOfText(String::from("Error")))).expect("Tried to tell main thread that an error occured. Main thread isn't listening any more.");
+ self.to_main.send_update(Err(PluginError::PrintToStdErr(err.to_string()))).expect("Tried to tell main thread that an error occured. Main thread isn't listening any more.");
+ }
+
}
impl<'p> SwayStatusModuleRunnable for PulseVolumeRunnable<'p> {
fn run(&self) {
- //TODO
+ let pulse = match &self.pulse {
+ Err(x) => {
+ self.send_error_to_main(x);
+ return;
+ }
+ Ok(x) => x
+ };
+ let context = match PulseContext::create(pulse) {
+ Err(x) => {
+ self.send_error_to_main(x);
+ return;
+ }
+ Ok(x) => x
+ };
+ let mut context_state = PaContextState::Unconnected;
+ let mut curr_default_sink = None;
+ let mut curr_volume = None;
+ let mut sink_we_care_about = match self.config.sink {
+ crate::config::Sink::Default => { None }
+ crate::config::Sink::Specific { sink_name } => {
+ Some(match SinkHandle::try_from(&*sink_name) {
+ Ok(x) => {x}
+ Err(e) => {
+ self.send_error_to_main(e);
+ return;
+ }
+ })
+ }
+ };
+ loop {
+ match context_state {
+ PaContextState::Unconnected => {
+ if let crate::config::Sink::Default = self.config.sink {
+ sink_we_care_about = None;
+ }
+ context.connect();
+ }
+ PaContextState::Failed | PaContextState::Terminated => {
+ match self.from_main.recv_timeout(std::time::Duration::from_secs(1)) {
+ Ok(x) => {
+ if let MessagesFromMain::Quit = x {
+ break;
+ }
+ }
+ Err(e) => {
+ if let RecvTimeoutError::Disconnected = e {
+ break;
+ }
+ }
+ }
+ if let crate::config::Sink::Default = self.config.sink {
+ sink_we_care_about = None;
+ }
+ context.connect();
+ }
+ PaContextState::Ready => {
+ if sink_we_care_about.is_none() {
+ //this may trigger several redundant refreshes, but it _should_ only happen
+ //during startup, so we don't really care.
+ context.refresh_default_sink();
+ }
+ }
+ _ => {}
+ }
+
+ let Pulse::IterationResult { default_sink, volume, state } = context.iterate(sink_we_care_about);
+ context_state = state.unwrap_or(context_state);
+ if default_sink.is_some() && default_sink != curr_default_sink {
+ curr_default_sink = default_sink;
+ if let crate::config::Sink::Default = self.config.sink {
+ sink_we_care_about = curr_default_sink;
+ context.refresh_volume();
+ }
+ }
+ if volume.is_some() && volume != curr_volume {
+ curr_volume = volume;
+ self.send_updated_volume_to_main(curr_volume);
+ }
+ match self.from_main.try_recv() {
+ Ok(x) => match x {
+ MessagesFromMain::Quit => {
+ break;
+ }
+ MessagesFromMain::Refresh => {
+ context.refresh_volume();
+ if let crate::config::Sink::Default = self.config.sink {
+ context.refresh_default_sink();
+ }
+ }
+ }
+ Err(e) => {
+ if let TryRecvError::Disconnected = e {
+ break;
+ }
+ }
+ }
+ }
}
}