Add mpmc support to audio-base.

This commit is contained in:
Sheldon Knuth 2019-07-01 21:35:06 +08:00
parent 0f38fba897
commit d75d632279
11 changed files with 615 additions and 196 deletions

5
.gitignore vendored
View File

@ -3,6 +3,11 @@
/target/ /target/
/*/target/ /*/target/
# Vim
**/*.vi
**/*.swp
# IntelliJ # IntelliJ
**/.idea/ **/.idea/

137
Cargo.lock generated
View File

@ -21,10 +21,21 @@ dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "alga"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "alsa-sys" name = "alsa-sys"
version = "0.1.1" version = "0.1.2"
source = "git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130#e7c086d0afc368a888ad133c3b1d928b16986130" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -268,16 +279,6 @@ dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "cgmath"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.7" version = "0.4.7"
@ -315,7 +316,7 @@ dependencies = [
[[package]] [[package]]
name = "claxon" name = "claxon"
version = "0.3.3" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -464,9 +465,9 @@ dependencies = [
[[package]] [[package]]
name = "cpal" name = "cpal"
version = "0.8.2" version = "0.8.2"
source = "git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130#e7c086d0afc368a888ad133c3b1d928b16986130" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"alsa-sys 0.1.1 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)", "alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -486,6 +487,19 @@ dependencies = [
"crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "crossbeam"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.2.6" version = "0.2.6"
@ -498,6 +512,15 @@ dependencies = [
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.5.2" version = "0.5.2"
@ -745,6 +768,11 @@ dependencies = [
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "find_folder"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "fixedbitset" name = "fixedbitset"
version = "0.1.9" version = "0.1.9"
@ -861,6 +889,14 @@ dependencies = [
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "gfx" name = "gfx"
version = "0.17.1" version = "0.17.1"
@ -1280,6 +1316,11 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "libm"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "line_drawing" name = "line_drawing"
version = "0.7.0" version = "0.7.0"
@ -1348,6 +1389,14 @@ dependencies = [
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "matrixmultiply"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "1.0.2" version = "1.0.2"
@ -1461,6 +1510,21 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "nalgebra"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.33" version = "0.2.33"
@ -2007,6 +2071,11 @@ dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "rawpointer"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.1.0" version = "1.1.0"
@ -2103,16 +2172,16 @@ dependencies = [
[[package]] [[package]]
name = "rodio" name = "rodio"
version = "0.8.1" version = "0.9.0"
source = "git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b#dd93f905c1afefaac03c496a666ecab27d3e391b" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cgmath 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"claxon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "cpal 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"cpal 0.8.2 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)",
"hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "hound 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lewton 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", "lewton 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
"minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "minimp3 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"nalgebra 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2507,6 +2576,11 @@ name = "tuple_utils"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typenum"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ucd-util" name = "ucd-util"
version = "0.1.3" version = "0.1.3"
@ -2581,6 +2655,7 @@ version = "0.2.0"
dependencies = [ dependencies = [
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"find_folder 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2630,6 +2705,7 @@ dependencies = [
"backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)",
"conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
"conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)",
"crossbeam 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2649,7 +2725,7 @@ dependencies = [
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"portpicker 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "portpicker 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rodio 0.8.1 (git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b)", "rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2867,7 +2943,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
"checksum alsa-sys 0.1.1 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)" = "<none>" "checksum alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d708cb68c7106ed1844de68f50f0157a7788c2909a6926fad5a87546ef6a4ff8"
"checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58"
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e" "checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
"checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" "checksum android_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
@ -2898,11 +2975,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49" "checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
"checksum cgmath 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87f025a17ad3f30d49015c787903976d5f9cd6115ece1eb7f4d6ffe06b8c4080"
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" "checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
"checksum clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e414af9726e1d11660801e73ccc7fb81803fb5f49e5903a25b348b2b3b480d2e" "checksum clang-sys 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e414af9726e1d11660801e73ccc7fb81803fb5f49e5903a25b348b2b3b480d2e"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum claxon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "35193597ff846c905e135b66b7a88876a8b684d269a24fa0f6086988fc2197c8" "checksum claxon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f86c952727a495bda7abaf09bafdee1a939194dd793d9a8e26281df55ac43b00"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0c23085dde1ef4429df6e5896b89356d35cdd321fb43afe3e378d010bb5adc6" "checksum cocoa 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0c23085dde1ef4429df6e5896b89356d35cdd321fb43afe3e378d010bb5adc6"
"checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b" "checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b"
@ -2919,9 +2995,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9" "checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
"checksum coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491" "checksum coreaudio-rs 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491"
"checksum coreaudio-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78fdbabf58d5b1f461e31b94a571c109284f384cec619a3d96e66ec55b4de82b" "checksum coreaudio-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78fdbabf58d5b1f461e31b94a571c109284f384cec619a3d96e66ec55b4de82b"
"checksum cpal 0.8.2 (git+https://github.com/desttinghim/cpal?rev=e7c086d0afc368a888ad133c3b1d928b16986130)" = "<none>" "checksum cpal 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d58ae1ed6536b1b233f5e3aeb6997a046ddb4d05e3f61701b58a92eb254a829e"
"checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650" "checksum crossbeam 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7408247b1b87f480890f28b670c5f8d9a8a4274833433fe74dc0dfd46d33650"
"checksum crossbeam 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14492071ca110999a20bf90e3833406d5d66bfd93b4e52ec9539025ff43fe0d"
"checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827" "checksum crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b85741761b7f160bc5e7e0c14986ef685b7f8bf9b7ad081c60c604bb4649827"
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
"checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a" "checksum crossbeam-deque 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7792c4a9b5a4222f654e3728a3dd945aacc24d2c3a1a096ed265d80e4929cb9a"
"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13"
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
@ -2949,6 +3027,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15" "checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum find_folder 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f6d018fb95a0b59f854aed68ecd96ce2b80af7911b92b1fed3c4b1fa516b91b"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
@ -2962,6 +3041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum gdk-pixbuf 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2d2199eba47ebcb9977ce28179649bdd59305ef465c4e6f9b65aaa41c24e6b5" "checksum gdk-pixbuf 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2d2199eba47ebcb9977ce28179649bdd59305ef465c4e6f9b65aaa41c24e6b5"
"checksum gdk-pixbuf-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df6a3b73e04fafc07f5ebc083f1096a773412e627828e1103a55e921f81187d8" "checksum gdk-pixbuf-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df6a3b73e04fafc07f5ebc083f1096a773412e627828e1103a55e921f81187d8"
"checksum gdk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3162ff940526ddff71bf1f630facee6b5e05d282d125ba0c4c803842819b80c3" "checksum gdk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3162ff940526ddff71bf1f630facee6b5e05d282d125ba0c4c803842819b80c3"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7d7ce0c1f747245342a73453fdb098ea0764c430421fbc4d98cdc8ef8ede4834" "checksum gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7d7ce0c1f747245342a73453fdb098ea0764c430421fbc4d98cdc8ef8ede4834"
"checksum gfx_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c74932837e61f20956c3da1a47471513707dde300274812bba94373ab51830ae" "checksum gfx_core 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c74932837e61f20956c3da1a47471513707dde300274812bba94373ab51830ae"
"checksum gfx_device_gl 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "def9cc76ab9ae3187a1ef5edb16c263fa7d713319ffa1d46e00c9d348081a982" "checksum gfx_device_gl 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "def9cc76ab9ae3187a1ef5edb16c263fa7d713319ffa1d46e00c9d348081a982"
@ -3005,6 +3085,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" "checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9" "checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9"
"checksum libloading 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5692f82b51823e27c4118b3e5c0d98aee9be90633ebc71ad12afef380b50219" "checksum libloading 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5692f82b51823e27c4118b3e5c0d98aee9be90633ebc71ad12afef380b50219"
"checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9" "checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
@ -3014,6 +3095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" "checksum mach 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1"
"checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
"checksum matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfed72d871629daa12b25af198f110e8095d7650f5f4c61c5bac28364604f9b"
"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
@ -3026,6 +3108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" "checksum mopa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915"
"checksum msgbox 0.1.1 (git+https://github.com/bekker/msgbox-rs.git)" = "<none>" "checksum msgbox 0.1.1 (git+https://github.com/bekker/msgbox-rs.git)" = "<none>"
"checksum nalgebra 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e12856109b5cb8e2934b5e45e4624839416e1c6c1f7d286711a7a66b79db29d"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
@ -3087,6 +3170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019"
"checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" "checksum rayon 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4"
"checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" "checksum rayon-core 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2"
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
@ -3097,7 +3181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd" "checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd"
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48" "checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
"checksum rodio 0.8.1 (git+https://github.com/desttinghim/rodio.git?rev=dd93f905c1afefaac03c496a666ecab27d3e391b)" = "<none>" "checksum rodio 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d0f961b254e66d147a7b550c78b01308934c97d807a34b417fd0f5a0a0f3a2d"
"checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" "checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5"
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
@ -3144,6 +3228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4834f28a0330cb9f3f2c87d2649dca723cb33802e2bdcf18da32759fbec7ce" "checksum tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4834f28a0330cb9f3f2c87d2649dca723cb33802e2bdcf18da32759fbec7ce"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e" "checksum tuple_utils 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbfecd7bb8f0a3e96b3b31c46af2677a55a588767c0091f484601424fcb20e7e"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"

View File

@ -24,3 +24,4 @@ rayon = "1.0"
lazy_static = "1.3" lazy_static = "1.3"
lz4-compress = "0.1" lz4-compress = "0.1"
fxhash = "0.2" fxhash = "0.2"
find_folder = "0.3"

View File

@ -5,9 +5,11 @@ use serde_json::Value;
use std::{ use std::{
any::Any, any::Any,
collections::HashMap, collections::HashMap,
fs::File, env,
fs::{read_dir, read_link, File, ReadDir},
io::BufReader, io::BufReader,
io::Read, io::Read,
path::{Path, PathBuf},
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -113,41 +115,60 @@ impl Asset for Value {
} }
// TODO: System to load file from specifiers (e.g.: "core.ui.backgrounds.city"). // TODO: System to load file from specifiers (e.g.: "core.ui.backgrounds.city").
fn try_open_with_path(name: &str) -> Option<File> { fn assets_folder() -> PathBuf {
debug!("Trying to access \"{}\"", name); match std::env::current_exe() {
let abs_path = std::env::current_dir().expect("No current directory?"); Ok(mut exe_path) => {
// TODO: don't do this? exe_path.pop();
// if it's stupid and it works.., find_folder::Search::Parents(2)
let platform_specific = "".to_string(); .of(exe_path)
#[cfg(target_os = "linux")] .for_folder("assets")
{
let platform_specific = "/usr/share/veloren/assets".to_string();
} }
[ Err(_) => find_folder::Search::Parents(2).for_folder("assets"),
std::env::var("VELOREN_ASSETS").unwrap_or("".to_owned()), }
"assets".to_string(), .expect("Could not find assets folder")
"../assets".to_string(), /* optimizations */
"../../assets".to_string(),
[env!("CARGO_MANIFEST_DIR"), "/../assets"].concat(),
[env!("CARGO_MANIFEST_DIR"), "/assets"].concat(),
[env!("CARGO_MANIFEST_DIR"), "/../../assets"].concat(),
"../../../assets".to_string(),
[env!("CARGO_MANIFEST_DIR"), "/../../../assets"].concat(),
platform_specific,
]
.into_iter()
.map(|bp| {
let mut p = abs_path.clone();
p.push(bp);
p.push(name);
p
})
.find_map(|ref filename| File::open(filename).ok())
} }
// TODO: System to load file from specifiers (e.g.: "core.ui.backgrounds.city").
pub fn load_from_path(name: &str) -> Result<BufReader<File>, Error> { pub fn load_from_path(name: &str) -> Result<BufReader<File>, Error> {
match try_open_with_path(name) { debug!("Trying to access \"{}\"", name);
Some(f) => Ok(BufReader::new(f)),
None => Err(Error::NotFound(name.to_owned())), let mut path = assets_folder();
path.push(name);
match File::open(path) {
Ok(file) => Ok(BufReader::new(file)),
Err(_) => Err(Error::NotFound(name.to_owned())),
}
}
/// Read directory from `veloren/assets/*`
pub fn read_from_assets(dir_name: &str) -> Result<ReadDir, Error> {
let mut entry = assets_folder();
entry.push("../assets/");
entry.push(dir_name);
match Path::new(&entry).exists() {
true => Ok(read_dir(entry).expect("`read_dir` failed.")),
false => Err(Error::NotFound(entry.to_str().unwrap().to_owned())),
}
}
/// Returns the cargo manifest directory when running the executable with cargo
/// or the directory in which the executable resides otherwise,
/// traversing symlinks if necessary.
pub fn application_root_dir() -> String {
match env::var("PROFILE") {
Ok(_) => String::from(env!("CARGO_MANIFEST_DIR")),
Err(_) => {
let mut path = env::current_exe().expect("Failed to find executable path.");
while let Ok(target) = read_link(path.clone()) {
path = target;
}
String::from(
path.parent()
.expect("Failed to get parent directory of the executable.")
.to_str()
.unwrap(),
)
}
} }
} }

View File

@ -27,9 +27,6 @@ conrod_core = { git = "https://gitlab.com/veloren/conrod.git" }
conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" } conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" }
euc = "0.2" euc = "0.2"
# Audio
rodio = { git = "https://github.com/desttinghim/rodio.git", rev = "dd93f905c1afefaac03c496a666ecab27d3e391b" }
# ECS # ECS
specs = "0.14" specs = "0.14"
@ -56,3 +53,5 @@ num = "0.2"
backtrace = "0.3" backtrace = "0.3"
rand = "0.5" rand = "0.5"
frustum_query = "0.1.2" frustum_query = "0.1.2"
rodio = "^0.9"
crossbeam = "^0.7.1"

411
voxygen/src/audio/base.rs Normal file
View File

@ -0,0 +1,411 @@
use crate::settings::{AudioSettings, Settings};
use common::assets::{load_from_path, read_from_assets};
use crossbeam::{
atomic::AtomicCell,
channel::{unbounded, Receiver, Sender},
queue::{PopError, SegQueue},
sync::{ShardedLock, WaitGroup},
};
use rodio::{Decoder, Device, Sink, SpatialSink};
use std::sync::Arc;
use std::thread;
trait AudioConfig {
fn set_volume(&mut self, volume: f32);
fn set_device(&mut self, name: String);
}
trait MonoMode {
fn set_mono(tx: Sender<AudioPlayerMsg>) -> Self;
}
trait StereoMode {
fn set_stereo(tx: Sender<AudioPlayerMsg>) -> Self;
}
#[derive(Debug)]
pub enum SinkError {
SinkNotMatch,
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Genre {
Bgm,
Sfx,
}
#[derive(Debug)]
pub enum AudioPlayerMsg {
AudioPlay,
AudioStop,
AudioTime(f64),
}
#[derive(Debug)]
pub enum Action {
Load(String),
Stop,
AdjustVolume(f32),
ChangeDevice(String),
}
#[derive(Clone)]
struct EventLoop {
condition: Arc<(ShardedLock<bool>, WaitGroup)>,
queue: Arc<SegQueue<Action>>,
playing: Arc<ShardedLock<bool>>,
}
impl EventLoop {
fn new() -> Self {
Self {
condition: Arc::new((ShardedLock::new(false), WaitGroup::new())),
queue: Arc::new(SegQueue::new()),
playing: Arc::new(ShardedLock::new(false)),
}
}
}
/// The `AudioPlayer` handles exactly what player does by playing audio from emitter.
pub struct AudioPlayer {
event_loop: EventLoop,
paused: AtomicCell<bool>,
tx: Sender<AudioPlayerMsg>,
}
impl AudioPlayer {
pub(crate) fn new(genre: Genre, tx: Sender<AudioPlayerMsg>) -> Self {
match genre {
Genre::Bgm => AudioPlayer::set_mono(tx),
Genre::Sfx => unimplemented!(),
}
}
pub(crate) fn load(&self, path: &str) {
self.emit(Action::Load(path.to_string()));
}
pub(crate) fn set_volume(&self, value: f32) {
self.emit(Action::AdjustVolume(value));
}
pub(crate) fn set_device(&self, device: &str) {
self.emit(Action::ChangeDevice(device.to_string()));
}
pub(crate) fn pause(&mut self) {
self.paused.store(true);
self.send(AudioPlayerMsg::AudioStop);
self.set_playing(false);
}
pub(crate) fn resume(&mut self) {
self.paused.store(false);
self.send(AudioPlayerMsg::AudioPlay);
self.set_playing(true);
}
pub(crate) fn is_paused(&self) -> bool {
self.paused.load()
}
pub(crate) fn stop(&mut self) {
self.paused.store(false);
self.send(AudioPlayerMsg::AudioStop);
self.emit(Action::Stop);
self.set_playing(false);
}
fn emit(&self, action: Action) {
self.event_loop.queue.push(action);
}
fn send(&mut self, msg: AudioPlayerMsg) {
send_msg(&mut self.tx, msg);
}
fn set_playing(&self, playing: bool) {
*self.event_loop.playing.write().unwrap() = playing;
let &(ref lock, ref wg) = &*self.event_loop.condition;
let mut started = lock.write().unwrap();
*started = playing;
let wg = wg.clone();
if playing {
wg.wait();
}
}
}
impl MonoMode for AudioPlayer {
/// Playing audio until a receive operation appears on the other side.
fn set_mono(tx: Sender<AudioPlayerMsg>) -> Self {
let event_loop = EventLoop::new();
{
let mut tx = tx.clone();
let event_loop = event_loop.clone();
let condition = event_loop.condition.clone();
thread::spawn(move || {
let block = || {
let &(ref lock, ref wg) = &*condition;
let mut started = lock.write().unwrap();
*started = false;
drop(wg);
};
let mut playback = MonoEmitter::new(&Settings::load().audio);
loop {
if let action = event_loop.queue.pop() {
match action {
Ok(Action::Load(path)) => {
if playback.stream.empty() {
playback.play_from(&path);
send_msg(&mut tx, AudioPlayerMsg::AudioPlay);
}
}
Ok(Action::Stop) => playback.stream.stop(),
Ok(Action::AdjustVolume(value)) => playback.set_volume(value),
Ok(Action::ChangeDevice(device)) => playback.set_device(device),
Err(PopError) => eprintln!("There's no soundtrack in the playlist!"),
}
}
}
});
}
Self {
event_loop,
paused: AtomicCell::new(false),
tx,
}
}
}
/// TODO: Implement treeview and modellist widgets for GUI design.
pub struct Jukebox {
// display the current song.
//current_song: RefCell<Option<String>>,
genre: AtomicCell<Genre>,
pub(crate) player: AudioPlayer,
pub(crate) device: AudioDevice,
}
impl Jukebox {
pub(crate) fn new(genre: Genre) -> Self {
let (tx, rx) = unbounded();
Self {
genre: AtomicCell::new(genre),
player: AudioPlayer::new(genre, tx),
device: AudioDevice::new(&AudioSettings::default()),
}
}
//pub(crate) fn update(&mut self) {
// if self.mono.stream.empty() {
// let index = rand::random::<usize>() % self.soundtracks.len();
// self.mono.play_from(&self.soundtracks[index]);
// }
//}
/// Listen by Conrod.
pub(crate) fn update(&mut self, msg: AudioPlayerMsg) {}
/// Display the current genre.
pub(crate) fn get_genre(self) -> Genre {
self.genre.into_inner()
}
}
pub struct AudioDevice {
device: Device,
devices: Vec<Device>,
}
impl AudioDevice {
fn new(settings: &AudioSettings) -> Self {
let device = match &settings.audio_device {
Some(dev) => rodio::output_devices()
.find(|x| &x.name() == dev)
.or_else(rodio::default_output_device)
.expect("No Audio devices found!"),
None => rodio::default_output_device().expect("No Audio devices found!"),
};
Self {
device,
devices: list_devices_raw(),
}
}
/// Returns a vec of the audio devices available.
/// Does not return rodio Device struct in case our audio backend changes.
pub(crate) fn list_devices(&self) -> Vec<String> {
self.devices.iter().map(|x| x.name()).collect()
}
/// Caches vec of devices for later reference
pub(crate) fn update_devices(&mut self) {
self.devices = list_devices_raw()
}
/// Returns the name of the current audio device.
/// Does not return rodio Device struct in case our audio backend changes.
pub(crate) fn get_device(&self) -> String {
self.device.name()
}
}
struct MonoEmitter {
device: AudioDevice,
stream: Sink,
}
struct StereoEmitter {
device: AudioDevice,
stream: SpatialSink,
}
impl MonoEmitter {
fn new(settings: &AudioSettings) -> Self {
let device = AudioDevice::new(settings);
let sink = Sink::new(&device.device);
sink.set_volume(settings.master_volume);
Self {
device,
stream: sink,
}
}
fn play_from(&mut self, path: &str) {
let bufreader = load_from_path(path).unwrap();
let src = Decoder::new(bufreader).unwrap();
self.stream.append(src);
}
}
impl AudioConfig for MonoEmitter {
fn set_volume(&mut self, volume: f32) {
self.stream.set_volume(volume.min(1.0).max(0.0))
}
/// Sets the current audio device from a string.
/// Does not use the rodio Device struct in case that detail changes.
/// If the string is an invalid audio device, then no change is made.
fn set_device(&mut self, name: String) {
if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
self.device.device = dev;
self.stream = Sink::new(&self.device.device);
}
}
}
impl StereoEmitter {
fn new(settings: &AudioSettings) -> Self {
let device = AudioDevice::new(settings);
let sink = SpatialSink::new(
&device.device,
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
);
sink.set_volume(settings.music_volume);
Self {
device,
stream: sink,
}
}
fn play_from(&mut self, path: &str) {
let bufreader = load_from_path(path).unwrap();
let src = Decoder::new(bufreader).unwrap();
self.stream.append(src);
}
}
impl AudioConfig for StereoEmitter {
fn set_volume(&mut self, volume: f32) {
self.stream.set_volume(volume.min(1.0).max(0.0))
}
/// Sets the current audio device from a string.
/// Does not use the rodio Device struct in case that detail changes.
/// If the string is an invalid audio device, then no change is made.
fn set_device(&mut self, name: String) {
if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
self.device.device = dev;
self.stream = SpatialSink::new(
&self.device.device,
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
);
}
}
}
/// Returns the default audio device.
/// Does not return rodio Device struct in case our audio backend changes.
pub(crate) fn get_default_device() -> String {
rodio::default_output_device()
.expect("No audio output devices detected.")
.name()
}
/// Returns vec of devices
fn list_devices_raw() -> Vec<Device> {
rodio::output_devices().collect()
}
/// Load the audio file directory selected by genre.
pub(crate) fn load_soundtracks(genre: &Genre) -> Vec<String> {
match *genre {
Genre::Bgm => {
let assets = read_from_assets("voxygen/audio/soundtrack/").unwrap();
let soundtracks = assets
.filter_map(|entry| {
entry.ok().map(|f| {
let path = f.path();
(*path.into_os_string().to_string_lossy()).to_owned()
})
})
.collect::<Vec<String>>();
soundtracks
}
Genre::Sfx => {
let assets = read_from_assets("voxygen/audio/soundtrack/").unwrap();
let soundtracks = assets
//.filter_map(|entry| {
// entry.ok().and_then(|f| {
// f.path()
// .file_name()
// .and_then(|n| n.to_str().map(|s| String::from(s)))
// })
//})
//.collect::<Vec<String>>();
.filter_map(|entry| {
entry.ok().map(|f| {
let path = f.path();
(*path.into_os_string().to_string_lossy()).to_owned()
})
})
.collect::<Vec<String>>();
soundtracks
}
}
}
pub(crate) fn select_random_music(genre: &Genre) -> String {
let soundtracks = load_soundtracks(genre);
let index = rand::random::<usize>() % soundtracks.len();
soundtracks[index].clone()
}
fn send_msg(tx: &mut Sender<AudioPlayerMsg>, msg: AudioPlayerMsg) {
tx.try_send(msg);
}

View File

@ -1,139 +1,33 @@
use crate::settings::AudioSettings; pub mod base;
use common::assets; use base::*;
use log::error; use crossbeam::{
use rodio::{Decoder, Device, SpatialSink}; channel::{unbounded, Receiver, Sender},
use std::iter::Iterator; queue::{PopError, SegQueue},
use std::panic::catch_unwind; };
use std::thread;
pub struct AudioFrontend { pub struct AudioFrontend {
device: Device, pub(crate) model: Jukebox,
// Performance optimisation, iterating through available audio devices takes time // mpsc sender and receiver used for audio playback threads.
devices: Vec<Device>, //tx_thread: mpsc::Sender,
// streams: HashMap<String, SpatialSink>, //always use SpatialSink even if no position is used for now //rx_thread: mpsc::Receiver,
stream: Option<SpatialSink>,
} }
impl AudioFrontend { impl AudioFrontend {
pub fn new(settings: &AudioSettings) -> Self { pub(crate) fn new() -> Self {
let device = match &settings.audio_device { Self {
Some(dev) => rodio::output_devices() model: Jukebox::new(Genre::Bgm),
.find(|x| &x.name() == dev)
.or_else(rodio::default_output_device)
.expect("No Audio devices found"),
None => rodio::default_output_device().expect("No audio devices found"),
};
let sink = catch_unwind(|| {
let sink = rodio::SpatialSink::new(
&device,
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
);
sink.set_volume(settings.music_volume);
Some(sink)
})
.unwrap_or_else(|e| {
error!("Error creating a SpatialSink (audio): ");
None
});
AudioFrontend {
device,
// streams: HashMap::<String, SpatialSink>::new(),
stream: sink,
devices: AudioFrontend::list_devices_raw(),
} }
} }
pub fn play_music(&mut self, path: &str) { /// Play audio.
let bufreader = assets::load_from_path(path).unwrap(); pub(crate) fn play(&mut self) {
let src = Decoder::new(bufreader).unwrap(); let path = base::select_random_music(&Genre::Bgm);
// TODO: stop previous audio from playing. Sink has this ability, but if self.model.player.is_paused() {
// SpatialSink does not for some reason. This means that we will self.model.player.resume();
// probably want to use sinks for music, and SpatialSink for sfx. } else {
if let Some(s) = &self.stream { self.model.player.load(&path);
s.append(src);
}
}
pub fn maintain(&mut self) {
let music = [
"voxygen/audio/soundtrack/Ethereal_Bonds.ogg",
"voxygen/audio/soundtrack/field_grazing.ogg",
"voxygen/audio/soundtrack/fiesta_del_pueblo.ogg",
"voxygen/audio/soundtrack/library_theme_with_harpsichord.ogg",
"voxygen/audio/soundtrack/Mineral_Deposits.ogg",
//"voxygen/audio/soundtrack/Ruination.ogg",
"voxygen/audio/soundtrack/sacred_temple.ogg",
"voxygen/audio/soundtrack/Snowtop_volume.ogg",
"voxygen/audio/soundtrack/veloren_title_tune-3.ogg",
];
if let Some(s) = &self.stream {
if s.empty() {
let i = rand::random::<usize>() % music.len();
self.play_music(music[i]);
}
}
}
pub fn set_volume(&mut self, volume: f32) {
if let Some(s) = &self.stream {
s.set_volume(volume.min(1.0).max(0.0));
}
}
/// Returns a vec of the audio devices available.
/// Does not return rodio Device struct in case our audio backend changes.
pub fn list_device_names(&self) -> Vec<String> {
self.devices.iter().map(|x| x.name()).collect()
}
/// Returns vec of devices
fn list_devices_raw() -> Vec<Device> {
rodio::output_devices().collect()
}
/// Caches vec of devices for later reference
fn maintain_devices(&mut self) {
self.devices = AudioFrontend::list_devices_raw()
}
/// Returns the default audio device.
/// Does not return rodio Device struct in case our audio backend changes.
pub fn get_default_device() -> String {
rodio::default_output_device()
.expect("No audio output devices detected.")
.name()
}
/// Returns the name of the current audio device.
/// Does not return rodio Device struct in case our audio backend changes.
pub fn get_device_name(&self) -> String {
self.device.name()
}
/// Sets the current audio device from a string.
/// Does not use the rodio Device struct in case that detail changes.
/// If the string is an invalid audio device, then no change is made.
pub fn set_device(&mut self, name: String) {
if let Some(dev) = rodio::output_devices().find(|x| x.name() == name) {
self.device = dev;
self.stream = catch_unwind(|| {
let sink = rodio::SpatialSink::new(
&self.device,
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[-1.0, 0.0, 0.0],
);
Some(sink)
})
.unwrap_or_else(|e| {
error!("Error creating a SpatialSink (audio): ");
None
});
} }
} }
} }

View File

@ -707,8 +707,8 @@ impl<'a> Widget for SettingsWindow<'a> {
} }
// Audio Device Selector -------------------------------------------- // Audio Device Selector --------------------------------------------
let device = self.global_state.audio.get_device_name(); let device = self.global_state.audio.model.device.get_device();
let device_list = self.global_state.audio.list_device_names(); let device_list = self.global_state.audio.model.device.list_devices();
Text::new("Volume") Text::new("Volume")
.down_from(state.ids.audio_volume_slider, 10.0) .down_from(state.ids.audio_volume_slider, 10.0)
.font_size(14) .font_size(14)

View File

@ -42,7 +42,8 @@ impl GlobalState {
} }
pub fn maintain(&mut self) { pub fn maintain(&mut self) {
self.audio.maintain(); // TODO: fix this issue.
self.audio.play();
} }
} }
@ -79,7 +80,7 @@ fn main() {
// Set up the global state. // Set up the global state.
let settings = Settings::load(); let settings = Settings::load();
let mut global_state = GlobalState { let mut global_state = GlobalState {
audio: AudioFrontend::new(&settings.audio), audio: AudioFrontend::new(),
window: Window::new(&settings).expect("Failed to create window!"), window: Window::new(&settings).expect("Failed to create window!"),
settings, settings,
}; };
@ -162,7 +163,7 @@ fn main() {
})); }));
if global_state.settings.audio.audio_device == None { if global_state.settings.audio.audio_device == None {
global_state.settings.audio.audio_device = Some(AudioFrontend::get_default_device()); global_state.settings.audio.audio_device = Some(crate::audio::base::get_default_device());
} }
// Set up the initial play state. // Set up the initial play state.

