diff --git a/src/main.rs b/src/main.rs index 81153954..9c0410fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,7 @@ fn main() { main_helper::add_session_arguments(&mut opts); main_helper::add_authentication_arguments(&mut opts); main_helper::add_player_arguments(&mut opts); + main_helper::add_program_arguments(&mut opts); let args: Vec = std::env::args().collect(); diff --git a/src/main_helper.rs b/src/main_helper.rs index 99119891..628a6ac6 100644 --- a/src/main_helper.rs +++ b/src/main_helper.rs @@ -54,6 +54,11 @@ pub fn add_player_arguments(opts: &mut getopts::Options) { opts.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE"); } +pub fn add_program_arguments(opts: &mut getopts::Options) { + opts.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM"); + opts.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM"); +} + pub fn create_session(matches: &getopts::Matches) -> Session { info!("librespot {} ({}). Built on {}.", version::short_sha(), @@ -77,10 +82,15 @@ pub fn create_session(matches: &getopts::Matches) -> Session { Box::new(DefaultCache::new(PathBuf::from(cache_location)).unwrap()) as Box }).unwrap_or_else(|| Box::new(NoCache) as Box); + let onstart = matches.opt_str("onstart"); + let onstop = matches.opt_str("onstop"); + let config = Config { user_agent: version::version_string(), device_name: name, bitrate: bitrate, + onstart: onstart, + onstop: onstop, }; Session::new(config, cache) diff --git a/src/player.rs b/src/player.rs index 383e1b57..7648fd7c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -212,6 +212,20 @@ fn load_track(session: &Session, track_id: SpotifyId) -> Option util::run_program(program), + None => {}, + }; +} + +fn run_onstop(session: &Session) { + match session.config().onstop { + Some(ref program) => util::run_program(program), + None => {}, + }; +} + impl PlayerInternal { fn run(self, mut sink: Box) { let mut decoder = None; @@ -229,6 +243,7 @@ impl PlayerInternal { self.update(|state| { if state.status == PlayStatus::kPlayStatusPlay { sink.stop().unwrap(); + run_onstop(&self.session); } state.end_of_track = false; state.status = PlayStatus::kPlayStatusPause; @@ -245,6 +260,7 @@ impl PlayerInternal { self.update(|state| { state.status = if play { + run_onstart(&self.session); sink.start().unwrap(); PlayStatus::kPlayStatusPlay } else { @@ -301,6 +317,7 @@ impl PlayerInternal { true }); + run_onstart(&self.session); sink.start().unwrap(); } Some(PlayerCommand::Pause) => { @@ -313,6 +330,7 @@ impl PlayerInternal { }); sink.stop().unwrap(); + run_onstop(&self.session); } Some(PlayerCommand::Volume(vol)) => { self.update(|state| { @@ -331,6 +349,7 @@ impl PlayerInternal { }); sink.stop().unwrap(); + run_onstop(&self.session); decoder = None; } None => (), @@ -362,6 +381,7 @@ impl PlayerInternal { }); sink.stop().unwrap(); + run_onstop(&self.session); decoder = None; } } diff --git a/src/session.rs b/src/session.rs index ac46cd00..097df7e8 100644 --- a/src/session.rs +++ b/src/session.rs @@ -39,6 +39,8 @@ pub struct Config { pub user_agent: String, pub device_name: String, pub bitrate: Bitrate, + pub onstart: Option, + pub onstop: Option, } pub struct SessionData { diff --git a/src/util/mod.rs b/src/util/mod.rs index 933e481e..0683f6a0 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -4,6 +4,7 @@ use std::io; use std::ops::{Mul, Rem, Shr}; use std::fs; use std::path::Path; +use std::process::Command; use std::time::{UNIX_EPOCH, SystemTime}; mod int128; @@ -51,6 +52,16 @@ pub fn mkdir_existing(path: &Path) -> io::Result<()> { }) } +pub fn run_program(program: &String) { + info!("Running {}", program); + let mut v: Vec<&str> = program.split_whitespace().collect(); + let status = Command::new(&v.remove(0)) + .args(&v) + .status() + .expect("program failed to start"); + info!("Exit status: {}", status); +} + pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint { let mut base = base.clone(); let mut exp = exp.clone();