Browse Source

Fix build on latest rust.

Paul Lietar 9 years ago
parent
commit
267ccbe65e
14 changed files with 290 additions and 256 deletions
  1. 118 75
      Cargo.lock
  2. 17 15
      Cargo.toml
  3. 23 23
      src/audio_file.rs
  4. 18 21
      src/audio_key.rs
  5. 3 4
      src/connection.rs
  6. 6 6
      src/lib.rs
  7. 3 5
      src/main.rs
  8. 26 35
      src/mercury.rs
  9. 10 9
      src/metadata.rs
  10. 15 16
      src/player.rs
  11. 26 24
      src/session.rs
  12. 20 18
      src/spirc.rs
  13. 3 3
      src/util/spotify_id.rs
  14. 2 2
      src/util/zerofile.rs

+ 118 - 75
Cargo.lock

@@ -2,27 +2,51 @@
 name = "librespot"
 version = "0.1.0"
 dependencies = [
- "byteorder 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "getopts 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clippy 0.0.12 (git+https://github.com/Manishearth/rust-clippy.git)",
+ "eventual 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "librespot-protocol 0.1.0",
  "mod_path 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "portaudio 0.1.2 (git+https://github.com/mvdnes/portaudio-rs)",
  "protobuf 1.0.1 (git+https://github.com/plietar/rust-protobuf.git)",
  "protobuf_macros 0.1.0 (git+https://github.com/plietar/rust-protobuf-macros.git)",
- "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "readall 0.1.0 (git+https://github.com/plietar/rust-readall.git)",
+ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rpassword 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust-crypto 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "rust-gmp 0.2.0 (git+https://github.com/plietar/rust-gmp.git)",
  "shannon 0.1.0 (git+https://github.com/plietar/rust-shannon.git)",
- "tempfile 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "vergen 0.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "vorbis 0.0.11 (git+https://github.com/plietar/vorbis-rs)",
+ "tempfile 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vergen 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vorbis 0.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "advapi32-sys"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "bit-set"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bit-vec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "bitflags"
 version = "0.1.1"
@@ -35,39 +59,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "byteorder"
-version = "0.3.11"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "gcc"
-version = "0.3.8"
+name = "clippy"
+version = "0.0.12"
+source = "git+https://github.com/Manishearth/rust-clippy.git#d3da9f6c81dd3e026bd679c09cea1d6b337ccd25"
+
+[[package]]
+name = "eventual"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syncbox 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
-name = "getopts"
-version = "0.2.11"
+name = "gcc"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "getopts"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "kernel32-sys"
-version = "0.1.2"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "winapi 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "lazy_static"
-version = "0.1.11"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libc"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -80,10 +120,10 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -93,11 +133,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num"
-version = "0.1.25"
+version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -105,8 +145,8 @@ name = "ogg-sys"
 version = "0.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -121,7 +161,7 @@ version = "0.1.2"
 source = "git+https://github.com/mvdnes/portaudio-rs#7c6d10f5edda0094cc33b682d88c3a6ea4919b9f"
 dependencies = [
  "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "portaudio_sys 0.1.0 (git+https://github.com/mvdnes/portaudio-rs)",
 ]
 
@@ -130,7 +170,7 @@ name = "portaudio_sys"
 version = "0.1.0"
 source = "git+https://github.com/mvdnes/portaudio-rs#7c6d10f5edda0094cc33b682d88c3a6ea4919b9f"
 dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -142,14 +182,16 @@ source = "git+https://github.com/plietar/rust-protobuf.git#dae87e292a52a66da7f78
 [[package]]
 name = "protobuf_macros"
 version = "0.1.0"
-source = "git+https://github.com/plietar/rust-protobuf-macros.git#3b49de3937a34b7a21be1d13caea4348a93c6de4"
+source = "git+https://github.com/plietar/rust-protobuf-macros.git#2b6a8129e015945300cb2bb7efae2ed78042ed48"
 
 [[package]]
 name = "rand"
-version = "0.3.8"
+version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -162,10 +204,10 @@ name = "rpassword"
 version = "0.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "termios 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -173,24 +215,24 @@ name = "rust-crypto"
 version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rust-gmp"
 version = "0.2.0"
-source = "git+https://github.com/plietar/rust-gmp.git#cc003c224559f6035cd34a7ed5c6284a49785816"
+source = "git+https://github.com/plietar/rust-gmp.git#d1bb4448fdbfa2505edadb83b6aac6257fe08ba2"
 dependencies = [
- "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-serialize"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -198,7 +240,7 @@ name = "shannon"
 version = "0.1.0"
 source = "git+https://github.com/plietar/rust-shannon.git#c6be8a879a523a77d81c50df46faa891b76fea25"
 dependencies = [
- "byteorder 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "readall 0.1.0 (git+https://github.com/plietar/rust-readall.git)",
  "shannon-sys 0.1.0 (git+https://github.com/plietar/rust-shannon.git)",
 ]
@@ -208,18 +250,27 @@ name = "shannon-sys"
 version = "0.1.0"
 source = "git+https://github.com/plietar/rust-shannon.git#c6be8a879a523a77d81c50df46faa891b76fea25"
 dependencies = [
- "gcc 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syncbox"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "tempfile"
-version = "1.0.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -227,34 +278,34 @@ name = "termios"
 version = "0.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "time"
-version = "0.1.30"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "vergen"
-version = "0.0.13"
+version = "0.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "vorbis"
-version = "0.0.11"
-source = "git+https://github.com/plietar/vorbis-rs#78058c3341832969030f49cbc4b8bc9deb376776"
+version = "0.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis-sys 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbisfile-sys 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -265,8 +316,8 @@ name = "vorbis-sys"
 version = "0.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -276,8 +327,8 @@ name = "vorbisfile-sys"
 version = "0.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "ogg-sys 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "vorbis-sys 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -285,19 +336,11 @@ dependencies = [
 
 [[package]]
 name = "winapi"
-version = "0.1.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "winapi"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "winapi-build"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 

+ 17 - 15
Cargo.toml

@@ -16,17 +16,22 @@ path = "src/main.rs"
 path = "protocol"
 
 [dependencies]
-mod_path = "*"
-byteorder = "*"
-num = "*"
-rand = "*"
-lazy_static = "0.1.*"
-rust-crypto = "*"
-time = "*"
-tempfile = "*"
-rpassword = "*"
-getopts = "0.2.4"
+bit-set     = "~0.2.0"
+byteorder   = "~0.3.13"
+eventual    = "~0.1.4"
+getopts     = "~0.2.14"
+lazy_static = "~0.1.14"
+mod_path    = "~0.1.5"
+num         = "~0.1.27"
+rand        = "~0.3.11"
+rpassword   = "~0.0.5"
+rust-crypto = "~0.2.31"
+time        = "~0.1.32"
+tempfile    = "~1.1.1"
+vorbis      = "~0.0.12"
 
+[dependencies.clippy]
+git = "https://github.com/Manishearth/rust-clippy.git"
 [dependencies.protobuf]
 git = "https://github.com/plietar/rust-protobuf.git"
 [dependencies.protobuf_macros]
@@ -35,12 +40,9 @@ git = "https://github.com/plietar/rust-protobuf-macros.git"
 git = "https://github.com/plietar/rust-gmp.git"
 [dependencies.shannon]
 git = "https://github.com/plietar/rust-shannon.git"
-[dependencies.readall]
-git = "https://github.com/plietar/rust-readall.git"
 [dependencies.portaudio]
 git = "https://github.com/mvdnes/portaudio-rs"
-[dependencies.vorbis]
-git = "https://github.com/plietar/vorbis-rs"
 
 [build-dependencies]
-vergen = "*"
+vergen = "~0.0.16"
+

+ 23 - 23
src/audio_file.rs

@@ -1,6 +1,6 @@
+use bit_set::BitSet;
 use byteorder::{ByteOrder, BigEndian};
 use std::cmp::min;
-use std::collections::BitSet;
 use std::sync::{Arc, Condvar, Mutex};
 use std::sync::mpsc::{self, TryRecvError};
 use std::thread;
@@ -9,27 +9,24 @@ use std::io::{self, Read, Write, Seek, SeekFrom};
 use std::path::PathBuf;
 use tempfile::TempFile;
 
-use stream::StreamEvent;
 use util::{FileId, IgnoreExt, ZeroFile, mkdir_existing};
 use session::Session;
+use stream::StreamEvent;
 
 const CHUNK_SIZE : usize = 0x20000;
 
-pub enum AudioFile<'s> {
+pub enum AudioFile {
     Direct(fs::File),
-    Loading(AudioFileLoading<'s>)
+    Loading(AudioFileLoading)
 }
 
-pub struct AudioFileLoading<'s> {
+pub struct AudioFileLoading {
     read_file: TempFile,
 
     position: u64,
     seek: mpsc::Sender<u64>,
 
     shared: Arc<AudioFileShared>,
-
-    #[allow(dead_code)]
-    thread: thread::JoinGuard<'s, ()>,
 }
 
 struct AudioFileShared {
@@ -40,7 +37,7 @@ struct AudioFileShared {
     bitmap: Mutex<BitSet>,
 }
 
-impl <'s> AudioFileLoading<'s> {
+impl AudioFileLoading {
     fn new(session: &Session, file_id: FileId) -> AudioFileLoading {
         let mut files_iter = TempFile::shared(2).unwrap().into_iter();
         let read_file = files_iter.next().unwrap();
@@ -70,17 +67,20 @@ impl <'s> AudioFileLoading<'s> {
 
         let (seek_tx, seek_rx) = mpsc::channel();
 
+        let _shared = shared.clone();
+        let _session = session.clone();
+
+        thread::spawn(move || {
+            AudioFileLoading::fetch(&_session, _shared, write_file, seek_rx)
+        });
+
         AudioFileLoading {
             read_file: read_file,
 
             position: 0,
             seek: seek_tx,
 
-            shared: shared.clone(),
-
-            thread: thread::scoped(move || {
-                AudioFileLoading::fetch(session, shared, write_file, seek_rx)
-            })
+            shared: shared
         }
     }
 
@@ -155,7 +155,7 @@ impl <'s> AudioFileLoading<'s> {
     }
 }
 
-impl <'s> Read for AudioFileLoading<'s> {
+impl Read for AudioFileLoading {
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
         let index = self.position as usize / CHUNK_SIZE;
         let offset = self.position as usize % CHUNK_SIZE;
@@ -167,15 +167,15 @@ impl <'s> Read for AudioFileLoading<'s> {
         }
         drop(bitmap);
 
-        let len = try!(self.read_file.read(&mut output[..len]));
+        let read_len = try!(self.read_file.read(&mut output[..len]));
 
-        self.position += len as u64;
+        self.position += read_len as u64;
 
-        Ok(len)
+        Ok(read_len)
     }
 }
 
-impl <'s> Seek for AudioFileLoading<'s> {
+impl Seek for AudioFileLoading {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.position = try!(self.read_file.seek(pos));
 
@@ -189,7 +189,7 @@ impl <'s> Seek for AudioFileLoading<'s> {
     }
 }
 
-impl <'s> Read for AudioFile<'s> {
+impl Read for AudioFile {
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
         match *self {
             AudioFile::Direct(ref mut file) => file.read(output),
@@ -198,7 +198,7 @@ impl <'s> Read for AudioFile<'s> {
     }
 }
 
-impl <'s> Seek for AudioFile<'s> {
+impl Seek for AudioFile {
     fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
         match *self {
             AudioFile::Direct(ref mut file) => file.seek(pos),
@@ -215,7 +215,7 @@ impl AudioFileManager {
 
     pub fn cache_dir(session: &Session, file_id: FileId) -> PathBuf {
         let name = file_id.to_base16();
-        session.config.cache_location.join(&name[0..2])
+        session.0.config.cache_location.join(&name[0..2])
     }
 
     pub fn cache_path(session: &Session, file_id: FileId) -> PathBuf {
@@ -223,7 +223,7 @@ impl AudioFileManager {
         AudioFileManager::cache_dir(session, file_id).join(&name[2..])
     }
 
-    pub fn request<'a> (&mut self, session: &'a Session, file_id: FileId) -> AudioFile<'a> {
+    pub fn request (&mut self, session: &Session, file_id: FileId) -> AudioFile {
         match fs::File::open(AudioFileManager::cache_path(session, file_id)) {
             Ok(f) => AudioFile::Direct(f),
             Err(..) => AudioFile::Loading(AudioFileLoading::new(session, file_id))

+ 18 - 21
src/audio_key.rs

@@ -1,11 +1,10 @@
-use std::collections::{HashMap, LinkedList};
-use std::sync::{mpsc, Future};
-use std::io::{Cursor, Write};
 use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
-use readall::ReadAllExt;
+use eventual;
+use std::collections::HashMap;
+use std::io::{Cursor, Read, Write};
 use std::mem;
 
-use util::{SpotifyId, FileId, IgnoreExt};
+use util::{SpotifyId, FileId};
 use session::Session;
 use connection::PacketHandler;
 
@@ -15,7 +14,7 @@ pub type AudioKey = [u8; 16];
 struct AudioKeyId(SpotifyId, FileId);
 
 enum AudioKeyStatus {
-    Loading(LinkedList<mpsc::Sender<AudioKey>>),
+    Loading(Vec<eventual::Complete<AudioKey, ()>>),
     Loaded(AudioKey)
 }
 
@@ -35,17 +34,17 @@ impl AudioKeyManager {
     }
 
     pub fn request(&mut self, session: &Session, track: SpotifyId, file: FileId)
-        -> Future<AudioKey> {
+        -> eventual::Future<AudioKey, ()> {
 
         let id = AudioKeyId(track, file);
-        self.cache.get_mut(&id).map(|status| match status {
-            &mut AudioKeyStatus::Loaded(key) => {
-                Future::from_value(key.clone())
+        self.cache.get_mut(&id).map(|status| match *status {
+            AudioKeyStatus::Loaded(key) => {
+                eventual::Future::of(key.clone())
             }
-            &mut AudioKeyStatus::Loading(ref mut req) => {
-                let (tx, rx) = mpsc::channel();
-                req.push_front(tx);
-                Future::from_receiver(rx)
+            AudioKeyStatus::Loading(ref mut req) => {
+                let (tx, rx) = eventual::Future::pair();
+                req.push(tx);
+                rx
             }
         }).unwrap_or_else(|| {
             let seq = self.next_seq;
@@ -61,11 +60,9 @@ impl AudioKeyManager {
 
             self.pending.insert(seq, id.clone());
 
-            let (tx, rx) = mpsc::channel();
-            let mut req = LinkedList::new();
-            req.push_front(tx);
-            self.cache.insert(id, AudioKeyStatus::Loading(req));
-            Future::from_receiver(rx)
+            let (tx, rx) = eventual::Future::pair();
+            self.cache.insert(id, AudioKeyStatus::Loading(vec!{ tx }));
+            rx
         })
     }
 }
@@ -77,14 +74,14 @@ impl PacketHandler for AudioKeyManager {
         let mut data = Cursor::new(data);
         let seq = data.read_u32::<BigEndian>().unwrap();
         let mut key = [0u8; 16];
-        data.read_all(&mut key).unwrap();
+        data.read_exact(&mut key).unwrap();
 
         if let Some(status) = self.pending.remove(&seq).and_then(|id| { self.cache.get_mut(&id) }) {
             let status = mem::replace(status, AudioKeyStatus::Loaded(key));
 
             if let AudioKeyStatus::Loading(cbs) = status {
                 for cb in cbs {
-                    cb.send(key).ignore();
+                    cb.complete(key);
                 }
             }
         }

+ 3 - 4
src/connection.rs

@@ -1,9 +1,8 @@
 use byteorder::{self, BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
-use readall::ReadAllExt;
 use shannon::ShannonStream;
 use std::convert;
 use std::io;
-use std::io::Write;
+use std::io::{Read, Write};
 use std::net::TcpStream;
 use std::result;
 
@@ -70,7 +69,7 @@ impl PlainConnection {
         let mut buffer = vec![0u8; size];
 
         BigEndian::write_u32(&mut buffer, size as u32);
-        try!(self.stream.read_all(&mut buffer[4..]));
+        try!(self.stream.read_exact(&mut buffer[4..]));
 
         Ok(buffer)
     }
@@ -98,7 +97,7 @@ impl CipherConnection {
         let size = try!(self.stream.read_u16::<BigEndian>()) as usize;
 
         let mut data = vec![0; size];
-        try!(self.stream.read_all(&mut data));
+        try!(self.stream.read_exact(&mut data));
 
         try!(self.stream.finish_recv());
 

+ 6 - 6
src/lib.rs

@@ -1,25 +1,25 @@
 #![crate_name = "librespot"]
 
-#![feature(plugin,scoped,zero_one,iter_arith,slice_position_elem,slice_bytes,bitset,arc_weak,append,future,mpsc_select)]
-#![allow(deprecated)]
-//#![allow(unused_imports,dead_code)]
+#![feature(plugin,read_exact,zero_one,iter_arith,slice_bytes,arc_weak,append,mpsc_select)]
+#![allow(needless_return)]
 
+#![plugin(clippy)]
 #![plugin(protobuf_macros)]
 #[macro_use] extern crate lazy_static;
 
-
+extern crate bit_set;
 extern crate byteorder;
 extern crate crypto;
+extern crate eventual;
 extern crate gmp;
 extern crate num;
 extern crate portaudio;
 extern crate protobuf;
 extern crate shannon;
 extern crate rand;
-extern crate readall;
-extern crate vorbis;
 extern crate time;
 extern crate tempfile;
+extern crate vorbis;
 
 extern crate librespot_protocol;
 

+ 3 - 5
src/main.rs

@@ -1,4 +1,3 @@
-#![feature(scoped)]
 #![feature(result_expect)]
 #![allow(deprecated)]
 
@@ -71,9 +70,10 @@ fn main() {
     session.login(username.clone(), password);
     session.poll();
 
-    let poll_thread = thread::scoped(|| {
+    let _session = session.clone();
+    thread::spawn(move || {
         loop {
-            session.poll();
+            _session.poll();
         }
     });
 
@@ -81,7 +81,5 @@ fn main() {
 
     let mut spirc_manager = SpircManager::new(&session, player, username, name);
     spirc_manager.run();
-
-    poll_thread.join();
 }
 

+ 26 - 35
src/mercury.rs

@@ -1,11 +1,10 @@
 use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
+use eventual;
 use protobuf::{self, Message};
-use readall::ReadAllExt;
-use std::collections::{HashMap, LinkedList};
+use std::collections::HashMap;
 use std::io::{Cursor, Read, Write};
-use std::fmt;
 use std::mem::replace;
-use std::sync::{mpsc, Future};
+use std::sync::mpsc;
 
 use librespot_protocol as protocol;
 use session::Session;
@@ -30,13 +29,13 @@ pub struct MercuryRequest {
 #[derive(Debug)]
 pub struct MercuryResponse {
     pub uri: String,
-    pub payload: LinkedList<Vec<u8>>
+    pub payload: Vec<Vec<u8>>
 }
 
 pub struct MercuryPending {
-    parts: LinkedList<Vec<u8>>,
+    parts: Vec<Vec<u8>>,
     partial: Option<Vec<u8>>,
-    callback: Option<mpsc::Sender<MercuryResponse>>
+    callback: Option<eventual::Complete<MercuryResponse, ()>>
 }
 
 pub struct MercuryManager {
@@ -45,14 +44,14 @@ pub struct MercuryManager {
     subscriptions: HashMap<String, mpsc::Sender<MercuryResponse>>,
 }
 
-impl fmt::Display for MercuryMethod {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        formatter.write_str(match *self {
+impl ToString for MercuryMethod {
+    fn to_string(&self) -> String {
+        match *self {
             MercuryMethod::GET => "GET",
             MercuryMethod::SUB => "SUB",
             MercuryMethod::UNSUB => "UNSUB",
             MercuryMethod::SEND => "SEND"
-        })
+        }.to_owned()
     }
 }
 
@@ -66,7 +65,7 @@ impl MercuryManager {
     }
 
     pub fn request(&mut self, session: &Session, req: MercuryRequest)
-        -> Future<MercuryResponse> {
+        -> eventual::Future<MercuryResponse, ()> {
 
         let mut seq = [0u8; 4];
         BigEndian::write_u32(&mut seq, self.next_seq);
@@ -81,14 +80,14 @@ impl MercuryManager {
 
         session.send_packet(cmd, &data).unwrap();
 
-        let (tx, rx) = mpsc::channel();
+        let (tx, rx) = eventual::Future::pair();
         self.pending.insert(seq.to_vec(), MercuryPending{
-            parts: LinkedList::new(),
+            parts: Vec::new(),
             partial: None,
             callback: Some(tx),
         });
 
-        Future::from_receiver(rx)
+        rx
     }
 
     pub fn subscribe(&mut self, session: &Session, uri: String)
@@ -109,33 +108,25 @@ impl MercuryManager {
     fn parse_part(mut s: &mut Read) -> Vec<u8> {
         let size = s.read_u16::<BigEndian>().unwrap() as usize;
         let mut buffer = vec![0; size];
-        s.read_all(&mut buffer).unwrap();
+        s.read_exact(&mut buffer).unwrap();
 
         buffer
     }
 
     fn complete_request(&mut self, cmd: u8, mut pending: MercuryPending) {
-        let header_data = match pending.parts.pop_front() {
-            Some(data) => data,
-            None => panic!("No header part !")
-        };
-
+        let header_data = pending.parts.remove(0);
         let header : protocol::mercury::Header =
             protobuf::parse_from_bytes(&header_data).unwrap();
 
-        let callback = if cmd == 0xb5 {
-            self.subscriptions.get(header.get_uri())
-        } else {
-            pending.callback.as_ref()
+        let response = MercuryResponse {
+            uri: header.get_uri().to_owned(),
+            payload: pending.parts
         };
 
-        if let Some(ref ch) = callback {
-             // Ignore send error.
-             // It simply means the receiver was closed
-            ch.send(MercuryResponse{
-                uri: header.get_uri().to_string(),
-                payload: pending.parts
-            }).ignore();
+        if cmd == 0xb5 {
+            self.subscriptions.get(header.get_uri()).map(|ch| ch.send(response).ignore());
+        } else {
+            pending.callback.map(|cb| cb.complete(response));
         }
     }
 
@@ -173,7 +164,7 @@ impl PacketHandler for MercuryManager {
         let seq = {
             let seq_length = packet.read_u16::<BigEndian>().unwrap() as usize;
             let mut seq = vec![0; seq_length];
-            packet.read_all(&mut seq).unwrap();
+            packet.read_exact(&mut seq).unwrap();
             seq
         };
         let flags = packet.read_u8().unwrap();
@@ -183,7 +174,7 @@ impl PacketHandler for MercuryManager {
             pending
         } else if cmd == 0xb5 {
             MercuryPending {
-                parts: LinkedList::new(),
+                parts: Vec::new(),
                 partial: None,
                 callback: None,
             }
@@ -202,7 +193,7 @@ impl PacketHandler for MercuryManager {
             if i == count - 1 && (flags == 2) {
                 pending.partial = Some(part)
             } else {
-                pending.parts.push_back(part);
+                pending.parts.push(part);
             }
         }
 

+ 10 - 9
src/metadata.rs

@@ -1,3 +1,4 @@
+use eventual::Async;
 use protobuf::{self, Message};
 use std::any::{Any, TypeId};
 use std::collections::HashMap;
@@ -11,7 +12,7 @@ use mercury::{MercuryRequest, MercuryMethod};
 use util::{SpotifyId, FileId};
 use session::Session;
 
-pub trait MetadataTrait : Send + Any + 'static {
+pub trait MetadataTrait : Send + Sized + Any + 'static {
     type Message: protobuf::MessageStatic;
     fn from_msg(msg: &Self::Message) -> Self;
     fn base_url() -> &'static str;
@@ -29,7 +30,7 @@ impl MetadataTrait for Track {
     type Message = protocol::metadata::Track;
     fn from_msg(msg: &Self::Message) -> Self {
         Track {
-            name: msg.get_name().to_string(),
+            name: msg.get_name().to_owned(),
             album: SpotifyId::from_raw(msg.get_album().get_gid()),
             files: msg.get_file().iter()
                 .map(|file| {
@@ -59,7 +60,7 @@ impl MetadataTrait for Album {
     type Message = protocol::metadata::Album;
     fn from_msg(msg: &Self::Message) -> Self {
         Album {
-            name: msg.get_name().to_string(),
+            name: msg.get_name().to_owned(),
             artists: msg.get_artist().iter()
                 .map(|a| SpotifyId::from_raw(a.get_gid()))
                 .collect(),
@@ -89,7 +90,7 @@ impl MetadataTrait for Artist {
     type Message = protocol::metadata::Artist;
     fn from_msg(msg: &Self::Message) -> Self {
         Artist {
-            name: msg.get_name().to_string(),
+            name: msg.get_name().to_owned(),
         }
     }
     fn base_url() -> &'static str {
@@ -164,7 +165,7 @@ impl <T: MetadataTrait> MetadataState<T> {
         }
     }
 
-    pub fn unwrap<'s>(&'s self) -> &'s T {
+    pub fn unwrap(&self) -> &T {
         match *self {
             MetadataState::Loaded(ref data) => data,
             _ => panic!("Not loaded")
@@ -180,7 +181,7 @@ pub enum MetadataRequest {
 }
 
 pub struct MetadataManager {
-    cache: HashMap<(SpotifyId, TypeId), Box<Any + Send>>
+    cache: HashMap<(SpotifyId, TypeId), Box<Any + Send + 'static>>
 }
 
 impl MetadataManager {
@@ -204,7 +205,7 @@ impl MetadataManager {
                     cond: Condvar::new()
                 });
 
-                self.cache.insert(key, Box::new(x.downgrade()));
+                self.cache.insert(key, Box::new(Arc::downgrade(&x)));
                 self.load(session, x.clone());
                 x
             })
@@ -219,10 +220,10 @@ impl MetadataManager {
         });
 
         thread::spawn(move || {
-            let response = rx.into_inner();
+            let response = rx.await().unwrap();
 
             let msg : T::Message = protobuf::parse_from_bytes(
-                response.payload.front().unwrap()).unwrap();
+                response.payload.first().unwrap()).unwrap();
 
             object.set(MetadataState::Loaded(T::from_msg(&msg)));
         });

+ 15 - 16
src/player.rs

@@ -1,7 +1,8 @@
+use eventual::Async;
 use portaudio;
-use vorbis;
 use std::sync::{mpsc, Mutex, Arc, Condvar, MutexGuard};
 use std::thread;
+use vorbis;
 
 use metadata::TrackRef;
 use session::Session;
@@ -9,13 +10,10 @@ use audio_decrypt::AudioDecrypt;
 use util::{self, SpotifyId, Subfile};
 use spirc::{SpircState, SpircDelegate, PlayStatus};
 
-pub struct Player<'s> {
+pub struct Player {
     state: Arc<(Mutex<PlayerState>, Condvar)>,
 
     commands: mpsc::Sender<PlayerCommand>,
-
-    #[allow(dead_code)]
-    thread: thread::JoinGuard<'s, ()>,
 }
 
 pub struct PlayerState {
@@ -27,10 +25,9 @@ pub struct PlayerState {
     end_of_track: bool
 }
 
-struct PlayerInternal<'s> {
+struct PlayerInternal {
     state: Arc<(Mutex<PlayerState>, Condvar)>,
-
-    session: &'s Session,
+    session: Session,
     commands: mpsc::Receiver<PlayerCommand>,
 }
 
@@ -42,7 +39,7 @@ enum PlayerCommand {
     Seek(u32)
 }
 
-impl <'s> Player<'s> {
+impl Player {
     pub fn new(session: &Session) -> Player {
         let (cmd_tx, cmd_rx) = mpsc::channel();
 
@@ -55,17 +52,18 @@ impl <'s> Player<'s> {
         }), Condvar::new()));
 
         let internal = PlayerInternal {
-            session: session,
+            session: session.clone(),
             commands: cmd_rx,
             state: state.clone()
         };
 
+        thread::spawn(move || {
+            internal.run()
+        });
+
         Player {
             commands: cmd_tx,
             state: state,
-            thread: thread::scoped(move || {
-                internal.run()
-            })
         }
     }
 
@@ -74,7 +72,7 @@ impl <'s> Player<'s> {
     }
 }
 
-impl <'s> PlayerInternal<'s> {
+impl PlayerInternal {
     fn run(self) {
         portaudio::initialize().unwrap();
 
@@ -102,7 +100,8 @@ impl <'s> PlayerInternal<'s> {
 
                     let track : TrackRef = self.session.metadata(id);
                     let file_id = *track.wait().unwrap().files.first().unwrap();
-                    let key = self.session.audio_key(track.id(), file_id).into_inner();
+
+                    let key = self.session.audio_key(track.id(), file_id).await().unwrap();
                     decoder = Some(
                         vorbis::Decoder::new(
                         Subfile::new(
@@ -217,7 +216,7 @@ impl <'s> PlayerInternal<'s> {
     }
 }
 
-impl <'s> SpircDelegate for Player<'s> {
+impl SpircDelegate for Player {
     type State = PlayerState;
 
     fn load(&self, track: SpotifyId,

+ 26 - 24
src/session.rs

@@ -1,8 +1,9 @@
 use crypto::digest::Digest;
 use crypto::sha1::Sha1;
+use eventual::Future;
 use protobuf::{self, Message};
 use rand::thread_rng;
-use std::sync::{Mutex, Arc, Future, mpsc};
+use std::sync::{Mutex, Arc, mpsc};
 use std::path::PathBuf;
 
 use connection::{self, PlainConnection, CipherConnection};
@@ -26,7 +27,7 @@ pub struct Config {
     pub cache_location: PathBuf,
 }
 
-pub struct Session {
+pub struct SessionData {
     pub config: Config,
 
     mercury: Mutex<MercuryManager>,
@@ -38,7 +39,8 @@ pub struct Session {
     tx_connection: Mutex<CipherConnection>,
 }
 
-type SessionRef = Arc<Session>;
+#[derive(Clone)]
+pub struct Session(pub Arc<SessionData>);
 
 impl Session {
     pub fn new(mut config: Config) -> Session {
@@ -114,7 +116,7 @@ impl Session {
 
         let cipher_connection = connection.setup_cipher(shared_keys);
 
-        Session {
+        Session(Arc::new(SessionData {
             config: config,
 
             rx_connection: Mutex::new(cipher_connection.clone()),
@@ -125,7 +127,7 @@ impl Session {
             stream: Mutex::new(StreamManager::new()),
             audio_key: Mutex::new(AudioKeyManager::new()),
             audio_file: Mutex::new(AudioFileManager::new()),
-        }
+        }))
     }
 
     pub fn login(&self, username: String, password: String) {
@@ -138,15 +140,15 @@ impl Session {
             system_info => {
                 cpu_family: protocol::authentication::CpuFamily::CPU_UNKNOWN,
                 os: protocol::authentication::Os::OS_UNKNOWN,
-                system_information_string: "librespot".to_string(),
-                device_id: self.config.device_id.clone()
+                system_information_string: "librespot".to_owned(),
+                device_id: self.0.config.device_id.clone()
             },
             version_string: util::version::version_string(),
             appkey => {
-                version: self.config.application_key[0] as u32,
-                devkey: self.config.application_key[0x1..0x81].to_vec(),
-                signature: self.config.application_key[0x81..0x141].to_vec(),
-                useragent: self.config.user_agent.clone(),
+                version: self.0.config.application_key[0] as u32,
+                devkey: self.0.config.application_key[0x1..0x81].to_vec(),
+                signature: self.0.config.application_key[0x81..0x141].to_vec(),
+                useragent: self.0.config.user_agent.clone(),
                 callback_hash: vec![0; 20],
             }
         });
@@ -156,14 +158,14 @@ impl Session {
 
     pub fn poll(&self) {
         let (cmd, data) =
-            self.rx_connection.lock().unwrap().recv_packet().unwrap();
+            self.0.rx_connection.lock().unwrap().recv_packet().unwrap();
 
         match cmd {
             0x4 => self.send_packet(0x49, &data).unwrap(),
             0x4a => (),
-            0x9  => self.stream.lock().unwrap().handle(cmd, data),
-            0xd | 0xe => self.audio_key.lock().unwrap().handle(cmd, data),
-            0xb2...0xb6 => self.mercury.lock().unwrap().handle(cmd, data),
+            0x9  => self.0.stream.lock().unwrap().handle(cmd, data),
+            0xd | 0xe => self.0.audio_key.lock().unwrap().handle(cmd, data),
+            0xb2...0xb6 => self.0.mercury.lock().unwrap().handle(cmd, data),
             0xac => eprintln!("Authentication succeedded"),
             0xad => eprintln!("Authentication failed"),
             _ => ()
@@ -171,31 +173,31 @@ impl Session {
     }
 
     pub fn send_packet(&self, cmd: u8, data: &[u8]) -> connection::Result<()> {
-        self.tx_connection.lock().unwrap().send_packet(cmd, data)
+        self.0.tx_connection.lock().unwrap().send_packet(cmd, data)
     }
     
-    pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey> {
-        self.audio_key.lock().unwrap().request(self, track, file)
+    pub fn audio_key(&self, track: SpotifyId, file: FileId) -> Future<AudioKey, ()> {
+        self.0.audio_key.lock().unwrap().request(self, track, file)
     }
 
     pub fn audio_file(&self, file: FileId) -> AudioFile {
-        self.audio_file.lock().unwrap().request(self, file)
+        self.0.audio_file.lock().unwrap().request(self, file)
     }
 
     pub fn stream(&self, file: FileId, offset: u32, size: u32) -> mpsc::Receiver<StreamEvent> {
-        self.stream.lock().unwrap().request(self, file, offset, size)
+        self.0.stream.lock().unwrap().request(self, file, offset, size)
     }
 
     pub fn metadata<T: MetadataTrait>(&self, id: SpotifyId) -> MetadataRef<T> {
-        self.metadata.lock().unwrap().get(self, id)
+        self.0.metadata.lock().unwrap().get(self, id)
     }
 
-    pub fn mercury(&self, req: MercuryRequest) -> Future<MercuryResponse> {
-        self.mercury.lock().unwrap().request(self, req)
+    pub fn mercury(&self, req: MercuryRequest) -> Future<MercuryResponse, ()> {
+        self.0.mercury.lock().unwrap().request(self, req)
     }
 
     pub fn mercury_sub(&self, uri: String) -> mpsc::Receiver<MercuryResponse> {
-        self.mercury.lock().unwrap().subscribe(self, uri)
+        self.0.mercury.lock().unwrap().subscribe(self, uri)
     }
 }
 

+ 20 - 18
src/spirc.rs

@@ -1,3 +1,4 @@
+use eventual::Async;
 use protobuf::{self, Message};
 use std::sync::{mpsc, MutexGuard};
 
@@ -70,7 +71,7 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
             seq_nr: 0,
 
             name: name,
-            ident: session.config.device_id.clone(),
+            ident: session.0.config.device_id.clone(),
             device_type: 5,
             can_play: true,
 
@@ -97,7 +98,8 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
             select! {
                 pkt = rx.recv() => {
                     let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(
-                        pkt.unwrap().payload.front().unwrap()).unwrap();
+                        pkt.unwrap().payload.first().unwrap()).unwrap();
+
                     println!("{:?} {} {} {} {}",
                              frame.get_typ(),
                              frame.get_device_state().get_name(),
@@ -127,7 +129,7 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
 
     fn handle(&mut self, frame: protocol::spirc::Frame) {
         if frame.get_recipient().len() > 0 {
-            self.last_command_ident = frame.get_ident().to_string();
+            self.last_command_ident = frame.get_ident().to_owned();
             self.last_command_msgid = frame.get_seq_nr();
         }
         match frame.get_typ() {
@@ -174,12 +176,12 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
         let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
             version: 1,
             ident: self.ident.clone(),
-            protocol_version: "2.0.0".to_string(),
+            protocol_version: "2.0.0".to_owned(),
             seq_nr: { self.seq_nr += 1; self.seq_nr  },
             typ: protocol::spirc::MessageType::kMessageTypeNotify,
             device_state: self.device_state(),
             recipient: protobuf::RepeatedField::from_vec(
-                recipient.map(|r| vec![r.to_string()] ).unwrap_or(vec![])
+                recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
             ),
             state_update_id: self.state_update_id as i64
         });
@@ -193,7 +195,7 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
             uri: format!("hm://remote/user/{}", self.username),
             content_type: None,
             payload: vec![ pkt.write_to_bytes().unwrap() ]
-        });
+        }).await().unwrap();
     }
 
     fn spirc_state(&self) -> protocol::spirc::State {
@@ -259,23 +261,23 @@ impl <'s, D: SpircDelegate> SpircManager<'s, D> {
                 @{
                     typ: protocol::spirc::CapabilityType::kSupportedContexts,
                     stringValue => [
-                        "album".to_string(),
-                        "playlist".to_string(),
-                        "search".to_string(),
-                        "inbox".to_string(),
-                        "toplist".to_string(),
-                        "starred".to_string(),
-                        "publishedstarred".to_string(),
-                        "track".to_string(),
+                        "album".to_owned(),
+                        "playlist".to_owned(),
+                        "search".to_owned(),
+                        "inbox".to_owned(),
+                        "toplist".to_owned(),
+                        "starred".to_owned(),
+                        "publishedstarred".to_owned(),
+                        "track".to_owned(),
                     ]
                 },
                 @{
                     typ: protocol::spirc::CapabilityType::kSupportedTypes,
                     stringValue => [
-                        "audio/local".to_string(),
-                        "audio/track".to_string(),
-                        "local".to_string(),
-                        "track".to_string(),
+                        "audio/local".to_owned(),
+                        "audio/track".to_owned(),
+                        "local".to_owned(),
+                        "track".to_owned(),
                     ]
                 }
             ],

+ 3 - 3
src/util/spotify_id.rs

@@ -19,7 +19,7 @@ impl SpotifyId {
 
         let mut n : u128 = std::num::Zero::zero();
         for c in data {
-            let d = BASE16_DIGITS.position_elem(c).unwrap() as u8;
+            let d = BASE16_DIGITS.iter().position(|e| e == c).unwrap() as u8;
             n = n * u128::from(16);
             n = n + u128::from(d);
         }
@@ -33,7 +33,7 @@ impl SpotifyId {
 
         let mut n : u128 = std::num::Zero::zero();
         for c in data {
-            let d = BASE62_DIGITS.position_elem(c).unwrap() as u8;
+            let d = BASE62_DIGITS.iter().position(|e| e == c).unwrap() as u8;
             n = n * u128::from(62);
             n = n + u128::from(d);
         }
@@ -62,7 +62,7 @@ impl SpotifyId {
             data[15-i] = BASE16_DIGITS[(high.wrapping_shr(4 * i as u32) & 0xF) as usize];
         }
 
-        std::str::from_utf8(&data).unwrap().to_string()
+        std::str::from_utf8(&data).unwrap().to_owned()
     }
 
     pub fn to_raw(&self) -> [u8; 16] {

+ 2 - 2
src/util/zerofile.rs

@@ -33,8 +33,8 @@ impl io::Read for ZeroFile {
     // TODO optimize with memset or similar
     fn read(&mut self, output: &mut [u8]) -> io::Result<usize> {
         let len = min(output.len(), (self.size - self.position) as usize);
-        for i in 0..len {
-            output[i] = 0;
+        for b in output {
+            *b = 0;
         }
 
         self.position += len as u64;