librespot/src/main.rs

111 lines
3.2 KiB
Rust
Raw Normal View History

extern crate getopts;
2015-07-09 19:08:56 +00:00
extern crate librespot;
extern crate rpassword;
2015-04-25 20:32:07 +00:00
2016-01-01 23:16:12 +00:00
use getopts::Options;
use rpassword::read_password;
2015-06-23 14:38:29 +00:00
use std::clone::Clone;
use std::fs::File;
use std::io::{stdout, Read, Write};
2016-01-01 23:16:12 +00:00
use std::path::{Path, PathBuf};
use std::thread;
2016-01-01 23:16:12 +00:00
use librespot::discovery::DiscoveryManager;
use librespot::player::Player;
2016-01-02 02:30:24 +00:00
use librespot::session::{Bitrate, Config, Session};
use librespot::spirc::SpircManager;
2016-01-01 23:16:12 +00:00
use librespot::util::version::version_string;
2015-04-25 20:32:07 +00:00
static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
fn usage(program: &str, opts: &Options) -> String {
let brief = format!("Usage: {} [options]", program);
format!("{}", opts.usage(&brief))
}
2015-04-25 20:32:07 +00:00
fn main() {
let args: Vec<String> = std::env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
2016-01-02 02:30:24 +00:00
opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY")
.optopt("u", "username", "Username to sign in with (optional)", "USERNAME")
.optopt("p", "password", "Password (optional)", "PASSWORD")
.reqopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
.reqopt("n", "name", "Device name", "NAME")
.optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE");
let matches = match opts.parse(&args[1..]) {
Ok(m) => { m },
Err(f) => {
print!("Error: {}\n{}", f.to_string(), usage(&*program, &opts));
return;
}
};
2016-01-01 23:16:12 +00:00
let appkey = {
let mut file = File::open(
Path::new(&*matches.opt_str("a").unwrap())
).expect("Could not open app key.");
let mut data = Vec::new();
file.read_to_end(&mut data).unwrap();
data
};
let username = matches.opt_str("u");
let cache_location = matches.opt_str("c").unwrap();
let name = matches.opt_str("n").unwrap();
let credentials = username.map(|u| {
let password = matches.opt_str("p").or_else(|| {
std::env::var(PASSWORD_ENV_NAME).ok()
}).unwrap_or_else(|| {
print!("Password: ");
stdout().flush().unwrap();
read_password().unwrap()
});
(u, password)
});
std::env::remove_var(PASSWORD_ENV_NAME);
2016-01-02 02:30:24 +00:00
let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
None => Bitrate::Bitrate160, // default value
Some("96") => Bitrate::Bitrate96,
Some("160") => Bitrate::Bitrate160,
Some("320") => Bitrate::Bitrate320,
Some(b) => panic!("Invalid bitrate {}", b),
};
let config = Config {
application_key: appkey,
2015-07-01 23:27:19 +00:00
user_agent: version_string(),
2016-01-01 23:16:12 +00:00
device_name: name,
2016-01-02 02:30:24 +00:00
cache_location: PathBuf::from(cache_location),
bitrate: bitrate
};
2015-06-23 14:38:29 +00:00
let session = Session::new(config);
if let Some((username, password)) = credentials {
session.login_password(username, password).unwrap();
} else {
let mut discovery = DiscoveryManager::new(session.clone());
discovery.run();
}
2016-01-01 23:16:12 +00:00
let player = Player::new(session.clone());
let mut spirc = SpircManager::new(session.clone(), player);
2015-09-01 11:20:37 +00:00
thread::spawn(move || {
2016-01-01 23:16:12 +00:00
spirc.run()
});
2016-01-01 23:16:12 +00:00
loop {
session.poll();
}
2015-07-01 17:49:03 +00:00
}