123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- extern crate getopts;
- extern crate librespot;
- extern crate rpassword;
- use getopts::Options;
- use rpassword::read_password;
- use std::clone::Clone;
- use std::fs::File;
- use std::io::{stdout, Read, Write};
- use std::path::{Path, PathBuf};
- use std::thread;
- use librespot::discovery::DiscoveryManager;
- use librespot::player::Player;
- use librespot::session::{Bitrate, Config, Session};
- use librespot::spirc::SpircManager;
- use librespot::util::version::version_string;
- 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))
- }
- fn main() {
- let args: Vec<String> = std::env::args().collect();
- let program = args[0].clone();
- let mut opts = Options::new();
- 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;
- }
- };
- 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);
- let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
- None => Bitrate::Bitrate160,
- Some("96") => Bitrate::Bitrate96,
- Some("160") => Bitrate::Bitrate160,
- Some("320") => Bitrate::Bitrate320,
- Some(b) => panic!("Invalid bitrate {}", b),
- };
- let config = Config {
- application_key: appkey,
- user_agent: version_string(),
- device_name: name,
- cache_location: PathBuf::from(cache_location),
- bitrate: bitrate,
- };
- 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();
- }
- let player = Player::new(session.clone());
- let mut spirc = SpircManager::new(session.clone(), player);
- thread::spawn(move || spirc.run());
- loop {
- session.poll();
- }
- }
|