Get rid of main_helper

This commit is contained in:
Paul Lietar 2017-01-10 16:31:12 +00:00
parent ae7c177823
commit aa499e0189
5 changed files with 123 additions and 138 deletions

View file

@ -86,3 +86,11 @@ declare_backends! {
("pipe", &mk_sink::<StdoutSink>), ("pipe", &mk_sink::<StdoutSink>),
]; ];
} }
pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<&'static (Fn(Option<&str>) -> Box<Sink> + Send + Sync)> {
if let Some(name) = name.as_ref().map(AsRef::as_ref) {
BACKENDS.iter().find(|backend| name == backend.0).map(|backend| backend.1)
} else {
Some(BACKENDS.first().expect("No backends were enabled at build time").1)
}
}

View file

@ -14,7 +14,6 @@
extern crate bit_set; extern crate bit_set;
extern crate byteorder; extern crate byteorder;
extern crate crypto; extern crate crypto;
extern crate env_logger;
extern crate eventual; extern crate eventual;
extern crate getopts; extern crate getopts;
extern crate hyper; extern crate hyper;
@ -56,7 +55,6 @@ pub mod cache;
pub mod connection; pub mod connection;
pub mod diffie_hellman; pub mod diffie_hellman;
pub mod link; pub mod link;
pub mod main_helper;
pub mod metadata; pub mod metadata;
pub mod player; pub mod player;
pub mod stream; pub mod stream;

View file

@ -1,27 +1,76 @@
#[macro_use] extern crate log;
extern crate getopts; extern crate getopts;
extern crate librespot; extern crate librespot;
extern crate ctrlc; extern crate ctrlc;
extern crate env_logger;
use env_logger::LogBuilder;
use std::io::{stderr, Write}; use std::io::{stderr, Write};
use std::process::exit; use std::process::exit;
use std::thread; use std::thread;
use std::env;
use std::path::PathBuf;
use std::str::FromStr;
use librespot::spirc::SpircManager; use librespot::spirc::SpircManager;
use librespot::main_helper;
use librespot::authentication::get_credentials; use librespot::authentication::get_credentials;
use librespot::audio_backend::{self, BACKENDS};
use librespot::cache::{Cache, DefaultCache, NoCache};
use librespot::player::Player;
use librespot::session::{Bitrate, Config, Session};
use librespot::version;
fn usage(program: &str, opts: &getopts::Options) -> String { fn usage(program: &str, opts: &getopts::Options) -> String {
let brief = format!("Usage: {} [options]", program); let brief = format!("Usage: {} [options]", program);
format!("{}", opts.usage(&brief)) format!("{}", opts.usage(&brief))
} }
fn main() { fn setup_logging(verbose: bool) {
let mut opts = getopts::Options::new(); let mut builder = LogBuilder::new();
main_helper::add_session_arguments(&mut opts);
main_helper::add_authentication_arguments(&mut opts);
main_helper::add_player_arguments(&mut opts);
let args: Vec<String> = std::env::args().collect(); match env::var("RUST_LOG") {
Ok(config) => {
builder.parse(&config);
builder.init().unwrap();
if verbose {
warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
}
}
Err(_) => {
if verbose {
builder.parse("mdns=info,librespot=trace");
} else {
builder.parse("mdns=info,librespot=info");
}
builder.init().unwrap();
}
}
}
fn list_backends() {
println!("Available Backends : ");
for (&(name, _), idx) in BACKENDS.iter().zip(0..) {
if idx == 0 {
println!("- {} (default)", name);
} else {
println!("- {}", name);
}
}
}
fn setup(args: &[String]) -> (Session, Player) {
let mut opts = getopts::Options::new();
opts.optopt("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")
.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
.optflag("v", "verbose", "Enable verbose output")
.optopt("u", "username", "Username to sign in with", "USERNAME")
.optopt("p", "password", "Password", "PASSWORD")
.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE");
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => m, Ok(m) => m,
@ -31,14 +80,57 @@ fn main() {
} }
}; };
main_helper::setup_logging(&matches); let verbose = matches.opt_present("verbose");
setup_logging(verbose);
info!("librespot {} ({}). Built on {}.",
version::short_sha(),
version::commit_date(),
version::short_now());
let backend_name = matches.opt_str("backend");
if backend_name == Some("?".into()) {
list_backends();
exit(0);
}
let backend = audio_backend::find(backend_name.as_ref())
.expect("Invalid backend");
let bitrate = matches.opt_str("b").as_ref()
.map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
.unwrap_or(Bitrate::Bitrate160);
let config = Config {
user_agent: version::version_string(),
device_name: matches.opt_str("name").unwrap(),
bitrate: bitrate,
onstart: matches.opt_str("onstart"),
onstop: matches.opt_str("onstop"),
};
let cache = matches.opt_str("c").map(|cache_location| {
Box::new(DefaultCache::new(PathBuf::from(cache_location)).unwrap())
as Box<Cache + Send + Sync>
}).unwrap_or_else(|| Box::new(NoCache));
let session = Session::new(config, cache);
let session = main_helper::create_session(&matches);
let credentials = get_credentials(&session, matches.opt_str("username"), let credentials = get_credentials(&session, matches.opt_str("username"),
matches.opt_str("password")); matches.opt_str("password"));
session.login(credentials).unwrap(); session.login(credentials).unwrap();
let player = main_helper::create_player(&session, &matches); let device_name = matches.opt_str("device");
let player = Player::new(session.clone(), move || {
(backend)(device_name.as_ref().map(AsRef::as_ref))
});
(session, player)
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let (session, player) = setup(&args);
let spirc = SpircManager::new(session.clone(), player); let spirc = SpircManager::new(session.clone(), player);
let spirc_signal = spirc.clone(); let spirc_signal = spirc.clone();

