Browse Source

Fix build on latest rust.

Paul Lietar 9 năm trước cách đây
mục cha
commit
267ccbe65e
14 tập tin đã thay đổi với 290 bổ sung256 xóa
  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;