From 946eed5a69cda7c5c53164ef9c91f97e964408f2 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 14 Dec 2021 18:30:02 +0900 Subject: [PATCH] WIP heavy refactoring/rewriting, use ggez --- Cargo.lock | 2316 +++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 +- src/display.rs | 50 + src/main.rs | 1027 +------------------- src/mpd_handler.rs | 604 ++++++++++++ 5 files changed, 2841 insertions(+), 1158 deletions(-) create mode 100644 src/display.rs create mode 100644 src/mpd_handler.rs diff --git a/Cargo.lock b/Cargo.lock index 4898075..4a538de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ab_glyph" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b228f2c198f98d4337ceb560333fb12cbb2f4948a953bf8c57d09deb219603" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser 0.13.2", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" + [[package]] name = "adler" version = "1.0.2" @@ -15,10 +31,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] -name = "ahash" -version = "0.4.7" +name = "alsa" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18" +dependencies = [ + "alsa-sys", + "bitflags", + "libc", + "nix 0.20.0", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "andrew" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" +dependencies = [ + "bitflags", + "rusttype", + "walkdir", + "xdg", + "xml-rs", +] + +[[package]] +name = "android_glue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" [[package]] name = "ansi_term" @@ -29,6 +80,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "approx" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "atty" version = "0.2.14" @@ -40,42 +106,61 @@ dependencies = [ "winapi", ] -[[package]] -name = "audir-sles" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea47348666a8edb7ad80cbee3940eb2bccf70df0e6ce09009abe1a836cb779f5" - -[[package]] -name = "audrey" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b92a84e89497e3cd25d3672cd5d1c288abaac02c18ff21283f17d118b889b8" -dependencies = [ - "dasp_frame", - "dasp_sample", - "hound", - "lewton", -] - [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base-x" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" + +[[package]] +name = "bindgen" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "bumpalo" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +[[package]] +name = "bytecount" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" + [[package]] name = "bytemuck" version = "1.7.2" @@ -88,11 +173,94 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "bzip2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "calloop" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" +dependencies = [ + "log", + "nix 0.18.0", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714a157da7991e23d90686b9524b9e12e0407a108647f52e9328f4b3d51ac7f" +dependencies = [ + "cargo-platform", + "semver 0.11.0", + "semver-parser 0.10.2", + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom 5.1.2", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -100,6 +268,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "clang-sys" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa66045b9cb23c2e9c1520732030608b02ee07e5cfaa5a521ec15ded7fa24c90" +dependencies = [ + "glob", + "libc", + "libloading 0.7.2", +] + [[package]] name = "clap" version = "2.33.3" @@ -109,25 +297,228 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + +[[package]] +name = "cocoa" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" +dependencies = [ + "bitflags", + "block", + "cocoa-foundation", + "core-foundation 0.9.2", + "core-graphics 0.22.3", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +dependencies = [ + "bitflags", + "block", + "core-foundation 0.9.2", + "core-graphics-types", + "foreign-types", + "libc", + "objc", +] + [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "combine" +version = "4.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b2f5d0ee456f3928812dfc8c6d9a1d592b98678f6d56db9b0cd2b7bc6c8db5" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "core-foundation" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +dependencies = [ + "core-foundation-sys 0.6.2", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +dependencies = [ + "core-foundation-sys 0.7.0", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +dependencies = [ + "core-foundation-sys 0.8.3", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" + +[[package]] +name = "core-foundation-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "core-graphics" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" +dependencies = [ + "bitflags", + "core-foundation 0.7.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +dependencies = [ + "bitflags", + "core-foundation 0.9.2", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +dependencies = [ + "bitflags", + "core-foundation 0.9.2", + "foreign-types", + "libc", +] + +[[package]] +name = "core-video-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" +dependencies = [ + "cfg-if 0.1.10", + "core-foundation-sys 0.7.0", + "core-graphics 0.19.2", + "libc", + "objc", +] + +[[package]] +name = "coreaudio-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" +dependencies = [ + "bitflags", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b7e3347be6a09b46aba228d6608386739fb70beff4f61e07422da87b0bb31fa" +dependencies = [ + "bindgen", +] + +[[package]] +name = "cpal" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f45f0a21f617cd2c788889ef710b63f075c949259593ea09c826f1e47a2418" +dependencies = [ + "alsa", + "core-foundation-sys 0.8.3", + "coreaudio-rs", + "jni", + "js-sys", + "lazy_static", + "libc", + "mach 0.3.2", + "ndk 0.3.0", + "ndk-glue 0.3.0", + "nix 0.20.0", + "oboe", + "parking_lot", + "stdweb 0.1.3", + "thiserror", + "web-sys", + "winapi", +] + [[package]] name = "crc32fast" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", ] [[package]] @@ -136,7 +527,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", ] @@ -146,7 +537,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] @@ -157,37 +548,73 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crossbeam-utils", "lazy_static", "memoffset", "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "lazy_static", ] [[package]] -name = "dasp_frame" -version = "0.11.0" +name = "cty" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6" +checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" + +[[package]] +name = "darling" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" dependencies = [ - "dasp_sample", + "darling_core", + "darling_macro", ] [[package]] -name = "dasp_sample" -version = "0.11.0" +name = "darling_core" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.9.3", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" +dependencies = [ + "darling_core", + "quote", + "syn", +] [[package]] name = "deflate" @@ -199,6 +626,91 @@ dependencies = [ "byteorder", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "directories" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "discard" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dlib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" +dependencies = [ + "libloading 0.6.7", +] + +[[package]] +name = "dlib" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" +dependencies = [ + "libloading 0.7.2", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "draw_state" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" +dependencies = [ + "bitflags", +] + [[package]] name = "either" version = "1.6.1" @@ -206,13 +718,136 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] -name = "fontdue" -version = "0.5.2" +name = "error-chain" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75712fff1702bac51b7eaa5a5ca9f9853b8055ef5906088a32f4fe196595a1d" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ - "hashbrown", - "ttf-parser", + "version_check", +] + +[[package]] +name = "euclid" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80" +dependencies = [ + "num-traits", +] + +[[package]] +name = "float_next_after" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "gfx" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01de46f9508a5c259aef105f0bff760ceddca832ea9c87ce03d1923e22ee155b" +dependencies = [ + "draw_state", + "gfx_core", + "log", +] + +[[package]] +name = "gfx_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75fbddaef2e12b4995900539d7209d947b988a3d87ee8737484d049b526e5441" +dependencies = [ + "bitflags", + "draw_state", + "log", +] + +[[package]] +name = "gfx_device_gl" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c385fa380c18888633aa27d1e16cbae518469702a2f69dcb5f52d5378bebc" +dependencies = [ + "gfx_core", + "gfx_gl", + "log", +] + +[[package]] +name = "gfx_gl" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d38164670920cfb7491bc0cf6f49f0554bd1c44cdbedc6c78d2bf91691ff5e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "ggez" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2481c5fcf83c5d51172850a3ee2ae36d86f9961d39851c6bec99108f87f085d" +dependencies = [ + "approx", + "bitflags", + "bytemuck", + "directories", + "gfx", + "gfx_core", + "gfx_device_gl", + "gilrs", + "glam", + "glutin", + "glyph_brush", + "image", + "log", + "lyon", + "mint", + "old_school_gfx_glutin_ext", + "rodio", + "serde", + "serde_derive", + "skeptic", + "smart-default", + "toml", + "winit", + "zip", ] [[package]] @@ -226,18 +861,172 @@ dependencies = [ ] [[package]] -name = "glam" -version = "0.14.0" +name = "gilrs" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333928d5eb103c5d4050533cec0384302db6be8ef7d3cebd30ec6a35350353da" +checksum = "0e986f911d937f4395dfc2a39618dcef452773d32dcdbe0828c623f76588f749" +dependencies = [ + "fnv", + "gilrs-core", + "log", + "uuid", + "vec_map", +] [[package]] -name = "hashbrown" -version = "0.9.1" +name = "gilrs-core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "9a5e5bb97bf9a0d9519a28cf38839cf1d6d9bb572b48e3c67202271fec2ed5e7" dependencies = [ - "ahash", + "core-foundation 0.6.4", + "io-kit-sys", + "libc", + "libudev-sys", + "log", + "nix 0.20.0", + "rusty-xinput", + "stdweb 0.4.20", + "uuid", + "vec_map", + "winapi", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68270e16582ea40f9c5b2fcd588fbc9cb696577222e04a64d9085cc314806a8a" +dependencies = [ + "mint", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "glutin" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "762d6cd2e1b855d99668ebe591cc9058659d85ac39a9a2078000eb122ddba8f0" +dependencies = [ + "android_glue", + "cgl", + "cocoa", + "core-foundation 0.9.2", + "glutin_egl_sys", + "glutin_emscripten_sys", + "glutin_gles2_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "lazy_static", + "libloading 0.7.2", + "log", + "objc", + "osmesa-sys", + "parking_lot", + "wayland-client", + "wayland-egl", + "winapi", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211" +dependencies = [ + "gl_generator", + "winapi", +] + +[[package]] +name = "glutin_emscripten_sys" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1" + +[[package]] +name = "glutin_gles2_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094e708b730a7c8a1954f4f8a31880af00eb8a1c5b5bf85d28a0a3c6d69103" +dependencies = [ + "gl_generator", + "objc", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5951a1569dbab865c6f2a863efafff193a93caf05538d193e9e3816d21696" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "glyph_brush" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21932fbf719272848eec4583740d978203c6e7da4c4e203358f5b95946c97409" +dependencies = [ + "glyph_brush_draw_cache", + "glyph_brush_layout", + "log", + "ordered-float", + "rustc-hash", + "twox-hash", +] + +[[package]] +name = "glyph_brush_draw_cache" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" +dependencies = [ + "ab_glyph", + "crossbeam-channel", + "crossbeam-deque", + "linked-hash-map", + "rayon", + "rustc-hash", +] + +[[package]] +name = "glyph_brush_layout" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" +dependencies = [ + "ab_glyph", + "approx", + "xi-unicode", ] [[package]] @@ -264,6 +1053,12 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "image" version = "0.23.14" @@ -283,6 +1078,60 @@ dependencies = [ "tiff", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "io-kit-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f21dcc74995dd4cd090b147e79789f8d65959cbfb5f0b118002db869ea3bd0a0" +dependencies = [ + "core-foundation-sys 0.6.2", + "mach 0.2.3", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.1.22" @@ -292,6 +1141,21 @@ dependencies = [ "rayon", ] +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + [[package]] name = "lazy_static" version = "1.4.0" @@ -299,14 +1163,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "lewton" -version = "0.9.4" +name = "lazycell" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d542c1a317036c45c2aa1cf10cc9d403ca91eb2d333ef1a4917e5cb10628bd0" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lewton" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" dependencies = [ "byteorder", "ogg", - "smallvec", + "tinyvec", ] [[package]] @@ -316,32 +1186,150 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" [[package]] -name = "macroquad" -version = "0.3.9" +name = "libloading" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c11792fb3af71339e4354ee3dbde4bbe5731dac266cc087b414338dfb1ca1bd" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" dependencies = [ - "bumpalo", - "fontdue", - "glam", - "image", - "macroquad_macro", - "miniquad", - "quad-rand", - "quad-snd", + "cfg-if 1.0.0", + "winapi", ] [[package]] -name = "macroquad_macro" -version = "0.1.6" +name = "libloading" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15db41b6abd0156c498868ec69f8973731ef75874768ac234980422579e70805" +checksum = "afe203d669ec979b7128619bae5a63b7b42e9203c1b29146079ee05e2f604b52" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] [[package]] -name = "maybe-uninit" -version = "2.0.0" +name = "libudev-sys" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "lyon" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb" +dependencies = [ + "lyon_algorithms", + "lyon_tessellation", +] + +[[package]] +name = "lyon_algorithms" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a" +dependencies = [ + "lyon_path", + "sid", +] + +[[package]] +name = "lyon_geom" +version = "0.17.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce99ce77c22bfd8f39a95b9c749dffbfc3e2491ea30c874764c801a8b1485489" +dependencies = [ + "arrayvec", + "euclid", + "num-traits", +] + +[[package]] +name = "lyon_path" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0" +dependencies = [ + "lyon_geom", +] + +[[package]] +name = "lyon_tessellation" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760" +dependencies = [ + "float_next_after", + "lyon_path", +] + +[[package]] +name = "mach" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" +dependencies = [ + "libc", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "memmap2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +dependencies = [ + "libc", +] [[package]] name = "memoffset" @@ -353,18 +1341,29 @@ dependencies = [ ] [[package]] -name = "miniquad" -version = "0.3.0-alpha.37" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6793a3ef846953fc7c01302093abf8749be22742c63db05c66ef0a2c889a7fbb" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "minimp3" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" dependencies = [ - "sapp-android", - "sapp-darwin", - "sapp-dummy", - "sapp-ios", - "sapp-linux", - "sapp-wasm", - "sapp-windows", + "minimp3-sys", + "slice-deque", + "thiserror", +] + +[[package]] +name = "minimp3-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" +dependencies = [ + "cc", ] [[package]] @@ -386,21 +1385,192 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mint" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162e591484b4b8fe9e1ca16ebf07ab584fdc3334508d76a788cd54d89cfc20dc" + +[[package]] +name = "mio" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "mio-misc" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b47412f3a52115b936ff2a229b803498c7b4d332adeb87c2f1498c9da54c398c" +dependencies = [ + "crossbeam", + "crossbeam-queue", + "log", + "mio", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + [[package]] name = "mpd_info_screen" version = "0.1.0" dependencies = [ + "ggez", "image", - "macroquad", "structopt", ] +[[package]] +name = "ndk" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8794322172319b972f528bf90c6b467be0079f1fa82780ffb431088e741a73ab" +dependencies = [ + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64d6af06fde0e527b1ba5c7b79a6cc89cfc46325b0b2887dffe8f70197e0c3c" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-glue" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5caf0c24d51ac1c905c27d4eda4fa0635bbe0de596b8f79235e0b17a4d29385" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk 0.3.0", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-glue" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e9e94628f24e7a3cb5b96a2dc5683acd9230bf11991c2a1677b87695138420" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk 0.4.0", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" +dependencies = [ + "darling", + "proc-macro-crate 0.1.5", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ndk-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" +[[package]] +name = "nix" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" +dependencies = [ + "bitflags", + "cc", + "cfg-if 0.1.10", + "libc", +] + +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags", + "cc", + "cfg-if 1.0.0", + "libc", +] + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +dependencies = [ + "memchr", + "minimal-lexical", + "version_check", +] + +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -453,14 +1623,173 @@ dependencies = [ ] [[package]] -name = "ogg" -version = "0.7.1" +name = "num_enum" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e571c3517af9e1729d4c63571a27edd660ade0667973bfc74a67c660c2b651" +checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" +dependencies = [ + "derivative", + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" +dependencies = [ + "proc-macro-crate 1.1.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "oboe" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e15e22bc67e047fe342a32ecba55f555e3be6166b04dd157cd0f803dfa9f48e1" +dependencies = [ + "jni", + "ndk 0.4.0", + "ndk-glue 0.4.0", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "338142ae5ab0aaedc8275aa8f67f460e43ae0fca76a695a742d56da0a269eadc" +dependencies = [ + "cc", +] + +[[package]] +name = "ogg" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" dependencies = [ "byteorder", ] +[[package]] +name = "old_school_gfx_glutin_ext" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1026bdd085523158bd5a1cf0ccbf39b7753c96ccbd54e7f6144ed1518f0046b3" +dependencies = [ + "gfx_core", + "gfx_device_gl", + "glutin", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "ordered-float" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "osmesa-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" +dependencies = [ + "shared_library", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" +dependencies = [ + "ttf-parser 0.6.2", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65ee3f72636e6f164cc41c9f9057f4e58c4e13507699ea7f5e5242b64b8198ee" +dependencies = [ + "ttf-parser 0.13.4", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + [[package]] name = "png" version = "0.16.8" @@ -473,6 +1802,31 @@ dependencies = [ "miniz_oxide 0.3.7", ] +[[package]] +name = "ppv-lite86" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -507,31 +1861,14 @@ dependencies = [ ] [[package]] -name = "quad-alsa-sys" -version = "0.3.2" +name = "pulldown-cmark" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66c2f04a6946293477973d85adc251d502da51c57b08cd9c997f0cfd8dcd4b5" +checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" dependencies = [ - "libc", -] - -[[package]] -name = "quad-rand" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658fa1faf7a4cc5f057c9ee5ef560f717ad9d8dc66d975267f709624d6e1ab88" - -[[package]] -name = "quad-snd" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b33c4e021bc86d54061b7d23ec96e6fd4c4400066658b043e2b2b36ebca737" -dependencies = [ - "audir-sles", - "audrey", - "libc", - "quad-alsa-sys", - "winapi", + "bitflags", + "memchr", + "unicase", ] [[package]] @@ -543,6 +1880,65 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "raw-window-handle" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" +dependencies = [ + "libc", + "raw-window-handle 0.4.2", +] + +[[package]] +name = "raw-window-handle" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba75eee94a9d5273a68c9e1e105d9cffe1ef700532325788389e5a83e2522b7" +dependencies = [ + "cty", +] + [[package]] name = "rayon" version = "1.5.1" @@ -569,66 +1965,118 @@ dependencies = [ ] [[package]] -name = "sapp-android" -version = "0.1.8" +name = "redox_syscall" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a4a81f462ba2783213978528560aa138adf2f94da1ac940c1b5c854c03e1724" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ - "libc", - "ndk-sys", + "bitflags", ] [[package]] -name = "sapp-darwin" -version = "0.1.6" +name = "redox_users" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0310e2445f307468aa13f1cde94d6fba6b8fd329afbb642dedbe3faf1a145f31" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "cc", + "getrandom", + "redox_syscall", ] [[package]] -name = "sapp-dummy" -version = "0.1.5" +name = "regex" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66f1ad26a5b6c682b9ca27c66db9aa91002b8d98a82ac7101ded57285215a478" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ - "libc", + "regex-syntax", ] [[package]] -name = "sapp-ios" -version = "0.1.2" +name = "regex-syntax" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081e6e5261c9ac2e938979b6a854a53b439f065fc3c897205ce7e69d3028b4a9" -dependencies = [ - "cc", -] +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] -name = "sapp-linux" -version = "0.1.13" +name = "remove_dir_all" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbdb2f8011955c62544d9e626a58333e788810d00bd7411d52b81611b92af142" -dependencies = [ - "libc", -] - -[[package]] -name = "sapp-wasm" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00e859e8645a3bcb85aecd40bab883438e4105f21b21bccbeac2348760f508bb" - -[[package]] -name = "sapp-windows" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8faec983cb54ce5e9529815fc0aae6c36bab9fba9cd0ae5590dfa17bc0719fa" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ "winapi", ] +[[package]] +name = "rodio" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9" +dependencies = [ + "claxon", + "cpal", + "hound", + "lewton", + "minimp3", +] + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rusttype" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser 0.6.0", +] + +[[package]] +name = "rusty-xinput" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2aa654bc32eb9ca14cce1a084abc9dfe43949a4547c35269a094c39272db3bb" +dependencies = [ + "lazy_static", + "log", + "winapi", +] + +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -642,20 +2090,238 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "smallvec" -version = "0.6.14" +name = "semver" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "maybe-uninit", + "semver-parser 0.7.0", ] +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser 0.10.2", + "serde", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.131" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + +[[package]] +name = "shared_library" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" +dependencies = [ + "lazy_static", + "libc", +] + +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "sid" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb" +dependencies = [ + "num-traits", +] + +[[package]] +name = "skeptic" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "188b810342d98f23f0bb875045299f34187b559370b041eb11520c905370a888" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + +[[package]] +name = "slice-deque" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" +dependencies = [ + "libc", + "mach 0.3.2", + "winapi", +] + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "smart-default" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" +dependencies = [ + "andrew", + "bitflags", + "calloop", + "dlib 0.4.2", + "lazy_static", + "log", + "memmap2", + "nix 0.18.0", + "wayland-client", + "wayland-cursor", + "wayland-protocols", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stdweb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" + +[[package]] +name = "stdweb" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" +dependencies = [ + "discard", + "rustc_version", + "serde", + "serde_json", + "stdweb-derive", + "stdweb-internal-macros", + "stdweb-internal-runtime", + "wasm-bindgen", +] + +[[package]] +name = "stdweb-derive" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "stdweb-internal-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" +dependencies = [ + "base-x", + "proc-macro2", + "quote", + "serde", + "serde_derive", + "serde_json", + "sha1", + "syn", +] + +[[package]] +name = "stdweb-internal-runtime" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" + [[package]] name = "structopt" version = "0.3.23" @@ -691,6 +2357,20 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempfile" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "rand", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -700,6 +2380,26 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tiff" version = "0.6.1" @@ -712,10 +2412,66 @@ dependencies = [ ] [[package]] -name = "ttf-parser" -version = "0.12.3" +name = "tinyvec" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "ttf-parser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" + +[[package]] +name = "ttf-parser" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76dacc724328b3d5e2ed67f9e30cdb56893a34ab239032502cc8f19f8dae4bbc" + +[[package]] +name = "twox-hash" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" +dependencies = [ + "cfg-if 1.0.0", + "rand", + "static_assertions", +] + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] [[package]] name = "unicode-segmentation" @@ -735,6 +2491,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + [[package]] name = "vec_map" version = "0.8.2" @@ -747,6 +2509,170 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasm-bindgen" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" + +[[package]] +name = "wayland-client" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ab332350e502f159382201394a78e3cc12d0f04db863429260164ea40e0355" +dependencies = [ + "bitflags", + "downcast-rs", + "libc", + "nix 0.20.0", + "scoped-tls", + "wayland-commons", + "wayland-scanner", + "wayland-sys", +] + +[[package]] +name = "wayland-commons" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21817947c7011bbd0a27e11b17b337bfd022e8544b071a2641232047966fbda" +dependencies = [ + "nix 0.20.0", + "once_cell", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-cursor" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be610084edd1586d45e7bdd275fe345c7c1873598caa464c4fb835dee70fa65a" +dependencies = [ + "nix 0.20.0", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-egl" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99ba1ab1e18756b23982d36f08856d521d7df45015f404a2d7c4f0b2d2f66956" +dependencies = [ + "wayland-client", + "wayland-sys", +] + +[[package]] +name = "wayland-protocols" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "286620ea4d803bacf61fa087a4242ee316693099ee5a140796aaba02b29f861f" +dependencies = [ + "bitflags", + "wayland-client", + "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce923eb2deb61de332d1f356ec7b6bf37094dc5573952e1c8936db03b54c03f1" +dependencies = [ + "proc-macro2", + "quote", + "xml-rs", +] + +[[package]] +name = "wayland-sys" +version = "0.28.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d841fca9aed7febf9bed2e9796c49bf58d4152ceda8ac949ebe00868d8f0feb8" +dependencies = [ + "dlib 0.5.0", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "weezl" version = "0.1.5" @@ -769,8 +2695,102 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winit" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79610794594d5e86be473ef7763f604f2159cbac8c94debd00df8fb41e86c2f8" +dependencies = [ + "bitflags", + "cocoa", + "core-foundation 0.9.2", + "core-graphics 0.22.3", + "core-video-sys", + "dispatch", + "instant", + "lazy_static", + "libc", + "log", + "mio", + "mio-misc", + "ndk 0.3.0", + "ndk-glue 0.3.0", + "ndk-sys", + "objc", + "parking_lot", + "percent-encoding", + "raw-window-handle 0.3.4", + "scopeguard", + "smithay-client-toolkit", + "wayland-client", + "winapi", + "x11-dl", +] + +[[package]] +name = "x11-dl" +version = "2.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" +dependencies = [ + "lazy_static", + "libc", + "pkg-config", +] + +[[package]] +name = "xcursor" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" +dependencies = [ + "nom 7.1.0", +] + +[[package]] +name = "xdg" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a23fe958c70412687039c86f578938b4a0bb50ec788e96bce4d6ab00ddd5803" +dependencies = [ + "dirs", +] + +[[package]] +name = "xi-unicode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" + +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "zip" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815" +dependencies = [ + "byteorder", + "bzip2", + "crc32fast", + "thiserror", +] diff --git a/Cargo.toml b/Cargo.toml index 4cd2d12..516272e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" [dependencies] structopt = "0.3" -macroquad = "0.3" image = "0.23" +ggez = "0.7" diff --git a/src/display.rs b/src/display.rs new file mode 100644 index 0000000..32568d7 --- /dev/null +++ b/src/display.rs @@ -0,0 +1,50 @@ +use crate::mpd_handler::MPDHandler; +use crate::Opt; +use ggez::event::{self, EventHandler}; +use ggez::graphics::{self, Color, DrawParam, Drawable, Text, TextFragment}; +use ggez::timer::{check_update_time, fps, yield_now}; +use ggez::Context; +use ggez::GameError; +use std::sync::{Arc, RwLock}; + +pub struct MPDDisplay { + opts: Opt, + mpd_handler: Option>>, + is_valid: bool, + is_initialized: bool, + notice_text: Text, +} + +impl MPDDisplay { + pub fn new(ctx: &mut Context, opts: Opt) -> Self { + Self { + opts, + mpd_handler: None, + is_valid: true, + is_initialized: false, + notice_text: Text::new(""), + } + } +} + +impl EventHandler for MPDDisplay { + fn update(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> { + if !check_update_time(ctx, 10) { + yield_now(); + return Ok(()); + } + + self.notice_text = Text::new(TextFragment::new(format!("fps is {}", fps(ctx)))); + + yield_now(); + Ok(()) + } + + fn draw(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> { + graphics::clear(ctx, Color::BLACK); + + self.notice_text.draw(ctx, DrawParam::default()); + + graphics::present(ctx) + } +} diff --git a/src/main.rs b/src/main.rs index 47471f6..b2d2a2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,37 +1,15 @@ -use image::{DynamicImage, ImageResult}; -use macroquad::prelude::*; -use std::convert::TryInto; -//use std::fs::File; -use std::io::{Read, Write}; -use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}; -use std::str::FromStr; -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, Mutex, -}; -use std::thread; -use std::time::{Duration, Instant}; -use structopt::StructOpt; +mod display; +mod mpd_handler; -const BUF_SIZE: usize = 1024 * 4; -const POLL_DURATION: Duration = Duration::from_secs(10); -const TEXT_X_OFFSET: f32 = 16.0f32; -const TEXT_Y_OFFSET: f32 = 16.0f32; -const TIME_MAX_DIFF: f64 = 2.0f64; -const INITIAL_FONT_SIZE: u16 = 96; -const TITLE_INITIAL_FONT_SIZE: u16 = 196; -const TITLE_INITIAL_MIN_FONT_SIZE: u16 = 44; -const TITLE_SCREEN_FACTOR: u16 = 800; -const ARTIST_INITIAL_FONT_SIZE: u16 = 48; -const TIMER_FONT_SIZE: u16 = 64; -const SCREEN_DIFF_MARGIN: f32 = 1.0; -const PROMPT_Y_OFFSET: f32 = 48.0; -const CHECK_SHARED_WAIT_TIME: f64 = 3.0; -const CHECK_TRACK_TIMER_MAX_COUNT: u64 = 30; +use ggez::conf::WindowSetup; +use ggez::event; +use ggez::ContextBuilder; +use std::net::Ipv4Addr; +use structopt::StructOpt; #[derive(StructOpt, Debug)] #[structopt(name = "mpd_info_screen")] -struct Opt { +pub struct Opt { host: Ipv4Addr, #[structopt(default_value = "6600")] port: u16, @@ -47,988 +25,19 @@ struct Opt { enable_prompt_password: bool, } -struct Shared { - art_data: Vec, - art_data_size: usize, - current_song_filename: String, - current_song_title: String, - current_song_artist: String, - current_song_length: f64, - current_song_position: f64, - current_song_pos_rec: Instant, - thread_running: bool, - stream: TcpStream, - password: String, - can_authenticate: bool, - can_get_album_art: bool, - can_get_album_art_in_dir: bool, - can_get_status: bool, -} - -impl Shared { - fn new(stream: TcpStream) -> Self { - Self { - art_data: Vec::new(), - art_data_size: 0, - current_song_filename: String::new(), - current_song_title: String::new(), - current_song_artist: String::new(), - current_song_length: 0.0, - current_song_position: 0.0, - current_song_pos_rec: Instant::now(), - thread_running: true, - stream, - password: String::new(), - can_authenticate: true, - can_get_album_art: true, - can_get_album_art_in_dir: true, - can_get_status: true, - } - } -} - -#[derive(Debug, PartialEq, Copy, Clone)] -enum PollState { - None, - Password, - CurrentSong, - Status, - ReadPicture, - ReadPictureInDir, -} - -#[derive(Debug, Clone)] -struct InfoFromShared { - filename: String, - title: String, - artist: String, - length: f64, - pos: f64, - instant_rec: Instant, - error_text: String, -} - -fn get_connection(host: Ipv4Addr, port: u16) -> Result { - let stream = TcpStream::connect_timeout( - &SocketAddr::new(IpAddr::V4(host), port), - Duration::from_secs(5), - ) - .map_err(|_| String::from("Failed to get connection"))?; - - Ok(stream) -} - -fn check_next_chars( - buf: &[u8], - idx: usize, - saved: &mut Vec, -) -> Result<(char, u8), (String, u8)> { - if idx >= buf.len() { - return Err((String::from("idx out of bounds"), 0u8)); - } - if buf[idx] & 0b10000000 == 0 { - let result_str = String::from_utf8(vec![buf[idx]]); - if let Ok(mut s) = result_str { - let popped_char = s.pop(); - if s.is_empty() { - Ok((popped_char.unwrap(), 1u8)) - } else { - Err((String::from("Not one-byte UTF-8 char"), 0u8)) - } - } else { - Err((String::from("Not one-byte UTF-8 char"), 0u8)) - } - } else if buf[idx] & 0b11100000 == 0b11000000 { - if idx + 1 >= buf.len() { - saved.push(buf[idx]); - return Err(( - String::from("Is two-byte UTF-8, but not enough bytes provided"), - 1u8, - )); - } - let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1]]); - if let Ok(mut s) = result_str { - let popped_char = s.pop(); - if s.is_empty() { - Ok((popped_char.unwrap(), 2u8)) - } else { - Err((String::from("Not two-byte UTF-8 char"), 0u8)) - } - } else { - Err((String::from("Not two-byte UTF-8 char"), 0u8)) - } - } else if buf[idx] & 0b11110000 == 0b11100000 { - if idx + 2 >= buf.len() { - for c in buf.iter().skip(idx) { - saved.push(*c); - } - return Err(( - String::from("Is three-byte UTF-8, but not enough bytes provided"), - (idx + 3 - buf.len()) as u8, - )); - } - let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]); - if let Ok(mut s) = result_str { - let popped_char = s.pop(); - if s.is_empty() { - Ok((popped_char.unwrap(), 3u8)) - } else { - Err((String::from("Not three-byte UTF-8 char"), 0u8)) - } - } else { - Err((String::from("Not three-byte UTF-8 char"), 0u8)) - } - } else if buf[idx] & 0b11111000 == 0b11110000 { - if idx + 3 >= buf.len() { - for c in buf.iter().skip(idx) { - saved.push(*c); - } - return Err(( - String::from("Is four-byte UTF-8, but not enough bytes provided"), - (idx + 4 - buf.len()) as u8, - )); - } - let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]); - if let Ok(mut s) = result_str { - let popped_char = s.pop(); - if s.is_empty() { - Ok((popped_char.unwrap(), 4u8)) - } else { - Err((String::from("Not four-byte UTF-8 char"), 0u8)) - } - } else { - Err((String::from("Not four-byte UTF-8 char"), 0u8)) - } - } else { - Err((String::from("Invalid UTF-8 char"), 0u8)) - } -} - -fn read_line( - buf: &mut Vec, - count: usize, - saved: &mut Vec, - init: bool, -) -> Result { - let mut result = String::new(); - - let mut buf_to_read: Vec = Vec::with_capacity(saved.len() + buf.len()); - - if !saved.is_empty() { - buf_to_read.append(saved); - } - buf_to_read.append(buf); - - let mut prev_three: Vec = Vec::with_capacity(4); - - let mut skip_count = 0; - for idx in 0..count { - if skip_count > 0 { - skip_count -= 1; - continue; - } - let next_char_result = check_next_chars(&buf_to_read, idx, saved); - if let Ok((c, s)) = next_char_result { - if !init { - prev_three.push(c); - if prev_three.len() > 3 { - prev_three.remove(0); - } - if ['O', 'K', '\n'] == prev_three.as_slice() && idx + 1 == count { - buf_to_read = buf_to_read.split_off(2); - result = String::from("OK"); - buf.append(&mut buf_to_read); - //println!("WARNING: OK was reached"); // DEBUG - return Ok(result); - } - } - if c == '\n' { - buf_to_read = buf_to_read.split_off(idx + s as usize); - buf.append(&mut buf_to_read); - return Ok(result); - } - result.push(c); - skip_count = s - 1; - } else if let Err((msg, count)) = next_char_result { - //println!("ERROR: {}", msg); // DEBUG - for i in 0..count { - saved.push(buf_to_read[idx + i as usize]); - } - buf_to_read = buf_to_read.split_off(idx); - buf.append(&mut buf_to_read); - return Err((msg, result)); - } else { - unreachable!(); - } - } - - *saved = buf_to_read; - Err((String::from("Newline not reached"), result)) -} - -//fn debug_write_albumart_to_file(data: &[u8]) -> Result<(), String> { -// let mut f = File::create("albumartOut.jpg") -// .map_err(|_| String::from("Failed to open file for writing albumart"))?; -// f.write_all(data) -// .map_err(|_| String::from("Failed to write to albumartOut.jpg"))?; -// -// Ok(()) -//} - -fn info_loop(shared_data: Arc>, dirty_flag: Arc) -> Result<(), String> { - let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE]; - let mut init: bool = true; - let mut saved: Vec = Vec::new(); - let mut saved_str: String = String::new(); - let mut authenticated: bool = false; - let mut song_title_get_time: Instant = Instant::now() - Duration::from_secs(10); - let mut song_pos_get_time: Instant = Instant::now() - Duration::from_secs(10); - let mut song_length_get_time: Instant = Instant::now() - Duration::from_secs(10); - let mut current_binary_size: usize = 0; - let mut poll_state = PollState::None; - let mut did_check_overtime = false; - let mut force_get_currentsong = false; - let mut force_get_status = false; - 'main: loop { - if !shared_data - .lock() - .map_err(|_| String::from("Failed to get shared_data.thread_running"))? - .thread_running - { - break; - } - - // read block - { - let lock_result = shared_data.try_lock(); - if let Ok(mut lock) = lock_result { - let read_result = lock.stream.read(&mut buf); - if let Ok(count) = read_result { - let mut read_vec: Vec = Vec::from(&buf[0..count]); - //println!("{}", String::from_utf8(read_vec.clone()).unwrap_or("Unknown reply".into())); // DEBUG - loop { - let mut count = read_vec.len(); - if current_binary_size > 0 { - if current_binary_size <= count { - lock.art_data - .extend_from_slice(&read_vec[0..current_binary_size]); - read_vec = read_vec.split_off(current_binary_size + 1); - count = read_vec.len(); - current_binary_size = 0; - poll_state = PollState::None; - dirty_flag.store(true, Ordering::Relaxed); - //println!( - // "art_data len is {} after fully reading", - // lock.art_data.len() - //); - // DEBUG - //let write_file_result = debug_write_albumart_to_file(&lock.art_data); - } else { - lock.art_data.extend_from_slice(&read_vec[0..count]); - current_binary_size -= count; - //println!("art_data len is {}", lock.art_data.len()); - continue 'main; - } - } - let read_line_result = read_line(&mut read_vec, count, &mut saved, init); - if let Ok(mut line) = read_line_result { - //println!("read_line_result line: \"{}\"", line); // DEBUG - line = saved_str + &line; - saved_str = String::new(); - if init { - if line.starts_with("OK MPD ") { - init = false; - println!("Got initial \"OK\" from MPD"); - poll_state = PollState::None; - break; - } else { - return Err(String::from( - "Did not get expected init message from MPD", - )); - } - } else { - //println!("Got response: {}", line); // DEBUG - if line.starts_with("OK") { - match poll_state { - PollState::Password => authenticated = true, - PollState::ReadPicture => { - if lock.art_data.is_empty() { - lock.can_get_album_art = false; - dirty_flag.store(true, Ordering::Relaxed); - println!("No embedded album art"); - } - } - PollState::ReadPictureInDir => { - if lock.art_data.is_empty() { - lock.can_get_album_art_in_dir = false; - dirty_flag.store(true, Ordering::Relaxed); - println!("No album art in dir"); - } - } - _ => (), - } - poll_state = PollState::None; - break; - } else if line.starts_with("ACK") { - println!("ERROR: {}", line); - match poll_state { - PollState::Password => { - lock.can_authenticate = false; - dirty_flag.store(true, Ordering::Relaxed); - } - PollState::CurrentSong | PollState::Status => { - lock.can_get_status = false; - dirty_flag.store(true, Ordering::Relaxed); - } - PollState::ReadPicture => { - lock.can_get_album_art = false; - dirty_flag.store(true, Ordering::Relaxed); - println!("Failed to get readpicture"); - } - PollState::ReadPictureInDir => { - lock.can_get_album_art_in_dir = false; - dirty_flag.store(true, Ordering::Relaxed); - println!("Failed to get albumart"); - } - _ => (), - } - poll_state = PollState::None; - } else if line.starts_with("file: ") { - //println!("Got \"file:\" : \"{}\"", line); // DEBUG - let song_file = line.split_off(6); - if song_file != lock.current_song_filename { - lock.current_song_filename = song_file; - lock.art_data.clear(); - lock.art_data_size = 0; - lock.can_get_album_art = true; - lock.can_get_album_art_in_dir = true; - //println!("Got different song file, clearing art_data..."); - lock.current_song_title.clear(); - lock.current_song_artist.clear(); - lock.current_song_length = 0.0; - lock.current_song_position = 0.0; - did_check_overtime = false; - force_get_status = true; - } - dirty_flag.store(true, Ordering::Relaxed); - song_title_get_time = Instant::now(); - } else if line.starts_with("elapsed: ") { - //println!("Got \"elapsed:\" : \"{}\"", line); // DEBUG - let parse_pos_result = f64::from_str(&line.split_off(9)); - if let Ok(value) = parse_pos_result { - lock.current_song_position = value; - dirty_flag.store(true, Ordering::Relaxed); - song_pos_get_time = Instant::now(); - lock.current_song_pos_rec = Instant::now(); - } else { - println!("Got error trying to get current_song_position"); - } - } else if line.starts_with("duration: ") { - //println!("Got \"duration:\" : \"{}\"", line); // DEBUG - let parse_pos_result = f64::from_str(&line.split_off(10)); - if let Ok(value) = parse_pos_result { - lock.current_song_length = value; - dirty_flag.store(true, Ordering::Relaxed); - song_length_get_time = Instant::now(); - } - } else if line.starts_with("size: ") { - //println!("Got \"size:\" : \"{}\"", line); // DEBUG - let parse_artsize_result = usize::from_str(&line.split_off(6)); - if let Ok(value) = parse_artsize_result { - lock.art_data_size = value; - dirty_flag.store(true, Ordering::Relaxed); - } - } else if line.starts_with("binary: ") { - //println!("Got \"binary:\" : \"{}\"", line); // DEBUG - let parse_artbinarysize_result = - usize::from_str(&line.split_off(8)); - if let Ok(value) = parse_artbinarysize_result { - current_binary_size = value; - } - } else if line.starts_with("Title: ") { - //println!("Got \"Title:\" : \"{}\"", line); // DEBUG - lock.current_song_title = line.split_off(7); - } else if line.starts_with("Artist: ") { - //println!("Got \"Artist:\" : \"{}\"", line); // DEBUG - lock.current_song_artist = line.split_off(8); - } - } - } else if let Err((msg, read_line_in_progress)) = read_line_result { - println!("Error during \"read_line\": {}", msg); - saved_str = read_line_in_progress; - break; - } else { - unreachable!(); - } - } - } - } else { - println!("INFO: Temporarily failed to acquire lock for reading from tcp stream"); - } - } - - // write block - if poll_state == PollState::None { - let lock_result = shared_data.try_lock(); - if let Ok(mut lock) = lock_result { - // first check if overtime - if !did_check_overtime - && lock.current_song_position + song_pos_get_time.elapsed().as_secs_f64() - 0.2 - > lock.current_song_length - { - did_check_overtime = true; - force_get_currentsong = true; - //println!("set \"force_get_currentsong\""); // DEBUG - } - - if !authenticated && !lock.password.is_empty() && lock.can_authenticate { - let p = lock.password.clone(); - let write_result = lock.stream.write(format!("password {}\n", p).as_bytes()); - if write_result.is_ok() { - poll_state = PollState::Password; - //println!("password"); // DEBUG - } else if let Err(e) = write_result { - println!("Got error requesting authentication: {}", e); - } - } else if (song_title_get_time.elapsed() > POLL_DURATION || force_get_currentsong) - && lock.can_get_status - { - force_get_currentsong = false; - let write_result = lock.stream.write(b"currentsong\n"); - if let Err(e) = write_result { - println!("Got error requesting currentsong info: {}", e); - } else { - poll_state = PollState::CurrentSong; - //println!("currentsong"); // DEBUG - } - } else if (song_length_get_time.elapsed() > POLL_DURATION - || song_pos_get_time.elapsed() > POLL_DURATION - || force_get_status) - && lock.can_get_status - { - force_get_status = false; - let write_result = lock.stream.write(b"status\n"); - if let Err(e) = write_result { - println!("Got error requesting status: {}", e); - } else { - poll_state = PollState::Status; - //println!("status"); // DEBUG - } - } else if (lock.art_data.is_empty() || lock.art_data.len() != lock.art_data_size) - && !lock.current_song_filename.is_empty() - { - let title = lock.current_song_filename.clone(); - let art_data_length = lock.art_data.len(); - if lock.can_get_album_art { - let write_result = lock.stream.write( - format!("readpicture \"{}\" {}\n", title, art_data_length).as_bytes(), - ); - if let Err(e) = write_result { - println!("Got error requesting albumart: {}", e); - } else { - poll_state = PollState::ReadPicture; - //println!("readpicture"); // DEBUG - } - } else if lock.can_get_album_art_in_dir { - let write_result = lock.stream.write( - format!("albumart \"{}\" {}\n", title, art_data_length).as_bytes(), - ); - if let Err(e) = write_result { - println!("Got error requesting albumart in dir: {}", e); - } else { - poll_state = PollState::ReadPictureInDir; - //println!("albumart"); // DEBUG - } - } - } - } else { - println!("INFO: Temporarily failed to acquire lock for writing to tcp stream"); - } - } else { - // DEBUG - //println!("poll_state == {:?}, skipping write...", poll_state); - } - - if poll_state != PollState::ReadPicture && poll_state != PollState::ReadPictureInDir { - thread::sleep(Duration::from_millis(50)); - } - } - Ok(()) -} - -fn get_info_from_shared(shared: Arc>) -> Result { - let mut filename: String = String::new(); - let mut title: String = String::new(); - let mut artist: String = String::new(); - let mut length: f64 = 0.0; - let mut pos: f64 = 0.0; - let mut instant_rec: Instant = Instant::now(); - let mut error_text = String::new(); - if let Ok(lock) = shared.lock() { - filename = lock.current_song_filename.clone(); - title = lock.current_song_title.clone(); - artist = lock.current_song_artist.clone(); - length = lock.current_song_length; - pos = lock.current_song_position; - instant_rec = lock.current_song_pos_rec; - //println!("Current song: {}", lock.current_song_filename); - //println!("Current song length: {}", lock.current_song_length); - //println!("Current song position: {}", lock.current_song_position); - if !lock.can_authenticate { - error_text = String::from("Failed to authenticate to mpd"); - } else if !lock.can_get_status { - error_text = String::from("Failed to get status from mpd"); - } else if !lock.can_get_album_art && !lock.can_get_album_art_in_dir { - error_text = String::from("Failed to get albumart from mpd"); - } - } - - Ok(InfoFromShared { - filename, - title, - artist, - length, - pos, - instant_rec, - error_text, - }) -} - -fn window_conf() -> Conf { - Conf { - window_title: String::from("mpd info screen"), - fullscreen: false, - window_width: 800, - window_height: 800, - ..Default::default() - } -} - -fn seconds_to_time(seconds: f64) -> String { - let seconds_int: u64 = seconds.floor() as u64; - let minutes = seconds_int / 60; - let new_seconds: f64 = seconds - (minutes * 60) as f64; - let mut result: String; - if minutes > 0 { - result = minutes.to_string(); - result.push(':'); - if new_seconds < 10.0 { - result.push('0'); - } - } else { - result = String::new(); - } - result.push_str(&new_seconds.to_string()); - let idx_result = result.find('.'); - if let Some(idx) = idx_result { - result.truncate(idx + 2); - } - - result -} - -#[macroquad::main(window_conf)] -async fn main() -> Result<(), String> { +fn main() -> Result<(), String> { let opt = Opt::from_args(); println!("Got host addr == {}, port == {}", opt.host, opt.port); - let mut password: Option = opt.password; + let (mut ctx, event_loop) = ContextBuilder::new("mpd_info_screen", "Stephen Seo") + .window_setup(WindowSetup { + title: "mpd info screen".into(), + ..Default::default() + }) + .build() + .expect("Failed to create ggez context"); - if opt.enable_prompt_password { - let mut input: String = String::new(); - let mut asterisks: String = String::new(); - let mut dirty: bool = true; - 'prompt_loop: loop { - draw_text( - "Input password:", - TEXT_X_OFFSET, - TEXT_Y_OFFSET + PROMPT_Y_OFFSET, - PROMPT_Y_OFFSET, - WHITE, - ); - if let Some(k) = get_last_key_pressed() { - if k == KeyCode::Backspace { - input.pop(); - dirty = true; - } else if k == KeyCode::Enter { - password = Some(input); - break 'prompt_loop; - } - } - if let Some(c) = get_char_pressed() { - input.push(c); - dirty = true; - } - if dirty { - let input_count = input.chars().count(); - if asterisks.len() < input_count { - for _ in 0..(input_count - asterisks.len()) { - asterisks.push('*'); - } - } else { - asterisks.truncate(input_count); - } - dirty = false; - } - draw_text( - &asterisks, - TEXT_X_OFFSET, - TEXT_Y_OFFSET + PROMPT_Y_OFFSET * 2.0, - PROMPT_Y_OFFSET, - WHITE, - ); + let display = display::MPDDisplay::new(&mut ctx, opt); - next_frame().await - } - } - - let connection = get_connection(opt.host, opt.port)?; - connection - .set_read_timeout(Some(Duration::from_millis(50))) - .expect("Should be able to set timeout for TcpStream reads"); - connection - .set_write_timeout(Some(Duration::from_secs(1))) - .expect("Should be able to set timeout for TcpStream writes"); - - let shared_data = Arc::new(Mutex::new(Shared::new(connection))); - if let Some(p) = password { - shared_data - .lock() - .expect("Should be able to get mutex lock") - .password = p; - } - let atomic_dirty_flag = Arc::new(AtomicBool::new(true)); - let thread_shared_data = shared_data.clone(); - let thread_dirty_flag = atomic_dirty_flag.clone(); - - let child = thread::spawn(move || { - info_loop(thread_shared_data, thread_dirty_flag).expect("Failure during info_loop"); - }); - - let mut timer: f64 = 0.0; - let mut track_timer: f64 = 0.0; - let mut filename: String = String::new(); - let mut title: String = String::new(); - let mut artist: String = String::new(); - let mut art_texture: Option = None; - let mut art_draw_params: Option = None; - let mut art_draw_width: f32 = 32.0; - let mut art_draw_height: f32 = 32.0; - let mut filename_font_size: Option = None; - let mut text_dim: TextDimensions = measure_text("undefined", None, 24, 1.0); - let mut prev_width = screen_width(); - let mut prev_height = screen_height(); - let mut error_text = String::new(); - let mut title_dim_opt: Option = None; - let mut title_font_size: u16 = INITIAL_FONT_SIZE; - let mut artist_dim_opt: Option = None; - let mut artist_font_size: u16 = ARTIST_INITIAL_FONT_SIZE; - let mut temp_offset_y: f32; - let mut check_due_to_track_timer_count: u64 = 0; - - 'macroquad_main: loop { - let dt: f64 = get_frame_time() as f64; - clear_background(BLACK); - - if is_key_pressed(KeyCode::Escape) || is_key_pressed(KeyCode::Q) { - break 'macroquad_main; - } else if (prev_width - screen_width()).abs() > SCREEN_DIFF_MARGIN - || (prev_height - screen_height()).abs() > SCREEN_DIFF_MARGIN - { - prev_width = screen_width(); - prev_height = screen_height(); - filename_font_size = None; - title_dim_opt = None; - artist_dim_opt = None; - art_draw_params = None; - } - - timer -= dt; - track_timer -= dt; - if timer < 0.0 - || (track_timer < 0.0 && check_due_to_track_timer_count < CHECK_TRACK_TIMER_MAX_COUNT) - { - if track_timer < 0.0 { - check_due_to_track_timer_count += 1; - //println!("check_due_to_track_timer_count incremented"); // DEBUG - } - timer = CHECK_SHARED_WAIT_TIME; - let dirty_flag = atomic_dirty_flag.load(Ordering::Relaxed); - if dirty_flag - || (track_timer < 0.0 - && check_due_to_track_timer_count < CHECK_TRACK_TIMER_MAX_COUNT) - { - if dirty_flag { - atomic_dirty_flag.store(false, Ordering::Relaxed); - } - let info_result = get_info_from_shared(shared_data.clone()); - if let Ok(info) = info_result { - if info.filename != filename { - filename = info.filename; - art_texture = None; - filename_font_size = None; - title.clear(); - title_dim_opt = None; - artist.clear(); - artist_dim_opt = None; - art_draw_params = None; - check_due_to_track_timer_count = 0; - } - let duration_since = info.instant_rec.elapsed(); - let recorded_time = info.length - info.pos - duration_since.as_secs_f64(); - if (recorded_time - track_timer).abs() > TIME_MAX_DIFF { - track_timer = info.length - info.pos - duration_since.as_secs_f64(); - } - if !info.error_text.is_empty() { - error_text = info.error_text; - } - if !info.title.is_empty() { - title = info.title; - } - if !info.artist.is_empty() { - artist = info.artist; - } - } - } - - if art_texture.is_none() { - let mut image_result: Option> = None; - { - let lock_result = shared_data.lock(); - if let Ok(l) = lock_result { - image_result = Some(image::load_from_memory(&l.art_data)); - } - } - if let Some(Ok(dynimg)) = image_result { - let img_buf = dynimg.to_rgba8(); - art_texture = Some(Texture2D::from_rgba8( - img_buf - .width() - .try_into() - .expect("width of image should fit in u16"), - img_buf - .height() - .try_into() - .expect("height of image should fit into u16"), - &img_buf.to_vec(), - )); - } - } - } - - if let Some(texture) = art_texture { - if texture.width() > prev_width || texture.height() > prev_height { - if art_draw_params.is_none() { - let ratio: f32 = texture.width() / texture.height(); - // try filling to height - art_draw_height = prev_height; - art_draw_width = prev_height * ratio; - if art_draw_width > prev_width { - // try filling to width instead - art_draw_width = prev_width; - art_draw_height = prev_width / ratio; - } - - art_draw_params = Some(DrawTextureParams { - dest_size: Some(Vec2::new(art_draw_width, art_draw_height)), - ..Default::default() - }); - } - draw_texture_ex( - texture, - (prev_width - art_draw_width) / 2.0f32, - (prev_height - art_draw_height) / 2.0f32, - WHITE, - art_draw_params.as_ref().unwrap().clone(), - ); - } else { - draw_texture( - texture, - (prev_width - texture.width()) / 2.0f32, - (prev_height - texture.height()) / 2.0f32, - WHITE, - ); - } - } - - if !is_key_down(KeyCode::H) { - temp_offset_y = 0.0; - if !filename.is_empty() && !opt.disable_show_filename { - if filename_font_size.is_none() { - filename_font_size = Some(INITIAL_FONT_SIZE); - loop { - text_dim = measure_text( - &filename, - None, - *filename_font_size.as_ref().unwrap(), - 1.0f32, - ); - if text_dim.width + TEXT_X_OFFSET > prev_width { - filename_font_size = filename_font_size.map(|s| s - 4); - } else { - break; - } - - if *filename_font_size.as_ref().unwrap() <= 4 { - filename_font_size = Some(4); - text_dim = measure_text( - &filename, - None, - *filename_font_size.as_ref().unwrap(), - 1.0f32, - ); - break; - } - } - } - draw_rectangle( - TEXT_X_OFFSET, - prev_height - TEXT_Y_OFFSET - text_dim.height, - text_dim.width, - text_dim.height, - Color::new(0.0, 0.0, 0.0, 0.4), - ); - draw_text( - &filename, - TEXT_X_OFFSET, - prev_height - TEXT_Y_OFFSET, - *filename_font_size.as_ref().unwrap() as f32, - WHITE, - ); - - temp_offset_y += TEXT_Y_OFFSET + text_dim.height; - } - - // Get title dimensions early so that artist size is at most title size - if !title.is_empty() && !opt.disable_show_title && title_dim_opt.is_none() { - let mut length: u16 = title.chars().count().try_into().unwrap_or(u16::MAX); - length /= 10; - if length <= 2 { - length = 3; - } - let screen_factor = 4 * screen_width() as u16 / TITLE_SCREEN_FACTOR; - title_font_size = TITLE_INITIAL_FONT_SIZE / length as u16 + screen_factor; - if title_font_size < TITLE_INITIAL_MIN_FONT_SIZE { - title_font_size = TITLE_INITIAL_MIN_FONT_SIZE; - } - loop { - title_dim_opt = Some(measure_text(&title, None, title_font_size, 1.0f32)); - if title_dim_opt.as_ref().unwrap().width + TEXT_X_OFFSET > prev_width { - title_font_size -= 4; - if title_font_size < 4 { - title_font_size = 4; - title_dim_opt = - Some(measure_text(&title, None, title_font_size, 1.0f32)); - break; - } - } else { - break; - } - } - } - - if !artist.is_empty() && !opt.disable_show_artist { - if artist_dim_opt.is_none() { - if !title.is_empty() && !opt.disable_show_title { - artist_font_size = title_font_size; - } else { - artist_font_size = ARTIST_INITIAL_FONT_SIZE; - } - loop { - artist_dim_opt = - Some(measure_text(&artist, None, artist_font_size, 1.0f32)); - if artist_dim_opt.as_ref().unwrap().width + TEXT_X_OFFSET > prev_width { - artist_font_size -= 4; - if artist_font_size < 4 { - artist_font_size = 4; - artist_dim_opt = - Some(measure_text(&artist, None, artist_font_size, 1.0f32)); - break; - } - } else { - break; - } - } - } - - let temp_dim_opt = artist_dim_opt.as_ref().unwrap(); - draw_rectangle( - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET - temp_dim_opt.height, - temp_dim_opt.width, - temp_dim_opt.height, - Color::new(0.0, 0.0, 0.0, 0.4), - ); - draw_text( - &artist, - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET, - artist_font_size.into(), - WHITE, - ); - - temp_offset_y += TEXT_Y_OFFSET + temp_dim_opt.height; - } - - if !title.is_empty() && !opt.disable_show_title { - let temp_dim_opt = title_dim_opt.as_ref().unwrap(); - draw_rectangle( - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET - temp_dim_opt.height, - temp_dim_opt.width, - temp_dim_opt.height, - Color::new(0.0, 0.0, 0.0, 0.4), - ); - draw_text( - &title, - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET, - title_font_size.into(), - WHITE, - ); - - temp_offset_y += TEXT_Y_OFFSET + temp_dim_opt.height; - } - - let timer_string = seconds_to_time(track_timer); - let timer_dim = measure_text(&timer_string, None, TIMER_FONT_SIZE, 1.0f32); - draw_rectangle( - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET - timer_dim.height, - timer_dim.width, - timer_dim.height, - Color::new(0.0, 0.0, 0.0, 0.4), - ); - draw_text( - &timer_string, - TEXT_X_OFFSET, - prev_height - temp_offset_y - TEXT_Y_OFFSET, - TIMER_FONT_SIZE.into(), - WHITE, - ); - - if !error_text.is_empty() { - draw_text(&error_text, 0.0, 32.0f32, 32.0f32, WHITE); - } - } - - next_frame().await - } - - println!("Stopping thread..."); - shared_data - .lock() - .map_err(|_| String::from("Failed to get shared_data.thread_running in main"))? - .thread_running = false; - - //println!("Waiting on thread..."); - thread::sleep(Duration::from_millis(200)); - - println!("Joining on thread..."); - child.join().expect("Should be able to join on thread"); - - //get_info_from_shared(shared_data.clone(), true) - // .expect("Should be able to get info from shared"); - - Ok(()) + event::run(ctx, event_loop, display); } diff --git a/src/mpd_handler.rs b/src/mpd_handler.rs new file mode 100644 index 0000000..546f7c2 --- /dev/null +++ b/src/mpd_handler.rs @@ -0,0 +1,604 @@ +use std::io::{Read, Write}; +use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream}; +use std::str::FromStr; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex, RwLock}; +use std::thread; +use std::time::{Duration, Instant}; + +const SLEEP_DURATION: Duration = Duration::from_millis(100); +const POLL_DURATION: Duration = Duration::from_secs(10); +const BUF_SIZE: usize = 1024 * 4; + +#[derive(Debug, PartialEq, Copy, Clone)] +enum PollState { + None, + Password, + CurrentSong, + Status, + ReadPicture, + ReadPictureInDir, +} + +#[derive(Debug, Clone)] +pub struct InfoFromShared { + filename: String, + title: String, + artist: String, + length: f64, + pos: f64, + error_text: String, +} + +pub struct MPDHandler { + art_data: Vec, + art_data_size: usize, + current_song_filename: String, + current_song_title: String, + current_song_artist: String, + current_song_length: f64, + current_song_position: f64, + current_binary_size: usize, + poll_state: PollState, + thread_running: bool, + stream: TcpStream, + password: String, + error_text: String, + can_authenticate: bool, + is_authenticated: bool, + can_get_album_art: bool, + can_get_album_art_in_dir: bool, + can_get_status: bool, + is_init: bool, + did_check_overtime: bool, + force_get_status: bool, + force_get_current_song: bool, + song_title_get_time: Instant, + song_pos_get_time: Instant, + song_length_get_time: Instant, + self_thread: Option>>>>, + dirty_flag: Arc, + stop_flag: Arc, +} + +fn check_next_chars( + buf: &[u8], + idx: usize, + saved: &mut Vec, +) -> Result<(char, u8), (String, u8)> { + if idx >= buf.len() { + return Err((String::from("idx out of bounds"), 0u8)); + } + if buf[idx] & 0b10000000 == 0 { + let result_str = String::from_utf8(vec![buf[idx]]); + if let Ok(mut s) = result_str { + let popped_char = s.pop(); + if s.is_empty() { + Ok((popped_char.unwrap(), 1u8)) + } else { + Err((String::from("Not one-byte UTF-8 char"), 0u8)) + } + } else { + Err((String::from("Not one-byte UTF-8 char"), 0u8)) + } + } else if buf[idx] & 0b11100000 == 0b11000000 { + if idx + 1 >= buf.len() { + saved.push(buf[idx]); + return Err(( + String::from("Is two-byte UTF-8, but not enough bytes provided"), + 1u8, + )); + } + let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1]]); + if let Ok(mut s) = result_str { + let popped_char = s.pop(); + if s.is_empty() { + Ok((popped_char.unwrap(), 2u8)) + } else { + Err((String::from("Not two-byte UTF-8 char"), 0u8)) + } + } else { + Err((String::from("Not two-byte UTF-8 char"), 0u8)) + } + } else if buf[idx] & 0b11110000 == 0b11100000 { + if idx + 2 >= buf.len() { + for c in buf.iter().skip(idx) { + saved.push(*c); + } + return Err(( + String::from("Is three-byte UTF-8, but not enough bytes provided"), + (idx + 3 - buf.len()) as u8, + )); + } + let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]); + if let Ok(mut s) = result_str { + let popped_char = s.pop(); + if s.is_empty() { + Ok((popped_char.unwrap(), 3u8)) + } else { + Err((String::from("Not three-byte UTF-8 char"), 0u8)) + } + } else { + Err((String::from("Not three-byte UTF-8 char"), 0u8)) + } + } else if buf[idx] & 0b11111000 == 0b11110000 { + if idx + 3 >= buf.len() { + for c in buf.iter().skip(idx) { + saved.push(*c); + } + return Err(( + String::from("Is four-byte UTF-8, but not enough bytes provided"), + (idx + 4 - buf.len()) as u8, + )); + } + let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]); + if let Ok(mut s) = result_str { + let popped_char = s.pop(); + if s.is_empty() { + Ok((popped_char.unwrap(), 4u8)) + } else { + Err((String::from("Not four-byte UTF-8 char"), 0u8)) + } + } else { + Err((String::from("Not four-byte UTF-8 char"), 0u8)) + } + } else { + Err((String::from("Invalid UTF-8 char"), 0u8)) + } +} + +fn read_line( + buf: &mut Vec, + saved: &mut Vec, + init: bool, +) -> Result { + let count = buf.len(); + let mut result = String::new(); + + let mut buf_to_read: Vec = Vec::with_capacity(saved.len() + buf.len()); + + if !saved.is_empty() { + buf_to_read.append(saved); + } + buf_to_read.append(buf); + + let mut prev_three: Vec = Vec::with_capacity(4); + + let mut skip_count = 0; + for idx in 0..count { + if skip_count > 0 { + skip_count -= 1; + continue; + } + let next_char_result = check_next_chars(&buf_to_read, idx, saved); + if let Ok((c, s)) = next_char_result { + if !init { + prev_three.push(c); + if prev_three.len() > 3 { + prev_three.remove(0); + } + if ['O', 'K', '\n'] == prev_three.as_slice() && idx + 1 == count { + buf_to_read = buf_to_read.split_off(2); + result = String::from("OK"); + buf.append(&mut buf_to_read); + //println!("WARNING: OK was reached"); // DEBUG + return Ok(result); + } + } + if c == '\n' { + buf_to_read = buf_to_read.split_off(idx + s as usize); + buf.append(&mut buf_to_read); + return Ok(result); + } + result.push(c); + skip_count = s - 1; + } else if let Err((msg, count)) = next_char_result { + //println!("ERROR: {}", msg); // DEBUG + for i in 0..count { + saved.push(buf_to_read[idx + i as usize]); + } + buf_to_read = buf_to_read.split_off(idx); + buf.append(&mut buf_to_read); + return Err((msg, result)); + } else { + unreachable!(); + } + } + + *saved = buf_to_read; + Err((String::from("Newline not reached"), result)) +} + +fn seconds_to_time(seconds: f64) -> String { + let seconds_int: u64 = seconds.floor() as u64; + let minutes = seconds_int / 60; + let new_seconds: f64 = seconds - (minutes * 60) as f64; + let mut result: String; + if minutes > 0 { + result = minutes.to_string(); + result.push(':'); + if new_seconds < 10.0 { + result.push('0'); + } + } else { + result = String::new(); + } + result.push_str(&new_seconds.to_string()); + let idx_result = result.find('.'); + if let Some(idx) = idx_result { + result.truncate(idx + 2); + } + + result +} + +impl MPDHandler { + pub fn new(host: Ipv4Addr, port: u16, password: String) -> Result>, String> { + let stream = TcpStream::connect_timeout( + &SocketAddr::new(IpAddr::V4(host), port), + Duration::from_secs(5), + ) + .map_err(|_| String::from("Failed to get TCP connection"))?; + + let mut s = Arc::new(RwLock::new(Self { + art_data: Vec::new(), + art_data_size: 0, + current_song_filename: String::new(), + current_song_title: String::new(), + current_song_artist: String::new(), + current_song_length: 0.0, + current_song_position: 0.0, + current_binary_size: 0, + poll_state: PollState::None, + thread_running: true, + stream, + password, + error_text: String::new(), + can_authenticate: true, + is_authenticated: false, + can_get_album_art: true, + can_get_album_art_in_dir: true, + can_get_status: true, + is_init: true, + did_check_overtime: false, + force_get_status: false, + force_get_current_song: false, + song_title_get_time: Instant::now() - Duration::from_secs(10), + song_pos_get_time: Instant::now() - Duration::from_secs(10), + song_length_get_time: Instant::now() - Duration::from_secs(10), + self_thread: None, + dirty_flag: Arc::new(AtomicBool::new(true)), + stop_flag: Arc::new(AtomicBool::new(false)), + })); + + let mut s_clone = s.clone(); + let mut thread = Arc::new(Mutex::new(thread::spawn(|| Self::handler_loop(s_clone)))); + + s.write() + .map_err(|_| String::from("Failed to start MPDHandler thread"))? + .self_thread = Some(thread.clone()); + + Ok(s) + } + + pub fn get_art_data(h: Arc>) -> Result, ()> { + if let Ok(read_lock) = h.read() { + if read_lock.art_data.len() == read_lock.art_data_size { + return Ok(read_lock.art_data.clone()); + } + } + + Err(()) + } + + pub fn can_get_art_data(h: Arc>) -> bool { + if let Ok(read_lock) = h.read() { + return read_lock.can_get_album_art || read_lock.can_get_album_art_in_dir; + } + + false + } + + pub fn get_current_song_info(h: Arc>) -> Result { + if let Ok(read_lock) = h.read() { + return Ok(InfoFromShared { + filename: read_lock.current_song_filename.clone(), + title: read_lock.current_song_title.clone(), + artist: read_lock.current_song_artist.clone(), + length: read_lock.current_song_length, + pos: read_lock.current_song_position, + error_text: read_lock.error_text.clone(), + }); + } + + Err(()) + } + + fn handler_loop(h: Arc>) -> Result<(), String> { + let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE]; + let mut saved: Vec = Vec::new(); + let mut saved_str: String = String::new(); + 'main: loop { + if !Self::is_reading_picture(h.clone()) { + thread::sleep(SLEEP_DURATION); + } + + if let Err(err_string) = + Self::handler_read_block(h.clone(), &mut buf, &mut saved, &mut saved_str) + { + println!("WARNING: read_block error: {}", err_string); + } else if let Err(err_string) = Self::handler_write_block(h.clone()) { + println!("WARNING: write_block error: {}", err_string); + } + + if let Ok(read_handle) = h.read() { + if read_handle.stop_flag.load(Ordering::Relaxed) { + break 'main; + } + } + } + + 'exit: loop { + if let Ok(mut write_handle) = h.write() { + write_handle.self_thread = None; + break 'exit; + } + thread::sleep(SLEEP_DURATION); + } + + Ok(()) + } + + fn handler_read_block( + h: Arc>, + buf: &mut [u8; BUF_SIZE], + saved: &mut Vec, + saved_str: &mut String, + ) -> Result<(), String> { + let mut write_handle = h + .write() + .map_err(|_| String::from("Failed to get MPDHandler write lock (read_block)"))?; + let read_result = write_handle + .stream + .read(buf) + .map_err(|io_err| format!("Failed to read from TCP stream: {}", io_err))?; + if read_result == 0 { + return Err(String::from("Got zero bytes from TCP stream")); + } + let mut buf_vec: Vec = Vec::from(&buf[0..read_result]); + + 'handle_buf: loop { + if write_handle.current_binary_size > 0 { + if write_handle.current_binary_size <= buf_vec.len() { + let count = write_handle.current_binary_size; + write_handle.art_data.extend_from_slice(&buf_vec[0..count]); + buf_vec = buf_vec.split_off(write_handle.current_binary_size + 1); + write_handle.current_binary_size = 0; + write_handle.poll_state = PollState::None; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + } else { + write_handle.art_data.extend_from_slice(&buf_vec); + write_handle.current_binary_size -= buf_vec.len(); + break 'handle_buf; + } + } + let read_line_result = read_line(&mut buf_vec, saved, write_handle.is_init); + if let Ok(mut line) = read_line_result { + line = saved_str.clone() + &line; + *saved_str = String::new(); + if write_handle.is_init { + if line.starts_with("OK MPD ") { + write_handle.is_init = false; + println!("Got initial \"OK\" from MPD"); + write_handle.poll_state = PollState::None; + break 'handle_buf; + } else { + return Err(String::from("Did not get expected init message from MPD")); + } + } // write_handle.is_init + + if line.starts_with("OK") { + match write_handle.poll_state { + PollState::Password => write_handle.is_authenticated = true, + PollState::ReadPicture => { + if write_handle.art_data.is_empty() { + write_handle.can_get_album_art = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + println!("No embedded album art"); + } + } + PollState::ReadPictureInDir => { + if write_handle.art_data.is_empty() { + write_handle.can_get_album_art_in_dir = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + println!("No album art in dir"); + } + } + _ => (), + } + write_handle.poll_state = PollState::None; + break 'handle_buf; + } else if line.starts_with("ACK") { + println!("ERROR: {}", line); + match write_handle.poll_state { + PollState::Password => { + write_handle.can_authenticate = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + } + PollState::CurrentSong | PollState::Status => { + write_handle.can_get_status = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + } + PollState::ReadPicture => { + write_handle.can_get_album_art = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + println!("Failed to get readpicture"); + } + PollState::ReadPictureInDir => { + write_handle.can_get_album_art_in_dir = false; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + println!("Failed to get albumart"); + } + _ => (), + } + write_handle.poll_state = PollState::None; + } else if line.starts_with("file: ") { + let song_file = line.split_off(6); + if song_file != write_handle.current_song_filename { + write_handle.current_song_filename = song_file; + write_handle.art_data.clear(); + write_handle.art_data_size = 0; + write_handle.can_get_album_art = true; + write_handle.can_get_album_art_in_dir = true; + write_handle.current_song_title.clear(); + write_handle.current_song_artist.clear(); + write_handle.current_song_length = 0.0; + write_handle.current_song_position = 0.0; + write_handle.did_check_overtime = false; + write_handle.force_get_status = true; + } + write_handle.dirty_flag.store(true, Ordering::Relaxed); + write_handle.song_title_get_time = Instant::now(); + } else if line.starts_with("elapsed: ") { + let parse_pos_result = f64::from_str(&line.split_off(9)); + if let Ok(value) = parse_pos_result { + write_handle.current_song_position = value; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + write_handle.song_pos_get_time = Instant::now(); + } else { + println!("WARNING: Failed to parse current song position"); + } + } else if line.starts_with("duration: ") { + let parse_pos_result = f64::from_str(&line.split_off(10)); + if let Ok(value) = parse_pos_result { + write_handle.current_song_length = value; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + write_handle.song_length_get_time = Instant::now(); + } else { + println!("WARNING: Failed to parse current song duration"); + } + } else if line.starts_with("size: ") { + let parse_artsize_result = usize::from_str(&line.split_off(6)); + if let Ok(value) = parse_artsize_result { + write_handle.art_data_size = value; + write_handle.dirty_flag.store(true, Ordering::Relaxed); + } else { + println!("WARNING: Failed to parse album art byte size"); + } + } else if line.starts_with("binary: ") { + let parse_artbinarysize_result = usize::from_str(&line.split_off(8)); + if let Ok(value) = parse_artbinarysize_result { + write_handle.current_binary_size = value; + } else { + println!("WARNING: Failed to parse album art chunk byte size"); + } + } else if line.starts_with("Title: ") { + write_handle.current_song_title = line.split_off(7); + } else if line.starts_with("Artist: ") { + write_handle.current_song_artist = line.split_off(8); + } else { + println!("WARNING: Got unrecognized line: {}", line); + } + } else if let Err((msg, read_line_in_progress)) = read_line_result { + println!("ERROR read_line: {}", msg); + *saved_str = read_line_in_progress; + break 'handle_buf; + } else { + unreachable!(); + } + } // 'handle_buf: loop + + Ok(()) + } + + fn handler_write_block(h: Arc>) -> Result<(), String> { + let mut write_handle = h + .write() + .map_err(|_| String::from("Failed to get MPDHandler write lock (write_block)"))?; + if write_handle.poll_state == PollState::None { + if !write_handle.did_check_overtime + && write_handle.current_song_position + + write_handle.song_pos_get_time.elapsed().as_secs_f64() + - 0.2 + > write_handle.current_song_length + { + write_handle.did_check_overtime = true; + write_handle.force_get_current_song = true; + } + + if !write_handle.is_authenticated + && !write_handle.password.is_empty() + && write_handle.can_authenticate + { + let p = write_handle.password.clone(); + let write_result = write_handle + .stream + .write(format!("password {}\n", p).as_bytes()); + if write_result.is_ok() { + write_handle.poll_state = PollState::Password; + } else if let Err(e) = write_result { + println!("ERROR: Failed to send password for authentication: {}", e); + } + } else if write_handle.can_get_status + && (write_handle.song_title_get_time.elapsed() > POLL_DURATION + || write_handle.force_get_current_song) + { + write_handle.force_get_current_song = false; + let write_result = write_handle.stream.write(b"currentsong\n"); + if write_result.is_ok() { + write_handle.poll_state = PollState::CurrentSong; + } else if let Err(e) = write_result { + println!("ERROR: Failed to request song info over stream: {}", e); + } + } else if write_handle.can_get_status + && (write_handle.song_length_get_time.elapsed() > POLL_DURATION + || write_handle.song_pos_get_time.elapsed() > POLL_DURATION + || write_handle.force_get_status) + { + write_handle.force_get_status = false; + let write_result = write_handle.stream.write(b"status\n"); + if write_result.is_ok() { + write_handle.poll_state = PollState::Status; + } else if let Err(e) = write_result { + println!("ERROR: Failed to request status over stream: {}", e); + } + } else if (write_handle.art_data.is_empty() + || write_handle.art_data.len() != write_handle.art_data_size) + && !write_handle.current_song_filename.is_empty() + { + let title = write_handle.current_song_filename.clone(); + let art_data_length = write_handle.art_data.len(); + if write_handle.can_get_album_art { + let write_result = write_handle.stream.write( + format!("readpicture \"{}\" {}\n", title, art_data_length).as_bytes(), + ); + if write_result.is_ok() { + write_handle.poll_state = PollState::ReadPicture; + } else if let Err(e) = write_result { + println!("ERROR: Failed to request album art: {}", e); + } + } else if write_handle.can_get_album_art_in_dir { + let write_result = write_handle + .stream + .write(format!("albumart \"{}\" {}\n", title, art_data_length).as_bytes()); + if write_result.is_ok() { + write_handle.poll_state = PollState::ReadPictureInDir; + } else if let Err(e) = write_result { + println!("ERROR: Failed to request album art in dir: {}", e); + } + } + } + } + + Ok(()) + } + + fn is_reading_picture(h: Arc>) -> bool { + if let Ok(read_handle) = h.read() { + return read_handle.poll_state == PollState::ReadPicture + || read_handle.poll_state == PollState::ReadPictureInDir; + } else { + return false; + } + } +}