Use single program on events, and pass events in envars.

This commit is contained in:
Simon Persson 2018-02-20 22:45:14 +01:00
parent 081a282e12
commit 2eb4aa61d3
2 changed files with 28 additions and 40 deletions

View file

@ -95,9 +95,7 @@ fn setup(args: &[String]) -> Setup {
.reqopt("n", "name", "Device name", "NAME")
.optopt("", "device-type", "Displayed device type", "DEVICE_TYPE")
.optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE")
.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
.optopt("", "onchange", "Run PROGRAM between two tracks.", "PROGRAM")
.optopt("", "onevent", "Run PROGRAM when playback is about to begin.", "PROGRAM")
.optflag("v", "verbose", "Enable verbose output")
.optopt("u", "username", "Username to sign in with", "USERNAME")
.optopt("p", "password", "Password", "PASSWORD")
@ -189,9 +187,7 @@ fn setup(args: &[String]) -> Setup {
PlayerConfig {
bitrate: bitrate,
event_sender: run_program_on_events(matches.opt_str("onstart"),
matches.opt_str("onstop"),
matches.opt_str("onchange"))
event_sender: matches.opt_str("onevent").map(run_program_on_events)
}
};

View file

@ -1,50 +1,42 @@
use std::process::Command;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::collections::HashMap;
use librespot::playback::player::PlayerEvent;
fn run_program(program: &str, args: Vec<String>) {
info!("Running {}", program);
fn run_program(program: &str, env_vars: HashMap<&str, String>) {
let mut v: Vec<&str> = program.split_whitespace().collect();
info!("Running {:?}", v);
let status = Command::new(&v.remove(0))
.args(&v)
.args(args)
.envs(env_vars.iter())
.status()
.expect("program failed to start");
info!("Exit status: {}", status);
}
pub fn run_program_on_events(onstart: Option<String>,
onstop: Option<String>,
onchange: Option<String>) -> Option<Sender<PlayerEvent>> {
if onstart.is_none() && onstop.is_none() && onchange.is_none() {
None
} else {
let (sender, receiver) = channel();
thread::spawn(move || {
while let Ok(msg) = receiver.recv() {
match msg {
PlayerEvent::Changed { old_track_id, new_track_id } => {
let args = vec![old_track_id.to_base16(), new_track_id.to_base16()];
if let Some(ref onchange) = onchange.as_ref() {
run_program(onchange, args);
}
},
PlayerEvent::Started { track_id } => {
let args = vec![track_id.to_base16()];
if let Some(ref onstart) = onstart.as_ref() {
run_program(onstart, args);
}
}
PlayerEvent::Stopped { track_id } => {
let args = vec![track_id.to_base16()];
if let Some(ref onstop) = onstop.as_ref() {
run_program(onstop, args);
}
}
pub fn run_program_on_events(onevent: String) -> Sender<PlayerEvent> {
let (sender, receiver) = channel();
thread::spawn(move || {
while let Ok(msg) = receiver.recv() {
let mut env_vars = HashMap::new();
match msg {
PlayerEvent::Changed { old_track_id, new_track_id } => {
env_vars.insert("PLAYER_EVENT", "change".to_string());
env_vars.insert("OLD_TRACK_ID", old_track_id.to_base16());
env_vars.insert("TRACK_ID", new_track_id.to_base16());
},
PlayerEvent::Started { track_id } => {
env_vars.insert("PLAYER_EVENT", "start".to_string());
env_vars.insert("TRACK_ID", track_id.to_base16());
}
PlayerEvent::Stopped { track_id } => {
env_vars.insert("PLAYER_EVENT", "stop".to_string());
env_vars.insert("TRACK_ID", track_id.to_base16());
}
}
});
Some(sender)
}
run_program(&onevent, env_vars);
}
});
sender
}