Quellcode durchsuchen

Merge pull request #423 from marcelbuesing/rust-2018

Migrate to rust 2018 edition
Sasha Hilton vor 4 Jahren
Ursprung
Commit
01be8e7efa
55 geänderte Dateien mit 448 neuen und 324 gelöschten Zeilen
  1. 2 0
      .travis.yml
  2. 1 0
      Cargo.toml
  3. 1 0
      audio/Cargo.toml
  4. 5 8
      audio/src/decrypt.rs
  5. 43 19
      audio/src/fetch.rs
  6. 1 1
      audio/src/lib.rs
  7. 2 2
      audio/src/libvorbis_decoder.rs
  8. 13 4
      audio/src/range_set.rs
  9. 1 0
      connect/Cargo.toml
  10. 2 2
      connect/src/context.rs
  11. 28 27
      connect/src/discovery.rs
  12. 2 2
      connect/src/lib.rs
  13. 44 22
      connect/src/spirc.rs
  14. 1 0
      core/Cargo.toml
  15. 10 9
      core/src/apresolve.rs
  16. 7 3
      core/src/audio_key.rs
  17. 16 15
      core/src/authentication.rs
  18. 4 4
      core/src/cache.rs
  19. 1 1
      core/src/channel.rs
  20. 1 1
      core/src/config.rs
  21. 2 1
      core/src/connection/codec.rs
  22. 14 12
      core/src/connection/handshake.rs
  23. 28 18
      core/src/connection/mod.rs
  24. 13 8
      core/src/diffie_hellman.rs
  25. 3 3
      core/src/keymaster.rs
  26. 4 4
      core/src/lib.rs
  27. 4 3
      core/src/mercury/mod.rs
  28. 3 2
      core/src/mercury/types.rs
  29. 5 2
      core/src/proxytunnel.rs
  30. 26 19
      core/src/session.rs
  31. 2 1
      core/src/spotify_id.rs
  32. 4 1
      core/src/util/mod.rs
  33. 3 1
      core/src/volume.rs
  34. 3 4
      examples/play.rs
  35. 6 13
      examples/playlist_tracks.rs
  36. 1 0
      metadata/Cargo.toml
  37. 7 4
      metadata/src/lib.rs
  38. 1 0
      playback/Cargo.toml
  39. 2 1
      playback/src/audio_backend/alsa.rs
  40. 10 5
      playback/src/audio_backend/jackaudio.rs
  41. 4 4
      playback/src/audio_backend/mod.rs
  42. 5 2
      playback/src/audio_backend/pipe.rs
  43. 6 4
      playback/src/audio_backend/portaudio.rs
  44. 5 1
      playback/src/audio_backend/pulseaudio.rs
  45. 9 8
      playback/src/audio_backend/rodio.rs
  46. 9 5
      playback/src/mixer/alsamixer.rs
  47. 9 8
      playback/src/mixer/mod.rs
  48. 1 1
      playback/src/mixer/softmixer.rs
  49. 39 20
      playback/src/player.rs
  50. 1 0
      protocol/Cargo.toml
  51. 9 12
      protocol/build.rs
  52. 1 2
      rustfmt.toml
  53. 0 9
      src/lib.rs
  54. 22 25
      src/main.rs
  55. 2 1
      src/player_event_handler.rs

+ 2 - 0
.travis.yml

@@ -29,12 +29,14 @@ addons:
       - libsdl2-dev
 
 before_script:
+    - rustup component add rustfmt
     - mkdir -p ~/.cargo
     - echo '[target.armv7-unknown-linux-gnueabihf]' > ~/.cargo/config
     - echo 'linker = "arm-linux-gnueabihf-gcc"' >> ~/.cargo/config
     - rustup target add armv7-unknown-linux-gnueabihf
 
 script:
+    - cargo fmt --all -- --check
     - cargo build --locked --no-default-features
     - cargo build --locked --examples
     - cargo build --locked --no-default-features --features "with-tremor"

+ 1 - 0
Cargo.toml

@@ -7,6 +7,7 @@ description = "An open source client library for Spotify, with support for Spoti
 keywords = ["spotify"]
 repository = "https://github.com/librespot-org/librespot"
 readme = "README.md"
+edition = "2018"
 
 [workspace]
 

+ 1 - 0
audio/Cargo.toml

@@ -4,6 +4,7 @@ version = "0.1.0"
 authors = ["Paul Lietar <paul@lietar.net>"]
 description="The audio fetching and processing logic for librespot"
 license="MIT"
+edition = "2018"
 
 [dependencies.librespot-core]
 path = "../core"

+ 5 - 8
audio/src/decrypt.rs

@@ -1,16 +1,13 @@
 use std::io;
 
-use aes_ctr::Aes128Ctr;
-use aes_ctr::stream_cipher::{
-    NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek
-};
 use aes_ctr::stream_cipher::generic_array::GenericArray;
