diff --git a/src/child_wait_future.rs b/src/child_wait_future.rs new file mode 100644 index 00000000..8a05c677 --- /dev/null +++ b/src/child_wait_future.rs @@ -0,0 +1,21 @@ +use futures::{Async, Future}; +use std::io; +use std::process::{Child, ExitStatus}; + +/// A future that resolves to a child process's exit status once it exits. +pub struct ChildWaitFuture { + pub child: Child, +} + +impl Future for ChildWaitFuture { + type Item = ExitStatus; + type Error = io::Error; + + fn poll(&mut self) -> Result, Self::Error> { + match self.child.try_wait() { + Ok(Some(status)) => Ok(Async::Ready(status)), + Ok(None) => Ok(Async::NotReady), + Err(e) => Err(e), + } + } +} diff --git a/src/main.rs b/src/main.rs index a18d7b5c..8e5442eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,9 @@ use librespot::playback::config::{Bitrate, PlayerConfig}; use librespot::playback::mixer::{self, Mixer}; use librespot::playback::player::{Player, PlayerEvent}; +mod child_wait_future; +use child_wait_future::ChildWaitFuture; + mod player_event_handler; use player_event_handler::run_program_on_events; @@ -466,7 +469,16 @@ impl Future for Main { if let Some(ref mut player_event_channel) = self.player_event_channel { if let Async::Ready(Some(event)) = player_event_channel.poll().unwrap() { if let Some(ref program) = self.player_event_program { - run_program_on_events(event, program); + let child = run_program_on_events(event, program) + .expect("program failed to start"); + + let wait_future = ChildWaitFuture { child } + .map(|status| if !status.success() { + error!("child exited with status {:?}", status.code()); + }) + .map_err(|e| error!("failed to wait on child process: {}", e)); + + self.handle.spawn(wait_future); } } } diff --git a/src/player_event_handler.rs b/src/player_event_handler.rs index b6a653dd..1d72d182 100644 --- a/src/player_event_handler.rs +++ b/src/player_event_handler.rs @@ -1,18 +1,18 @@ use librespot::playback::player::PlayerEvent; use std::collections::HashMap; -use std::process::Command; +use std::io; +use std::process::{Child, Command}; -fn run_program(program: &str, env_vars: HashMap<&str, String>) { +fn run_program(program: &str, env_vars: HashMap<&str, String>) -> io::Result { let mut v: Vec<&str> = program.split_whitespace().collect(); info!("Running {:?} with environment variables {:?}", v, env_vars); Command::new(&v.remove(0)) .args(&v) .envs(env_vars.iter()) .spawn() - .expect("program failed to start"); } -pub fn run_program_on_events(event: PlayerEvent, onevent: &str) { +pub fn run_program_on_events(event: PlayerEvent, onevent: &str) -> io::Result { let mut env_vars = HashMap::new(); match event { PlayerEvent::Changed { @@ -32,5 +32,5 @@ pub fn run_program_on_events(event: PlayerEvent, onevent: &str) { env_vars.insert("TRACK_ID", track_id.to_base16()); } } - run_program(onevent, env_vars); + run_program(onevent, env_vars) }