View file

@ -1,125 +0,0 @@
use env_logger::LogBuilder;
use getopts;
use std::env;
use std::path::PathBuf;
use std::process::exit;
use audio_backend::{BACKENDS, Sink};
use cache::{Cache, DefaultCache, NoCache};
use player::Player;
use session::{Bitrate, Config, Session};
use version;
pub fn find_backend(name: Option<&str>) -> &'static (Fn(Option<&str>) -> Box<Sink> + Send + Sync) {
match name {
Some("?") => {
println!("Available Backends : ");
for (&(name, _), idx) in BACKENDS.iter().zip(0..) {
if idx == 0 {
println!("- {} (default)", name);
} else {
println!("- {}", name);
}
}
exit(0);
},
Some(name) => {
BACKENDS.iter().find(|backend| name == backend.0).expect("Unknown backend").1
},
None => {
BACKENDS.first().expect("No backends were enabled at build time").1
}
}
}
pub fn add_session_arguments(opts: &mut getopts::Options) {
opts.optopt("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")
.optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
.optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
.optflag("v", "verbose", "Enable verbose output");
}
pub fn add_authentication_arguments(opts: &mut getopts::Options) {
opts.optopt("u", "username", "Username to sign in with", "USERNAME")
.optopt("p", "password", "Password", "PASSWORD");
}
pub fn add_player_arguments(opts: &mut getopts::Options) {
opts.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE");
}
pub fn create_session(matches: &getopts::Matches) -> Session {
info!("librespot {} ({}). Built on {}.",
version::short_sha(),
version::commit_date(),
version::short_now());
let name = matches.opt_str("n").unwrap();
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) => {
error!("Invalid bitrate {}", b);
exit(1)
}
};
let cache = matches.opt_str("c").map(|cache_location| {
Box::new(DefaultCache::new(PathBuf::from(cache_location)).unwrap()) as Box<Cache + Send + Sync>
}).unwrap_or_else(|| Box::new(NoCache) as Box<Cache + Send + Sync>);
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)
}
pub fn create_player(session: &Session, matches: &getopts::Matches) -> Player {
let backend_name = matches.opt_str("backend");
let device_name = matches.opt_str("device");
let make_backend = find_backend(backend_name.as_ref().map(AsRef::as_ref));
Player::new(session.clone(), move || {
make_backend(device_name.as_ref().map(AsRef::as_ref))
})
}
pub fn setup_logging(matches: &getopts::Matches) {
let verbose = matches.opt_present("verbose");
let mut builder = LogBuilder::new();
match env::var("RUST_LOG") {
Ok(config) => {
builder.parse(&config);
builder.init().unwrap();
if verbose {
warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
}
}
Err(_) => {
if verbose {
builder.parse("mdns=info,librespot=trace");
} else {
builder.parse("mdns=info,librespot=info");
}
builder.init().unwrap();
}
}
}

View file

@ -10,6 +10,7 @@ use rand::thread_rng;
use std::io::{Read, Write, Cursor}; use std::io::{Read, Write, Cursor};
use std::result::Result; use std::result::Result;
use std::sync::{Mutex, RwLock, Arc, mpsc}; use std::sync::{Mutex, RwLock, Arc, mpsc};
use std::str::FromStr;
use album_cover::AlbumCover; use album_cover::AlbumCover;
use apresolve::apresolve; use apresolve::apresolve;
@ -34,6 +35,17 @@ pub enum Bitrate {
Bitrate160, Bitrate160,
Bitrate320, Bitrate320,
} }
impl FromStr for Bitrate {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"96" => Ok(Bitrate::Bitrate96),
"160" => Ok(Bitrate::Bitrate160),
"320" => Ok(Bitrate::Bitrate320),
_ => Err(s.into()),
}
}
}
pub struct Config { pub struct Config {
pub user_agent: String, pub user_agent: String,