+use aes_ctr::stream_cipher::{NewStreamCipher, SyncStreamCipher, SyncStreamCipherSeek};
+use aes_ctr::Aes128Ctr;
 
 use librespot_core::audio_key::AudioKey;
 
 const AUDIO_AESIV: [u8; 16] = [
-    0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77,
-    0xeb, 0xe8, 0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93,
+    0x72, 0xe0, 0x67, 0xfb, 0xdd, 0xcb, 0xcf, 0x77, 0xeb, 0xe8, 0xbc, 0x64, 0x3f, 0x63, 0x0d, 0x93,
 ];
 
 pub struct AudioDecrypt<T: io::Read> {
@@ -30,7 +27,7 @@ impl<T: io::Read> AudioDecrypt<T> {
 
 impl<T: io::Read> io::Read for AudioDecrypt<T> {
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
-        let len = try!(self.reader.read(output));
+        let len = self.reader.read(output)?;
 
         self.cipher.apply_keystream(&mut output[..len]);
 
@@ -40,7 +37,7 @@ impl<T: io::Read> io::Read for AudioDecrypt<T> {
 
 impl<T: io::Read + io::Seek> io::Seek for AudioDecrypt<T> {
     fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
-        let newpos = try!(self.reader.seek(pos));
+        let newpos = self.reader.seek(pos)?;
 
         self.cipher.seek(newpos);
 

+ 43 - 19
audio/src/fetch.rs

@@ -1,9 +1,9 @@
+use crate::range_set::{Range, RangeSet};
 use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
 use bytes::Bytes;
 use futures::sync::{mpsc, oneshot};
 use futures::Stream;
 use futures::{Async, Future, Poll};
-use range_set::{Range, RangeSet};
 use std::cmp::{max, min};
 use std::fs;
 use std::io::{self, Read, Seek, SeekFrom, Write};
@@ -446,7 +446,7 @@ impl AudioFile {
                     channel_tx: None,
                     stream_shared: None,
                     file_size: file.metadata().unwrap().len() as usize,
-                }
+                };
             }
         }
     }
@@ -514,7 +514,10 @@ impl AudioFileFetchDataReceiver {
         request_length: usize,
         request_sent_time: Instant,
     ) -> AudioFileFetchDataReceiver {
-        let measure_ping_time = shared.number_of_open_requests.load(atomic::Ordering::SeqCst) == 0;
+        let measure_ping_time = shared
+            .number_of_open_requests
+            .load(atomic::Ordering::SeqCst)
+            == 0;
 
         shared
             .number_of_open_requests
@@ -562,7 +565,8 @@ impl Future for AudioFileFetchDataReceiver {
                         if let Some(request_sent_time) = self.request_sent_time {
                             let duration = Instant::now() - request_sent_time;
                             let duration_ms: u64;
-                            if 0.001 * (duration.as_millis() as f64) > MAXIMUM_ASSUMED_PING_TIME_SECONDS
+                            if 0.001 * (duration.as_millis() as f64)
+                                > MAXIMUM_ASSUMED_PING_TIME_SECONDS
                             {
                                 duration_ms = (MAXIMUM_ASSUMED_PING_TIME_SECONDS * 1000.0) as u64;
                             } else {
@@ -714,8 +718,13 @@ impl AudioFileFetch {
         ranges_to_request.subtract_range_set(&download_status.requested);
 
         for range in ranges_to_request.iter() {
-            let (_headers, data) =
-                request_range(&self.session, self.shared.file_id, range.start, range.length).split();
+            let (_headers, data) = request_range(
+                &self.session,
+                self.shared.file_id,
+                range.start,
+                range.length,
+            )
+            .split();
 
             download_status.requested.add_range(range);
 
@@ -749,7 +758,10 @@ impl AudioFileFetch {
             // download data from after the current read position first
             let mut tail_end = RangeSet::new();
             let read_position = self.shared.read_position.load(atomic::Ordering::Relaxed);
-            tail_end.add_range(&Range::new(read_position, self.shared.file_size - read_position));
+            tail_end.add_range(&Range::new(
+                read_position,
+                self.shared.file_size - read_position,
+            ));
             let tail_end = tail_end.intersection(&missing_data);
 
             if !tail_end.is_empty() {
@@ -794,8 +806,9 @@ impl AudioFileFetch {
                     let ping_time_ms: usize = match self.network_response_times_ms.len() {
                         1 => self.network_response_times_ms[0] as usize,
                         2 => {
-                            ((self.network_response_times_ms[0] + self.network_response_times_ms[1]) / 2)
-                                as usize
+                            ((self.network_response_times_ms[0]
+                                + self.network_response_times_ms[1])
+                                / 2) as usize
                         }
                         3 => {
                             let mut times = self.network_response_times_ms.clone();
@@ -863,10 +876,12 @@ impl AudioFileFetch {
                     self.download_range(request.start, request.length);
                 }
                 Ok(Async::Ready(Some(StreamLoaderCommand::RandomAccessMode()))) => {
-                    *(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::RandomAccess();
+                    *(self.shared.download_strategy.lock().unwrap()) =
+                        DownloadStrategy::RandomAccess();
                 }
                 Ok(Async::Ready(Some(StreamLoaderCommand::StreamMode()))) => {
-                    *(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::Streaming();
+                    *(self.shared.download_strategy.lock().unwrap()) =
+                        DownloadStrategy::Streaming();
                 }
                 Ok(Async::Ready(Some(StreamLoaderCommand::Close()))) => {
                     return Ok(Async::Ready(()));
@@ -908,15 +923,20 @@ impl Future for AudioFileFetch {
         }
 
         if let DownloadStrategy::Streaming() = self.get_download_strategy() {
-            let number_of_open_requests =
-                self.shared.number_of_open_requests.load(atomic::Ordering::SeqCst);
+            let number_of_open_requests = self
+                .shared
+                .number_of_open_requests
+                .load(atomic::Ordering::SeqCst);
             let max_requests_to_send =
                 MAX_PREFETCH_REQUESTS - min(MAX_PREFETCH_REQUESTS, number_of_open_requests);
 
             if max_requests_to_send > 0 {
                 let bytes_pending: usize = {
                     let download_status = self.shared.download_status.lock().unwrap();
-                    download_status.requested.minus(&download_status.downloaded).len()
+                    download_status
+                        .requested
+                        .minus(&download_status.downloaded)
+                        .len()
                 };
 
                 let ping_time_seconds =
@@ -924,9 +944,11 @@ impl Future for AudioFileFetch {
                 let download_rate = self.session.channel().get_download_rate_estimate();
 
                 let desired_pending_bytes = max(
-                    (PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * self.shared.stream_data_rate as f64)
+                    (PREFETCH_THRESHOLD_FACTOR
+                        * ping_time_seconds
+                        * self.shared.stream_data_rate as f64) as usize,
+                    (FAST_PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * download_rate as f64)
                         as usize,
-                    (FAST_PREFETCH_THRESHOLD_FACTOR * ping_time_seconds * download_rate as f64) as usize,
                 );
 
                 if bytes_pending < desired_pending_bytes {
@@ -1003,13 +1025,15 @@ impl Read for AudioFileStreaming {
                 .unwrap()
                 .0;
         }
-        let available_length = download_status.downloaded.contained_length_from_value(offset);
+        let available_length = download_status
+            .downloaded
+            .contained_length_from_value(offset);
         assert!(available_length > 0);
         drop(download_status);
 
         self.position = self.read_file.seek(SeekFrom::Start(offset as u64)).unwrap();
         let read_len = min(length, available_length);
-        let read_len = try!(self.read_file.read(&mut output[..read_len]));
+        let read_len = self.read_file.read(&mut output[..read_len])?;
 
         if download_message_printed {
             debug!(
@@ -1031,7 +1055,7 @@ impl Read for AudioFileStreaming {
 
 impl Seek for AudioFileStreaming {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.position = try!(self.read_file.seek(pos));
+        self.position = self.read_file.seek(pos)?;
         // Do not seek past EOF
         self.shared
             .read_position

+ 1 - 1
audio/src/lib.rs

@@ -31,6 +31,6 @@ pub use fetch::{
 };
 
 #[cfg(not(any(feature = "with-tremor", feature = "with-vorbis")))]
-pub use lewton_decoder::{VorbisDecoder, VorbisError, VorbisPacket};
+pub use crate::lewton_decoder::{VorbisDecoder, VorbisError, VorbisPacket};
 #[cfg(any(feature = "with-tremor", feature = "with-vorbis"))]
 pub use libvorbis_decoder::{VorbisDecoder, VorbisError, VorbisPacket};

+ 2 - 2
audio/src/libvorbis_decoder.rs

@@ -77,7 +77,7 @@ impl error::Error for VorbisError {
         error::Error::description(&self.0)
     }
 
-    fn cause(&self) -> Option<&error::Error> {
-        error::Error::cause(&self.0)
+    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+        error::Error::source(&self.0)
     }
 }

+ 13 - 4
audio/src/range_set.rs

@@ -113,7 +113,8 @@ impl RangeSet {
                 // the new range starts after anything we already passed and ends before the next range starts (they don't touch) -> insert it.
                 self.ranges.insert(index, range.clone());
                 return;
-            } else if range.start <= self.ranges[index].end() && self.ranges[index].start <= range.end()
+            } else if range.start <= self.ranges[index].end()
+                && self.ranges[index].start <= range.end()
             {
                 // the new range overlaps (or touches) the first range. They are to be merged.
                 // In addition we might have to merge further ranges in as well.
@@ -161,7 +162,9 @@ impl RangeSet {
             if range.end() <= self.ranges[index].start {
                 // the remaining ranges are past the one to subtract. -> we're done.
                 return;
-            } else if range.start <= self.ranges[index].start && self.ranges[index].start < range.end() {
+            } else if range.start <= self.ranges[index].start
+                && self.ranges[index].start < range.end()
+            {
                 // the range to subtract started before the current range and reaches into the current range
                 // -> we have to remove the beginning of the range or the entire range and do the same for following ranges.
 
@@ -223,8 +226,14 @@ impl RangeSet {
                 other_index += 1;
             } else {
                 // the two intervals overlap. Add the union and advance the index of the one that ends first.
-                let new_start = max(self.ranges[self_index].start, other.ranges[other_index].start);
-                let new_end = min(self.ranges[self_index].end(), other.ranges[other_index].end());
+                let new_start = max(
+                    self.ranges[self_index].start,
+                    other.ranges[other_index].start,
+                );
+                let new_end = min(
+                    self.ranges[self_index].end(),
+                    other.ranges[other_index].end(),
+                );
                 assert!(new_start <= new_end);
                 result.add_range(&Range::new(new_start, new_end - new_start));
                 if self.ranges[self_index].end() <= other.ranges[other_index].end() {

+ 1 - 0
connect/Cargo.toml

@@ -4,6 +4,7 @@ version = "0.1.0"
 authors = ["Paul Lietar <paul@lietar.net>"]
 description="The discovery and Spotify Connect logic for librespot"
 license="MIT"
+edition = "2018"
 
 [dependencies.librespot-core]
 path = "../core"

+ 2 - 2
connect/src/context.rs

@@ -1,5 +1,5 @@
+use crate::protocol::spirc::TrackRef;
 use librespot_core::spotify_id::SpotifyId;
-use protocol::spirc::TrackRef;
 
 use serde;
 
@@ -69,7 +69,7 @@ fn deserialize_protobuf_TrackRef<'d, D>(de: D) -> Result<Vec<TrackRef>, D::Error
 where
     D: serde::Deserializer<'d>,
 {
-    let v: Vec<TrackContext> = try!(serde::Deserialize::deserialize(de));
+    let v: Vec<TrackContext> = serde::Deserialize::deserialize(de)?;
     let track_vec = v
         .iter()
         .map(|v| {

+ 28 - 27
connect/src/discovery.rs

@@ -1,13 +1,13 @@
-use base64;
-use sha1::{Sha1, Digest};
-use hmac::{Hmac, Mac};
-use aes_ctr::Aes128Ctr;
-use aes_ctr::stream_cipher::{NewStreamCipher, SyncStreamCipher};
 use aes_ctr::stream_cipher::generic_array::GenericArray;
+use aes_ctr::stream_cipher::{NewStreamCipher, SyncStreamCipher};
+use aes_ctr::Aes128Ctr;
+use base64;
 use futures::sync::mpsc;
 use futures::{Future, Poll, Stream};
+use hmac::{Hmac, Mac};
 use hyper::server::{Http, Request, Response, Service};
 use hyper::{self, Get, Post, StatusCode};
+use sha1::{Digest, Sha1};
 
 #[cfg(feature = "with-dns-sd")]
 use dns_sd::DNSService;
@@ -114,21 +114,18 @@ impl Discovery {
         let base_key = &base_key[..16];
 
         let checksum_key = {
-            let mut h = HmacSha1::new_varkey(base_key)
-                .expect("HMAC can take key of any size");
+            let mut h = HmacSha1::new_varkey(base_key).expect("HMAC can take key of any size");
             h.input(b"checksum");
             h.result().code()
         };
 
         let encryption_key = {
-            let mut h = HmacSha1::new_varkey(&base_key)
-                .expect("HMAC can take key of any size");
+            let mut h = HmacSha1::new_varkey(&base_key).expect("HMAC can take key of any size");
             h.input(b"encryption");
             h.result().code()
         };
 
-        let mut h = HmacSha1::new_varkey(&checksum_key)
-            .expect("HMAC can take key of any size");
+        let mut h = HmacSha1::new_varkey(&checksum_key).expect("HMAC can take key of any size");
         h.input(encrypted);
         if let Err(_) = h.verify(cksum) {
             warn!("Login error for user {:?}: MAC mismatch", username);
@@ -139,7 +136,7 @@ impl Discovery {
             });
 
             let body = result.to_string();
-            return ::futures::finished(Response::new().with_body(body))
+            return ::futures::finished(Response::new().with_body(body));
         }
 
         let decrypted = {
@@ -152,7 +149,8 @@ impl Discovery {
             String::from_utf8(data).unwrap()
         };
 
-        let credentials = Credentials::with_blob(username.to_owned(), &decrypted, &self.0.device_id);
+        let credentials =
+            Credentials::with_blob(username.to_owned(), &decrypted, &self.0.device_id);
 
         self.0.tx.unbounded_send(credentials).unwrap();
 
@@ -175,7 +173,7 @@ impl Service for Discovery {
     type Request = Request;
     type Response = Response;
     type Error = hyper::Error;
-    type Future = Box<Future<Item = Response, Error = hyper::Error>>;
+    type Future = Box<dyn Future<Item = Response, Error = hyper::Error>>;
 
     fn call(&self, request: Request) -> Self::Future {
         let mut params = BTreeMap::new();
@@ -194,17 +192,18 @@ impl Service for Discovery {
             body.fold(Vec::new(), |mut acc, chunk| {
                 acc.extend_from_slice(chunk.as_ref());
                 Ok::<_, hyper::Error>(acc)
-            }).map(move |body| {
-                    params.extend(url::form_urlencoded::parse(&body).into_owned());
-                    params
-                })
-                .and_then(
-                    move |params| match (method, params.get("action").map(AsRef::as_ref)) {
-                        (Get, Some("getInfo")) => this.handle_get_info(&params),
-                        (Post, Some("addUser")) => this.handle_add_user(&params),
-                        _ => this.not_found(),
-                    },
-                ),
+            })
+            .map(move |body| {
+                params.extend(url::form_urlencoded::parse(&body).into_owned());
+                params
+            })
+            .and_then(move |params| {
+                match (method, params.get("action").map(AsRef::as_ref)) {
+                    (Get, Some("getInfo")) => this.handle_get_info(&params),
+                    (Post, Some("addUser")) => this.handle_add_user(&params),
+                    _ => this.not_found(),
+                }
+            }),
         )
     }
 }
@@ -235,7 +234,8 @@ pub fn discovery(
             &format!("0.0.0.0:{}", port).parse().unwrap(),
             &handle,
             move || Ok(discovery.clone()),
-        ).unwrap()
+        )
+        .unwrap()
     };
 
     let s_port = serve.incoming_ref().local_addr().port();
@@ -260,7 +260,8 @@ pub fn discovery(
         None,
         s_port,
         &["VERSION=1.0", "CPath=/"],
-    ).unwrap();
+    )
+    .unwrap();
 
     #[cfg(not(feature = "with-dns-sd"))]
     let responder = libmdns::Responder::spawn(&handle)?;

+ 2 - 2
connect/src/lib.rs

@@ -15,10 +15,10 @@ extern crate rand;
 extern crate tokio_core;
 extern crate url;
 
-extern crate sha1;
-extern crate hmac;
 extern crate aes_ctr;
 extern crate block_modes;
+extern crate hmac;
+extern crate sha1;
 
 #[cfg(feature = "with-dns-sd")]
 extern crate dns_sd;

+ 44 - 22
connect/src/spirc.rs

@@ -9,7 +9,11 @@ use rand;
 use rand::seq::SliceRandom;
 use serde_json;
 
-use context::StationContext;
+use crate::context::StationContext;
+use crate::playback::mixer::Mixer;
+use crate::playback::player::Player;
+use crate::protocol;
+use crate::protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
 use librespot_core::config::ConnectConfig;
 use librespot_core::mercury::MercuryError;
 use librespot_core::session::Session;
@@ -17,14 +21,10 @@ use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId, SpotifyIdError};
 use librespot_core::util::SeqGenerator;
 use librespot_core::version;
 use librespot_core::volume::Volume;
-use playback::mixer::Mixer;
-use playback::player::Player;
-use protocol;
-use protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
 
 pub struct SpircTask {
     player: Player,
-    mixer: Box<Mixer>,
+    mixer: Box<dyn Mixer>,
     config: SpircTaskConfig,
 
     sequence: SeqGenerator<u32>,
@@ -33,15 +33,15 @@ pub struct SpircTask {
     device: DeviceState,
     state: State,
 
-    subscription: Box<Stream<Item = Frame, Error = MercuryError>>,
-    sender: Box<Sink<SinkItem = Frame, SinkError = MercuryError>>,
+    subscription: Box<dyn Stream<Item = Frame, Error = MercuryError>>,
+    sender: Box<dyn Sink<SinkItem = Frame, SinkError = MercuryError>>,
     commands: mpsc::UnboundedReceiver<SpircCommand>,
-    end_of_track: Box<Future<Item = (), Error = oneshot::Canceled>>,
+    end_of_track: Box<dyn Future<Item = (), Error = oneshot::Canceled>>,
 
     shutdown: bool,
     session: Session,
-    context_fut: Box<Future<Item = serde_json::Value, Error = MercuryError>>,
-    autoplay_fut: Box<Future<Item = String, Error = MercuryError>>,
+    context_fut: Box<dyn Future<Item = serde_json::Value, Error = MercuryError>>,
+    autoplay_fut: Box<dyn Future<Item = String, Error = MercuryError>>,
     context: Option<StationContext>,
 }
 
@@ -221,7 +221,7 @@ impl Spirc {
         config: ConnectConfig,
         session: Session,
         player: Player,
-        mixer: Box<Mixer>,
+        mixer: Box<dyn Mixer>,
     ) -> (Spirc, SpircTask) {
         debug!("new Spirc[{}]", session.session_id());
 
@@ -526,7 +526,8 @@ impl SpircTask {
 
                 if self.state.get_track().len() > 0 {
                     let now = self.now_ms();
-                    self.state.set_position_ms(frame.get_state().get_position_ms());
+                    self.state
+                        .set_position_ms(frame.get_state().get_position_ms());
                     self.state.set_position_measured_at(now as u64);
 
                     let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
@@ -689,7 +690,8 @@ impl SpircTask {
             tracks_len - new_index < CONTEXT_FETCH_THRESHOLD
         );
         let context_uri = self.state.get_context_uri().to_owned();
-        if (context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:"))
+        if (context_uri.starts_with("spotify:station:")
+            || context_uri.starts_with("spotify:dailymix:"))
             && ((self.state.get_track().len() as u32) - new_index) < CONTEXT_FETCH_THRESHOLD
         {
             self.context_fut = self.resolve_station(&context_uri);
@@ -785,18 +787,28 @@ impl SpircTask {
         self.state.get_position_ms() + diff as u32
     }
 
-    fn resolve_station(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
+    fn resolve_station(
+        &self,
+        uri: &str,
+    ) -> Box<dyn Future<Item = serde_json::Value, Error = MercuryError>> {
         let radio_uri = format!("hm://radio-apollo/v3/stations/{}", uri);
 
         self.resolve_uri(&radio_uri)
     }
 
-    fn resolve_autoplay_uri(&self, uri: &str) -> Box<Future<Item = String, Error = MercuryError>> {
+    fn resolve_autoplay_uri(
+        &self,
+        uri: &str,
+    ) -> Box<dyn Future<Item = String, Error = MercuryError>> {
         let query_uri = format!("hm://autoplay-enabled/query?uri={}", uri);
         let request = self.session.mercury().get(query_uri);
         Box::new(request.and_then(move |response| {
             if response.status_code == 200 {
-                let data = response.payload.first().expect("Empty autoplay uri").to_vec();
+                let data = response
+                    .payload
+                    .first()
+                    .expect("Empty autoplay uri")
+                    .to_vec();
                 let autoplay_uri = String::from_utf8(data).unwrap();
                 Ok(autoplay_uri)
             } else {
@@ -806,11 +818,17 @@ impl SpircTask {
         }))
     }
 
-    fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
+    fn resolve_uri(
+        &self,
+        uri: &str,
+    ) -> Box<dyn Future<Item = serde_json::Value, Error = MercuryError>> {
         let request = self.session.mercury().get(uri);
 
         Box::new(request.and_then(move |response| {
-            let data = response.payload.first().expect("Empty payload on context uri");
+            let data = response
+                .payload
+                .first()
+                .expect("Empty payload on context uri");
             let response: serde_json::Value = serde_json::from_slice(&data).unwrap();
 
             Ok(response)
@@ -828,7 +846,8 @@ impl SpircTask {
                 track_vec.drain(0..head);
             }
             track_vec.extend_from_slice(&new_tracks);
-            self.state.set_track(protobuf::RepeatedField::from_vec(track_vec));
+            self.state
+                .set_track(protobuf::RepeatedField::from_vec(track_vec));
 
             // Update playing index
             if let Some(new_index) = self
@@ -849,7 +868,9 @@ impl SpircTask {
         let context_uri = frame.get_state().get_context_uri().to_owned();
         let tracks = frame.get_state().get_track();
         debug!("Frame has {:?} tracks", tracks.len());
-        if context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:") {
+        if context_uri.starts_with("spotify:station:")
+            || context_uri.starts_with("spotify:dailymix:")
+        {
             self.context_fut = self.resolve_station(&context_uri);
         } else if self.config.autoplay {
             info!("Fetching autoplay context uri");
@@ -889,7 +910,8 @@ impl SpircTask {
         let track = {
             let mut track_ref = self.state.get_track()[index as usize].clone();
             let mut track_id = self.get_spotify_id_for_track(&track_ref);
-            while track_id.is_err() || track_id.unwrap().audio_type == SpotifyAudioType::NonPlayable {
+            while track_id.is_err() || track_id.unwrap().audio_type == SpotifyAudioType::NonPlayable
+            {
                 warn!(
                     "Skipping track <{:?}> at position [{}] of {}",
                     track_ref.get_uri(),

+ 1 - 0
core/Cargo.toml

@@ -5,6 +5,7 @@ authors = ["Paul Lietar <paul@lietar.net>"]
 build = "build.rs"
 description="The core functionality provided by librespot"
 license="MIT"
+edition = "2018"
 
 [dependencies.librespot-protocol]
 path = "../protocol"

+ 10 - 9
core/src/apresolve.rs

@@ -10,7 +10,7 @@ use std::str::FromStr;
 use tokio_core::reactor::Handle;
 use url::Url;
 
-error_chain!{}
+error_chain! {}
 
 #[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct APResolveData {
@@ -21,7 +21,7 @@ fn apresolve(
     handle: &Handle,
     proxy: &Option<Url>,
     ap_port: &Option<u16>,
-) -> Box<Future<Item = String, Error = Error>> {
+) -> Box<dyn Future<Item = String, Error = Error>> {
     let url = Uri::from_str(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL");
     let use_proxy = proxy.is_some();
 
@@ -52,19 +52,20 @@ fn apresolve(
         })
     });
     let body = body.then(|result| result.chain_err(|| "HTTP error"));
-    let body = body.and_then(|body| String::from_utf8(body).chain_err(|| "invalid UTF8 in response"));
+    let body =
+        body.and_then(|body| String::from_utf8(body).chain_err(|| "invalid UTF8 in response"));
 
-    let data =
-        body.and_then(|body| serde_json::from_str::<APResolveData>(&body).chain_err(|| "invalid JSON"));
+    let data = body
+        .and_then(|body| serde_json::from_str::<APResolveData>(&body).chain_err(|| "invalid JSON"));
 
     let p = ap_port.clone();
 
     let ap = data.and_then(move |data| {
         let mut aps = data.ap_list.iter().filter(|ap| {
             if p.is_some() {
-                Uri::from_str(ap)
-                    .ok()
-                    .map_or(false, |uri| uri.port().map_or(false, |port| port == p.unwrap()))
+                Uri::from_str(ap).ok().map_or(false, |uri| {
+                    uri.port().map_or(false, |port| port == p.unwrap())
+                })
             } else if use_proxy {
                 // It is unlikely that the proxy will accept CONNECT on anything other than 443.
                 Uri::from_str(ap)
@@ -86,7 +87,7 @@ pub(crate) fn apresolve_or_fallback<E>(
     handle: &Handle,
     proxy: &Option<Url>,
     ap_port: &Option<u16>,
-) -> Box<Future<Item = String, Error = E>>
+) -> Box<dyn Future<Item = String, Error = E>>
 where
     E: 'static,
 {

+ 7 - 3
core/src/audio_key.rs

@@ -5,8 +5,8 @@ use futures::{Async, Future, Poll};
 use std::collections::HashMap;
 use std::io::Write;
 
-use spotify_id::{FileId, SpotifyId};
-use util::SeqGenerator;
+use crate::spotify_id::{FileId, SpotifyId};
+use crate::util::SeqGenerator;
 
 #[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
 pub struct AudioKey(pub [u8; 16]);
@@ -35,7 +35,11 @@ impl AudioKeyManager {
                     let _ = sender.send(Ok(AudioKey(key)));
                 }
                 0xe => {
-                    warn!("error audio key {:x} {:x}", data.as_ref()[0], data.as_ref()[1]);
+                    warn!(
+                        "error audio key {:x} {:x}",
+                        data.as_ref()[0],
+                        data.as_ref()[1]
+                    );
                     let _ = sender.send(Err(AudioKeyError));
                 }
                 _ => (),

+ 16 - 15
core/src/authentication.rs

@@ -1,18 +1,18 @@
+use aes::Aes192;
 use base64;
 use byteorder::{BigEndian, ByteOrder};
-use aes::Aes192;
 use hmac::Hmac;
-use sha1::{Sha1, Digest};
 use pbkdf2::pbkdf2;
 use protobuf::ProtobufEnum;
 use serde;
 use serde_json;
+use sha1::{Digest, Sha1};
 use std::fs::File;
 use std::io::{self, Read, Write};
 use std::ops::FnOnce;
 use std::path::Path;
 
-use protocol::authentication::AuthenticationType;
+use crate::protocol::authentication::AuthenticationType;
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct Credentials {
@@ -40,24 +40,24 @@ impl Credentials {
     pub fn with_blob(username: String, encrypted_blob: &str, device_id: &str) -> Credentials {
         fn read_u8<R: Read>(stream: &mut R) -> io::Result<u8> {
             let mut data = [0u8];
-            try!(stream.read_exact(&mut data));
+            stream.read_exact(&mut data)?;
             Ok(data[0])
         }
 
         fn read_int<R: Read>(stream: &mut R) -> io::Result<u32> {
-            let lo = try!(read_u8(stream)) as u32;
+            let lo = read_u8(stream)? as u32;
             if lo & 0x80 == 0 {
                 return Ok(lo);
             }
 
-            let hi = try!(read_u8(stream)) as u32;
+            let hi = read_u8(stream)? as u32;
             Ok(lo & 0x7f | hi << 7)
         }
 
         fn read_bytes<R: Read>(stream: &mut R) -> io::Result<Vec<u8>> {
-            let length = try!(read_int(stream));
+            let length = read_int(stream)?;
             let mut data = vec![0u8; length as usize];
-            try!(stream.read_exact(&mut data));
+            stream.read_exact(&mut data)?;
 
             Ok(data)
         }
@@ -76,9 +76,9 @@ impl Credentials {
 
         // decrypt data using ECB mode without padding
         let blob = {
-            use aes::block_cipher_trait::BlockCipher;
-            use aes::block_cipher_trait::generic_array::GenericArray;
             use aes::block_cipher_trait::generic_array::typenum::Unsigned;
+            use aes::block_cipher_trait::generic_array::GenericArray;
+            use aes::block_cipher_trait::BlockCipher;
 
             let mut data = base64::decode(encrypted_blob).unwrap();
             let cipher = Aes192::new(GenericArray::from_slice(&key));
@@ -148,7 +148,7 @@ where
     T: ProtobufEnum,
     D: serde::Deserializer<'de>,
 {
-    let v: i32 = try!(serde::Deserialize::deserialize(de));
+    let v: i32 = serde::Deserialize::deserialize(de)?;
     T::from_i32(v).ok_or_else(|| serde::de::Error::custom("Invalid enum value"))
 }
 
@@ -164,7 +164,7 @@ fn deserialize_base64<'de, D>(de: D) -> Result<Vec<u8>, D::Error>
 where
     D: serde::Deserializer<'de>,
 {
-    let v: String = try!(serde::Deserialize::deserialize(de));
+    let v: String = serde::Deserialize::deserialize(de)?;
     base64::decode(&v).map_err(|e| serde::de::Error::custom(e.to_string()))
 }
 
@@ -181,9 +181,10 @@ pub fn get_credentials<F: FnOnce(&String) -> String>(
             Some(credentials.clone())
         }
 
-        (Some(username), None, _) => {
-            Some(Credentials::with_password(username.clone(), prompt(&username)))
-        }
+        (Some(username), None, _) => Some(Credentials::with_password(
+            username.clone(),
+            prompt(&username),
+        )),
 
         (None, _, Some(credentials)) => Some(credentials),
 

+ 4 - 4
core/src/cache.rs

@@ -5,9 +5,9 @@ use std::io::Read;
 use std::path::Path;
 use std::path::PathBuf;
 
-use authentication::Credentials;
-use spotify_id::FileId;
-use volume::Volume;
+use crate::authentication::Credentials;
+use crate::spotify_id::FileId;
+use crate::volume::Volume;
 
 #[derive(Clone)]
 pub struct Cache {
@@ -80,7 +80,7 @@ impl Cache {
         File::open(self.file_path(file)).ok()
     }
 
-    pub fn save_file(&self, file: FileId, contents: &mut Read) {
+    pub fn save_file(&self, file: FileId, contents: &mut dyn Read) {
         if self.use_audio_cache {
             let path = self.file_path(file);
 

+ 1 - 1
core/src/channel.rs

@@ -5,7 +5,7 @@ use futures::{Async, Poll, Stream};
 use std::collections::HashMap;
 use std::time::Instant;
 
-use util::SeqGenerator;
+use crate::util::SeqGenerator;
 
 component! {
     ChannelManager : ChannelManagerInner {

+ 1 - 1
core/src/config.rs

@@ -3,7 +3,7 @@ use std::str::FromStr;
 use url::Url;
 use uuid::Uuid;
 
-use version;
+use crate::version;
 
 #[derive(Clone, Debug)]
 pub struct SessionConfig {

+ 2 - 1
core/src/connection/codec.rs

@@ -88,7 +88,8 @@ impl Decoder for APCodec {
 
                 let mut payload = buf.split_to(size + MAC_SIZE);
 
-                self.decode_cipher.decrypt(&mut payload.get_mut(..size).unwrap());
+                self.decode_cipher
+                    .decrypt(&mut payload.get_mut(..size).unwrap());
                 let mac = payload.split_off(size);
                 self.decode_cipher.check_mac(mac.as_ref())?;
 

+ 14 - 12
core/src/connection/handshake.rs

@@ -1,9 +1,9 @@
 use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
-use hmac::{Hmac, Mac};
-use sha1::Sha1;
 use futures::{Async, Future, Poll};
+use hmac::{Hmac, Mac};
 use protobuf::{self, Message};
 use rand::thread_rng;
+use sha1::Sha1;
 use std::io::{self, Read};
 use std::marker::PhantomData;
 use tokio_codec::{Decoder, Framed};
@@ -11,10 +11,10 @@ use tokio_io::io::{read_exact, write_all, ReadExact, Window, WriteAll};
 use tokio_io::{AsyncRead, AsyncWrite};
 
 use super::codec::APCodec;
-use diffie_hellman::DHLocalKeys;
-use protocol;
-use protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
-use util;
+use crate::diffie_hellman::DHLocalKeys;
+use crate::protocol;
+use crate::protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
+use crate::util;
 
 pub struct Handshake<T> {
     keys: DHLocalKeys,
@@ -62,7 +62,8 @@ impl<T: AsyncRead + AsyncWrite> Future for Handshake<T> {
                         .to_owned();
 
                     let shared_secret = self.keys.shared_secret(&remote_key);
-                    let (challenge, send_key, recv_key) = compute_keys(&shared_secret, &accumulator);
+                    let (challenge, send_key, recv_key) =
+                        compute_keys(&shared_secret, &accumulator);
                     let codec = APCodec::new(&send_key, &recv_key);
 
                     let write = client_response(connection, challenge);
@@ -92,7 +93,10 @@ fn client_hello<T: AsyncWrite>(connection: T, gc: Vec<u8>) -> WriteAll<T, Vec<u8
     packet
         .mut_cryptosuites_supported()
         .push(protocol::keyexchange::Cryptosuite::CRYPTO_SUITE_SHANNON);
-    packet.mut_login_crypto_hello().mut_diffie_hellman().set_gc(gc);
+    packet
+        .mut_login_crypto_hello()
+        .mut_diffie_hellman()
+        .set_gc(gc);
     packet
         .mut_login_crypto_hello()
         .mut_diffie_hellman()
@@ -190,15 +194,13 @@ fn compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<
 
     let mut data = Vec::with_capacity(0x64);
     for i in 1..6 {
-        let mut mac = HmacSha1::new_varkey(&shared_secret)
-            .expect("HMAC can take key of any size");
+        let mut mac = HmacSha1::new_varkey(&shared_secret).expect("HMAC can take key of any size");
         mac.input(packets);
         mac.input(&[i]);
         data.extend_from_slice(&mac.result().code());
     }
 
-    let mut mac = HmacSha1::new_varkey(&data[..0x14])
-        .expect("HMAC can take key of any size");;
+    let mut mac = HmacSha1::new_varkey(&data[..0x14]).expect("HMAC can take key of any size");
     mac.input(packets);
 
     (

+ 28 - 18
core/src/connection/mod.rs

@@ -8,15 +8,15 @@ use futures::{Future, Sink, Stream};
 use protobuf::{self, Message};
 use std::io;
 use std::net::ToSocketAddrs;
+use tokio_codec::Framed;
 use tokio_core::net::TcpStream;
 use tokio_core::reactor::Handle;
-use tokio_codec::Framed;
 use url::Url;
 
-use authentication::Credentials;
-use version;
+use crate::authentication::Credentials;
+use crate::version;
 
-use proxytunnel;
+use crate::proxytunnel;
 
 pub type Transport = Framed<TcpStream, APCodec>;
 
@@ -24,7 +24,7 @@ pub fn connect(
     addr: String,
     handle: &Handle,
     proxy: &Option<Url>,
-) -> Box<Future<Item = Transport, Error = io::Error>> {
+) -> Box<dyn Future<Item = Transport, Error = io::Error>> {
     let (addr, connect_url) = match *proxy {
         Some(ref url) => {
             info!("Using proxy \"{}\"", url);
@@ -48,23 +48,31 @@ pub fn authenticate(
     transport: Transport,
     credentials: Credentials,
     device_id: String,
-) -> Box<Future<Item = (Transport, Credentials), Error = io::Error>> {
-    use protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
-    use protocol::keyexchange::APLoginFailed;
+) -> Box<dyn Future<Item = (Transport, Credentials), Error = io::Error>> {
+    use crate::protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
+    use crate::protocol::keyexchange::APLoginFailed;
 
     let mut packet = ClientResponseEncrypted::new();
-    packet.mut_login_credentials().set_username(credentials.username);
-    packet.mut_login_credentials().set_typ(credentials.auth_type);
+    packet
+        .mut_login_credentials()
+        .set_username(credentials.username);
+    packet
+        .mut_login_credentials()
+        .set_typ(credentials.auth_type);
     packet
         .mut_login_credentials()
         .set_auth_data(credentials.auth_data);
-    packet.mut_system_info().set_cpu_family(CpuFamily::CPU_UNKNOWN);
+    packet
+        .mut_system_info()
+        .set_cpu_family(CpuFamily::CPU_UNKNOWN);
     packet.mut_system_info().set_os(Os::OS_UNKNOWN);
-    packet.mut_system_info().set_system_information_string(format!(
-        "librespot_{}_{}",
-        version::short_sha(),
-        version::build_id()
-    ));
+    packet
+        .mut_system_info()
+        .set_system_information_string(format!(
+            "librespot_{}_{}",
+            version::short_sha(),
+            version::build_id()
+        ));
     packet.mut_system_info().set_device_id(device_id);
     packet.set_version_string(version::version_string());
 
@@ -77,7 +85,8 @@ pub fn authenticate(
             .and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
             .and_then(|(packet, transport)| match packet {
                 Some((0xac, data)) => {
-                    let welcome_data: APWelcome = protobuf::parse_from_bytes(data.as_ref()).unwrap();
+                    let welcome_data: APWelcome =
+                        protobuf::parse_from_bytes(data.as_ref()).unwrap();
 
                     let reusable_credentials = Credentials {
                         username: welcome_data.get_canonical_username().to_owned(),
@@ -89,7 +98,8 @@ pub fn authenticate(
                 }
 
                 Some((0xad, data)) => {
-                    let error_data: APLoginFailed = protobuf::parse_from_bytes(data.as_ref()).unwrap();
+                    let error_data: APLoginFailed =
+                        protobuf::parse_from_bytes(data.as_ref()).unwrap();
                     panic!(
                         "Authentication failed with reason: {:?}",
                         error_data.get_error_code()

+ 13 - 8
core/src/diffie_hellman.rs

@@ -2,17 +2,18 @@ use num_bigint::BigUint;
 use num_traits::FromPrimitive;
 use rand::Rng;
 
-use util;
+use crate::util;
 
 lazy_static! {
     pub static ref DH_GENERATOR: BigUint = BigUint::from_u64(0x2).unwrap();
     pub static ref DH_PRIME: BigUint = BigUint::from_bytes_be(&[
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
-        0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
-        0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
-        0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
-        0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
-        0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2,
+        0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67,
+        0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
+        0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
+        0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5,
+        0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     ]);
 }
 
@@ -39,7 +40,11 @@ impl DHLocalKeys {
     }
 
     pub fn shared_secret(&self, remote_key: &[u8]) -> Vec<u8> {
-        let shared_key = util::powm(&BigUint::from_bytes_be(remote_key), &self.private_key, &DH_PRIME);
+        let shared_key = util::powm(
+            &BigUint::from_bytes_be(remote_key),
+            &self.private_key,
+            &DH_PRIME,
+        );
         shared_key.to_bytes_be()
     }
 }

+ 3 - 3
core/src/keymaster.rs

@@ -1,8 +1,8 @@
 use futures::Future;
 use serde_json;
 
-use mercury::MercuryError;
-use session::Session;
+use crate::mercury::MercuryError;
+use crate::session::Session;
 
 #[derive(Deserialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
@@ -17,7 +17,7 @@ pub fn get_token(
     session: &Session,
     client_id: &str,
     scopes: &str,
-) -> Box<Future<Item = Token, Error = MercuryError>> {
+) -> Box<dyn Future<Item = Token, Error = MercuryError>> {
     let url = format!(
         "hm://keymaster/token/authenticated?client_id={}&scope={}",
         client_id, scopes

+ 4 - 4
core/src/lib.rs

@@ -11,29 +11,29 @@ extern crate log;
 #[macro_use]
 extern crate serde_derive;
 
+extern crate aes;
 extern crate base64;
 extern crate byteorder;
 extern crate bytes;
+extern crate hmac;
 extern crate httparse;
 extern crate hyper;
 extern crate hyper_proxy;
 extern crate num_bigint;
 extern crate num_integer;
 extern crate num_traits;
+extern crate pbkdf2;
 extern crate protobuf;
 extern crate rand;
 extern crate serde;
 extern crate serde_json;
+extern crate sha1;
 extern crate shannon;
 extern crate tokio_codec;
 extern crate tokio_core;
 extern crate tokio_io;
 extern crate url;
 extern crate uuid;
-extern crate sha1;
-extern crate hmac;
-extern crate pbkdf2;
-extern crate aes;
 
 extern crate librespot_protocol as protocol;
 

+ 4 - 3
core/src/mercury/mod.rs

@@ -1,13 +1,13 @@
+use crate::protocol;
 use byteorder::{BigEndian, ByteOrder};
 use bytes::Bytes;
 use futures::sync::{mpsc, oneshot};
 use futures::{Async, Future, Poll};
 use protobuf;
-use protocol;
 use std::collections::HashMap;
 use std::mem;
 
-use util::SeqGenerator;
+use crate::util::SeqGenerator;
 
 mod types;
 pub use self::types::*;
@@ -95,7 +95,8 @@ impl MercuryManager {
     pub fn subscribe<T: Into<String>>(
         &self,
         uri: T,
-    ) -> Box<Future<Item = mpsc::UnboundedReceiver<MercuryResponse>, Error = MercuryError>> {
+    ) -> Box<dyn Future<Item = mpsc::UnboundedReceiver<MercuryResponse>, Error = MercuryError>>
+    {
         let uri = uri.into();
         let request = self.request(MercuryRequest {
             method: MercuryMethod::SUB,

+ 3 - 2
core/src/mercury/types.rs

@@ -2,7 +2,7 @@ use byteorder::{BigEndian, WriteBytesExt};
 use protobuf::Message;
 use std::io::Write;
 
-use protocol;
+use crate::protocol;
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum MercuryMethod {
@@ -37,7 +37,8 @@ impl ToString for MercuryMethod {
             MercuryMethod::SUB => "SUB",
             MercuryMethod::UNSUB => "UNSUB",
             MercuryMethod::SEND => "SEND",
-        }.to_owned()
+        }
+        .to_owned()
     }
 }
 

+ 5 - 2
core/src/proxytunnel.rs

@@ -57,7 +57,9 @@ impl<T: AsyncRead + AsyncWrite> Future for ProxyTunnel<T> {
                     let mut response = httparse::Response::new(&mut headers);
                     let status = match response.parse(&buf) {
                         Ok(status) => status,
-                        Err(err) => return Err(io::Error::new(io::ErrorKind::Other, err.description())),
+                        Err(err) => {
+                            return Err(io::Error::new(io::ErrorKind::Other, err.description()));
+                        }
                     };
 
                     if status.is_complete() {
@@ -102,7 +104,8 @@ fn proxy_connect<T: AsyncWrite>(connection: T, connect_url: &str) -> WriteAll<T,
          \r\n",
         uri.host().expect(&format!("No host in {}", uri)),
         uri.port().expect(&format!("No port in {}", uri))
-    ).into_bytes();
+    )
+    .into_bytes();
 
     write_all(connection, buffer)
 }

+ 26 - 19
core/src/session.rs

@@ -1,23 +1,23 @@
 use std::io;
-use std::sync::{Arc, RwLock, Weak};
 use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, RwLock, Weak};
 use std::time::{SystemTime, UNIX_EPOCH};
 
 use byteorder::{BigEndian, ByteOrder};
 use bytes::Bytes;
-use futures::{Async, Future, IntoFuture, Poll, Stream};
 use futures::sync::mpsc;
+use futures::{Async, Future, IntoFuture, Poll, Stream};
 use tokio_core::reactor::{Handle, Remote};
 
-use apresolve::apresolve_or_fallback;
-use audio_key::AudioKeyManager;
-use authentication::Credentials;
-use cache::Cache;
-use channel::ChannelManager;
-use component::Lazy;
-use config::SessionConfig;
-use connection;
-use mercury::MercuryManager;
+use crate::apresolve::apresolve_or_fallback;
+use crate::audio_key::AudioKeyManager;
+use crate::authentication::Credentials;
+use crate::cache::Cache;
+use crate::channel::ChannelManager;
+use crate::component::Lazy;
+use crate::config::SessionConfig;
+use crate::connection;
+use crate::mercury::MercuryManager;
 
 struct SessionData {
     country: String,
@@ -53,8 +53,9 @@ impl Session {
         credentials: Credentials,
         cache: Option<Cache>,
         handle: Handle,
-    ) -> Box<Future<Item = Session, Error = io::Error>> {
-        let access_point = apresolve_or_fallback::<io::Error>(&handle, &config.proxy, &config.ap_port);
+    ) -> Box<dyn Future<Item = Session, Error = io::Error>> {
+        let access_point =
+            apresolve_or_fallback::<io::Error>(&handle, &config.proxy, &config.ap_port);
 
         let handle_ = handle.clone();
         let proxy = config.proxy.clone();
@@ -64,8 +65,9 @@ impl Session {
         });
 
         let device_id = config.device_id.clone();
-        let authentication = connection
-            .and_then(move |connection| connection::authenticate(connection, credentials, device_id));
+        let authentication = connection.and_then(move |connection| {
+            connection::authenticate(connection, credentials, device_id)
+        });
 
         let result = authentication.map(move |(transport, reusable_credentials)| {
             info!("Authenticated as \"{}\" !", reusable_credentials.username);
@@ -97,7 +99,7 @@ impl Session {
         config: SessionConfig,
         cache: Option<Cache>,
         username: String,
-    ) -> (Session, Box<Future<Item = (), Error = io::Error>>) {
+    ) -> (Session, Box<dyn Future<Item = (), Error = io::Error>>) {
         let (sink, stream) = transport.split();
 
         let (sender_tx, sender_rx) = mpsc::unbounded();
@@ -133,7 +135,11 @@ impl Session {
             .map(|_| ());
         let receiver_task = DispatchTask(stream, session.weak());
 
-        let task = Box::new((receiver_task, sender_task).into_future().map(|((), ())| ()));
+        let task = Box::new(
+            (receiver_task, sender_task)
+                .into_future()
+                .map(|((), ())| ()),
+        );
 
         (session, task)
     }
@@ -197,7 +203,7 @@ impl Session {
 
             0x9 | 0xa => self.channel().dispatch(cmd, data),
             0xd | 0xe => self.audio_key().dispatch(cmd, data),
-            0xb2...0xb6 => self.mercury().dispatch(cmd, data),
+            0xb2..=0xb6 => self.mercury().dispatch(cmd, data),
             _ => (),
         }
     }
@@ -289,7 +295,8 @@ where
                     session.shutdown();
                     return Err(From::from(e));
                 }
-            }.expect("connection closed");
+            }
+            .expect("connection closed");
 
             session.dispatch(cmd, data);
         }

+ 2 - 1
core/src/spotify_id.rs

@@ -17,7 +17,8 @@ pub struct SpotifyId {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct SpotifyIdError;
 
-const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+const BASE62_DIGITS: &'static [u8] =
+    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";
 
 impl SpotifyId {

+ 4 - 1
core/src/util/mod.rs

@@ -6,7 +6,10 @@ use std::mem;
 use std::ops::{Mul, Rem, Shr};
 
 pub fn rand_vec<G: Rng>(rng: &mut G, size: usize) -> Vec<u8> {
-    ::std::iter::repeat(()).map(|()| rng.gen()).take(size).collect()
+    ::std::iter::repeat(())
+        .map(|()| rng.gen())
+        .take(size)
+        .collect()
 }
 
 pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {

+ 3 - 1
core/src/volume.rs

@@ -21,7 +21,9 @@ impl Volume {
 
     // write volume to file
     fn save_to_writer<W: Write>(&self, writer: &mut W) {
-        writer.write_all(self.volume.to_string().as_bytes()).unwrap();
+        writer
+            .write_all(self.volume.to_string().as_bytes())
+            .unwrap();
     }
 
     pub(crate) fn save_to_file<P: AsRef<Path>>(&self, path: P) {

+ 3 - 4
examples/play.rs

@@ -1,6 +1,3 @@
-extern crate librespot;
-extern crate tokio_core;
-
 use std::env;
 use tokio_core::reactor::Core;
 
@@ -37,7 +34,9 @@ fn main() {
         .run(Session::connect(session_config, credentials, None, handle))
         .unwrap();
 
-    let (player, _) = Player::new(player_config, session.clone(), None, move || (backend)(None));
+    let (player, _) = Player::new(player_config, session.clone(), None, move || {
+        (backend)(None)
+    });
 
     println!("Playing...");
     core.run(player.load(track, true, 0)).unwrap();

+ 6 - 13
examples/playlist_tracks.rs

@@ -1,11 +1,4 @@
-extern crate log;
-extern crate env_logger;
-
-extern crate librespot;
-extern crate tokio_core;
-extern crate tokio_io;
-extern crate futures;
-
+use env_logger;
 use std::env;
 use tokio_core::reactor::Core;
 
@@ -13,7 +6,7 @@ use librespot::core::authentication::Credentials;
 use librespot::core::config::SessionConfig;
 use librespot::core::session::Session;
 use librespot::core::spotify_id::SpotifyId;
-use librespot::metadata::{Metadata, Track, Playlist};
+use librespot::metadata::{Metadata, Playlist, Track};
 
 fn main() {
     env_logger::init();
@@ -32,16 +25,16 @@ fn main() {
 
     let uri_split = args[3].split(":");
     let uri_parts: Vec<&str> = uri_split.collect();
-    println!("{}, {}, {}",uri_parts[0], uri_parts[1], uri_parts[2]);
-    
+    println!("{}, {}, {}", uri_parts[0], uri_parts[1], uri_parts[2]);
+
     let plist_uri = SpotifyId::from_base62(uri_parts[2]).unwrap();
-    
+
     let session = core
         .run(Session::connect(session_config, credentials, None, handle))
         .unwrap();
 
     let plist = core.run(Playlist::get(&session, plist_uri)).unwrap();
-    println!("{:?}",plist);
+    println!("{:?}", plist);
     for track_id in plist.tracks {
         let plist_track = core.run(Track::get(&session, track_id)).unwrap();
         println!("track: {} ", plist_track.name);

+ 1 - 0
metadata/Cargo.toml

@@ -4,6 +4,7 @@ version = "0.1.0"
 authors = ["Paul Lietar <paul@lietar.net>"]
 description="The metadata logic for librespot"
 license="MIT"
+edition = "2018"
 
 [dependencies]
 byteorder = "1.3"

+ 7 - 4
metadata/src/lib.rs

@@ -19,7 +19,7 @@ use librespot_core::mercury::MercuryError;
 use librespot_core::session::Session;
 use librespot_core::spotify_id::{FileId, SpotifyAudioType, SpotifyId};
 
-pub use protocol::metadata::AudioFile_Format as FileFormat;
+pub use crate::protocol::metadata::AudioFile_Format as FileFormat;
 
 fn countrylist_contains(list: &str, country: &str) -> bool {
     list.chunks(2).any(|cc| cc == country)
@@ -301,7 +301,6 @@ impl Metadata for Playlist {
     }
 
     fn parse(msg: &Self::Message, _: &Session) -> Self {
-
         let tracks = msg
             .get_contents()
             .get_items()
@@ -312,9 +311,13 @@ impl Metadata for Playlist {
                 SpotifyId::from_base62(uri_parts[2]).unwrap()
             })
             .collect::<Vec<_>>();
-        
+
         if tracks.len() != msg.get_length() as usize {
-            warn!("Got {} tracks, but the playlist should contain {} tracks.", tracks.len(), msg.get_length());
+            warn!(
+                "Got {} tracks, but the playlist should contain {} tracks.",
+                tracks.len(),
+                msg.get_length()
+            );
         }
 
         Playlist {

+ 1 - 0
playback/Cargo.toml

@@ -4,6 +4,7 @@ version = "0.1.0"
 authors = ["Sasha Hilton <sashahilton00@gmail.com>"]
 description="The audio playback logic for librespot"
 license="MIT"
+edition = "2018"
 
 [dependencies.librespot-audio]
 path = "../audio"

+ 2 - 1
playback/src/audio_backend/alsa.rs

@@ -64,7 +64,8 @@ impl Open for AlsaSink {
             }
             Some(device) => device,
             None => "default",
-        }.to_string();
+        }
+        .to_string();
 
         AlsaSink(None, name)
     }

+ 10 - 5
playback/src/audio_backend/jackaudio.rs

@@ -1,7 +1,7 @@
 use super::{Open, Sink};
 use jack::prelude::{
-    client_options, AsyncClient, AudioOutPort, AudioOutSpec, Client, JackControl, Port, ProcessHandler,
-    ProcessScope,
+    client_options, AsyncClient, AudioOutPort, AudioOutSpec, Client, JackControl, Port,
+    ProcessHandler, ProcessScope,
 };
 use std::io;
 use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
@@ -45,9 +45,14 @@ impl Open for JackSink {
         info!("Using jack sink!");
 
         let client_name = client_name.unwrap_or("librespot".to_string());
-        let (client, _status) = Client::new(&client_name[..], client_options::NO_START_SERVER).unwrap();
-        let ch_r = client.register_port("out_0", AudioOutSpec::default()).unwrap();
-        let ch_l = client.register_port("out_1", AudioOutSpec::default()).unwrap();
+        let (client, _status) =
+            Client::new(&client_name[..], client_options::NO_START_SERVER).unwrap();
+        let ch_r = client
+            .register_port("out_0", AudioOutSpec::default())
+            .unwrap();
+        let ch_l = client
+            .register_port("out_1", AudioOutSpec::default())
+            .unwrap();
         // buffer for samples from librespot (~10ms)
         let (tx, rx) = sync_channel(2 * 1024 * 4);
         let jack_data = JackData {

+ 4 - 4
playback/src/audio_backend/mod.rs

@@ -1,7 +1,7 @@
 use std::io;
 
 pub trait Open {
-    fn open(Option<String>) -> Self;
+    fn open(_: Option<String>) -> Self;
 }
 
 pub trait Sink {
@@ -10,7 +10,7 @@ pub trait Sink {
     fn write(&mut self, data: &[i16]) -> io::Result<()>;
 }
 
-fn mk_sink<S: Sink + Open + 'static>(device: Option<String>) -> Box<Sink> {
+fn mk_sink<S: Sink + Open + 'static>(device: Option<String>) -> Box<dyn Sink> {
     Box::new(S::open(device))
 }
 
@@ -46,7 +46,7 @@ use self::sdl::SdlSink;
 mod pipe;
 use self::pipe::StdoutSink;
 
-pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<Sink>)] = &[
+pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<dyn Sink>)] = &[
     #[cfg(feature = "alsa-backend")]
     ("alsa", mk_sink::<AlsaSink>),
     #[cfg(feature = "portaudio-backend")]
@@ -62,7 +62,7 @@ pub const BACKENDS: &'static [(&'static str, fn(Option<String>) -> Box<Sink>)] =
     ("pipe", mk_sink::<StdoutSink>),
 ];
 
-pub fn find(name: Option<String>) -> Option<fn(Option<String>) -> Box<Sink>> {
+pub fn find(name: Option<String>) -> Option<fn(Option<String>) -> Box<dyn Sink>> {
     if let Some(name) = name {
         BACKENDS
             .iter()

+ 5 - 2
playback/src/audio_backend/pipe.rs

@@ -4,7 +4,7 @@ use std::io::{self, Write};
 use std::mem;
 use std::slice;
 
-pub struct StdoutSink(Box<Write>);
+pub struct StdoutSink(Box<dyn Write>);
 
 impl Open for StdoutSink {
     fn open(path: Option<String>) -> StdoutSink {
@@ -28,7 +28,10 @@ impl Sink for StdoutSink {
 
     fn write(&mut self, data: &[i16]) -> io::Result<()> {
         let data: &[u8] = unsafe {
-            slice::from_raw_parts(data.as_ptr() as *const u8, data.len() * mem::size_of::<i16>())
+            slice::from_raw_parts(
+                data.as_ptr() as *const u8,
+                data.len() * mem::size_of::<i16>(),
+            )
         };
 
         self.0.write_all(data)?;

+ 6 - 4
playback/src/audio_backend/portaudio.rs

@@ -11,7 +11,7 @@ pub struct PortAudioSink<'a>(
     StreamParameters<i16>,
 );
 
-fn output_devices() -> Box<Iterator<Item = (DeviceIndex, DeviceInfo)>> {
+fn output_devices() -> Box<dyn Iterator<Item = (DeviceIndex, DeviceInfo)>> {
     let count = portaudio_rs::device::get_count().unwrap();
     let devices = (0..count)
         .filter_map(|idx| portaudio_rs::device::get_info(idx).map(|info| (idx, info)))
@@ -51,7 +51,8 @@ impl<'a> Open for PortAudioSink<'a> {
             }
             Some(device) => find_output(device),
             None => get_default_output_index(),
-        }.expect("Could not find device");
+        }
+        .expect("Could not find device");
 
         let info = portaudio_rs::device::get_info(device_idx);
         let latency = match info {
@@ -81,8 +82,9 @@ impl<'a> Sink for PortAudioSink<'a> {
                     FRAMES_PER_BUFFER_UNSPECIFIED,
                     StreamFlags::empty(),
                     None,
-                ).unwrap(),
-            );;
+                )
+                .unwrap(),
+            );
         }
 
         self.0.as_mut().unwrap().start().unwrap();

+ 5 - 1
playback/src/audio_backend/pulseaudio.rs

@@ -14,7 +14,11 @@ pub struct PulseAudioSink {
     desc: CString,
 }
 
-fn call_pulseaudio<T, F, FailCheck>(f: F, fail_check: FailCheck, kind: io::ErrorKind) -> io::Result<T>
+fn call_pulseaudio<T, F, FailCheck>(
+    f: F,
+    fail_check: FailCheck,
+    kind: io::ErrorKind,
+) -> io::Result<T>
 where
     T: Copy,
     F: Fn(*mut libc::c_int) -> T,

+ 9 - 8
playback/src/audio_backend/rodio.rs

@@ -1,8 +1,8 @@
 use super::{Open, Sink};
-extern crate rodio;
 extern crate cpal;
-use std::{io, thread, time};
+extern crate rodio;
 use std::process::exit;
+use std::{io, thread, time};
 
 pub struct RodioSink {
     rodio_sink: rodio::Sink,
@@ -14,7 +14,7 @@ fn list_formats(ref device: &rodio::Device) {
         Err(e) => {
             warn!("Error getting default rodio::Sink format: {:?}", e);
             return;
-        },
+        }
     };
 
     let mut output_formats = match device.supported_output_formats() {
@@ -22,13 +22,16 @@ fn list_formats(ref device: &rodio::Device) {
         Err(e) => {
             warn!("Error getting supported rodio::Sink formats: {:?}", e);
             return;
-        },
+        }
     };
 
     if output_formats.peek().is_some() {
         debug!("  Available formats:");
         for format in output_formats {
-            let s = format!("{}ch, {:?}, min {:?}, max {:?}", format.channels, format.data_type, format.min_sample_rate, format.max_sample_rate);
+            let s = format!(
+                "{}ch, {:?}, min {:?}, max {:?}",
+                format.channels, format.data_type, format.min_sample_rate, format.max_sample_rate
+            );
             if format == default_fmt {
                 debug!("    (default) {}", s);
             } else {
@@ -79,9 +82,7 @@ impl Open for RodioSink {
         }
         let sink = rodio::Sink::new(&rodio_device);
 
-        RodioSink {
-            rodio_sink: sink,
-        }
+        RodioSink { rodio_sink: sink }
     }
 }
 

+ 9 - 5
playback/src/mixer/alsamixer.rs

@@ -10,13 +10,17 @@ pub struct AlsaMixer {
 }
 
 impl AlsaMixer {
-    fn map_volume(&self, set_volume: Option<u16>) -> Result<(u16), Box<Error>> {
+    fn map_volume(&self, set_volume: Option<u16>) -> Result<(u16), Box<dyn Error>> {
         let mixer = alsa::mixer::Mixer::new(&self.config.card, false)?;
         let sid = alsa::mixer::SelemId::new(&*self.config.mixer, self.config.index);
 
-        let selem = mixer
-            .find_selem(&sid)
-            .expect(format!("Couldn't find simple mixer control for {}", self.config.mixer).as_str());
+        let selem = mixer.find_selem(&sid).expect(
+            format!(
+                "Couldn't find simple mixer control for {}",
+                self.config.mixer
+            )
+            .as_str(),
+        );
         let (min, max) = selem.get_playback_volume_range();
         let range = (max - min) as f64;
 
@@ -72,7 +76,7 @@ impl Mixer for AlsaMixer {
         }
     }
 
-    fn get_audio_filter(&self) -> Option<Box<AudioFilter + Send>> {
+    fn get_audio_filter(&self) -> Option<Box<dyn AudioFilter + Send>> {
         None
     }
 }

+ 9 - 8
playback/src/mixer/mod.rs

@@ -1,12 +1,12 @@
 pub trait Mixer: Send {
-    fn open(Option<MixerConfig>) -> Self
+    fn open(_: Option<MixerConfig>) -> Self
     where
         Self: Sized;
     fn start(&self);
     fn stop(&self);
     fn set_volume(&self, volume: u16);
     fn volume(&self) -> u16;
-    fn get_audio_filter(&self) -> Option<Box<AudioFilter + Send>> {
+    fn get_audio_filter(&self) -> Option<Box<dyn AudioFilter + Send>> {
         None
     }
 }
@@ -28,10 +28,11 @@ pub struct MixerConfig {
 }
 
 impl Default for MixerConfig {
-    fn default() -> MixerConfig { MixerConfig {
-        card: String::from("default"),
-        mixer: String::from("PCM"),
-        index: 0,
+    fn default() -> MixerConfig {
+        MixerConfig {
+            card: String::from("default"),
+            mixer: String::from("PCM"),
+            index: 0,
         }
     }
 }
@@ -39,11 +40,11 @@ impl Default for MixerConfig {
 pub mod softmixer;
 use self::softmixer::SoftMixer;
 
-fn mk_sink<M: Mixer + 'static>(device: Option<MixerConfig>) -> Box<Mixer> {
+fn mk_sink<M: Mixer + 'static>(device: Option<MixerConfig>) -> Box<dyn Mixer> {
     Box::new(M::open(device))
 }
 
-pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<fn(Option<MixerConfig>) -> Box<Mixer>> {
+pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<fn(Option<MixerConfig>) -> Box<dyn Mixer>> {
     match name.as_ref().map(AsRef::as_ref) {
         None | Some("softvol") => Some(mk_sink::<SoftMixer>),
         #[cfg(feature = "alsa-backend")]

+ 1 - 1
playback/src/mixer/softmixer.rs

@@ -23,7 +23,7 @@ impl Mixer for SoftMixer {
     fn set_volume(&self, volume: u16) {
         self.volume.store(volume as usize, Ordering::Relaxed);
     }
-    fn get_audio_filter(&self) -> Option<Box<AudioFilter + Send>> {
+    fn get_audio_filter(&self) -> Option<Box<dyn AudioFilter + Send>> {
         Some(Box::new(SoftVolumeApplier {
             volume: self.volume.clone(),
         }))

+ 39 - 20
playback/src/player.rs

@@ -11,19 +11,19 @@ use std::sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError};
 use std::thread;
 use std::time::Duration;
 
-use config::{Bitrate, PlayerConfig};
+use crate::config::{Bitrate, PlayerConfig};
 use librespot_core::session::Session;
 use librespot_core::spotify_id::SpotifyId;
 
-use audio::{AudioDecrypt, AudioFile, StreamLoaderController};
-use audio::{VorbisDecoder, VorbisPacket};
-use audio::{
+use crate::audio::{AudioDecrypt, AudioFile, StreamLoaderController};
+use crate::audio::{VorbisDecoder, VorbisPacket};
+use crate::audio::{
     READ_AHEAD_BEFORE_PLAYBACK_ROUNDTRIPS, READ_AHEAD_BEFORE_PLAYBACK_SECONDS,
     READ_AHEAD_DURING_PLAYBACK_ROUNDTRIPS, READ_AHEAD_DURING_PLAYBACK_SECONDS,
 };
-use audio_backend::Sink;
-use metadata::{AudioItem, FileFormat};
-use mixer::AudioFilter;
+use crate::audio_backend::Sink;
+use crate::metadata::{AudioItem, FileFormat};
+use crate::mixer::AudioFilter;
 
 pub struct Player {
     commands: Option<std::sync::mpsc::Sender<PlayerCommand>>,
@@ -36,9 +36,9 @@ struct PlayerInternal {
     commands: std::sync::mpsc::Receiver<PlayerCommand>,
 
     state: PlayerState,
-    sink: Box<Sink>,
+    sink: Box<dyn Sink>,
     sink_running: bool,
-    audio_filter: Option<Box<AudioFilter + Send>>,
+    audio_filter: Option<Box<dyn AudioFilter + Send>>,
     event_sender: futures::sync::mpsc::UnboundedSender<PlayerEvent>,
 }
 
@@ -98,8 +98,10 @@ impl NormalisationData {
     }
 
     fn get_factor(config: &PlayerConfig, data: NormalisationData) -> f32 {
-        let mut normalisation_factor =
-            f32::powf(10.0, (data.track_gain_db + config.normalisation_pregain) / 20.0);
+        let mut normalisation_factor = f32::powf(
+            10.0,
+            (data.track_gain_db + config.normalisation_pregain) / 20.0,
+        );
 
         if normalisation_factor * data.track_peak > 1.0 {
             warn!("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.");
@@ -117,11 +119,11 @@ impl Player {
     pub fn new<F>(
         config: PlayerConfig,
         session: Session,
-        audio_filter: Option<Box<AudioFilter + Send>>,
+        audio_filter: Option<Box<dyn AudioFilter + Send>>,
         sink_builder: F,
     ) -> (Player, PlayerEventChannel)
     where
-        F: FnOnce() -> Box<Sink> + Send + 'static,
+        F: FnOnce() -> Box<dyn Sink> + Send + 'static,
     {
         let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
         let (event_sender, event_receiver) = futures::sync::mpsc::unbounded();
@@ -238,7 +240,12 @@ impl PlayerState {
         use self::PlayerState::*;
         match *self {
             Stopped | EndOfTrack { .. } => None,
-            Paused { ref mut decoder, .. } | Playing { ref mut decoder, .. } => Some(decoder),
+            Paused {
+                ref mut decoder, ..
+            }
+            | Playing {
+                ref mut decoder, ..
+            } => Some(decoder),
             Invalid => panic!("invalid state"),
         }
     }
@@ -518,7 +525,10 @@ impl PlayerInternal {
                 if let Some(stream_loader_controller) = self.state.stream_loader_controller() {
                     stream_loader_controller.set_stream_mode();
                 }
-                if let PlayerState::Playing { bytes_per_second, .. } = self.state {
+                if let PlayerState::Playing {
+                    bytes_per_second, ..
+                } = self.state
+                {
                     if let Some(stream_loader_controller) = self.state.stream_loader_controller() {
                         // Request our read ahead range
                         let request_data_length = max(
@@ -592,7 +602,10 @@ impl PlayerInternal {
                     .iter()
                     .map(|alt_id| AudioItem::get_audio_item(&self.session, *alt_id));
                 let alternatives = future::join_all(alternatives).wait().unwrap();
-                alternatives.into_iter().find(|alt| alt.available).map(Cow::Owned)
+                alternatives
+                    .into_iter()
+                    .find(|alt| alt.available)
+                    .map(Cow::Owned)
             } else {
                 None
             }
@@ -670,8 +683,12 @@ impl PlayerInternal {
         let play_from_beginning = position == 0;
 
         let key = self.session.audio_key().request(spotify_id, file_id);
-        let encrypted_file =
-            AudioFile::open(&self.session, file_id, bytes_per_second, play_from_beginning);
+        let encrypted_file = AudioFile::open(
+            &self.session,
+            file_id,
+            bytes_per_second,
+            play_from_beginning,
+        );
 
         let encrypted_file = encrypted_file.wait().unwrap();
 
@@ -689,7 +706,9 @@ impl PlayerInternal {
         let mut decrypted_file = AudioDecrypt::new(key, encrypted_file);
 
         let normalisation_factor = match NormalisationData::parse_from_file(&mut decrypted_file) {
-            Ok(normalisation_data) => NormalisationData::get_factor(&self.config, normalisation_data),
+            Ok(normalisation_data) => {
+                NormalisationData::get_factor(&self.config, normalisation_data)
+            }
             Err(_) => {
                 warn!("Unable to extract normalisation data, using default value.");
                 1.0 as f32
@@ -768,7 +787,7 @@ impl<T: Read + Seek> Seek for Subfile<T> {
             x => x,
         };
 
-        let newpos = try!(self.stream.seek(pos));
+        let newpos = self.stream.seek(pos)?;
         if newpos > self.offset {
             Ok(newpos - self.offset)
         } else {

+ 1 - 0
protocol/Cargo.toml

@@ -5,6 +5,7 @@ authors = ["Paul Liétar <paul@lietar.net>"]
 build = "build.rs"
 description="The protobuf logic for communicating with Spotify servers"
 license="MIT"
+edition = "2018"
 
 [dependencies]
 protobuf = "2.8.1"

+ 9 - 12
protocol/build.rs

@@ -1,14 +1,16 @@
 extern crate protobuf_codegen; // Does the business
 extern crate protobuf_codegen_pure; // Helper function
 
-use std::path::Path;
 use std::fs::{read_to_string, write};
+use std::path::Path;
 
-use protobuf_codegen_pure::Customize;
 use protobuf_codegen_pure::parse_and_typecheck;
+use protobuf_codegen_pure::Customize;
 
 fn main() {
-    let customizations = Customize { ..Default::default() };
+    let customizations = Customize {
+        ..Default::default()
+    };
 
     let lib_str = read_to_string("src/lib.rs").unwrap();
 
@@ -21,10 +23,9 @@ fn main() {
 
         let name;
         if line.starts_with("pub mod ") {
-            name = &line[8..len-1]; // Remove keywords and semi-colon
-        }
-        else {
-            name = &line[4..len-1]; // Remove keywords and semi-colon
+            name = &line[8..len - 1]; // Remove keywords and semi-colon
+        } else {
+            name = &line[4..len - 1]; // Remove keywords and semi-colon
         }
 
         // Build the paths to relevant files.
@@ -44,11 +45,7 @@ fn main() {
         let p = parse_and_typecheck(&["proto"], &[src]).expect("protoc");
         // But generate them with the protobuf-codegen crate directly.
         // Then we can keep the result in-memory.
-        let result = protobuf_codegen::gen(
-            &p.file_descriptors,
-            &p.relative_paths,
-            &customizations,
-        );
+        let result = protobuf_codegen::gen(&p.file_descriptors, &p.relative_paths, &customizations);
         // Protoc result as a byte array.
         let new = &result.first().unwrap().content;
         // Convert to utf8 to compare with existing.

+ 1 - 2
rustfmt.toml

@@ -1,4 +1,3 @@
-max_width = 105
+# max_width = 105
 reorder_imports = true
-reorder_imports_in_group = true
 reorder_modules = true

+ 0 - 9
src/lib.rs

@@ -1,15 +1,6 @@
 #![crate_name = "librespot"]
 #![cfg_attr(feature = "cargo-clippy", allow(unused_io_amount))]
 
-extern crate base64;
-extern crate futures;
-extern crate hyper;
-extern crate num_bigint;
-extern crate protobuf;
-extern crate rand;
-extern crate tokio_core;
-extern crate url;
-
 pub extern crate librespot_audio as audio;
 pub extern crate librespot_connect as connect;
 pub extern crate librespot_core as core;

+ 22 - 25
src/main.rs

@@ -1,20 +1,6 @@
-extern crate env_logger;
-extern crate futures;
-extern crate getopts;
-extern crate librespot;
-#[macro_use]
-extern crate log;
-extern crate hex;
-extern crate rpassword;
-extern crate sha1;
-extern crate tokio_core;
-extern crate tokio_io;
-extern crate tokio_process;
-extern crate tokio_signal;
-extern crate url;
-
 use futures::sync::mpsc::UnboundedReceiver;
 use futures::{Async, Future, Poll, Stream};
+use log::{error, info, trace, warn};
 use sha1::{Digest, Sha1};
 use std::env;
 use std::io::{self, stderr, Write};
@@ -40,7 +26,7 @@ use librespot::playback::mixer::{self, Mixer, MixerConfig};
 use librespot::playback::player::{Player, PlayerEvent};
 
 mod player_event_handler;
-use player_event_handler::run_program_on_events;
+use crate::player_event_handler::run_program_on_events;
 
 fn device_id(name: &str) -> String {
     hex::encode(Sha1::digest(name.as_bytes()))
@@ -86,10 +72,10 @@ fn list_backends() {
 
 #[derive(Clone)]
 struct Setup {
-    backend: fn(Option<String>) -> Box<Sink>,
+    backend: fn(Option<String>) -> Box<dyn Sink>,
     device: Option<String>,
 
-    mixer: fn(Option<MixerConfig>) -> Box<Mixer>,
+    mixer: fn(Option<MixerConfig>) -> Box<dyn Mixer>,
 
     cache: Option<Cache>,
     player_config: PlayerConfig,
@@ -198,7 +184,13 @@ fn setup(args: &[String]) -> Setup {
     let matches = match opts.parse(&args[1..]) {
         Ok(m) => m,
         Err(f) => {
-            writeln!(stderr(), "error: {}\n{}", f.to_string(), usage(&args[0], &opts)).unwrap();
+            writeln!(
+                stderr(),
+                "error: {}\n{}",
+                f.to_string(),
+                usage(&args[0], &opts)
+            )
+            .unwrap();
             exit(1);
         }
     };
@@ -232,7 +224,9 @@ fn setup(args: &[String]) -> Setup {
     let mixer = mixer::find(mixer_name.as_ref()).expect("Invalid mixer");
 
     let mixer_config = MixerConfig {
-        card: matches.opt_str("mixer-card").unwrap_or(String::from("default")),
+        card: matches
+            .opt_str("mixer-card")
+            .unwrap_or(String::from("default")),
         mixer: matches.opt_str("mixer-name").unwrap_or(String::from("PCM")),
         index: matches
             .opt_str("mixer-index")
@@ -367,9 +361,9 @@ struct Main {
     player_config: PlayerConfig,
     session_config: SessionConfig,
     connect_config: ConnectConfig,
-    backend: fn(Option<String>) -> Box<Sink>,
+    backend: fn(Option<String>) -> Box<dyn Sink>,
     device: Option<String>,
-    mixer: fn(Option<MixerConfig>) -> Box<Mixer>,
+    mixer: fn(Option<MixerConfig>) -> Box<dyn Mixer>,
     mixer_config: MixerConfig,
     handle: Handle,
 
@@ -378,7 +372,7 @@ struct Main {
 
     spirc: Option<Spirc>,
     spirc_task: Option<SpircTask>,
-    connect: Box<Future<Item = Session, Error = io::Error>>,
+    connect: Box<dyn Future<Item = Session, Error = io::Error>>,
 
     shutdown: bool,
 
@@ -414,7 +408,8 @@ impl Main {
             let config = task.connect_config.clone();
             let device_id = task.session_config.device_id.clone();
 
-            task.discovery = Some(discovery(&handle, config, device_id, setup.zeroconf_port).unwrap());
+            task.discovery =
+                Some(discovery(&handle, config, device_id, setup.zeroconf_port).unwrap());
         }
 
         if let Some(credentials) = setup.credentials {
@@ -447,7 +442,9 @@ impl Future for Main {
         loop {
             let mut progress = false;
 
-            if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
+            if let Some(Async::Ready(Some(creds))) =
+                self.discovery.as_mut().map(|d| d.poll().unwrap())
+            {
                 if let Some(ref spirc) = self.spirc {
                     spirc.shutdown();
                 }

+ 2 - 1
src/player_event_handler.rs

@@ -1,8 +1,9 @@
 use librespot::playback::player::PlayerEvent;
-use tokio_process::{Child, CommandExt};
+use log::info;
 use std::collections::HashMap;
 use std::io;
 use std::process::Command;
+use tokio_process::{Child, CommandExt};
 
 fn run_program(program: &str, env_vars: HashMap<&str, String>) -> io::Result<Child> {
     let mut v: Vec<&str> = program.split_whitespace().collect();