mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
parent
2853e2230b
commit
d940ed161a
12 changed files with 437 additions and 194 deletions
161
Cargo.lock
generated
161
Cargo.lock
generated
|
@ -6,7 +6,6 @@ dependencies = [
|
|||
"base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -27,13 +26,14 @@ dependencies = [
|
|||
"rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)",
|
||||
"tempfile 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)",
|
||||
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -61,7 +61,7 @@ name = "aster"
|
|||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -72,6 +72,14 @@ dependencies = [
|
|||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.4.0"
|
||||
|
@ -100,6 +108,11 @@ name = "bitflags"
|
|||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "0.5.3"
|
||||
|
@ -120,16 +133,6 @@ name = "crossbeam"
|
|||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dns-parser"
|
||||
version = "0.3.2"
|
||||
|
@ -169,7 +172,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "futures-cpupool"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -195,11 +198,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.11.0-a.0"
|
||||
source = "git+https://github.com/hyperium/hyper#2f18ce20348392893f6815519f8c0ad2b5649e66"
|
||||
source = "git+https://github.com/hyperium/hyper#435fe84bf52fbbf819068402d6c8e902aa7a6685"
|
||||
dependencies = [
|
||||
"base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -220,7 +223,7 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -336,6 +339,15 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.0"
|
||||
|
@ -454,8 +466,8 @@ version = "0.6.0"
|
|||
source = "git+https://github.com/plietar/rust-protobuf-macros#f186dc5a16c0d79f14c319ac8ce30b06de0cefee"
|
||||
dependencies = [
|
||||
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -465,7 +477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.12"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -489,7 +501,7 @@ dependencies = [
|
|||
"aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -554,36 +566,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.9.6"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_codegen_internals"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "0.9.6"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "0.9.5"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -617,37 +629,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.11.4"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntex"
|
||||
version = "0.58.0"
|
||||
version = "0.58.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntex_errors"
|
||||
version = "0.58.0"
|
||||
version = "0.58.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntex_pos"
|
||||
version = "0.58.0"
|
||||
version = "0.58.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -655,14 +676,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syntex_syntax"
|
||||
version = "0.58.0"
|
||||
version = "0.58.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -711,7 +732,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -765,6 +786,20 @@ dependencies = [
|
|||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-signal"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tremor"
|
||||
version = "0.1.0"
|
||||
|
@ -795,7 +830,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -919,22 +954,23 @@ dependencies = [
|
|||
"checksum alsa 0.0.1 (git+https://github.com/plietar/rust-alsa)" = "<none>"
|
||||
"checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0"
|
||||
"checksum base64 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d156a04ec694d726e92ea3c13e4a62949b4f0488a9344f04341d679ec6b127b"
|
||||
"checksum base64 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065a0ce220ab84d0b6d5ae3e7bb77232209519c366f51f946fe28c19e84989d0"
|
||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
|
||||
"checksum bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32866f4d103c4e438b1db1158aa1b1a80ee078e5d77a59a2f906fd62a577389c"
|
||||
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
|
||||
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
|
||||
"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
|
||||
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
||||
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
|
||||
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
|
||||
"checksum ctrlc 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77f98bb69e3fefadcc5ca80a1368a55251f70295168203e01165bcaecb270891"
|
||||
"checksum dns-parser 0.3.2 (git+https://github.com/plietar/dns-parser)" = "<none>"
|
||||
"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
|
||||
"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
|
||||
"checksum error-chain 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e92ecf0a508c8e074c0e6fa8fe0fa38414848ad4dfc4db6f74c5e9753330b248"
|
||||
"checksum futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c1913eb7083840b1bbcbf9631b7fda55eaf35fe7ead13cca034e8946f9e2bc41"
|
||||
"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
|
||||
"checksum futures-cpupool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e48a3fff6a58fe9df1eed13d2599650416a987386c43a19aec656c3e6a2c229"
|
||||
"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
|
||||
"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
|
||||
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
|
||||
|
@ -954,6 +990,7 @@ dependencies = [
|
|||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
"checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
|
||||
"checksum mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "eecdbdd49a849336e77b453f021c89972a2cfb5b51931a0026ae0ac4602de681"
|
||||
"checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de"
|
||||
"checksum miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a78d2605eb97302c10cf944b8d96b0a2a890c52957caf92fcd1f24f69049579"
|
||||
"checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2"
|
||||
"checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2"
|
||||
|
@ -969,7 +1006,7 @@ dependencies = [
|
|||
"checksum protobuf 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22eaac7d4be49a479dbd875f6f84ab79eef282aa51ba36ce884ec10efd91d355"
|
||||
"checksum protobuf_macros 0.6.0 (git+https://github.com/plietar/rust-protobuf-macros)" = "<none>"
|
||||
"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
|
||||
"checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"
|
||||
"checksum quote 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08de3f12e670f83f61e450443cbae34496a35b665691fd8e99b24ec662f75865"
|
||||
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
|
||||
"checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
|
||||
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
|
||||
|
@ -981,33 +1018,35 @@ dependencies = [
|
|||
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
||||
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||
"checksum serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ae9a3c8b07c09dbe43022486d55a18c629a0618d2241e49829aaef9b6d862f9"
|
||||
"checksum serde_codegen_internals 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3172bf2940b975c0e4f6ab42a511c0a4407d4f46ccef87a9d3615db5c26fa96"
|
||||
"checksum serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecc6e0379ca933ece58302d2d3034443f06fbf38fd535857c1dc516195cbc3bf"
|
||||
"checksum serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cf37ce931677e98b4fa5e6469aaa3ab4b6228309ea33b1b22d3ec055adfc4515"
|
||||
"checksum serde 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "204db0f2a5335be7313fd4453132fd56d2085aed081c673140a256772903e116"
|
||||
"checksum serde_codegen_internals 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5113d5bd16471b183803b374f0fe4877ad9658b95e33b11f4a004d73aacc74a"
|
||||
"checksum serde_derive 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e88ec062a02cbebfd6276044a305d665a9919b497aa6acb2e12c070d1a50d32d"
|
||||
"checksum serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6501ac6f8b74f9b1033f7ddf79a08edfa0f58d6f8e3190cb8dc97736afa257a8"
|
||||
"checksum shannon 0.1.1 (git+https://github.com/plietar/rust-shannon)" = "<none>"
|
||||
"checksum shannon-sys 0.1.0 (git+https://github.com/plietar/rust-shannon)" = "<none>"
|
||||
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
|
||||
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||
"checksum syn 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f94368aae82bb29656c98443a7026ca931a659e8d19dcdc41d6e273054e820"
|
||||
"checksum syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35f3cc9d446323ef8fefad933b65cd6de271d29fa14a2e9d036a084770c6d6d5"
|
||||
"checksum syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3af03823ea45d420dd2c1a44bb074e13ea55f9b99afe960fd58eb4069b7f6cad"
|
||||
"checksum syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e502a4a904d9f37cf975dbdbb0b08f2d111322f6792bda6eb095b4112c9a24b"
|
||||
"checksum syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf936464c3863952ea3fab848860ea891eba8647b6008b04c36f0bb007192a3"
|
||||
"checksum syn 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e28da8d02d75d1e58b89258e0741128f0b0d8a8309fb5c627be0fbd37a76c67"
|
||||
"checksum synom 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8fece1853fb872b0acdc3ff88f37c474018e125ef81cd4cb8c0ca515746b62ed"
|
||||
"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e"
|
||||
"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c"
|
||||
"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047"
|
||||
"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791"
|
||||
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
|
||||
"checksum tempfile 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3213fd2b7ed87e39306737ccfac04b1233b57a33ca64cfbf52f2ffaa2b765e2f"
|
||||
"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
|
||||
"checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a"
|
||||
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
|
||||
"checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d"
|
||||
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
|
||||
"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
|
||||
"checksum tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1be481b55126f02ef88ff86748086473cb537a949fc4a8f4be403a530ae54b"
|
||||
"checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808"
|
||||
"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
|
||||
"checksum tokio-signal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d121715f6917878a0df69f39365d01dd66c4463e4ba19efdcddcdfeb1bcb2bc"
|
||||
"checksum tremor 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
|
||||
"checksum tremor-sys 0.1.0 (git+https://github.com/plietar/rust-tremor)" = "<none>"
|
||||
"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
|
||||
"checksum unicode-bidi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b61814f3e7fd0e0f15370f767c7c943e08bc2e3214233ae8f88522b334ceb778"
|
||||
"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
|
||||
"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
|
|
|
@ -25,7 +25,6 @@ path = "protocol"
|
|||
base64 = "0.3.0"
|
||||
bit-set = "0.4.0"
|
||||
byteorder = "1.0"
|
||||
ctrlc = { version = "2.0", features = ["termination"] }
|
||||
env_logger = "0.4.0"
|
||||
getopts = "0.2.14"
|
||||
hyper = { git = "https://github.com/hyperium/hyper" }
|
||||
|
@ -59,6 +58,7 @@ error-chain = { version = "0.9.0", default_features = false }
|
|||
futures = "0.1.8"
|
||||
tokio-core = "0.1.2"
|
||||
tokio-proto = "0.1.0"
|
||||
tokio-signal = "0.1"
|
||||
|
||||
[build-dependencies]
|
||||
vergen = "0.1.0"
|
||||
|
|
|
@ -4,7 +4,7 @@ use crypto::mac::Mac;
|
|||
use crypto;
|
||||
use diffie_hellman::{DH_GENERATOR, DH_PRIME};
|
||||
use futures::sync::mpsc;
|
||||
use futures::{Future, Stream, BoxFuture};
|
||||
use futures::{Future, Stream, BoxFuture, Poll, Async};
|
||||
use hyper::server::{Service, NewService, Request, Response, Http};
|
||||
use hyper::{self, Get, Post, StatusCode};
|
||||
use mdns;
|
||||
|
@ -12,7 +12,6 @@ use num_bigint::BigUint;
|
|||
use rand;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use tokio_core::net::TcpListener;
|
||||
use tokio_core::reactor::Handle;
|
||||
|
@ -51,26 +50,6 @@ impl Discovery {
|
|||
|
||||
(discovery, rx)
|
||||
}
|
||||
|
||||
pub fn serve(&self, addr: &SocketAddr, handle: &Handle)
|
||||
-> hyper::Result<SocketAddr>
|
||||
{
|
||||
let listener = TcpListener::bind(addr, handle)?;
|
||||
let addr = listener.local_addr()?;
|
||||
|
||||
let http = Http::new();
|
||||
let svc = self.clone();
|
||||
let handle_ = handle.clone();
|
||||
|
||||
let task = listener.incoming().for_each(move |(socket, addr)| {
|
||||
http.bind_connection(&handle_, socket, addr, svc.clone());
|
||||
Ok(())
|
||||
});
|
||||
|
||||
handle.spawn(task.map_err(|e| panic!(e)));
|
||||
|
||||
Ok(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl Discovery {
|
||||
|
@ -189,7 +168,9 @@ impl Service for Discovery {
|
|||
params.extend(url::form_urlencoded::parse(query.as_bytes()).into_owned());
|
||||
}
|
||||
|
||||
if method != Get {
|
||||
debug!("{:?} {:?} {:?}", method, uri.path(), params);
|
||||
}
|
||||
|
||||
let this = self.clone();
|
||||
body.fold(Vec::new(), |mut acc, chunk| {
|
||||
|
@ -219,34 +200,51 @@ impl NewService for Discovery {
|
|||
}
|
||||
}
|
||||
|
||||
use tokio_core::reactor::Core;
|
||||
pub struct DiscoveryStream {
|
||||
credentials: mpsc::UnboundedReceiver<Credentials>,
|
||||
_svc: mdns::Service,
|
||||
task: Box<Future<Item=(), Error=io::Error>>,
|
||||
}
|
||||
|
||||
pub fn discovery_login<A,B>(device_name: A, device_id: B) -> Result<Credentials, ()>
|
||||
where A: Into<String>,
|
||||
B: Into<String>
|
||||
pub fn discovery(handle: &Handle, device_name: String, device_id: String)
|
||||
-> io::Result<DiscoveryStream>
|
||||
{
|
||||
let device_name = device_name.into();
|
||||
let device_id = device_id.into();
|
||||
|
||||
let (discovery, creds_rx) = Discovery::new(device_name.clone(), device_id);
|
||||
|
||||
let creds_rx = creds_rx.into_future()
|
||||
.map(move |(creds, _)| creds.unwrap()).map_err(|(e, _)| e);
|
||||
let listener = TcpListener::bind(&"0.0.0.0:0".parse().unwrap(), handle)?;
|
||||
let addr = listener.local_addr()?;
|
||||
|
||||
let addr = "0.0.0.0:0".parse().unwrap();
|
||||
let http = Http::new();
|
||||
let handle_ = handle.clone();
|
||||
let task = Box::new(listener.incoming().for_each(move |(socket, addr)| {
|
||||
http.bind_connection(&handle_, socket, addr, discovery.clone());
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
let mut core = Core::new().unwrap();
|
||||
let handle = core.handle();
|
||||
let listening_addr = discovery.serve(&addr, &handle).unwrap();
|
||||
|
||||
let responder = mdns::Responder::spawn(&handle).unwrap();
|
||||
let _svc = responder.register(
|
||||
let responder = mdns::Responder::spawn(&handle)?;
|
||||
let svc = responder.register(
|
||||
"_spotify-connect._tcp".to_owned(),
|
||||
device_name,
|
||||
listening_addr.port(),
|
||||
addr.port(),
|
||||
&["VERSION=1.0", "CPath=/"]);
|
||||
|
||||
let creds = core.run(creds_rx).unwrap();
|
||||
|
||||
Ok(creds)
|
||||
Ok(DiscoveryStream {
|
||||
credentials: creds_rx,
|
||||
_svc: svc,
|
||||
task: task,
|
||||
})
|
||||
}
|
||||
|
||||
impl Stream for DiscoveryStream {
|
||||
type Item = Credentials;
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
match self.task.poll()? {
|
||||
Async::Ready(()) => unreachable!(),
|
||||
Async::NotReady => (),
|
||||
}
|
||||
|
||||
Ok(self.credentials.poll().unwrap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ use std::path::Path;
|
|||
|
||||
use protocol::authentication::AuthenticationType;
|
||||
|
||||
pub mod discovery;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Credentials {
|
||||
|
@ -169,35 +171,28 @@ fn deserialize_base64<D>(de: D) -> Result<Vec<u8>, D::Error>
|
|||
base64::decode(&v).map_err(|e| serde::de::Error::custom(e.to_string()))
|
||||
}
|
||||
|
||||
mod discovery;
|
||||
pub use self::discovery::discovery_login;
|
||||
|
||||
pub fn get_credentials(device_name: &str, device_id: &str,
|
||||
username: Option<String>, password: Option<String>,
|
||||
pub fn get_credentials(username: Option<String>, password: Option<String>,
|
||||
cached_credentials: Option<Credentials>)
|
||||
-> Credentials
|
||||
-> Option<Credentials>
|
||||
{
|
||||
match (username, password, cached_credentials) {
|
||||
|
||||
(Some(username), Some(password), _)
|
||||
=> Credentials::with_password(username, password),
|
||||
=> Some(Credentials::with_password(username, password)),
|
||||
|
||||
(Some(ref username), _, Some(ref credentials))
|
||||
if *username == credentials.username => credentials.clone(),
|
||||
if *username == credentials.username => Some(credentials.clone()),
|
||||
|
||||
(Some(username), None, _) => {
|
||||
write!(stderr(), "Password for {}: ", username).unwrap();
|
||||
stderr().flush().unwrap();
|
||||
let password = rpassword::read_password().unwrap();
|
||||
Credentials::with_password(username.clone(), password)
|
||||
Some(Credentials::with_password(username.clone(), password))
|
||||
}
|
||||
|
||||
(None, _, Some(credentials))
|
||||
=> credentials,
|
||||
=> Some(credentials),
|
||||
|
||||
(None, _, None) => {
|
||||
info!("No username provided and no stored credentials, starting discovery ...");
|
||||
discovery_login(device_name, device_id).unwrap()
|
||||
}
|
||||
(None, _, None) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ macro_rules! component {
|
|||
impl $name {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(session: $crate::session::SessionWeak) -> $name {
|
||||
debug!(target:"librespot::component", "new {}", stringify!($name));
|
||||
|
||||
$name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
|
||||
$($key : $value,)*
|
||||
}))))
|
||||
|
@ -25,6 +27,12 @@ macro_rules! component {
|
|||
struct $inner {
|
||||
$($key : $ty,)*
|
||||
}
|
||||
|
||||
impl Drop for $inner {
|
||||
fn drop(&mut self) {
|
||||
debug!(target:"librespot::component", "drop {}", stringify!($name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
202
src/main.rs
202
src/main.rs
|
@ -1,23 +1,25 @@
|
|||
#[macro_use] extern crate log;
|
||||
extern crate ctrlc;
|
||||
extern crate env_logger;
|
||||
extern crate futures;
|
||||
extern crate getopts;
|
||||
extern crate librespot;
|
||||
extern crate tokio_core;
|
||||
extern crate tokio_signal;
|
||||
|
||||
use env_logger::LogBuilder;
|
||||
use futures::Future;
|
||||
use std::cell::{RefCell, Cell};
|
||||
use futures::{Future, Async, Poll, Stream};
|
||||
use std::env;
|
||||
use std::io::{stderr, Write};
|
||||
use std::io::{self, stderr, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::process::exit;
|
||||
use std::str::FromStr;
|
||||
use tokio_core::reactor::Core;
|
||||
use tokio_core::reactor::{Handle, Core};
|
||||
use tokio_core::io::IoStream;
|
||||
use std::mem;
|
||||
|
||||
use librespot::spirc::Spirc;
|
||||
use librespot::spirc::{Spirc, SpircTask};
|
||||
use librespot::authentication::{get_credentials, Credentials};
|
||||
use librespot::authentication::discovery::{discovery, DiscoveryStream};
|
||||
use librespot::audio_backend::{self, Sink, BACKENDS};
|
||||
use librespot::cache::Cache;
|
||||
use librespot::player::Player;
|
||||
|
@ -33,7 +35,6 @@ fn usage(program: &str, opts: &getopts::Options) -> String {
|
|||
|
||||
fn setup_logging(verbose: bool) {
|
||||
let mut builder = LogBuilder::new();
|
||||
|
||||
match env::var("RUST_LOG") {
|
||||
Ok(config) => {
|
||||
builder.parse(&config);
|
||||
|
@ -65,13 +66,17 @@ fn list_backends() {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Setup {
|
||||
backend: fn(Option<String>) -> Box<Sink>,
|
||||
mixer: Box<Mixer + Send>,
|
||||
device: Option<String>,
|
||||
|
||||
mixer: fn() -> Box<Mixer>,
|
||||
|
||||
cache: Option<Cache>,
|
||||
config: Config,
|
||||
credentials: Credentials,
|
||||
device: Option<String>,
|
||||
credentials: Option<Credentials>,
|
||||
enable_discovery: bool,
|
||||
}
|
||||
|
||||
fn setup(args: &[String]) -> Setup {
|
||||
|
@ -84,6 +89,7 @@ fn setup(args: &[String]) -> Setup {
|
|||
.optflag("v", "verbose", "Enable verbose output")
|
||||
.optopt("u", "username", "Username to sign in with", "USERNAME")
|
||||
.optopt("p", "password", "Password", "PASSWORD")
|
||||
.optflag("", "disable-discovery", "Disable discovery mode")
|
||||
.optopt("", "backend", "Audio backend to use. Use '?' to list options", "BACKEND")
|
||||
.optopt("", "device", "Audio device to use. Use '?' to list options", "DEVICE")
|
||||
.optopt("", "mixer", "Mixer to use", "MIXER");
|
||||
|
@ -130,11 +136,12 @@ fn setup(args: &[String]) -> Setup {
|
|||
|
||||
let cached_credentials = cache.as_ref().and_then(Cache::credentials);
|
||||
|
||||
let credentials = get_credentials(&name, &device_id,
|
||||
matches.opt_str("username"),
|
||||
let credentials = get_credentials(matches.opt_str("username"),
|
||||
matches.opt_str("password"),
|
||||
cached_credentials);
|
||||
|
||||
let enable_discovery = !matches.opt_present("disable-discovery");
|
||||
|
||||
let config = Config {
|
||||
user_agent: version::version_string(),
|
||||
name: name,
|
||||
|
@ -148,11 +155,143 @@ fn setup(args: &[String]) -> Setup {
|
|||
|
||||
Setup {
|
||||
backend: backend,
|
||||
mixer: mixer,
|
||||
cache: cache,
|
||||
config: config,
|
||||
credentials: credentials,
|
||||
device: device,
|
||||
enable_discovery: enable_discovery,
|
||||
mixer: mixer,
|
||||
}
|
||||
}
|
||||
|
||||
struct Main {
|
||||
cache: Option<Cache>,
|
||||
config: Config,
|
||||
backend: fn(Option<String>) -> Box<Sink>,
|
||||
device: Option<String>,
|
||||
mixer: fn() -> Box<Mixer>,
|
||||
handle: Handle,
|
||||
|
||||
discovery: Option<DiscoveryStream>,
|
||||
signal: IoStream<()>,
|
||||
|
||||
spirc: Option<Spirc>,
|
||||
spirc_task: Option<SpircTask>,
|
||||
connect: Box<Future<Item=Session, Error=io::Error>>,
|
||||
|
||||
shutdown: bool,
|
||||
}
|
||||
|
||||
impl Main {
|
||||
fn new(handle: Handle,
|
||||
config: Config,
|
||||
backend: fn(Option<String>) -> Box<Sink>,
|
||||
device: Option<String>,
|
||||
mixer: fn() -> Box<Mixer>) -> Main
|
||||
{
|
||||
Main {
|
||||
handle: handle.clone(),
|
||||
config: config,
|
||||
backend: backend,
|
||||
device: device,
|
||||
mixer: mixer,
|
||||
|
||||
cache: None,
|
||||
connect: Box::new(futures::future::empty()),
|
||||
discovery: None,
|
||||
spirc: None,
|
||||
spirc_task: None,
|
||||
shutdown: false,
|
||||
signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
|
||||
}
|
||||
}
|
||||
|
||||
fn discovery(&mut self) {
|
||||
let name = self.config.name.clone();
|
||||
let device_id = self.config.device_id.clone();
|
||||
self.discovery = Some(discovery(&self.handle, name, device_id).unwrap());
|
||||
}
|
||||
|
||||
fn credentials(&mut self, credentials: Credentials) {
|
||||
let config = self.config.clone();
|
||||
let handle = self.handle.clone();
|
||||
let connection = Session::connect(config, credentials, self.cache.clone(), handle);
|
||||
|
||||
self.connect = connection;
|
||||
self.spirc = None;
|
||||
let task = mem::replace(&mut self.spirc_task, None);
|
||||
if let Some(task) = task {
|
||||
self.handle.spawn(task);
|
||||
}
|
||||
}
|
||||
|
||||
fn cache(&mut self, cache: Cache) {
|
||||
self.cache = Some(cache);
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for Main {
|
||||
type Item = ();
|
||||
type Error = ();
|
||||
|
||||
fn poll(&mut self) -> Poll<(), ()> {
|
||||
loop {
|
||||
let mut progress = false;
|
||||
|
||||
if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
|
||||
if let Some(ref spirc) = self.spirc {
|
||||
spirc.shutdown();
|
||||
}
|
||||
self.credentials(creds);
|
||||
|
||||
progress = true;
|
||||
}
|
||||
|
||||
if let Async::Ready(session) = self.connect.poll().unwrap() {
|
||||
self.connect = Box::new(futures::future::empty());
|
||||
let device = self.device.clone();
|
||||
let mixer = (self.mixer)();
|
||||
|
||||
let audio_filter = mixer.get_audio_filter();
|
||||
let backend = self.backend;
|
||||
let player = Player::new(session.clone(), audio_filter, move || {
|
||||
(backend)(device)
|
||||
});
|
||||
|
||||
let (spirc, spirc_task) = Spirc::new(session, player, mixer);
|
||||
self.spirc = Some(spirc);
|
||||
self.spirc_task = Some(spirc_task);
|
||||
|
||||
progress = true;
|
||||
}
|
||||
|
||||
if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
|
||||
if !self.shutdown {
|
||||
if let Some(ref spirc) = self.spirc {
|
||||
spirc.shutdown();
|
||||
}
|
||||
self.shutdown = true;
|
||||
} else {
|
||||
return Ok(Async::Ready(()));
|
||||
}
|
||||
|
||||
progress = true;
|
||||
}
|
||||
|
||||
if let Some(ref mut spirc_task) = self.spirc_task {
|
||||
if let Async::Ready(()) = spirc_task.poll().unwrap() {
|
||||
if self.shutdown {
|
||||
return Ok(Async::Ready(()));
|
||||
} else {
|
||||
panic!("Spirc shut down unexpectedly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !progress {
|
||||
return Ok(Async::NotReady);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,35 +300,18 @@ fn main() {
|
|||
let handle = core.handle();
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let Setup { backend, config, device, cache, enable_discovery, credentials, mixer } = setup(&args);
|
||||
|
||||
let Setup { backend, mixer, cache, config, credentials, device }
|
||||
= setup(&args);
|
||||
|
||||
let connection = Session::connect(config, credentials, cache, handle);
|
||||
|
||||
let task = connection.and_then(move |session| {
|
||||
let audio_filter = mixer.get_audio_filter();
|
||||
let player = Player::new(session.clone(), audio_filter, move || {
|
||||
(backend)(device)
|
||||
});
|
||||
|
||||
let (spirc, task) = Spirc::new(session.clone(), player, mixer);
|
||||
let spirc = RefCell::new(spirc);
|
||||
|
||||
let shutting_down = Cell::new(false);
|
||||
ctrlc::set_handler(move || {
|
||||
if shutting_down.get() {
|
||||
warn!("Forced shutdown");
|
||||
exit(1);
|
||||
} else {
|
||||
info!("Shutting down");
|
||||
spirc.borrow_mut().shutdown();
|
||||
shutting_down.set(true);
|
||||
let mut task = Main::new(handle, config.clone(), backend, device, mixer);
|
||||
if enable_discovery {
|
||||
task.discovery();
|
||||
}
|
||||
if let Some(credentials) = credentials {
|
||||
task.credentials(credentials);
|
||||
}
|
||||
if let Some(cache) = cache {
|
||||
task.cache(cache);
|
||||
}
|
||||
});
|
||||
|
||||
task.map_err(|()| panic!("spirc error"))
|
||||
});
|
||||
|
||||
core.run(task).unwrap()
|
||||
}
|
||||
|
|
|
@ -186,8 +186,12 @@ impl MercuryManager {
|
|||
|
||||
if cmd == 0xb5 {
|
||||
self.lock(|inner| {
|
||||
if let Some(cb) = inner.subscriptions.get(&response.uri) {
|
||||
cb.send(response).unwrap();
|
||||
use std::collections::hash_map::Entry;
|
||||
if let Entry::Occupied(entry) = inner.subscriptions.entry(response.uri.clone()) {
|
||||
// TODO: send unsub message
|
||||
if entry.get().send(response).is_err() {
|
||||
entry.remove();
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if let Some(cb) = pending.callback {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
pub trait Mixer {
|
||||
pub trait Mixer : Send {
|
||||
fn open() -> Self where Self: Sized;
|
||||
fn start(&self);
|
||||
fn stop(&self);
|
||||
fn set_volume(&self, volume: u16);
|
||||
|
@ -15,9 +16,13 @@ pub trait AudioFilter {
|
|||
pub mod softmixer;
|
||||
use self::softmixer::SoftMixer;
|
||||
|
||||
pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<Box<Mixer + Send>> {
|
||||
fn mk_sink<M: Mixer + 'static>() -> Box<Mixer> {
|
||||
Box::new(M::open())
|
||||
}
|
||||
|
||||
pub fn find<T: AsRef<str>>(name: Option<T>) -> Option<fn() -> Box<Mixer>> {
|
||||
match name.as_ref().map(AsRef::as_ref) {
|
||||
None | Some("softvol") => Some(Box::new(SoftMixer::new())),
|
||||
None | Some("softvol") => Some(mk_sink::<SoftMixer>),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,17 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use super::Mixer;
|
||||
use super::AudioFilter;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SoftMixer {
|
||||
volume: Arc<AtomicUsize>
|
||||
}
|
||||
|
||||
impl SoftMixer {
|
||||
pub fn new() -> SoftMixer {
|
||||
impl Mixer for SoftMixer {
|
||||
fn open() -> SoftMixer {
|
||||
SoftMixer {
|
||||
volume: Arc::new(AtomicUsize::new(0xFFFF))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mixer for SoftMixer {
|
||||
fn start(&self) {
|
||||
}
|
||||
fn stop(&self) {
|
||||
|
|
|
@ -44,6 +44,8 @@ impl Player {
|
|||
let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
|
||||
|
||||
thread::spawn(move || {
|
||||
debug!("new Player[{}]", session.session_id());
|
||||
|
||||
let internal = PlayerInternal {
|
||||
session: session,
|
||||
commands: cmd_rx,
|
||||
|
@ -383,6 +385,12 @@ impl PlayerInternal {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for PlayerInternal {
|
||||
fn drop(&mut self) {
|
||||
debug!("drop Player[{}]", self.session.session_id());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "with-tremor"))]
|
||||
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
|
||||
decoder.time_seek(ms as f64 / 1000f64)
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crypto::digest::Digest;
|
||||
use crypto::sha1::Sha1;
|
||||
use futures::Future;
|
||||
use futures::sync::mpsc;
|
||||
use futures::{Stream, BoxFuture, IntoFuture};
|
||||
use futures::{Future, Stream, BoxFuture, IntoFuture, Poll, Async};
|
||||
use std::io;
|
||||
use std::result::Result;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{RwLock, Arc, Weak};
|
||||
use tokio_core::io::EasyBuf;
|
||||
use tokio_core::reactor::{Handle, Remote};
|
||||
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
|
||||
use apresolve::apresolve_or_fallback;
|
||||
use authentication::Credentials;
|
||||
|
@ -69,14 +69,15 @@ pub struct SessionInternal {
|
|||
cache: Option<Arc<Cache>>,
|
||||
|
||||
handle: Remote,
|
||||
|
||||
session_id: usize,
|
||||
}
|
||||
|
||||
static SESSION_COUNTER : AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Session(pub Arc<SessionInternal>);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SessionWeak(pub Weak<SessionInternal>);
|
||||
|
||||
pub fn device_id(name: &str) -> String {
|
||||
let mut h = Sha1::new();
|
||||
h.input_str(name);
|
||||
|
@ -102,7 +103,7 @@ impl Session {
|
|||
});
|
||||
|
||||
let result = authentication.map(move |(transport, reusable_credentials)| {
|
||||
info!("Authenticated !");
|
||||
info!("Authenticated as \"{}\" !", reusable_credentials.username);
|
||||
if let Some(ref cache) = cache {
|
||||
cache.save_credentials(&reusable_credentials);
|
||||
}
|
||||
|
@ -126,10 +127,9 @@ impl Session {
|
|||
let (sink, stream) = transport.split();
|
||||
|
||||
let (sender_tx, sender_rx) = mpsc::unbounded();
|
||||
let session_id = SESSION_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
let sender_task = sender_rx
|
||||
.map_err(|e| -> io::Error { panic!(e) })
|
||||
.forward(sink).map(|_| ());
|
||||
debug!("new Session[{}]", session_id);
|
||||
|
||||
let session = Session(Arc::new(SessionInternal {
|
||||
config: config,
|
||||
|
@ -149,15 +149,14 @@ impl Session {
|
|||
metadata: Lazy::new(),
|
||||
|
||||
handle: handle.remote().clone(),
|
||||
|
||||
session_id: session_id,
|
||||
}));
|
||||
|
||||
let receiver_task = {
|
||||
let session = session.clone();
|
||||
stream.for_each(move |(cmd, data)| {
|
||||
session.dispatch(cmd, data);
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
let sender_task = sender_rx
|
||||
.map_err(|e| -> io::Error { panic!(e) })
|
||||
.forward(sink).map(|_| ());
|
||||
let receiver_task = DispatchTask(stream, session.weak());
|
||||
|
||||
let task = (receiver_task, sender_task).into_future()
|
||||
.map(|((), ())| ()).boxed();
|
||||
|
@ -193,10 +192,18 @@ impl Session {
|
|||
self.0.handle.spawn(f)
|
||||
}
|
||||
|
||||
fn debug_info(&self) {
|
||||
debug!("Session[{}] strong={} weak={}",
|
||||
self.0.session_id, Arc::strong_count(&self.0), Arc::weak_count(&self.0));
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
|
||||
fn dispatch(&self, cmd: u8, data: EasyBuf) {
|
||||
match cmd {
|
||||
0x4 => self.send_packet(0x49, data.as_ref().to_owned()),
|
||||
0x4 => {
|
||||
self.debug_info();
|
||||
self.send_packet(0x49, data.as_ref().to_owned());
|
||||
},
|
||||
0x4a => (),
|
||||
0x1b => {
|
||||
let country = String::from_utf8(data.as_ref().to_owned()).unwrap();
|
||||
|
@ -237,10 +244,59 @@ impl Session {
|
|||
pub fn weak(&self) -> SessionWeak {
|
||||
SessionWeak(Arc::downgrade(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl SessionWeak {
|
||||
pub fn upgrade(&self) -> Session {
|
||||
Session(self.0.upgrade().expect("Session died"))
|
||||
pub fn session_id(&self) -> usize {
|
||||
self.0.session_id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SessionWeak(pub Weak<SessionInternal>);
|
||||
|
||||
impl SessionWeak {
|
||||
pub fn try_upgrade(&self) -> Option<Session> {
|
||||
self.0.upgrade().map(Session)
|
||||
}
|
||||
|
||||
pub fn upgrade(&self) -> Session {
|
||||
self.try_upgrade().expect("Session died")
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SessionInternal {
|
||||
fn drop(&mut self) {
|
||||
debug!("drop Session[{}]", self.session_id);
|
||||
}
|
||||
}
|
||||
|
||||
struct DispatchTask<S>(S, SessionWeak)
|
||||
where S: Stream<Item = (u8, EasyBuf)>;
|
||||
|
||||
impl <S> Future for DispatchTask<S>
|
||||
where S: Stream<Item = (u8, EasyBuf)>
|
||||
{
|
||||
type Item = ();
|
||||
type Error = S::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
let session = match self.1.try_upgrade() {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
return Ok(Async::Ready(()))
|
||||
},
|
||||
};
|
||||
|
||||
loop {
|
||||
let (cmd, data) = try_ready!(self.0.poll()).expect("connection closed");
|
||||
session.dispatch(cmd, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <S> Drop for DispatchTask<S>
|
||||
where S: Stream<Item = (u8, EasyBuf)>
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
debug!("drop Dispatch");
|
||||
}
|
||||
}
|
||||
|
|
14
src/spirc.rs
14
src/spirc.rs
|
@ -17,7 +17,7 @@ use protocol::spirc::{PlayStatus, State, MessageType, Frame, DeviceState};
|
|||
|
||||
pub struct SpircTask {
|
||||
player: Player,
|
||||
mixer: Box<Mixer + Send>,
|
||||
mixer: Box<Mixer>,
|
||||
|
||||
sequence: SeqGenerator<u32>,
|
||||
|
||||
|
@ -31,6 +31,7 @@ pub struct SpircTask {
|
|||
end_of_track: BoxFuture<(), oneshot::Canceled>,
|
||||
|
||||
shutdown: bool,
|
||||
session: Session,
|
||||
}
|
||||
|
||||
pub enum SpircCommand {
|
||||
|
@ -110,9 +111,11 @@ fn initial_device_state(name: String, volume: u16) -> DeviceState {
|
|||
}
|
||||
|
||||
impl Spirc {
|
||||
pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>)
|
||||
pub fn new(session: Session, player: Player, mixer: Box<Mixer>)
|
||||
-> (Spirc, SpircTask)
|
||||
{
|
||||
debug!("new Spirc[{}]", session.session_id());
|
||||
|
||||
let ident = session.device_id().to_owned();
|
||||
let name = session.config().name.clone();
|
||||
|
||||
|
@ -152,6 +155,7 @@ impl Spirc {
|
|||
end_of_track: future::empty().boxed(),
|
||||
|
||||
shutdown: false,
|
||||
session: session.clone(),
|
||||
};
|
||||
|
||||
let spirc = Spirc {
|
||||
|
@ -431,6 +435,12 @@ impl SpircTask {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for SpircTask {
|
||||
fn drop(&mut self) {
|
||||
debug!("drop Spirc[{}]", self.session.session_id());
|
||||
}
|
||||
}
|
||||
|
||||
struct CommandSender<'a> {
|
||||
spirc: &'a mut SpircTask,
|
||||
frame: protocol::spirc::Frame,
|
||||
|
|
Loading…
Reference in a new issue