From 15ae48210535358ad90dc85c4bc8809a71627d1d Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Fri, 4 Jun 2021 21:48:01 +0200 Subject: Pulse now displays volume correctly. Still missing actual functionality beyond a numeric display, and error cases have not been tested, but hey, it's there! --- pulse/src/runnable/mod.rs | 192 +++++++++++++++++++++++++++------------------- 1 file changed, 112 insertions(+), 80 deletions(-) (limited to 'pulse/src/runnable/mod.rs') diff --git a/pulse/src/runnable/mod.rs b/pulse/src/runnable/mod.rs index 7286c31..352a10a 100644 --- a/pulse/src/runnable/mod.rs +++ b/pulse/src/runnable/mod.rs @@ -31,103 +31,135 @@ impl<'p : 's, 's> PulseVolumeRunnable<'p> { 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."); } + fn send_updated_volume_to_main(&self, volume : &pulse::Volume) -> Result<(),PluginCommunicationError> { + self.to_main.send_update(Ok(self.format_volume(volume))) + } + + fn format_volume(&self, volume : &pulse::Volume) -> String { + format!("{}",volume.volume) + } } impl<'p> SwayStatusModuleRunnable for PulseVolumeRunnable<'p> { fn run(&self) { - 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(); + 'outer : loop { + let pulse = match &self.pulse { + Err(x) => { + self.send_error_to_main(x); + return; + } + Ok(x) => x + }; + let mut scratch = pulse::ContextScratch::default(); + let mut context = match PulseContext::create(pulse, &mut scratch) { + Err(x) => { + self.send_error_to_main(x); + return; + } + Ok(x) => x + }; + 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 as &str) { + Ok(x) => {x} + Err(e) => { + self.send_error_to_main(e); + return; + } + }) } - PaContextState::Failed | PaContextState::Terminated => { - match self.from_main.recv_timeout(std::time::Duration::from_secs(1)) { - Ok(x) => { - if let MessagesFromMain::Quit = x { - break; + }; + loop { + match context.get_state() { + PaContextState::Unconnected => { + if let crate::config::Sink::Default = &self.config.sink { + sink_we_care_about = None; + } + if let Err(e) = context.connect_and_set_callbacks() { + self.send_error_to_main(e); + match self.from_main.recv_timeout(std::time::Duration::from_secs(1)) { + Ok(x) => { + if let MessagesFromMain::Quit = x { + break 'outer; + } + } + Err(e) => { + if let RecvTimeoutError::Disconnected = e { + break 'outer; + } + } } } - Err(e) => { - if let RecvTimeoutError::Disconnected = e { - break; + } + PaContextState::Failed | PaContextState::Terminated => { + //context is dead. Wait a second, and start over. + self.to_main.send_update(Err(PluginError::ShowInsteadOfText(String::from("Context died")))).expect("Tried to tell main thread that pulse context died. Main thread isn't listening."); + self.to_main.send_update(Err(PluginError::PrintToStdErr(String::from("Pulseaudio context entered either the Terminated or Failed state. Creating a new context and retrying")))).expect("Tried to tell main thread that pulse context died. Main thread isn't listening."); + match self.from_main.recv_timeout(std::time::Duration::from_secs(1)) { + Ok(x) => { + if let MessagesFromMain::Quit = x { + break 'outer; + } + } + Err(e) => { + if let RecvTimeoutError::Disconnected = e { + break 'outer; + } } } + continue 'outer; } - if let crate::config::Sink::Default = self.config.sink { - sink_we_care_about = None; + 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(); + } } - context.connect(); + _ => {} + } + + let iteration_result = context.iterate(&sink_we_care_about); + if let Err(e) = iteration_result { + self.send_error_to_main(e); + break 'outer; } - 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 } = iteration_result.unwrap(); + 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.clone(); + if let Some(s) = &sink_we_care_about { + context.refresh_volume(s); + } } } - _ => {} - } - - 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.as_ref().unwrap()).expect("Tried to inform main thread about volume update. Main thread isn't listening."); } - } - 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(); + match self.from_main.try_recv() { + Ok(x) => match x { + MessagesFromMain::Quit => { + break 'outer; + } + MessagesFromMain::Refresh => { + if let Some(s) = &sink_we_care_about { + context.refresh_volume(s); + } + if let crate::config::Sink::Default = self.config.sink { + context.refresh_default_sink(); + } } } - } - Err(e) => { - if let TryRecvError::Disconnected = e { - break; + Err(e) => { + if let TryRecvError::Disconnected = e { + break 'outer; + } } } } -- cgit v1.2.3