main.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. extern crate getopts;
  2. extern crate librespot;
  3. extern crate rpassword;
  4. use getopts::Options;
  5. use rpassword::read_password;
  6. use std::clone::Clone;
  7. use std::fs::File;
  8. use std::io::{stdout, Read, Write};
  9. use std::path::{Path, PathBuf};
  10. use std::thread;
  11. use librespot::discovery::DiscoveryManager;
  12. use librespot::player::Player;
  13. use librespot::session::{Bitrate, Config, Session};
  14. use librespot::spirc::SpircManager;
  15. use librespot::util::version::version_string;
  16. static PASSWORD_ENV_NAME: &'static str = "SPOTIFY_PASSWORD";
  17. fn usage(program: &str, opts: &Options) -> String {
  18. let brief = format!("Usage: {} [options]", program);
  19. format!("{}", opts.usage(&brief))
  20. }
  21. fn main() {
  22. let args: Vec<String> = std::env::args().collect();
  23. let program = args[0].clone();
  24. let mut opts = Options::new();
  25. opts.reqopt("a", "appkey", "Path to a spotify appkey", "APPKEY")
  26. .optopt("u", "username", "Username to sign in with (optional)", "USERNAME")
  27. .optopt("p", "password", "Password (optional)", "PASSWORD")
  28. .reqopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
  29. .reqopt("n", "name", "Device name", "NAME")
  30. .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE");
  31. let matches = match opts.parse(&args[1..]) {
  32. Ok(m) => m,
  33. Err(f) => {
  34. print!("Error: {}\n{}", f.to_string(), usage(&*program, &opts));
  35. return;
  36. }
  37. };
  38. let appkey = {
  39. let mut file = File::open(Path::new(&*matches.opt_str("a").unwrap()))
  40. .expect("Could not open app key.");
  41. let mut data = Vec::new();
  42. file.read_to_end(&mut data).unwrap();
  43. data
  44. };
  45. let username = matches.opt_str("u");
  46. let cache_location = matches.opt_str("c").unwrap();
  47. let name = matches.opt_str("n").unwrap();
  48. let credentials = username.map(|u| {
  49. let password = matches.opt_str("p")
  50. .or_else(|| std::env::var(PASSWORD_ENV_NAME).ok())
  51. .unwrap_or_else(|| {
  52. print!("Password: ");
  53. stdout().flush().unwrap();
  54. read_password().unwrap()
  55. });
  56. (u, password)
  57. });
  58. std::env::remove_var(PASSWORD_ENV_NAME);
  59. let bitrate = match matches.opt_str("b").as_ref().map(String::as_ref) {
  60. None => Bitrate::Bitrate160, // default value
  61. Some("96") => Bitrate::Bitrate96,
  62. Some("160") => Bitrate::Bitrate160,
  63. Some("320") => Bitrate::Bitrate320,
  64. Some(b) => panic!("Invalid bitrate {}", b),
  65. };
  66. let config = Config {
  67. application_key: appkey,
  68. user_agent: version_string(),
  69. device_name: name,
  70. cache_location: PathBuf::from(cache_location),
  71. bitrate: bitrate,
  72. };
  73. let session = Session::new(config);
  74. if let Some((username, password)) = credentials {
  75. session.login_password(username, password).unwrap();
  76. } else {
  77. let mut discovery = DiscoveryManager::new(session.clone());
  78. discovery.run();
  79. }
  80. let player = Player::new(session.clone());
  81. let mut spirc = SpircManager::new(session.clone(), player);
  82. thread::spawn(move || spirc.run());
  83. loop {
  84. session.poll();
  85. }
  86. }