View File

@ -215,7 +215,7 @@ impl PlayState for SessionState {
} }
} }
HudEvent::AdjustVolume(volume) => { HudEvent::AdjustVolume(volume) => {
global_state.audio.set_volume(volume); global_state.audio.model.player.set_volume(volume);
global_state.settings.audio.music_volume = volume; global_state.settings.audio.music_volume = volume;
if let Err(err) = global_state.settings.save_to_file() { if let Err(err) = global_state.settings.save_to_file() {
@ -223,7 +223,7 @@ impl PlayState for SessionState {
} }
} }
HudEvent::ChangeAudioDevice(name) => { HudEvent::ChangeAudioDevice(name) => {
global_state.audio.set_device(name.clone()); global_state.audio.model.player.set_device(&name.clone());
global_state.settings.audio.audio_device = Some(name); global_state.settings.audio.audio_device = Some(name);
if let Err(err) = global_state.settings.save_to_file() { if let Err(err) = global_state.settings.save_to_file() {

View File

@ -138,6 +138,7 @@ impl Default for GraphicsSettings {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct AudioSettings { pub struct AudioSettings {
pub master_volume: f32,
pub music_volume: f32, pub music_volume: f32,
pub sfx_volume: f32, pub sfx_volume: f32,
@ -148,6 +149,7 @@ pub struct AudioSettings {
impl Default for AudioSettings { impl Default for AudioSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
master_volume: 1.0,
music_volume: 0.5, music_volume: 0.5,
sfx_volume: 0.5, sfx_volume: 0.5,
audio_device: None, audio_device: None,