mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Get rid of main_helper
This commit is contained in:
parent
ae7c177823
commit
aa499e0189
5 changed files with 123 additions and 138 deletions
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
114
src/main.rs
114
src/main.rs
|
@ -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();
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue