From 0f474d831bae2bc33b7362a3a7a56af21f3dd444 Mon Sep 17 00:00:00 2001 From: eladyn Date: Mon, 21 Oct 2024 02:19:53 +0200 Subject: [PATCH 01/17] chore: bump dependencies except librespot and logging --- Cargo.lock | 1695 +++++++++++++++++++--------------------------------- Cargo.toml | 12 +- 2 files changed, 613 insertions(+), 1094 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7533d3a..84affb4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,19 +25,7 @@ checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" dependencies = [ "aes-soft", "aesni", - "cipher 0.2.5", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher 0.3.0", - "cpufeatures", - "opaque-debug", + "cipher", ] [[package]] @@ -48,7 +36,7 @@ checksum = "7729c3cde54d67063be556aeac75a81330d802f0259500ca40cb52967f975763" dependencies = [ "aes-soft", "aesni", - "cipher 0.2.5", + "cipher", "ctr", ] @@ -58,7 +46,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" dependencies = [ - "cipher 0.2.5", + "cipher", "opaque-debug", ] @@ -68,15 +56,15 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" dependencies = [ - "cipher 0.2.5", + "cipher", "opaque-debug", ] [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -90,19 +78,19 @@ dependencies = [ "alsa-sys", "bitflags 1.3.2", "libc", - "nix 0.23.2", + "nix", ] [[package]] name = "alsa" -version = "0.7.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", - "bitflags 1.3.2", + "bitflags 2.6.0", + "cfg-if", "libc", - "nix 0.24.3", ] [[package]] @@ -140,133 +128,65 @@ dependencies = [ ] [[package]] -name = "async-broadcast" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" -dependencies = [ - "event-listener", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand 1.9.0", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.6.0" +name = "anstream" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ - "async-lock", - "autocfg", - "blocking", - "futures-lite", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "async-io" -version = "1.13.0" +name = "anstyle" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.26", - "slab", - "socket2 0.4.9", - "waker-fn", -] +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] -name = "async-lock" -version = "2.8.0" +name = "anstyle-parse" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ - "event-listener", + "utf8parse", ] [[package]] -name = "async-process" -version = "1.7.0" +name = "anstyle-query" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "async-io", - "async-lock", - "autocfg", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 0.37.26", - "signal-hook", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] -name = "async-recursion" -version = "1.0.4" +name = "anstyle-wincon" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "anstyle", + "windows-sys 0.52.0", ] -[[package]] -name = "async-task" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" - [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", ] -[[package]] -name = "atomic-waker" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" - [[package]] name = "atty" version = "0.2.14" @@ -280,15 +200,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -307,28 +227,32 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.3" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bindgen" -version = "0.64.0" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cexpr", "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", + "itertools", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 1.0.109", + "syn 2.0.82", ] [[package]] @@ -339,9 +263,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -361,63 +285,33 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-modes" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" -dependencies = [ - "block-padding", - "cipher 0.3.0", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "blocking" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" -dependencies = [ - "async-channel", - "async-lock", - "async-task", - "atomic-waker", - "fastrand 1.9.0", - "futures-lite", - "log", -] - [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -443,18 +337,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.28" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -466,24 +359,15 @@ dependencies = [ "generic-array", ] -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.7.4", + "libloading 0.8.5", ] [[package]] @@ -503,9 +387,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -518,9 +402,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -529,22 +413,19 @@ dependencies = [ ] [[package]] -name = "combine" -version = "4.6.6" +name = "colorchoice" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] -name = "concurrent-queue" -version = "2.2.0" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "crossbeam-utils", + "bytes", + "memchr", ] [[package]] @@ -554,7 +435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ "percent-encoding", - "time 0.3.36", + "time", "version_check", ] @@ -571,25 +452,15 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "time 0.3.36", + "time", "url", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "coreaudio-rs" @@ -603,9 +474,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" +checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" dependencies = [ "bindgen", ] @@ -627,7 +498,7 @@ dependencies = [ "mach", "ndk", "ndk-glue", - "nix 0.23.2", + "nix", "oboe", "parking_lot 0.11.2", "stdweb", @@ -638,22 +509,13 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -680,7 +542,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" dependencies = [ - "cipher 0.2.5", + "cipher", ] [[package]] @@ -769,17 +631,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "digest" version = "0.9.0" @@ -797,7 +648,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "crypto-common", - "subtle", ] [[package]] @@ -818,53 +668,48 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "enum_dispatch" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", -] - -[[package]] -name = "enumflags2" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" -dependencies = [ - "enumflags2_derive", - "serde", + "syn 2.0.82", ] [[package]] -name = "enumflags2_derive" -version = "0.7.7" +name = "env_filter" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", + "log", + "regex", ] [[package]] name = "env_logger" -version = "0.10.0" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ + "anstream", + "anstyle", + "env_filter", "humantime", - "is-terminal", "log", - "regex", - "termcolor", ] [[package]] @@ -875,23 +720,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -903,17 +737,11 @@ dependencies = [ "version_check", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -921,18 +749,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fern" @@ -958,18 +777,18 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -982,9 +801,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -992,15 +811,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1009,53 +828,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1081,30 +885,32 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.4.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" +checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" dependencies = [ - "libc", - "windows-targets", + "rustix", + "windows-targets 0.52.6", ] [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1120,18 +926,17 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "headers" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.13.1", - "bitflags 1.3.2", + "base64 0.21.7", "bytes", "headers-core", "http", @@ -1160,9 +965,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -1175,9 +980,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1185,15 +990,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac 0.12.1", -] - [[package]] name = "hmac" version = "0.11.0" @@ -1204,15 +1000,6 @@ dependencies = [ "digest 0.9.0", ] -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "hostname" version = "0.3.1" @@ -1226,9 +1013,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1237,9 +1024,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1248,9 +1035,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1266,9 +1053,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", @@ -1280,7 +1067,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -1304,16 +1091,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1343,9 +1130,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1379,50 +1166,43 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.15.0", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.2", - "libc", - "windows-sys", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] -name = "is-terminal" -version = "0.4.9" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.10", - "windows-sys", + "either", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jack" @@ -1471,47 +1251,36 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] [[package]] name = "keyring" -version = "2.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52a1d320b55eacc02d4561fed9714af4e98b7989cf4e696bee192b03fc99720" +checksum = "11351fce7c6e2b5f1871e3c8ed048d60d909ab6fea6b96bfe41a6409277a2ee5" dependencies = [ - "byteorder", - "lazy_static", - "linux-keyutils", - "secret-service", - "security-framework", - "winapi", + "log", ] [[package]] name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lewton" @@ -1526,9 +1295,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libdbus-sys" @@ -1551,19 +1320,19 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "winapi", + "windows-targets 0.52.6", ] [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmdns" @@ -1577,9 +1346,9 @@ dependencies = [ "if-addrs", "log", "multimap", - "nix 0.23.2", + "nix", "rand", - "socket2 0.4.9", + "socket2 0.4.10", "thiserror", "tokio", "winapi", @@ -1633,6 +1402,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "librespot-audio" version = "0.4.2" @@ -1676,14 +1455,14 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d" dependencies = [ - "aes 0.6.0", + "aes", "base64 0.13.1", "byteorder", "bytes", "form_urlencoded", "futures-core", "futures-util", - "hmac 0.11.0", + "hmac", "http", "httparse", "hyper", @@ -1721,7 +1500,7 @@ dependencies = [ "base64 0.13.1", "form_urlencoded", "futures-core", - "hmac 0.11.0", + "hmac", "hyper", "libmdns", "librespot-core", @@ -1766,7 +1545,7 @@ dependencies = [ "librespot-metadata", "log", "ogg", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "portaudio-rs", "rand", "rand_distr", @@ -1774,7 +1553,7 @@ dependencies = [ "shell-words", "thiserror", "tokio", - "zerocopy", + "zerocopy 0.6.6", ] [[package]] @@ -1789,42 +1568,26 @@ dependencies = [ ] [[package]] -name = "linux-keyutils" -version = "0.2.3" +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f27bb67f6dd1d0bb5ab582868e4f65052e58da6401188a08f0da09cf512b84b" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ - "bitflags 1.3.2", - "libc", + "autocfg", + "scopeguard", ] [[package]] -name = "linux-raw-sys" -version = "0.3.8" +name = "log" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "mach" @@ -1843,20 +1606,20 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "maybe-async" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.82", ] [[package]] name = "memchr" -version = "2.6.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -1867,15 +1630,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -1890,22 +1644,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "wasi", + "windows-sys 0.52.0", ] [[package]] @@ -1983,30 +1738,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", + "memoffset", ] [[package]] @@ -2019,41 +1751,17 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", "rand", ] -[[package]] -name = "num-complex" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -2073,57 +1781,23 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - [[package]] name = "num_enum" version = "0.5.11" @@ -2147,18 +1821,18 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "object" -version = "0.32.0" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2197,15 +1871,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "option-ext" @@ -2213,28 +1887,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "owo-colors" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "parking" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" - [[package]] name = "parking_lot" version = "0.11.2" @@ -2248,12 +1906,12 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.10", ] [[package]] @@ -2272,18 +1930,18 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "backtrace", "cfg-if", "libc", "petgraph", - "redox_syscall 0.3.5", + "redox_syscall 0.5.7", "smallvec", "thread-id", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2293,36 +1951,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" dependencies = [ "crypto-mac", - "hmac 0.11.0", + "hmac", ] -[[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.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.6.0", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2332,9 +1984,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "pledge" @@ -2345,22 +1997,6 @@ dependencies = [ "libc", ] -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys", -] - [[package]] name = "portaudio-rs" version = "0.3.2" @@ -2390,15 +2026,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] [[package]] name = "priority-queue" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff39edfcaec0d64e8d0da38564fad195d2d51b680940295fcc307366e101e61" +checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" dependencies = [ "autocfg", "indexmap 1.9.3", @@ -2411,7 +2050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -2440,9 +2079,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -2474,9 +2113,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2532,38 +2171,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.4" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -2573,9 +2203,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2584,22 +2214,23 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" -version = "0.17.3" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -2613,11 +2244,11 @@ dependencies = [ [[package]] name = "rspotify" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c6f1d86b10201655f0cd4002088bafe4abcc75cc610613c995abd719f40fcb" +checksum = "71aa4a990ef1bacbed874fbab621e16c61a8b5a56854ada6b2bcccf19acb5795" dependencies = [ - "base64 0.21.3", + "base64 0.22.1", "chrono", "getrandom", "log", @@ -2634,9 +2265,9 @@ dependencies = [ [[package]] name = "rspotify-http" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad45cd393a8685ee36ec6d2accbb2c955e21ac036a2e4eb175985783f30ed78" +checksum = "a193f73ee55ab66aeb0337170d120bc73ec4963b150d9c66d68b28d14bc5ac5f" dependencies = [ "log", "maybe-async", @@ -2647,15 +2278,15 @@ dependencies = [ [[package]] name = "rspotify-macros" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4892882851a97ee7210e423725ce116e8239157c649af37e208fe93855638a" +checksum = "b78387b0ebb8da6d4c72e728496b09701b7054c0ef88ea2f4f40e46b9107a6de" [[package]] name = "rspotify-model" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae90ab3d6e4cb4ccd7f2887c4363d19b1419800e132d3fb95e2f9b24c05f4d7" +checksum = "1b6ce0f0ecf4eb3b0b8ab7c6932328d03040dd77169b1c533a3ead1308985af6" dependencies = [ "chrono", "enum_dispatch", @@ -2667,9 +2298,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -2679,45 +2310,31 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.37.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] - -[[package]] -name = "rustix" -version = "0.38.10" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6248e1caa625eb708e266e06159f135e8c26f2bb7ceb72dc4b2766d0340964" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "errno", "libc", - "linux-raw-sys 0.4.5", - "windows-sys", + "linux-raw-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -2737,15 +2354,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2772,101 +2389,49 @@ dependencies = [ "untrusted", ] -[[package]] -name = "secret-service" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95" -dependencies = [ - "aes 0.7.5", - "block-modes", - "futures-util", - "generic-array", - "hkdf", - "num", - "once_cell", - "rand", - "serde", - "sha2", - "zbus", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" -version = "1.0.18" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] -[[package]] -name = "serde_repr" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", -] - [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2897,9 +2462,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -2908,9 +2473,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -2928,9 +2493,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -2947,21 +2512,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2977,15 +2532,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2993,12 +2548,23 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socks" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" dependencies = [ + "byteorder", "libc", - "windows-sys", + "winapi", ] [[package]] @@ -3011,7 +2577,7 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" name = "spotifyd" version = "0.3.5" dependencies = [ - "alsa 0.7.1", + "alsa 0.9.1", "chrono", "color-eyre", "daemonize", @@ -3045,12 +2611,6 @@ dependencies = [ "whoami", ] -[[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" @@ -3095,24 +2655,24 @@ dependencies = [ [[package]] name = "strum" -version = "0.25.0" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.25.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.29", + "syn 2.0.82", ] [[package]] @@ -3134,9 +2694,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", @@ -3145,37 +2705,28 @@ dependencies = [ [[package]] name = "syslog" -version = "6.1.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7434e95bcccce1215d30f4bf84fe8c00e8de1b9be4fb736d747ca53d36e7f96f" +checksum = "dfc7e95b5b795122fafe6519e27629b5ab4232c73ebb2428f568e82b1a457ad3" dependencies = [ "error-chain", "hostname", "libc", "log", - "time 0.3.36", + "time", ] [[package]] name = "tempfile" -version = "3.8.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", - "fastrand 2.0.0", - "redox_syscall 0.3.5", - "rustix 0.38.10", - "windows-sys", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", ] [[package]] @@ -3189,56 +2740,44 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", ] [[package]] name = "thread-id" -version = "4.2.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79474f573561cdc4871a0de34a51c92f7f5a56039113fbb5b9c9f96bdb756669" +checksum = "cfe8f25bbdd100db7e1d34acf7fd2dc59c4bf8f7483f505eaa7d4f12f76cc0ea" dependencies = [ "libc", - "redox_syscall 0.2.16", "winapi", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.36" @@ -3274,9 +2813,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -3289,39 +2828,38 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.3", + "socket2 0.5.7", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -3330,86 +2868,83 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.7.6" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.22.22", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.20", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", -] - [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3427,9 +2962,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "sharded-slab", "thread_local", @@ -3438,58 +2973,48 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "uds_windows" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" -dependencies = [ - "tempfile", - "winapi", -] +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "untrusted" @@ -3503,7 +3028,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" dependencies = [ - "base64 0.21.3", + "base64 0.21.7", "cookie", "cookie_store", "log", @@ -3512,26 +3037,33 @@ dependencies = [ "rustls-webpki", "serde", "serde_json", + "socks", "url", "webpki-roots", ] [[package]] name = "url" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.4.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", ] @@ -3561,21 +3093,15 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.0" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -3590,12 +3116,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3610,34 +3130,35 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3645,28 +3166,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.82", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -3674,17 +3195,17 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "whoami" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fec781d48b41f8163426ed18e8fc2864c12937df9ce54c88ede7bd47270893e" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "redox_syscall 0.4.1", + "redox_syscall 0.5.7", "wasite", "web-sys", ] @@ -3707,11 +3228,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -3721,12 +3242,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3735,7 +3256,25 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3744,13 +3283,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3759,24 +3314,54 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3784,100 +3369,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "windows_x86_64_gnu" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_msvc" +name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "winnow" -version = "0.5.15" +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" -dependencies = [ - "memchr", -] +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "xdg-home" -version = "1.0.0" +name = "windows_x86_64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" -dependencies = [ - "nix 0.26.4", - "winapi", -] +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "zbus" -version = "3.14.1" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "byteorder", - "derivative", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.26.4", - "once_cell", - "ordered-stream", - "rand", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tracing", - "uds_windows", - "winapi", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", -] +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "zbus_macros" -version = "3.14.1" +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "zvariant_utils", + "memchr", ] [[package]] -name = "zbus_names" -version = "2.6.0" +name = "winnow" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ - "serde", - "static_assertions", - "zvariant", + "memchr", ] [[package]] @@ -3887,54 +3423,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.6.6", ] [[package]] -name = "zerocopy-derive" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.29", -] - -[[package]] -name = "zvariant" -version = "3.15.0" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "enumflags2", - "libc", - "serde", - "static_assertions", - "zvariant_derive", + "zerocopy-derive 0.7.35", ] [[package]] -name = "zvariant_derive" -version = "3.15.0" +name = "zerocopy-derive" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" dependencies = [ - "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", - "zvariant_utils", + "syn 2.0.82", ] [[package]] -name = "zvariant_utils" -version = "1.0.1" +name = "zerocopy-derive" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.82", ] diff --git a/Cargo.toml b/Cargo.toml index 4ecf0fdf..2e51ff11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,19 +9,19 @@ version = "0.3.5" rust-version = "1.67" [dependencies] -alsa = { version = "0.7", optional = true } +alsa = { version = "0.9.1", optional = true } chrono = "0.4" dbus = { version = "0.9", optional = true } dbus-tokio = { version = "0.7.3", optional = true } dbus-crossroads = { version = "0.5.0", optional = true } fern = { version = "0.6.0", features = ["syslog-6"] } futures = "0.3.15" -gethostname = "0.4.0" +gethostname = "0.5.0" hex = "0.4" -keyring = { version = "2.0", optional = true } +keyring = { version = "3.5", optional = true } libc = "0.2.82" log = "0.4.6" -rspotify = { version = "0.12.0", features = ["client-ureq", "ureq-rustls-tls"], default-features = false, optional = true } +rspotify = { version = "0.13.0", features = ["client-ureq", "ureq-rustls-tls"], default-features = false, optional = true } serde = { version = "1.0.115", features = ["derive"] } sha-1 = "0.10" structopt = "0.3.17" @@ -33,7 +33,7 @@ librespot-playback = { version = "0.4", default-features = false } librespot-core = { version = "0.4" } librespot-discovery = { version = "0.4" } librespot-connect = { version = "0.4" } -toml = "0.7" +toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" @@ -48,7 +48,7 @@ whoami = "1" pledge = "0.4.2" [dev-dependencies] -env_logger = "0.10" +env_logger = "0.11" [features] alsa_backend = ["librespot-playback/alsa-backend", "alsa"] From 0a76720d57dd023dff49a8ca7311c9ad02760eb0 Mon Sep 17 00:00:00 2001 From: eladyn Date: Mon, 21 Oct 2024 05:11:31 +0200 Subject: [PATCH 02/17] upgrade to librespot to 0.5 except dbus --- Cargo.lock | 1911 +++++++++++++++++++++++++++++++++++----------- Cargo.toml | 14 +- src/config.rs | 9 +- src/main_loop.rs | 99 +-- src/process.rs | 112 ++- src/setup.rs | 68 +- 6 files changed, 1659 insertions(+), 554 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84affb4e..5b1eaf16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,45 +19,13 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" -dependencies = [ - "aes-soft", - "aesni", - "cipher", -] - -[[package]] -name = "aes-ctr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7729c3cde54d67063be556aeac75a81330d802f0259500ca40cb52967f975763" -dependencies = [ - "aes-soft", - "aesni", - "cipher", - "ctr", -] - -[[package]] -name = "aes-soft" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" -dependencies = [ - "cipher", - "opaque-debug", -] - -[[package]] -name = "aesni" -version = "0.10.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ + "cfg-if", "cipher", - "opaque-debug", + "cpufeatures", ] [[package]] @@ -69,18 +37,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alsa" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b" -dependencies = [ - "alsa-sys", - "bitflags 1.3.2", - "libc", - "nix", -] - [[package]] name = "alsa" version = "0.9.1" @@ -176,6 +132,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "anyhow" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "async-trait" version = "0.1.83" @@ -187,6 +155,12 @@ dependencies = [ "syn 2.0.82", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -204,6 +178,33 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "aws-lc-rs" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +dependencies = [ + "aws-lc-sys", + "mirai-annotations", + "paste", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +dependencies = [ + "bindgen 0.69.5", + "cc", + "cmake", + "dunce", + "fs_extra", + "libc", + "paste", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -237,6 +238,35 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.82", + "which", +] + [[package]] name = "bindgen" version = "0.70.1" @@ -246,7 +276,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -267,15 +297,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -291,6 +312,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + [[package]] name = "byteorder" version = "1.5.0" @@ -352,11 +379,12 @@ dependencies = [ [[package]] name = "cipher" -version = "0.2.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] @@ -385,6 +413,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cmake" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +dependencies = [ + "cc", +] + [[package]] name = "color-eyre" version = "0.6.3" @@ -428,6 +465,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "cookie" version = "0.17.0" @@ -456,6 +499,16 @@ dependencies = [ "url", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -464,11 +517,12 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "coreaudio-rs" -version = "0.10.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ "bitflags 1.3.2", + "core-foundation-sys", "coreaudio-sys", ] @@ -478,33 +532,31 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ce857aa0b77d77287acc1ac3e37a05a8c95a2af3647d23b15f263bdaeb7562b" dependencies = [ - "bindgen", + "bindgen 0.70.1", ] [[package]] name = "cpal" -version = "0.13.5" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" dependencies = [ - "alsa 0.6.0", + "alsa", "core-foundation-sys", "coreaudio-rs", + "dasp_sample", "jack", "jni", "js-sys", - "lazy_static", "libc", - "mach", + "mach2", "ndk", - "ndk-glue", - "nix", + "ndk-context", "oboe", - "parking_lot 0.11.2", - "stdweb", - "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", - "winapi", + "windows 0.54.0", ] [[package]] @@ -526,21 +578,11 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-mac" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "ctr" -version = "0.6.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] @@ -556,9 +598,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.13.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -566,29 +608,41 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.13.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 1.0.109", + "strsim 0.11.1", + "syn 2.0.82", ] [[package]] name = "darling_macro" -version = "0.13.4" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 1.0.109", + "syn 2.0.82", ] +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "dbus" version = "0.9.7" @@ -622,6 +676,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.11" @@ -632,12 +697,34 @@ dependencies = [ ] [[package]] -name = "digest" -version = "0.9.0" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "generic-array", + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.82", ] [[package]] @@ -646,8 +733,10 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -671,12 +760,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "enum_dispatch" version = "0.3.13" @@ -784,6 +888,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.31" @@ -855,6 +965,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -918,6 +1034,63 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "governor" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a7ecdc5898f6a43e08a7e2c9e2266beb98fd4dfbf2634182540fbb715245093" +dependencies = [ + "cfg-if", + "futures-sink", + "futures-timer", + "futures-util", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "rand", + "smallvec", + "spinning_top", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -932,14 +1105,14 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "headers" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http", + "http 1.1.0", "httpdate", "mime", "sha1", @@ -947,11 +1120,11 @@ dependencies = [ [[package]] name = "headers-core" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http", + "http 1.1.0", ] [[package]] @@ -992,12 +1165,20 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "crypto-mac", - "digest 0.9.0", + "digest", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", ] [[package]] @@ -1011,6 +1192,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows 0.52.0", +] + [[package]] name = "http" version = "0.2.12" @@ -1022,6 +1214,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1029,17 +1232,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", "pin-project-lite", ] [[package]] -name = "httparse" -version = "1.9.5" +name = "http-body" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1061,13 +1287,14 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.7", + "socket2", "tokio", "tower-service", "tracing", @@ -1075,18 +1302,116 @@ dependencies = [ ] [[package]] -name = "hyper-proxy" -version = "0.9.1" +name = "hyper" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca815a891b24fdfb243fa3239c86154392b0953ee584aa1a2a1f66d20cbe75cc" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", - "futures", + "futures-channel", + "futures-util", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-proxy2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9043b7b23fb0bc4a1c7014c27b50a4fc42cc76206f71d34fc0dfe5b28ddc3faf" +dependencies = [ + "bytes", + "futures-util", "headers", - "http", - "hyper", + "http 1.1.0", + "hyper 1.5.0", + "hyper-rustls 0.26.0", + "hyper-util", + "pin-project-lite", + "rustls-native-certs 0.7.3", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", + "webpki", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.31", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "log", + "rustls 0.22.4", + "rustls-native-certs 0.7.3", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.5.0", + "hyper-util", + "log", + "rustls 0.23.15", + "rustls-native-certs 0.8.0", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.5.0", + "pin-project-lite", + "socket2", "tokio", "tower-service", + "tracing", ] [[package]] @@ -1100,7 +1425,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1140,12 +1465,12 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.7.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +checksum = "bb2a33e9c38988ecbda730c85b0fd9ddcdf83c0305ac7fd21c8bb9f57f2f0cc8" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -1175,20 +1500,35 @@ dependencies = [ ] [[package]] -name = "instant" -version = "0.1.13" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "cfg-if", + "generic-array", ] +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1206,9 +1546,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jack" -version = "0.8.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2ac12f11bb369f3c50d24dbb9fdb00dc987434c9dd622a12c13f618106e153" +checksum = "0e5a18a3c2aefb354fb77111ade228b20267bdc779de84e7a4ccf7ea96b9a6cd" dependencies = [ "bitflags 1.3.2", "jack-sys", @@ -1219,28 +1559,32 @@ dependencies = [ [[package]] name = "jack-sys" -version = "0.2.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b91f2d2d10bc2bab38f4dfa4bc77123a988828af39dd3f30dd9db14d44f2cc1" +checksum = "6013b7619b95a22b576dfb43296faa4ecbe40abbdb97dfd22ead520775fc86ab" dependencies = [ + "bitflags 1.3.2", "lazy_static", "libc", - "libloading 0.6.7", + "libloading 0.7.4", + "log", "pkg-config", ] [[package]] name = "jni" -version = "0.19.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", + "cfg-if", "combine", "jni-sys", "log", "thiserror", "walkdir", + "windows-sys 0.45.0", ] [[package]] @@ -1281,17 +1625,15 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] -name = "lewton" -version = "0.10.2" +name = "lazycell" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" @@ -1310,9 +1652,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.6.7" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ "cfg-if", "winapi", @@ -1336,22 +1678,20 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libmdns" -version = "0.7.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b04ae6b56b3b19ade26f0e7e7c1360a1713514f326c5ed0797cf2c109c9e010" +checksum = "48854699e11b111433431b69cee2365fcab0b29b06993f48c257dfbaf6395862" dependencies = [ "byteorder", "futures-util", - "hostname", + "hostname 0.4.0", "if-addrs", "log", "multimap", - "nix", "rand", - "socket2 0.4.10", + "socket2", "thiserror", "tokio", - "winapi", ] [[package]] @@ -1363,7 +1703,7 @@ dependencies = [ "bitflags 1.3.2", "libc", "libpulse-sys", - "num-derive", + "num-derive 0.3.3", "num-traits", "winapi", ] @@ -1396,7 +1736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc19e110fbf42c17260d30f6d3dc545f58491c7830d38ecb9aaca96e26067a9b" dependencies = [ "libc", - "num-derive", + "num-derive 0.3.3", "num-traits", "pkg-config", "winapi", @@ -1414,30 +1754,34 @@ dependencies = [ [[package]] name = "librespot-audio" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c176a31355e1ea8e0b9c4ced19df4947bfe4770661c25c142b6fba2365940d9d" +checksum = "5fbda070a5598b32718e497f585f46891f7113e64aff20a13c0f2ba8fe7ccad9" dependencies = [ - "aes-ctr", - "byteorder", + "aes", "bytes", + "ctr", "futures-util", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "librespot-core", "log", + "parking_lot", "tempfile", + "thiserror", "tokio", ] [[package]] name = "librespot-connect" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ffafb6a443e9445ccb3d5d591573b5b1da3c89a9b8846c63ba2c3710210d3ec" +checksum = "699745eaeff6f53b67e93fe973eb72c818cba58d10cfdbdd4c1bf7893f9b705b" dependencies = [ "form_urlencoded", "futures-util", "librespot-core", - "librespot-discovery", "librespot-playback", "librespot-protocol", "log", @@ -1445,126 +1789,159 @@ dependencies = [ "rand", "serde", "serde_json", + "thiserror", "tokio", "tokio-stream", ] [[package]] name = "librespot-core" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046349f25888e644bf02d9c5de0164b2a493d29aa4ce18e1ad0b756da9b55d6d" +checksum = "505a5ddd966231755994b60435607a1e8ae1d41c7f1169b078e0511bfb82d931" dependencies = [ "aes", - "base64 0.13.1", + "base64 0.22.1", "byteorder", "bytes", + "data-encoding", "form_urlencoded", "futures-core", "futures-util", + "governor", "hmac", - "http", + "http 1.1.0", + "http-body-util", "httparse", - "hyper", - "hyper-proxy", + "hyper 1.5.0", + "hyper-proxy2", + "hyper-rustls 0.27.3", + "hyper-util", + "librespot-oauth", "librespot-protocol", "log", + "nonzero_ext", "num-bigint", + "num-derive 0.4.2", "num-integer", "num-traits", "once_cell", + "parking_lot", "pbkdf2", + "pin-project-lite", "priority-queue", "protobuf", + "quick-xml", "rand", + "rsa", "serde", "serde_json", - "sha-1 0.9.8", + "sha1", "shannon", + "sysinfo", "thiserror", + "time", "tokio", "tokio-stream", + "tokio-tungstenite", "tokio-util", "url", "uuid", - "vergen", + "vergen-gitcl", ] [[package]] name = "librespot-discovery" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aa877d18f6150364012cb4be5682d62d7c712c88bae2d0d01720fd7c15e2f06" +checksum = "abca1d9420179c0875189cee50b1cd75ad91c6180f38d079eae3a62a40b4745f" dependencies = [ - "aes-ctr", - "base64 0.13.1", + "aes", + "base64 0.22.1", + "bytes", + "ctr", "form_urlencoded", "futures-core", + "futures-util", "hmac", - "hyper", + "http-body-util", + "hyper 1.5.0", + "hyper-util", "libmdns", "librespot-core", "log", "rand", "serde_json", - "sha-1 0.9.8", + "sha1", "thiserror", "tokio", ] [[package]] name = "librespot-metadata" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b80361fcbcb5092056fd47c08c34d5d51b08385d8efb6941c0d3e46d032c21c" +checksum = "6a10ab5a390f65281e763cd09c617b173f0e665994eae3d242526924625fdc66" dependencies = [ "async-trait", - "byteorder", + "bytes", "librespot-core", "librespot-protocol", "log", "protobuf", + "serde", + "serde_json", + "thiserror", + "uuid", +] + +[[package]] +name = "librespot-oauth" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bda94233b358fb41c04ed15507c61136c80efe876c6e05a10ddb9a182b144e" +dependencies = [ + "log", + "oauth2", + "thiserror", + "url", ] [[package]] name = "librespot-playback" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190a0b9bcc7f70ee4196a6b4a1c731d405ca130d4a6fcd4c561cfdde8b7cfb7" +checksum = "5b1bcfe1d72c5ac14c798c7e3e1c20e1fb6af2b9c254794545cfcb1f2a4627e2" dependencies = [ - "alsa 0.6.0", - "byteorder", + "alsa", "cpal", - "futures-executor", "futures-util", - "lewton", "libpulse-binding", "libpulse-simple-binding", "librespot-audio", "librespot-core", "librespot-metadata", "log", - "ogg", - "parking_lot 0.12.3", + "parking_lot", "portaudio-rs", "rand", "rand_distr", "rodio", "shell-words", + "symphonia", "thiserror", "tokio", - "zerocopy 0.6.6", + "zerocopy", ] [[package]] name = "librespot-protocol" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d3ac6196ac0ea67bbe039f56d6730a5d8b31502ef9bce0f504ed729dcb39f" +checksum = "0d6f343f573e0469d3ff8a02b99bbd9789faa01e2ff167332542ac840a8b31e7" dependencies = [ - "glob", "protobuf", - "protobuf-codegen-pure", + "protobuf-codegen", ] [[package]] @@ -1590,10 +1967,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] -name = "mach" -version = "0.3.2" +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -1621,15 +1998,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.17" @@ -1663,23 +2031,30 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" dependencies = [ "serde", ] [[package]] name = "ndk" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "jni-sys", + "log", "ndk-sys", "num_enum", "thiserror", @@ -1692,63 +2067,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] -name = "ndk-glue" -version = "0.6.2" +name = "ndk-sys" +version = "0.5.0+25.2.9519653" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" dependencies = [ - "lazy_static", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", + "jni-sys", ] [[package]] -name = "ndk-macro" -version = "0.3.0" +name = "no-std-compat" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" [[package]] -name = "ndk-sys" -version = "0.3.0" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "jni-sys", + "memchr", + "minimal-lexical", ] [[package]] -name = "nix" -version = "0.23.2" +name = "nonzero_ext" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if", - "libc", - "memoffset", -] +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" [[package]] -name = "nom" -version = "7.1.3" +name = "ntapi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" dependencies = [ - "memchr", - "minimal-lexical", + "winapi", ] [[package]] @@ -1762,6 +2117,23 @@ dependencies = [ "rand", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1779,6 +2151,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -1789,34 +2172,45 @@ dependencies = [ ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "num-iter" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", - "libm", + "num-integer", + "num-traits", ] [[package]] -name = "num_enum" -version = "0.5.11" +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.82", ] [[package]] @@ -1828,6 +2222,26 @@ dependencies = [ "libc", ] +[[package]] +name = "oauth2" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" +dependencies = [ + "base64 0.13.1", + "chrono", + "getrandom", + "http 0.2.12", + "rand", + "reqwest", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror", + "url", +] + [[package]] name = "object" version = "0.32.2" @@ -1839,36 +2253,27 @@ dependencies = [ [[package]] name = "oboe" -version = "0.4.6" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" dependencies = [ "jni", "ndk", "ndk-context", - "num-derive", + "num-derive 0.4.2", "num-traits", "oboe-sys", ] [[package]] name = "oboe-sys" -version = "0.4.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" 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 = "once_cell" version = "1.20.2" @@ -1876,10 +2281,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] -name = "opaque-debug" -version = "0.3.1" +name = "openssl-probe" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "option-ext" @@ -1893,17 +2298,6 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[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 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -1911,21 +2305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -1938,22 +2318,37 @@ dependencies = [ "cfg-if", "libc", "petgraph", - "redox_syscall 0.5.7", + "redox_syscall", "smallvec", "thread-id", "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pbkdf2" -version = "0.8.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "crypto-mac", + "digest", "hmac", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1982,6 +2377,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.31" @@ -1997,6 +2413,12 @@ dependencies = [ "libc", ] +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "portaudio-rs" version = "0.3.2" @@ -2030,17 +2452,28 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy 0.7.35", + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d" +dependencies = [ + "proc-macro2", + "syn 2.0.82", ] [[package]] name = "priority-queue" -version = "1.4.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" +checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" dependencies = [ "autocfg", - "indexmap 1.9.3", + "equivalent", + "indexmap 2.6.0", ] [[package]] @@ -2088,27 +2521,63 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.28.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" +checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror", +] [[package]] name = "protobuf-codegen" -version = "2.28.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033460afb75cf755fcfc16dfaed20b86468082a2ea24e05ac35ab4a099a017d6" +checksum = "e26b833f144769a30e04b1db0146b2aaa53fd2fd83acf10a6b5f996606c18144" dependencies = [ + "anyhow", + "once_cell", "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror", ] [[package]] -name = "protobuf-codegen-pure" -version = "2.28.0" +name = "protobuf-parse" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a29399fc94bcd3eeaa951c715f7bea69409b2445356b00519740bcd6ddd865" +checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257" dependencies = [ + "anyhow", + "indexmap 2.6.0", + "log", "protobuf", - "protobuf-codegen", + "protobuf-support", + "tempfile", + "thiserror", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" +dependencies = [ + "thiserror", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", + "serde", ] [[package]] @@ -2160,15 +2629,6 @@ dependencies = [ "rand", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.7" @@ -2218,6 +2678,47 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.31", + "hyper-rustls 0.24.2", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls 0.24.1", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + [[package]] name = "ring" version = "0.17.8" @@ -2235,11 +2736,32 @@ dependencies = [ [[package]] name = "rodio" -version = "0.15.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e" +checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" dependencies = [ "cpal", + "thiserror", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", ] [[package]] @@ -2308,15 +2830,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "0.38.37" @@ -2338,10 +2851,89 @@ checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.23.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2352,6 +2944,18 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.18" @@ -2373,6 +2977,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2390,10 +3003,27 @@ dependencies = [ ] [[package]] -name = "semver" -version = "1.0.23" +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] name = "serde" @@ -2427,6 +3057,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.8" @@ -2437,16 +3077,15 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.9.8" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "form_urlencoded", + "itoa", + "ryu", + "serde", ] [[package]] @@ -2457,7 +3096,7 @@ checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2468,7 +3107,7 @@ checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2479,7 +3118,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -2521,6 +3160,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "slab" version = "0.4.9" @@ -2536,16 +3185,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.7" @@ -2573,11 +3212,30 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "spotifyd" version = "0.3.5" dependencies = [ - "alsa 0.9.1", + "alsa", "chrono", "color-eyre", "daemonize", @@ -2596,14 +3254,16 @@ dependencies = [ "librespot-connect", "librespot-core", "librespot-discovery", + "librespot-metadata", "librespot-playback", "log", "pledge", "rspotify", "serde", - "sha-1 0.10.1", + "sha-1", "structopt", "syslog", + "thiserror", "tokio", "tokio-stream", "toml", @@ -2611,12 +3271,6 @@ dependencies = [ "whoami", ] -[[package]] -name = "stdweb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" - [[package]] name = "strsim" version = "0.8.0" @@ -2625,9 +3279,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "structopt" @@ -2641,45 +3295,129 @@ dependencies = [ ] [[package]] -name = "structopt-derive" -version = "0.4.18" +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck 0.3.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.82", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symphonia" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" +dependencies = [ + "lazy_static", + "symphonia-bundle-mp3", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-ogg", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3" dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", ] [[package]] -name = "strum" -version = "0.26.3" +name = "symphonia-format-ogg" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" dependencies = [ - "strum_macros", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "strum_macros" -version = "0.26.4" +name = "symphonia-metadata" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c" dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.82", + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", ] [[package]] -name = "subtle" -version = "2.4.1" +name = "symphonia-utils-xiph" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] [[package]] name = "syn" @@ -2703,6 +3441,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sysinfo" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "windows 0.57.0", +] + [[package]] name = "syslog" version = "6.1.1" @@ -2710,12 +3467,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc7e95b5b795122fafe6519e27629b5ab4232c73ebb2428f568e82b1a457ad3" dependencies = [ "error-chain", - "hostname", + "hostname 0.3.1", "libc", "log", "time", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.13.0" @@ -2836,10 +3614,10 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot 0.12.3", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.7", + "socket2", "tokio-macros", "windows-sys 0.52.0", ] @@ -2855,6 +3633,38 @@ dependencies = [ "syn 2.0.82", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.15", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.16" @@ -2866,6 +3676,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.15", + "rustls-native-certs 0.8.0", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.12" @@ -2977,6 +3803,26 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand", + "rustls 0.23.15", + "rustls-pki-types", + "sha1", + "thiserror", + "utf-8", +] + [[package]] name = "typenum" version = "1.17.0" @@ -3033,8 +3879,8 @@ dependencies = [ "cookie_store", "log", "once_cell", - "rustls", - "rustls-webpki", + "rustls 0.21.12", + "rustls-webpki 0.101.7", "serde", "serde_json", "socks", @@ -3051,8 +3897,15 @@ dependencies = [ "form_urlencoded", "idna 0.5.0", "percent-encoding", + "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3066,6 +3919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", + "rand", ] [[package]] @@ -3082,13 +3936,40 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "3.2.0" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7141e445af09c8919f1d5f8a20dae0b20c3b57a45dee0d5823c6ed5d237f15a" +checksum = "349ed9e45296a581f455bc18039878f409992999bc1d5da12a6800eb18c8752f" dependencies = [ - "bitflags 1.3.2", - "chrono", - "rustc_version", + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3a7f91caabecefc3c249fd864b11d4abe315c166fbdb568964421bccfd2b7a" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229eaddb0050920816cf051e619affaf18caa3dd512de8de5839ccbc8e53abb0" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", ] [[package]] @@ -3154,6 +4035,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.95" @@ -3193,19 +4086,41 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki-roots" version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "whoami" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "redox_syscall 0.5.7", + "redox_syscall", "wasite", "web-sys", ] @@ -3241,6 +4156,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -3250,6 +4195,68 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3277,6 +4284,21 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -3308,6 +4330,12 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3320,6 +4348,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3332,6 +4366,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3350,6 +4390,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3362,6 +4408,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3374,6 +4426,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3386,6 +4444,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3417,13 +4481,13 @@ dependencies = [ ] [[package]] -name = "zerocopy" -version = "0.6.6" +name = "winreg" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "byteorder", - "zerocopy-derive 0.6.6", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] @@ -3433,14 +4497,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive 0.7.35", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.6.6" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", @@ -3448,12 +4512,7 @@ dependencies = [ ] [[package]] -name = "zerocopy-derive" -version = "0.7.35" +name = "zeroize" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.82", -] +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 2e51ff11..91290b04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "A Spotify daemon" repository = "https://github.com/Spotifyd/spotifyd" license = "GPL-3.0-only" version = "0.3.5" -rust-version = "1.67" +rust-version = "1.74" [dependencies] alsa = { version = "0.9.1", optional = true } @@ -28,14 +28,16 @@ structopt = "0.3.17" tokio = {version = "1.26.0", features = ["signal", "rt-multi-thread", "process", "io-std"] } tokio-stream = "0.1.7" url = "2.2.2" -librespot-audio = { version = "0.4", default-features = false } -librespot-playback = { version = "0.4", default-features = false } -librespot-core = { version = "0.4" } -librespot-discovery = { version = "0.4" } -librespot-connect = { version = "0.4" } +librespot-audio = { version = "0.5", default-features = false } +librespot-playback = { version = "0.5", default-features = false } +librespot-core = { version = "0.5" } +librespot-discovery = { version = "0.5" } +librespot-connect = { version = "0.5" } +librespot-metadata = "0.5.0" toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" +thiserror = "1.0.64" [target."cfg(unix)".dependencies] daemonize = "0.5" diff --git a/src/config.rs b/src/config.rs index c52cef92..53c2ae5f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,9 +5,7 @@ use crate::{ }; use color_eyre::Report; use gethostname::gethostname; -use librespot_core::{ - cache::Cache, config::DeviceType as LSDeviceType, config::SessionConfig, version, -}; +use librespot_core::{cache::Cache, config::DeviceType as LSDeviceType, config::SessionConfig}; use librespot_playback::{ config::{AudioFormat as LSAudioFormat, Bitrate as LSBitrate, PlayerConfig}, dither::{mk_ditherer, DithererBuilder, TriangularDitherer}, @@ -750,7 +748,6 @@ pub(crate) struct SpotifydConfig { pub(crate) shell: String, pub(crate) zeroconf_port: Option, pub(crate) device_type: String, - pub(crate) autoplay: bool, } pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { @@ -915,17 +912,17 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { device_name, player_config: pc, session_config: SessionConfig { - user_agent: version::VERSION_STRING.to_string(), + autoplay: Some(autoplay), device_id, proxy: proxy_url, ap_port: Some(443), + ..Default::default() }, onevent: config.shared_config.on_song_change_hook, pid, shell, zeroconf_port: config.shared_config.zeroconf_port, device_type, - autoplay, } } diff --git a/src/main_loop.rs b/src/main_loop.rs index 597edcad..4a30fd52 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -8,33 +8,15 @@ use futures::{ stream::Peekable, Future, FutureExt, StreamExt, }; -use librespot_connect::spirc::Spirc; -use librespot_core::{ - authentication::Credentials, - cache::Cache, - config::{ConnectConfig, DeviceType, SessionConfig}, - session::{Session, SessionError}, -}; +use librespot_connect::{config::ConnectConfig, spirc::Spirc}; +use librespot_core::{authentication::Credentials, config::DeviceType, session::Session, Error}; use librespot_discovery::Discovery; -use librespot_playback::{ - audio_backend::Sink, - config::{AudioFormat, PlayerConfig}, - mixer::Mixer, - player::Player, -}; +use librespot_playback::{mixer::Mixer, player::Player}; use log::error; use std::pin::Pin; use std::sync::Arc; -pub struct AudioSetup { - pub mixer: Box Box>, - pub backend: fn(Option, AudioFormat) -> Box, - pub audio_device: Option, - pub audio_format: AudioFormat, -} - pub struct SpotifydState { - pub cache: Option, pub device_name: String, pub player_event_program: Option, } @@ -73,11 +55,10 @@ impl CredentialsProvider { } pub(crate) struct MainLoop { - pub(crate) audio_setup: AudioSetup, pub(crate) spotifyd_state: SpotifydState, - pub(crate) player_config: PlayerConfig, - pub(crate) session_config: SessionConfig, - pub(crate) autoplay: bool, + pub(crate) mixer: Box Arc>, + pub(crate) session: Session, + pub(crate) player: Arc, pub(crate) has_volume_ctrl: bool, pub(crate) initial_volume: Option, pub(crate) shell: String, @@ -90,15 +71,25 @@ pub(crate) struct MainLoop { } impl MainLoop { - async fn get_session(&mut self) -> Result { + async fn get_connection(&mut self) -> Result<(Spirc, impl Future), Error> { let creds = self.credentials_provider.get_credentials().await; - - let session_config = self.session_config.clone(); - let cache = self.spotifyd_state.cache.clone(); - - Session::connect(session_config, creds, cache, true) - .await - .map(|(session, _creds)| session) + self.session.connect(creds.clone(), true).await?; + + // TODO: expose is_group + Spirc::new( + ConnectConfig { + name: self.spotifyd_state.device_name.clone(), + device_type: self.device_type, + is_group: false, + initial_volume: self.initial_volume, + has_volume_ctrl: self.has_volume_ctrl, + }, + self.session.clone(), + creds, + self.player.clone(), + (self.mixer)(), + ) + .await } pub(crate) async fn run(&mut self) { @@ -107,13 +98,13 @@ impl MainLoop { } 'mainloop: loop { - let session = tokio::select!( + let (spirc, spirc_task) = tokio::select!( _ = &mut ctrl_c => { break 'mainloop; } - session = self.get_session() => { - match session { - Ok(session) => session, + spirc = self.get_connection() => { + match spirc { + Ok(spirc) => spirc, Err(err) => { error!("failed to connect to spotify: {}", err); break 'mainloop; @@ -122,30 +113,6 @@ impl MainLoop { } ); - let mixer = (self.audio_setup.mixer)(); - let backend = self.audio_setup.backend; - let audio_device = self.audio_setup.audio_device.clone(); - let audio_format = self.audio_setup.audio_format; - let (player, mut event_channel) = Player::new( - self.player_config.clone(), - session.clone(), - mixer.get_soft_volume(), - move || (backend)(audio_device, audio_format), - ); - - let (spirc, spirc_task) = Spirc::new( - ConnectConfig { - autoplay: self.autoplay, - name: self.spotifyd_state.device_name.clone(), - device_type: self.device_type, - initial_volume: self.initial_volume, - has_volume_ctrl: self.has_volume_ctrl, - }, - session.clone(), - player, - mixer, - ); - tokio::pin!(spirc_task); let shared_spirc = Arc::new(spirc); @@ -157,7 +124,7 @@ impl MainLoop { let mpris_event_tx = if self.use_mpris { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); dbus_server = Box::pin(DbusServer::new( - session, + self.session.clone(), shared_spirc.clone(), self.spotifyd_state.device_name.clone(), rx, @@ -170,16 +137,18 @@ impl MainLoop { let mut running_event_program = Box::pin(Fuse::terminated()); + let mut event_channel = self.player.get_player_event_channel(); + loop { tokio::select!( // a new session has been started via the discovery stream _ = self.credentials_provider.incoming_connection() => { - shared_spirc.shutdown(); + let _ = shared_spirc.shutdown(); break; } // the program should shut down _ = &mut ctrl_c => { - shared_spirc.shutdown(); + let _ = shared_spirc.shutdown(); break 'mainloop; } // spirc was shut down by some external factor @@ -188,7 +157,7 @@ impl MainLoop { } // dbus stopped unexpectedly _ = &mut dbus_server => { - shared_spirc.shutdown(); + let _ = shared_spirc.shutdown(); break 'mainloop; } // a new player event is available and no program is running diff --git a/src/process.rs b/src/process.rs index 886187f1..39d92ac4 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,4 +1,5 @@ use crate::error::Error; +use librespot_metadata::audio::AudioItem; use librespot_playback::player::PlayerEvent; use log::info; use std::{collections::HashMap, process::Stdio}; @@ -44,6 +45,18 @@ fn spawn_program(shell: &str, cmd: &str, env: HashMap<&str, String>) -> Result, env: &mut HashMap<&str, String>) { + env.insert( + "TRACK_ID", + audio_item.track_id.to_base62().unwrap_or_default(), + ); + env.insert("TRACK_NAME", audio_item.name); + env.insert("TRACK_DURATION", audio_item.duration_ms.to_string()); + if let Some(cover) = audio_item.covers.into_iter().max_by_key(|c| c.width) { + env.insert("TRACK_COVER", cover.url); + } +} + /// Spawns provided command in a subprocess using the provided shell. /// Various environment variables are included in the subprocess's environment /// depending on the `PlayerEvent` that was passed in. @@ -54,15 +67,11 @@ pub(crate) fn spawn_program_on_event( ) -> Result { let mut env = HashMap::new(); match event { - PlayerEvent::Changed { - old_track_id, - new_track_id, - } => { - env.insert("OLD_TRACK_ID", old_track_id.to_base62().unwrap()); + PlayerEvent::TrackChanged { audio_item } => { env.insert("PLAYER_EVENT", "change".to_string()); - env.insert("TRACK_ID", new_track_id.to_base62().unwrap()); + audio_item_to_env(audio_item, &mut env); } - PlayerEvent::Started { + PlayerEvent::Playing { track_id, play_request_id, position_ms, @@ -90,29 +99,15 @@ pub(crate) fn spawn_program_on_event( env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); env.insert("POSITION_MS", position_ms.to_string()); } - PlayerEvent::Playing { - track_id, - play_request_id, - position_ms, - duration_ms, - } => { - env.insert("PLAYER_EVENT", "play".to_string()); - env.insert("TRACK_ID", track_id.to_base62().unwrap()); - env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); - env.insert("POSITION_MS", position_ms.to_string()); - env.insert("DURATION_MS", duration_ms.to_string()); - } PlayerEvent::Paused { track_id, play_request_id, position_ms, - duration_ms, } => { env.insert("PLAYER_EVENT", "pause".to_string()); env.insert("TRACK_ID", track_id.to_base62().unwrap()); env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); env.insert("POSITION_MS", position_ms.to_string()); - env.insert("DURATION_MS", duration_ms.to_string()); } PlayerEvent::TimeToPreloadNextTrack { track_id, @@ -130,7 +125,7 @@ pub(crate) fn spawn_program_on_event( env.insert("TRACK_ID", track_id.to_base62().unwrap()); env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); } - PlayerEvent::VolumeSet { volume } => { + PlayerEvent::VolumeChanged { volume } => { env.insert("PLAYER_EVENT", "volumeset".to_string()); env.insert("VOLUME", volume.to_string()); } @@ -146,6 +141,79 @@ pub(crate) fn spawn_program_on_event( env.insert("PLAYER_EVENT", "preloading".to_string()); env.insert("TRACK_ID", track_id.to_base62().unwrap()); } + PlayerEvent::PositionCorrection { + play_request_id, + track_id, + position_ms, + } => { + env.insert("PLAYER_EVENT", "positioncorrection".to_string()); + env.insert("TRACK_ID", track_id.to_base62().unwrap()); + env.insert("POSITION_MS", position_ms.to_string()); + env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); + } + PlayerEvent::Seeked { + play_request_id, + track_id, + position_ms, + } => { + env.insert("PLAYER_EVENT", "seeked".to_string()); + env.insert("TRACK_ID", track_id.to_base62().unwrap()); + env.insert("POSITION_MS", position_ms.to_string()); + env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); + } + PlayerEvent::PlayRequestIdChanged { play_request_id } => { + env.insert("PLAYER_EVENT", "playrequestid_changed".to_string()); + env.insert("PLAY_REQUEST_ID", play_request_id.to_string()); + } + PlayerEvent::SessionConnected { + connection_id, + user_name, + } => { + env.insert("PLAYER_EVENT", "sessionconnected".to_string()); + env.insert("USERNAME", user_name); + env.insert("CONNECTION_ID", connection_id); + } + PlayerEvent::SessionDisconnected { + connection_id, + user_name, + } => { + env.insert("PLAYER_EVENT", "sessiondisconnected".to_string()); + env.insert("USERNAME", user_name); + env.insert("CONNECTION_ID", connection_id); + } + PlayerEvent::SessionClientChanged { + client_id, + client_name, + client_brand_name, + client_model_name, + } => { + env.insert("PLAYER_EVENT", "clientchanged".to_string()); + env.insert("CLIENT_ID", client_id); + env.insert("CLIENT_NAME", client_name); + env.insert("CLIENT_BRAND", client_brand_name); + env.insert("CLIENT_MODEL", client_model_name); + } + PlayerEvent::ShuffleChanged { shuffle } => { + env.insert("PLAYER_EVENT", "shuffle_changed".to_string()); + env.insert("SHUFFLE", shuffle.to_string()); + } + PlayerEvent::RepeatChanged { repeat } => { + env.insert("PLAYER_EVENT", "repeat_changed".to_string()); + let val = match repeat { + true => "all", + false => "none", + } + .to_string(); + env.insert("REPEAT", val); + } + PlayerEvent::AutoPlayChanged { auto_play } => { + env.insert("PLAYER_EVENT", "autoplay_changed".to_string()); + env.insert("AUTOPLAY", auto_play.to_string()); + } + PlayerEvent::FilterExplicitContentChanged { filter } => { + env.insert("PLAYER_EVENT", "filterexplicit_changed".to_string()); + env.insert("FILTEREXPLICIT", filter.to_string()); + } } spawn_program(shell, cmd, env) } diff --git a/src/setup.rs b/src/setup.rs index 07a713c3..8f2f3d6b 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -6,24 +6,24 @@ use crate::{ }; #[cfg(feature = "dbus_keyring")] use keyring::Entry; -use librespot_core::{authentication::Credentials, cache::Cache, config::DeviceType}; -use librespot_playback::mixer::MixerConfig; +use librespot_core::{authentication::Credentials, cache::Cache, config::DeviceType, Session}; use librespot_playback::{ audio_backend::{Sink, BACKENDS}, config::AudioFormat, mixer::{self, Mixer}, }; +use librespot_playback::{mixer::MixerConfig, player::Player}; #[allow(unused_imports)] // cfg use log::{debug, error, info, warn}; -use std::{str::FromStr, thread, time::Duration}; +use std::{str::FromStr, sync::Arc, thread, time::Duration}; pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLoop { - let mixer = { + let mut mixer = { match config.volume_controller { config::VolumeController::None => { info!("Using no volume controller."); - Box::new(|| Box::new(crate::no_mixer::NoMixer) as Box) - as Box Box> + Box::new(|| Arc::new(crate::no_mixer::NoMixer) as Arc) + as Box Arc> } #[cfg(feature = "alsa_backend")] config::VolumeController::Alsa | config::VolumeController::AlsaLinear => { @@ -36,22 +36,22 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo config::VolumeController::AlsaLinear ); Box::new(move || { - Box::new(alsa_mixer::AlsaMixer { + Arc::new(alsa_mixer::AlsaMixer { device: control_device .clone() .or_else(|| audio_device.clone()) .unwrap_or_else(|| "default".to_string()), mixer: mixer.clone().unwrap_or_else(|| "Master".to_string()), linear_scaling: linear, - }) as Box - }) as Box Box> + }) as Arc + }) as Box Arc> } _ => { info!("Using software volume controller."); Box::new(move || { - Box::new(mixer::softmixer::SoftMixer::open(MixerConfig::default())) - as Box - }) as Box Box> + Arc::new(mixer::softmixer::SoftMixer::open(MixerConfig::default())) + as Arc + }) as Box Arc> } } }; @@ -60,7 +60,6 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo let player_config = config.player_config; let session_config = config.session_config; let backend = config.backend.clone(); - let autoplay = config.autoplay; let has_volume_ctrl = !matches!(config.volume_controller, config::VolumeController::None); @@ -100,11 +99,14 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo let mut retry_counter = 0; let mut backoff = Duration::from_secs(5); let discovery_stream = loop { - match librespot_discovery::Discovery::builder(session_config.device_id.clone()) - .name(config.device_name.clone()) - .device_type(device_type) - .port(zeroconf_port) - .launch() + match librespot_discovery::Discovery::builder( + session_config.device_id.clone(), + session_config.client_id.clone(), + ) + .name(config.device_name.clone()) + .device_type(device_type) + .port(zeroconf_port) + .launch() { Ok(discovery_stream) => break discovery_stream, Err(err) => { @@ -124,26 +126,32 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo }; let backend = find_backend(backend.as_ref().map(String::as_ref)); + + let session = Session::new(session_config, cache); + let player = { + let audio_device = config.audio_device; + let audio_format = config.audio_format; + Player::new( + player_config, + session.clone(), + mixer().get_soft_volume(), + move || backend(audio_device, audio_format), + ) + }; + main_loop::MainLoop { credentials_provider, - audio_setup: main_loop::AudioSetup { - mixer, - backend, - audio_device: config.audio_device, - audio_format: config.audio_format, - }, + mixer, spotifyd_state: main_loop::SpotifydState { - cache, device_name: config.device_name, player_event_program: config.onevent, }, - player_config, - session_config, + session, + player, initial_volume: config.initial_volume, has_volume_ctrl, shell: config.shell, device_type, - autoplay, use_mpris: config.use_mpris, dbus_type: config.dbus_type, } @@ -155,7 +163,9 @@ fn get_credentials( password: &Option, ) -> Option { if let Some(credentials) = cache.as_ref().and_then(Cache::credentials) { - if username.as_ref() == Some(&credentials.username) { + if Option::zip(username.as_deref(), credentials.username.as_deref()) + .is_some_and(|(user_config, user_cached)| user_config == user_cached) + { return Some(credentials); } } From 18978de9d0f9352e0c2a1e7fe5f944aac289ada0 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 03:30:58 +0100 Subject: [PATCH 03/17] dbus_mpris: refactor and remove web API --- Cargo.lock | 9 +- Cargo.toml | 1 + src/dbus_mpris.rs | 1237 ++++++++++++++++++++++----------------------- src/main_loop.rs | 71 ++- 4 files changed, 649 insertions(+), 669 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b1eaf16..a1c7ed54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3264,6 +3264,7 @@ dependencies = [ "structopt", "syslog", "thiserror", + "time", "tokio", "tokio-stream", "toml", @@ -3558,9 +3559,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -3581,9 +3582,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", diff --git a/Cargo.toml b/Cargo.toml index 91290b04..7bbd8005 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" thiserror = "1.0.64" +time = { version = "0.3.37", default-features = false, features = ["formatting"] } [target."cfg(unix)".dependencies] daemonize = "0.5" diff --git a/src/dbus_mpris.rs b/src/dbus_mpris.rs index d5e221db..7e71d207 100644 --- a/src/dbus_mpris.rs +++ b/src/dbus_mpris.rs @@ -4,184 +4,403 @@ use dbus::{ arg::{RefArg, Variant}, channel::{MatchingReceiver, Sender}, message::{MatchRule, SignalArgs}, + nonblock::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged, MethodErr, }; use dbus_crossroads::{Crossroads, IfaceToken}; -use dbus_tokio::connection; +use dbus_tokio::connection::{self, IOResourceError}; use futures::{ - self, task::{Context, Poll}, Future, }; use librespot_connect::spirc::Spirc; -use librespot_core::{ - keymaster::{get_token, Token as LibrespotToken}, - mercury::MercuryError, - session::Session, - spotify_id::SpotifyAudioType, -}; +use librespot_metadata::audio::AudioItem; use librespot_playback::player::PlayerEvent; -use log::{error, info, warn}; -use rspotify::{ - model::{ - offset::Offset, parse_uri, AlbumId, ArtistId, EpisodeId, IdError, PlayableItem, PlaylistId, - RepeatState, ShowId, TrackId, Type, - }, - prelude::*, - AuthCodeSpotify, Token as RspotifyToken, +use log::{error, warn}; +use std::convert::TryFrom; +use std::{ + collections::HashMap, + pin::Pin, + sync::{Arc, Mutex, RwLock}, }; -use std::{collections::HashMap, env, pin::Pin, sync::Arc}; +use thiserror::Error; +use time::format_description::well_known::Iso8601; use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; -pub struct DbusServer { - session: Session, - spirc: Arc, - spotify_client: Arc, - dbus_type: DBusType, - #[allow(clippy::type_complexity)] - token_request: Option>>>>, - dbus_future: Option>>>, - device_name: String, - event_rx: UnboundedReceiver, - event_tx: Option>, +type DbusMap = HashMap>>; + +const MPRIS_PATH: &'static str = "/org/mpris/MediaPlayer2"; +const CONTROLS_PATH: &'static str = "/rs/spotifyd/Controls"; + +pub enum ControlMessage { + SetSpirc(Arc), + DropSpirc, + Shutdown, } -const CLIENT_ID: &str = "2c1ea588dfbc4a989e2426f8385297c3"; -const SCOPE: &str = - "user-read-playback-state,user-modify-playback-state,user-read-currently-playing"; +pub(crate) struct DbusServer { + dbus_future: Pin>>>, + control_tx: UnboundedSender, +} impl DbusServer { - pub fn new( - session: Session, - spirc: Arc, - device_name: String, - event_rx: UnboundedReceiver, - dbus_type: DBusType, - ) -> DbusServer { + pub fn new(event_rx: UnboundedReceiver, dbus_type: DBusType) -> DbusServer { + let (control_tx, control_rx) = tokio::sync::mpsc::unbounded_channel(); + let dbus_future = Box::pin(create_dbus_server(event_rx, control_rx, dbus_type)); DbusServer { - session, - spirc, - spotify_client: Default::default(), - dbus_type, - token_request: None, - dbus_future: None, - device_name, - event_rx, - event_tx: None, + dbus_future, + control_tx, } } + + pub fn set_spirc(&self, spirc: Arc) -> Result<(), DbusError> { + self.control_tx + .send(ControlMessage::SetSpirc(spirc)) + .map_err(|_| DbusError::ControlChannelBroken) + } + + pub fn drop_spirc(&self) -> Result<(), DbusError> { + self.control_tx + .send(ControlMessage::DropSpirc) + .map_err(|_| DbusError::ControlChannelBroken) + } + + /// Sends a shutdown signal and returns false, if the server was already shut down. + pub fn shutdown(&self) -> bool { + self.control_tx.send(ControlMessage::Shutdown).is_ok() + } +} + +#[derive(Debug, Error)] +pub(crate) enum DbusError { + #[error("Failed to initialize D-Bus: {}", .0)] + InitFailure(#[from] dbus::Error), + #[error("The connection was terminated unexpectedly: {}", .0)] + ConnectionFailure(#[from] IOResourceError), + #[error("Unexpectedly lost control of dbus server")] + ControlChannelBroken, } impl Future for DbusServer { - type Output = (); + type Output = Result<(), DbusError>; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { - if self.event_tx.is_some() { - if let Poll::Ready(Some(msg)) = self.event_rx.poll_recv(cx) { - self.event_tx.as_ref().unwrap().send(msg).unwrap(); - } + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.dbus_future.as_mut().poll(cx) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +enum PlaybackStatus { + Playing, + Paused, + Stopped, +} + +impl PlaybackStatus { + fn to_mpris(&self) -> &'static str { + match self { + PlaybackStatus::Playing => "Playing", + PlaybackStatus::Paused => "Paused", + PlaybackStatus::Stopped => "Stopped", } - let needs_token = match *self.spotify_client.get_token().lock().unwrap() { - Some(ref token) => token.is_expired(), - None => true, - }; - - if needs_token { - if let Some(mut fut) = self.token_request.take() { - if let Poll::Ready(token) = fut.as_mut().poll(cx) { - let token = match token { - Ok(token) => token, - Err(_) => { - error!("failed to request a token for the web API"); - // shutdown DBus-Server - return Poll::Ready(()); - } - }; - - let expires_in = Duration::seconds(token.expires_in as i64); - let api_token = RspotifyToken { - access_token: token.access_token, - expires_in, - expires_at: Some(Utc::now() + expires_in), - ..RspotifyToken::default() - }; - - if self.dbus_future.is_none() { - self.spotify_client = Arc::new(AuthCodeSpotify::from_token(api_token)); - - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - self.event_tx = Some(tx); - self.dbus_future = Some(Box::pin(create_dbus_server( - Arc::clone(&self.spotify_client), - self.spirc.clone(), - self.device_name.clone(), - rx, - self.dbus_type, - ))); - } else { - *self.spotify_client.get_token().lock().unwrap() = Some(api_token); - } - } else { - self.token_request = Some(fut); + } +} + +#[derive(Debug)] +struct Position { + last_position: Duration, + last_update: DateTime, +} + +impl Position { + fn new() -> Self { + Self { + last_position: Duration::zero(), + last_update: Local::now(), + } + } + fn update_position(&mut self, new_position: Duration) { + self.last_update = Local::now(); + self.last_position = new_position; + } + + fn get_position(&self) -> Duration { + (Local::now() - self.last_update) + self.last_position + } +} + +#[derive(Clone, Copy, Debug)] +enum RepeatState { + None, + // Track, + All, +} + +impl RepeatState { + fn to_mpris(&self) -> &'static str { + match self { + RepeatState::None => "None", + // RepeatState::Track => "Track", + RepeatState::All => "Playlist", + } + } +} + +#[derive(Debug)] +struct CurrentStateInner { + status: PlaybackStatus, + position: Option, + audio_item: Option>, + volume: u16, + shuffle: bool, + repeat: RepeatState, +} + +fn insert_attr(map: &mut DbusMap, attr: impl ToString, value: impl RefArg + 'static) { + map.insert(attr.to_string(), Variant(Box::new(value))); +} + +impl CurrentStateInner { + fn mpris_volume(&self) -> f64 { + self.volume as f64 / u16::MAX as f64 + } + + fn get_position(&self) -> Option { + let position = self.position.as_ref()?; + match self.status { + PlaybackStatus::Playing => Some(position.get_position()), + PlaybackStatus::Paused => Some(position.last_position), + PlaybackStatus::Stopped => None, + } + } + + fn update_position(&mut self, position: Duration) { + self.position + .get_or_insert_with(Position::new) + .update_position(position); + } + + fn handle_event(&mut self, event: PlayerEvent) -> (DbusMap, bool) { + let mut changed = DbusMap::new(); + let mut seeked = false; + let mut current_track_id = None; + match event { + PlayerEvent::VolumeChanged { volume } => { + self.volume = volume; + insert_attr(&mut changed, "Volume", self.mpris_volume()); + } + PlayerEvent::Stopped { .. } => { + self.status = PlaybackStatus::Stopped; + insert_attr( + &mut changed, + "PlaybackStatus", + self.status.to_mpris().to_string(), + ); + } + PlayerEvent::Playing { + track_id, + position_ms, + .. + } => { + if self.status != PlaybackStatus::Playing { + self.status = PlaybackStatus::Playing; + insert_attr( + &mut changed, + "PlaybackStatus", + self.status.to_mpris().to_string(), + ); } - } else { - self.token_request = Some(Box::pin({ - let sess = self.session.clone(); - // This is more meant as a fast hotfix than anything else! - let client_id = - env::var("SPOTIFYD_CLIENT_ID").unwrap_or_else(|_| CLIENT_ID.to_string()); - async move { get_token(&sess, &client_id, SCOPE).await } - })); + self.update_position(Duration::milliseconds(position_ms as i64)); + seeked = true; + current_track_id = Some(track_id); + } + PlayerEvent::Paused { + track_id, + position_ms, + .. + } => { + if self.status != PlaybackStatus::Paused { + self.status = PlaybackStatus::Paused; + insert_attr( + &mut changed, + "PlaybackStatus", + self.status.to_mpris().to_string(), + ) + } + current_track_id = Some(track_id); + self.update_position(Duration::milliseconds(position_ms as i64)); + seeked = true; + } + PlayerEvent::TrackChanged { audio_item } => { + self.audio_item = Some(audio_item); + insert_attr(&mut changed, "Metadata", self.to_metadata()); + } + PlayerEvent::Loading { track_id, .. } | PlayerEvent::Preloading { track_id } => { + current_track_id = Some(track_id) + } + PlayerEvent::PositionCorrection { + track_id, + position_ms, + .. } + | PlayerEvent::Seeked { + track_id, + position_ms, + .. + } => { + current_track_id = Some(track_id); + self.update_position(Duration::milliseconds(position_ms as i64)); + seeked = true; + } + PlayerEvent::ShuffleChanged { shuffle } => { + self.shuffle = shuffle; + insert_attr(&mut changed, "Shuffle", self.shuffle); + } + PlayerEvent::RepeatChanged { repeat } => { + self.repeat = if repeat { + RepeatState::All + } else { + RepeatState::None + }; + insert_attr( + &mut changed, + "LoopStatus", + self.repeat.to_mpris().to_string(), + ) + } + PlayerEvent::TimeToPreloadNextTrack { .. } + | PlayerEvent::EndOfTrack { .. } + | PlayerEvent::Unavailable { .. } + | PlayerEvent::PlayRequestIdChanged { .. } + | PlayerEvent::AutoPlayChanged { .. } + | PlayerEvent::FilterExplicitContentChanged { .. } + | PlayerEvent::SessionConnected { .. } + | PlayerEvent::SessionDisconnected { .. } + | PlayerEvent::SessionClientChanged { .. } => (), + } + + if current_track_id + .zip(self.audio_item.as_ref()) + .is_some_and(|(track_id, item)| track_id != item.track_id) + { + self.audio_item = None; + insert_attr(&mut changed, "Metadata", self.to_metadata()); } - // Not polling the future here in some cases is fine, since we will poll it - // immediately after the token request has completed. - // If we would poll the future in any case, we would risk using invalid tokens for API requests. - if self.token_request.is_none() { - if let Some(ref mut fut) = self.dbus_future { - return fut.as_mut().poll(cx); + (changed, seeked) + } + + fn to_metadata(&self) -> DbusMap { + let mut m = HashMap::new(); + + if let Some(audio_item) = self.audio_item.as_deref() { + insert_attr( + &mut m, + "mpris:trackid", + uri_to_object_path(audio_item.track_id.to_uri().as_deref().unwrap_or_default()), + ); + + if let Some(length) = + Duration::milliseconds(audio_item.duration_ms as i64).num_microseconds() + { + insert_attr(&mut m, "mpris:length", length); + } + + if let Some(cover) = audio_item.covers.iter().max_by_key(|im| im.width) { + insert_attr(&mut m, "mpris:artUrl", cover.url.clone()); + } + + insert_attr(&mut m, "xesam:title", audio_item.name.clone()); + + use librespot_metadata::audio::UniqueFields::*; + match &audio_item.unique_fields { + Track { + artists, + album, + album_artists, + popularity, + number, + disc_number, + } => { + insert_attr( + &mut m, + "xesam:artist", + artists + .iter() + .map(|artist| artist.name.clone()) + .collect::>(), + ); + insert_attr(&mut m, "xesam:album", album.clone()); + insert_attr(&mut m, "xesam:albumArtist", album_artists.clone()); + insert_attr(&mut m, "xesam:autoRating", (*popularity as f64) / 100.0); + insert_attr(&mut m, "xesam:trackNumber", *number); + insert_attr(&mut m, "xesam:discNumber", *disc_number); + } + Episode { + description, + publish_time, + show_name, + } => { + insert_attr(&mut m, "xesam:artist", vec![show_name.clone()]); + insert_attr(&mut m, "xesam:comment", vec![description.clone()]); + if let Ok(formatted_publish) = publish_time.format(&Iso8601::DEFAULT) { + insert_attr(&mut m, "xesam:contentCreated", formatted_publish); + } + } } } - Poll::Pending + m } } -#[derive(Clone, Copy, PartialEq, Eq)] -enum PlaybackStatus { - Playing, - Paused, - Stopped, +#[derive(Debug)] +struct CurrentState(RwLock); + +#[derive(Clone, Copy, Debug, Error)] +#[error("internal state no longer available due to application error")] +struct StatePoisonError; + +impl From for MethodErr { + fn from(value: StatePoisonError) -> Self { + MethodErr::failed(&value) + } +} + +impl CurrentState { + fn new(inner: CurrentStateInner) -> Self { + Self(RwLock::new(inner)) + } + + fn read(&self) -> Result, StatePoisonError> { + self.0.read().map_err(|_| StatePoisonError) + } + + fn write(&self) -> Result, StatePoisonError> { + self.0.write().map_err(|_| StatePoisonError) + } } async fn create_dbus_server( - spotify_api_client: Arc, - spirc: Arc, - device_name: String, mut event_rx: UnboundedReceiver, + mut control_rx: UnboundedReceiver, dbus_type: DBusType, -) { +) -> Result<(), DbusError> { let (resource, conn) = match dbus_type { DBusType::Session => connection::new_session_sync(), DBusType::System => connection::new_system_sync(), - } - .expect("Failed to initialize DBus connection"); - tokio::spawn(async { - let err = resource.await; - panic!("Lost connection to D-Bus: {}", err); - }); + }?; + let mut connection_task = tokio::spawn(async { Err::<(), _>(resource.await) }); - let path = format!( + // this name will be used, once we can provide the mpris interface + let mpris_name = format!( "org.mpris.MediaPlayer2.spotifyd.instance{}", std::process::id() ); + // this name will always be available to allow easy discovery of the controls interface + let spotifyd_name = format!("rs.spotifyd.instance{}", std::process::id()); - // TODO: The first `true` allows us to replace orphaned dbus servers from previous sessions - // later. We should instead properly release the name when the session ends. - conn.request_name(path, true, true, true) - .await - .expect("Failed to register dbus player name"); + conn.request_name(&spotifyd_name, false, true, true).await?; let mut cr = Crossroads::new(); cr.set_async_support(Some(( @@ -191,16 +410,141 @@ async fn create_dbus_server( }), ))); + let current_state = Arc::new(CurrentState::new(CurrentStateInner { + status: PlaybackStatus::Stopped, + position: None, + audio_item: None, + volume: u16::MAX, + shuffle: false, + repeat: RepeatState::None, + })); + + let (quit_tx, mut quit_rx) = tokio::sync::mpsc::unbounded_channel(); + + let cr = Arc::new(Mutex::new(cr)); + + let crossroads = cr.clone(); + conn.start_receive( + MatchRule::new_method_call(), + Box::new(move |msg, conn| { + let mut cr = cr.lock().unwrap(); + cr.handle_message(msg, conn).unwrap(); + true + }), + ); + + let mut spirc: Option> = None; + let mut cur_conn_id: Option = None; + + loop { + tokio::select! { + _ = quit_rx.recv() => { + break; + } + result = &mut connection_task => { + result.expect("the dbus connection panicked")?; + break; + } + event = event_rx.recv() => { + let event = event.expect("event channel was unexpectedly closed"); + + if let PlayerEvent::SessionConnected { connection_id, .. } = event { + let mut cr = crossroads.lock().unwrap(); + let spirc = spirc.clone().unwrap(); + register_player_interface(&mut cr, spirc, current_state.clone(), quit_tx.clone()); + if cur_conn_id.is_none() { + conn.request_name(&mpris_name, true, true, true).await?; + } + cur_conn_id = Some(connection_id); + } else if let PlayerEvent::SessionDisconnected { connection_id, .. } = event { + // if this message isn't outdated yet, we vanish from the bus + if cur_conn_id == Some(connection_id) { + let mut cr = crossroads.lock().unwrap(); + conn.release_name(&mpris_name).await?; + cr.remove::<()>(&MPRIS_PATH.into()); + cur_conn_id = None; + } + } else { + let (changed, seeked) = current_state + .write() + .expect("state has been poisoned") + .handle_event(event); + + if seeked { + if let Some(position) = current_state + .read() + .expect("state has been poisoned") + .get_position() + { + let msg = dbus::message::Message::signal( + &dbus::Path::new(MPRIS_PATH).unwrap(), + &dbus::strings::Interface::new("org.mpris.MediaPlayer2.Player") + .unwrap(), + &dbus::strings::Member::new("Seeked").unwrap(), + ) + // position should be in microseconds + .append1(position.num_microseconds().unwrap_or_default()); + conn.send(msg).unwrap(); + } + } + + if !changed.is_empty() { + let msg = PropertiesPropertiesChanged { + interface_name: "org.mpris.MediaPlayer2.Player".to_owned(), + changed_properties: changed, + invalidated_properties: Vec::new(), + }; + conn.send( + msg.to_emit_message(&dbus::Path::new(MPRIS_PATH).unwrap()), + ) + .unwrap(); + } + } + + } + control = control_rx.recv() => { + let control = control.expect("control channel was unexpectedly closed"); + match control { + ControlMessage::Shutdown => { + break; + }, + ControlMessage::SetSpirc(new_spirc) => { + let mut cr = crossroads.lock().unwrap(); + register_controls_interface(&mut cr, new_spirc.clone()); + spirc = Some(new_spirc); + } + ControlMessage::DropSpirc => { + let mut cr = crossroads.lock().unwrap(); + conn.release_name(&mpris_name).await?; + cr.remove::<()>(&MPRIS_PATH.into()); + cr.remove::<()>(&CONTROLS_PATH.into()); + spirc = None; + } + } + } + } + } + conn.release_name(&mpris_name).await?; + conn.release_name(&spotifyd_name).await?; + Ok(()) +} + +fn register_player_interface( + cr: &mut Crossroads, + spirc: Arc, + current_state: Arc, + quit_tx: tokio::sync::mpsc::UnboundedSender<()>, +) { // The following methods and properties are part of the MediaPlayer2 interface. // https://specifications.freedesktop.org/mpris-spec/latest/Media_Player.html - let media_player2_interface = cr.register("org.mpris.MediaPlayer2", |b| { + let media_player2_interface = cr.register("org.mpris.MediaPlayer2", move |b| { + let mut quit_tx = Some(quit_tx); b.method("Raise", (), (), move |_, _, (): ()| { // noop Ok(()) }); - let local_spirc = spirc.clone(); b.method("Quit", (), (), move |_, _, (): ()| { - local_spirc.shutdown(); + quit_tx.take().unwrap().send(()).ok(); Ok(()) }); b.property("CanQuit") @@ -232,229 +576,124 @@ async fn create_dbus_server( let player_interface: IfaceToken<()> = cr.register("org.mpris.MediaPlayer2.Player", |b| { let local_spirc = spirc.clone(); b.method("VolumeUp", (), (), move |_, _, (): ()| { - local_spirc.volume_up(); - Ok(()) + local_spirc.volume_up().map_err(|e| MethodErr::failed(&e)) }) .deprecated(); let local_spirc = spirc.clone(); b.method("VolumeDown", (), (), move |_, _, (): ()| { - local_spirc.volume_down(); - Ok(()) + local_spirc.volume_down().map_err(|e| MethodErr::failed(&e)) }) .deprecated(); let local_spirc = spirc.clone(); b.method("Next", (), (), move |_, _, (): ()| { - local_spirc.next(); - Ok(()) + local_spirc.next().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("Previous", (), (), move |_, _, (): ()| { - local_spirc.prev(); - Ok(()) + local_spirc.prev().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("Pause", (), (), move |_, _, (): ()| { - local_spirc.pause(); - Ok(()) + local_spirc.pause().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("PlayPause", (), (), move |_, _, (): ()| { - local_spirc.play_pause(); - Ok(()) + local_spirc.play_pause().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("Play", (), (), move |_, _, (): ()| { - local_spirc.play(); - Ok(()) + local_spirc.play().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("Stop", (), (), move |_, _, (): ()| { - // TODO: add real stop implementation. - local_spirc.pause(); - Ok(()) + local_spirc.disconnect().map_err(|e| MethodErr::failed(&e)) }); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); - b.method("Seek", ("offset",), (), move |_, _, (pos,): (i64,)| { - if let Ok(Some(playback)) = sp_client.current_playback(None, None::>) { - if playback.device.name == mv_device_name { - let new_pos = playback - .progress - .and_then(|d| d.checked_add(&Duration::milliseconds(pos / 1000))); - - if let Some(new_pos) = new_pos { - let duration: Duration = match playback.item { - Some(PlayableItem::Track(t)) => t.duration, - Some(PlayableItem::Episode(e)) => e.duration, - None => return Ok(()), - }; - - // MPRIS spec: negative values should be treated as 0 - let new_pos = new_pos.max(Duration::zero()); - if new_pos <= duration { - let _ = sp_client.seek_track(new_pos, playback.device.id.as_deref()); - } else { - // MPRIS spec: values beyond track bounds should act like Next - let _ = sp_client.next_track(playback.device.id.as_deref()); - } - } - } + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); + b.method("Seek", ("offset",), (), move |_, _, (offset,): (i64,)| { + let Some(position) = local_state.read()?.get_position() else { + return Err(dbus::MethodErr::failed( + "cannot seek while playback is stopped", + )); + }; + let new_pos = position + Duration::microseconds(offset); + let new_pos_ms = u32::try_from(new_pos.num_milliseconds()).map_err(|err| { + dbus::MethodErr::invalid_arg(&format!("new position out of bounds: {err}")) + })?; + if let Err(err) = local_spirc.set_position_ms(new_pos_ms) { + warn!("failed to seek by {offset}ms: {err}"); + return Err(dbus::MethodErr::failed(&err)); } Ok(()) }); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); b.method( "SetPosition", ("track_id", "position"), (), move |_, _, (track_id, pos): (dbus::Path, i64)| { - if let Ok(Some(playback)) = sp_client.current_playback(None, None::>) { - let (track_matches, duration) = if let Some(item) = playback.item { - let track_matches = item - .id() - .map(|id| uri_to_object_path(id.uri()) == track_id) - .unwrap_or(false); - let duration = match item { - PlayableItem::Track(t) => t.duration.num_microseconds(), - PlayableItem::Episode(e) => e.duration.num_microseconds(), - } - .unwrap_or(i64::MAX); - (track_matches, duration) - } else { - return Ok(()); - }; - - // as per MPRIS spec: pos must be in track bounds and track id must match - if playback.device.name == mv_device_name - && track_matches - && (0..=duration).contains(&pos) - { - // pos is in microseconds, seek_track takes milliseconds - let _ = sp_client.seek_track( - Duration::milliseconds(pos / 1000), - playback.device.id.as_deref(), - ); - } + let Some((current_track_id, duration)) = local_state + .read()? + .audio_item + .as_ref() + .map(|item| (item.track_id, item.duration_ms)) + else { + return Err(dbus::MethodErr::failed( + "can set position while nothing is playing", + )); + }; + let duration = Duration::milliseconds(duration.into()); + + if !track_id.ends_with(¤t_track_id.to_base62().unwrap()) { + // as per mpris spec: ignore as stale + return Ok(()); + } + let new_position = Duration::microseconds(pos); + if new_position < Duration::zero() || new_position > duration { + // ignore as per spec + return Ok(()); } + if let Err(err) = + local_spirc.set_position_ms(new_position.num_milliseconds() as u32) + { + return Err(dbus::MethodErr::failed(&err)); + } + Ok(()) }, ); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); - b.method("OpenUri", ("uri",), (), move |_, _, (uri,): (String,)| { - enum AnyId<'a> { - Playable(PlayableId<'a>), - Context(PlayContextId<'a>), - } - - fn uri_to_id(uri: &str) -> Result, IdError> { - use AnyId::*; - Ok(match parse_uri(uri)? { - (Type::Track, id) => Playable(TrackId::from_id(id)?.into()), - (Type::Episode, id) => Playable(EpisodeId::from_id(id)?.into()), - (Type::Artist, id) => Context(ArtistId::from_id(id)?.into()), - (Type::Album, id) => Context(AlbumId::from_id(id)?.into()), - (Type::Playlist, id) => Context(PlaylistId::from_id(id)?.into()), - (Type::Show, id) => Context(ShowId::from_id(id)?.into()), - (Type::User | Type::Collection | Type::Collectionyourepisodes, _) => { - Err(IdError::InvalidType)? - } - }) - } - - let id = uri_to_id(&uri).map_err(|e| MethodErr::invalid_arg(&e))?; - - let device_id = get_device_id(&sp_client, &mv_device_name, true); - - if let Some(device_id) = device_id { - match id { - AnyId::Playable(id) => { - let _ = sp_client.start_uris_playback( - Some(id), - Some(&device_id), - Some(Offset::Position(Duration::zero())), - None, - ); - } - AnyId::Context(id) => { - let _ = sp_client.start_context_playback( - id, - Some(&device_id), - Some(Offset::Position(Duration::zero())), - None, - ); - } - } - } - Ok(()) + b.method("OpenUri", ("uri",), (), move |_, _, (_,): (String,)| { + warn!("OpenUri is currently not implemented"); + Err::<(), _>(dbus::MethodErr::no_method( + "this method is currently not implemented", + )) }); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); + let local_state = current_state.clone(); b.property("PlaybackStatus") .emits_changed_false() .get(move |_, _| { - if let Ok(Some(playback)) = sp_client.current_playback(None, None::>) { - if playback.device.name == mv_device_name { - if playback.is_playing { - return Ok("Playing".to_string()); - } else { - return Ok("Paused".to_string()); - } - } - } - Ok("Stopped".to_string()) + let playback_state = local_state.read()?.status; + Ok(playback_state.to_mpris().to_string()) }); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); - let sp_client2 = Arc::clone(&spotify_api_client); + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); b.property("Shuffle") .emits_changed_false() - .get(move |_, _| { - let shuffle_status = sp_client - .current_playback(None, None::>) - .ok() - .flatten() - .map_or(false, |p| p.shuffle_state); - Ok(shuffle_status) - }) + .get(move |_, _| Ok(local_state.read()?.shuffle)) .set(move |_, _, value| { - let device_id = get_device_id(&sp_client2, &mv_device_name, true); - if let Some(device_id) = device_id { - match sp_client2.shuffle(value, Some(&device_id)) { - Ok(_) => Ok(None), - Err(err) => { - let e = format!("SetShuffle failed: {}", err); - error!("{}", e); - Err(MethodErr::failed(&e)) - } - } - } else { - let msg = format!("Could not find device with name {}", mv_device_name); - warn!("SetShuffle: {}", msg); - Err(MethodErr::failed(&msg)) - } + local_spirc + .shuffle(value) + .map(|_| None) + .map_err(|err| dbus::MethodErr::failed(&err)) }); b.property("Rate").emits_changed_const().get(|_, _| Ok(1.0)); - - let sp_client = Arc::clone(&spotify_api_client); - b.property("Volume").emits_changed_false().get(move |_, _| { - let vol = sp_client - .current_playback(None, None::>) - .ok() - .flatten() - .and_then(|p| p.device.volume_percent) - .unwrap_or(0) as f64; - - Ok(vol) - }); - b.property("MaximumRate") .emits_changed_const() .get(|_, _| Ok(1.0)); @@ -462,59 +701,57 @@ async fn create_dbus_server( .emits_changed_const() .get(|_, _| Ok(1.0)); - let sp_client = Arc::clone(&spotify_api_client); + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); + b.property("Volume") + .emits_changed_false() + .get(move |_, _| Ok(local_state.read()?.mpris_volume())) + .set(move |_, _, value| { + if let Err(err) = local_spirc.set_volume((value * u16::MAX as f64) as u16) { + return Err(dbus::MethodErr::failed(&err)); + } + Ok(None) + }); + + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); b.property("LoopStatus") .emits_changed_false() .get(move |_, _| { - let status = - if let Ok(Some(player)) = sp_client.current_playback(None, None::>) { - match player.repeat_state { - RepeatState::Off => "None", - RepeatState::Track => "Track", - RepeatState::Context => "Playlist", - } - } else { - "None" + let repeat = local_state.read()?.repeat; + Ok(repeat.to_mpris().to_string()) + }) + .set(move |_, _, value| { + let new_repeat = match value.as_str() { + "None" => false, + "Playlist" => true, + mode => { + return Err(dbus::MethodErr::failed(&format!( + "unsupported repeat mode: {mode}" + ))) } - .to_string(); - Ok(status) + }; + local_spirc + .repeat(new_repeat) + .map_err(|e| MethodErr::failed(&e))?; + Ok(None) }); - let sp_client = Arc::clone(&spotify_api_client); + let local_state = current_state.clone(); b.property("Position") .emits_changed_false() .get(move |_, _| { - let pos = sp_client - .current_playback(None, None::>) - .ok() - .flatten() - .and_then(|p| p.progress?.num_microseconds()) - .unwrap_or(0); - - Ok(pos) + let Some(position) = local_state.read()?.get_position() else { + return Err(dbus::MethodErr::failed("no position available currently")); + }; + + Ok(position.num_microseconds().unwrap_or_default()) }); - let sp_client = Arc::clone(&spotify_api_client); + let local_state = current_state.clone(); b.property("Metadata") .emits_changed_false() - .get(move |_, _| { - let mut m: HashMap>> = HashMap::new(); - let item = match sp_client.current_playing(None, None::>) { - Ok(playing) => playing.and_then(|playing| playing.item), - Err(e) => { - info!("Couldn't fetch metadata from spotify: {:?}", e); - return Ok(m); - } - }; - - if let Some(item) = item { - insert_metadata(&mut m, item); - } else { - info!("Couldn't fetch metadata from spotify: Nothing playing at the moment."); - } - - Ok(m) - }); + .get(move |_, _| Ok(local_state.read()?.to_metadata())); for prop in [ "CanPlay", @@ -528,202 +765,30 @@ async fn create_dbus_server( } }); + cr.insert(MPRIS_PATH, &[media_player2_interface, player_interface], ()); +} + +fn register_controls_interface(cr: &mut Crossroads, spirc: Arc) { let spotifyd_ctrls_interface: IfaceToken<()> = cr.register("rs.spotifyd.Controls", |b| { let local_spirc = spirc.clone(); b.method("VolumeUp", (), (), move |_, _, (): ()| { - local_spirc.volume_up(); - Ok(()) + local_spirc.volume_up().map_err(|e| MethodErr::failed(&e)) }); let local_spirc = spirc.clone(); b.method("VolumeDown", (), (), move |_, _, (): ()| { - local_spirc.volume_down(); - Ok(()) + local_spirc.volume_down().map_err(|e| MethodErr::failed(&e)) }); - let mv_device_name = device_name.clone(); - let sp_client = Arc::clone(&spotify_api_client); + let local_spirc = spirc.clone(); b.method("TransferPlayback", (), (), move |_, _, (): ()| { - let device_id = get_device_id(&sp_client, &mv_device_name, false); - if let Some(device_id) = device_id { - info!("Transferring playback to device {}", device_id); - match sp_client.transfer_playback(&device_id, Some(true)) { - Ok(_) => Ok(()), - Err(err) => { - let e = format!("TransferPlayback failed: {}", err); - error!("{}", e); - Err(MethodErr::failed(&e)) - } - } - } else { - let msg = format!("Could not find device with name {}", mv_device_name); - warn!("TransferPlayback: {}", msg); - Err(MethodErr::failed(&msg)) - } + local_spirc.activate().map_err(|e| MethodErr::failed(&e)) }); }); - cr.insert( - "/org/mpris/MediaPlayer2", - &[media_player2_interface, player_interface], - (), - ); - - cr.insert("/rs/spotifyd/Controls", &[spotifyd_ctrls_interface], ()); - - conn.start_receive( - MatchRule::new_method_call(), - Box::new(move |msg, conn| { - cr.handle_message(msg, conn).unwrap(); - true - }), - ); - - // Store current playback state to be able to detect changes - let mut last_track_id = None; - let mut last_playback_status = None; - let mut last_volume = None; - - loop { - let event = event_rx - .recv() - .await - .expect("Changed track channel was unexpectedly closed"); - let mut seeked_position_ms = None; - - // Update playback state from event - let (track_id, playback_status, player_volume) = match event { - PlayerEvent::VolumeSet { volume } => { - (last_track_id, last_playback_status, Some(volume)) - } - PlayerEvent::Playing { - track_id, - position_ms, - .. - } => { - seeked_position_ms = Some(position_ms); - (Some(track_id), Some(PlaybackStatus::Playing), last_volume) - } - PlayerEvent::Stopped { .. } => { - (last_track_id, Some(PlaybackStatus::Stopped), last_volume) - } - PlayerEvent::Paused { .. } => { - (last_track_id, Some(PlaybackStatus::Paused), last_volume) - } - _ => continue, - }; - - // if playback_status, track_id or volume have changed, emit a PropertiesChanged signal - if last_playback_status != playback_status - || last_track_id != track_id - || last_volume != player_volume - { - let mut changed_properties: HashMap>> = HashMap::new(); - - if last_volume != player_volume { - if let Some(player_volume) = player_volume { - // convert u16 to float - let mut vol_mpris = player_volume as f64; - // max. vol = 1.0 according to mpris spec, round to two decimal places - vol_mpris = (vol_mpris / 65535.0 * 100.0).round() / 100.0; - changed_properties - .insert("Volume".to_owned(), Variant(Box::new(vol_mpris.to_owned()))); - } - } else { - if let Some(track_id) = track_id { - let item = match track_id.audio_type { - SpotifyAudioType::Track => { - let track_id = TrackId::from_id(track_id.to_base62().unwrap()).unwrap(); - let track = spotify_api_client - .track(track_id, None) - .map(PlayableItem::Track); - Some(track) - } - SpotifyAudioType::Podcast => { - let id = EpisodeId::from_id(track_id.to_base62().unwrap()).unwrap(); - let episode = spotify_api_client - .get_an_episode(id, None) - .map(PlayableItem::Episode); - Some(episode) - } - SpotifyAudioType::NonPlayable => None, - }; - - if let Some(item) = item { - match item { - Ok(item) => { - let mut m: HashMap>> = - HashMap::new(); - insert_metadata(&mut m, item); - - changed_properties - .insert("Metadata".to_owned(), Variant(Box::new(m))); - } - Err(e) => info!("Couldn't fetch metadata from spotify: {:?}", e), - } - } - } - if let Some(playback_status) = playback_status { - changed_properties.insert( - "PlaybackStatus".to_owned(), - Variant(Box::new(match playback_status { - PlaybackStatus::Playing => "Playing".to_owned(), - PlaybackStatus::Paused => "Paused".to_owned(), - PlaybackStatus::Stopped => "Stopped".to_owned(), - })), - ); - } - } - - let msg = dbus::nonblock::stdintf::org_freedesktop_dbus::PropertiesPropertiesChanged { - interface_name: "org.mpris.MediaPlayer2.Player".to_owned(), - changed_properties, - invalidated_properties: Vec::new(), - }; - conn.send(msg.to_emit_message(&dbus::Path::new("/org/mpris/MediaPlayer2").unwrap())) - .unwrap(); - - last_playback_status = playback_status; - last_track_id = track_id; - last_volume = player_volume; - } - - // if position in track has changed emit a Seeked signal - if let Some(position_ms) = seeked_position_ms { - let msg = dbus::message::Message::signal( - &dbus::Path::new("/org/mpris/MediaPlayer2").unwrap(), - &dbus::strings::Interface::new("org.mpris.MediaPlayer2.Player").unwrap(), - &dbus::strings::Member::new("Seeked").unwrap(), - ) - // position should be in microseconds - .append1(position_ms as i64 * 1000); - conn.send(msg).unwrap(); - } - } + cr.insert(CONTROLS_PATH, &[spotifyd_ctrls_interface], ()); } -fn get_device_id( - sp_client: &AuthCodeSpotify, - device_name: &str, - only_active: bool, -) -> Option { - let device_result = sp_client.device(); - match device_result { - Ok(devices) => devices.into_iter().find_map(|d| { - if d.name == device_name && (d.is_active || !only_active) { - info!("Found device: {}, active: {}", d.name, d.is_active); - d.id - } else { - None - } - }), - Err(err) => { - error!("Get devices error: {}", err); - None - } - } -} - -fn uri_to_object_path(uri: String) -> dbus::Path<'static> { +fn uri_to_object_path(uri: &str) -> dbus::Path<'static> { let mut path = String::with_capacity(uri.len() + 1); for element in uri.split(':') { path.push('/'); @@ -731,121 +796,3 @@ fn uri_to_object_path(uri: String) -> dbus::Path<'static> { } dbus::Path::new(path).unwrap() } - -fn insert_metadata(m: &mut HashMap>>, item: PlayableItem) { - use rspotify::model::{ - Image, - PlayableItem::{Episode, Track}, - }; - - // some fields that only make sense or only exist for tracks - struct TrackFields { - artists: Vec, - popularity: u32, - track_number: u32, - disc_number: i32, - } - - // a common denominator struct for FullEpisode and FullTrack - struct TrackOrEpisode { - id: Option>, - duration: chrono::Duration, - images: Vec, - name: String, - album_name: String, - album_artists: Vec, - external_urls: HashMap, - track_fields: Option, - } - - let item = match item { - Track(t) => TrackOrEpisode { - id: t.id.map(|t| uri_to_object_path(t.uri())), - duration: t.duration, - images: t.album.images, - name: t.name, - album_name: t.album.name, - album_artists: t.album.artists.into_iter().map(|a| a.name).collect(), - external_urls: t.external_urls, - track_fields: Some(TrackFields { - artists: t.artists.into_iter().map(|a| a.name).collect(), - popularity: t.popularity, - track_number: t.track_number, - disc_number: t.disc_number, - }), - }, - Episode(e) => TrackOrEpisode { - id: Some(uri_to_object_path(e.id.uri())), - duration: e.duration, - images: e.show.images, - name: e.name, - album_name: e.show.name, - album_artists: vec![e.show.publisher], - external_urls: e.external_urls, - track_fields: None, - }, - }; - - m.insert( - "mpris:trackid".to_string(), - Variant(Box::new(item.id.unwrap_or_default())), - ); - - m.insert( - "mpris:length".to_string(), - Variant(Box::new( - item.duration.num_microseconds().unwrap_or_default(), - )), - ); - - m.insert( - "mpris:artUrl".to_string(), - Variant(Box::new( - item.images - .into_iter() - .max_by_key(|i| i.width.unwrap_or(0)) - .map(|i| i.url) - .unwrap_or_default(), - )), - ); - - m.insert("xesam:title".to_string(), Variant(Box::new(item.name))); - - m.insert( - "xesam:album".to_string(), - Variant(Box::new(item.album_name)), - ); - - m.insert( - "xesam:albumArtist".to_string(), - Variant(Box::new(item.album_artists)), - ); - - if let Some(track) = item.track_fields { - m.insert("xesam:artist".to_string(), Variant(Box::new(track.artists))); - - m.insert( - "xesam:autoRating".to_string(), - Variant(Box::new(f64::from(track.popularity) / 100.0)), - ); - - m.insert( - "xesam:trackNumber".to_string(), - Variant(Box::new(track.track_number)), - ); - - m.insert( - "xesam:discNumber".to_string(), - Variant(Box::new(track.disc_number)), - ); - } - - // to avoid cloning here, we take the relevant url directly from the HashMap - let mut external_urls = item.external_urls; - m.insert( - "xesam:url".to_string(), - Variant(Box::new( - external_urls.remove("spotify").unwrap_or_default(), - )), - ); -} diff --git a/src/main_loop.rs b/src/main_loop.rs index 4a30fd52..61dbac7f 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -2,6 +2,9 @@ use crate::config::DBusType; #[cfg(feature = "dbus_mpris")] use crate::dbus_mpris::DbusServer; use crate::process::spawn_program_on_event; +use futures::future::Either; +#[cfg(not(feature = "dbus_mpris"))] +use futures::future::Pending; use futures::{ self, future::{self, Fuse, FusedFuture}, @@ -16,6 +19,9 @@ use log::error; use std::pin::Pin; use std::sync::Arc; +#[cfg(not(feature = "dbus_mpris"))] +type DbusServer = Pending<()>; + pub struct SpotifydState { pub device_name: String, pub player_event_program: Option, @@ -73,7 +79,6 @@ pub(crate) struct MainLoop { impl MainLoop { async fn get_connection(&mut self) -> Result<(Spirc, impl Future), Error> { let creds = self.credentials_provider.get_credentials().await; - self.session.connect(creds.clone(), true).await?; // TODO: expose is_group Spirc::new( @@ -95,8 +100,19 @@ impl MainLoop { pub(crate) async fn run(&mut self) { tokio::pin! { let ctrl_c = tokio::signal::ctrl_c(); + // we don't necessarily have a dbus server + let dbus_server = Either::::Right(future::pending()); } + #[cfg(feature = "dbus_mpris")] + let mpris_event_tx = if self.use_mpris { + let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + *dbus_server.as_mut() = Either::Left(DbusServer::new(rx, self.dbus_type)); + Some(tx) + } else { + None + }; + 'mainloop: loop { let (spirc, spirc_task) = tokio::select!( _ = &mut ctrl_c => { @@ -117,23 +133,14 @@ impl MainLoop { let shared_spirc = Arc::new(spirc); - // we don't necessarily have a dbus server - let mut dbus_server: Pin>> = Box::pin(future::pending()); - #[cfg(feature = "dbus_mpris")] - let mpris_event_tx = if self.use_mpris { - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - dbus_server = Box::pin(DbusServer::new( - self.session.clone(), - shared_spirc.clone(), - self.spotifyd_state.device_name.clone(), - rx, - self.dbus_type, - )); - Some(tx) - } else { - None - }; + if let Either::Left(mut dbus_server) = Either::as_pin_mut(dbus_server.as_mut()) { + if let Err(err) = dbus_server.as_mut().set_spirc(shared_spirc.clone()) { + error!("failed to configure dbus server: {err}"); + let _ = shared_spirc.shutdown(); + break 'mainloop; + } + } let mut running_event_program = Box::pin(Fuse::terminated()); @@ -156,9 +163,18 @@ impl MainLoop { break; } // dbus stopped unexpectedly - _ = &mut dbus_server => { - let _ = shared_spirc.shutdown(); - break 'mainloop; + result = &mut dbus_server => { + #[cfg(feature = "dbus_mpris")] + { + if let Err(err) = result { + error!("DBus terminated unexpectedly: {err}"); + } + let _ = shared_spirc.shutdown(); + *dbus_server.as_mut() = Either::Right(future::pending()); + break 'mainloop; + } + #[cfg(not(feature = "dbus_mpris"))] + result // unused variable } // a new player event is available and no program is running event = event_channel.recv(), if running_event_program.is_terminated() => { @@ -185,6 +201,21 @@ impl MainLoop { } ) } + #[cfg(feature = "dbus_mpris")] + if let Either::Left(dbus_server) = Either::as_pin_mut(dbus_server.as_mut()) { + if let Err(err) = dbus_server.drop_spirc() { + error!("failed to reconfigure dbus server: {err}"); + break 'mainloop; + } + } + } + #[cfg(feature = "dbus_mpris")] + if let Either::Left(dbus_server) = Either::as_pin_mut(dbus_server.as_mut()) { + if dbus_server.shutdown() { + if let Err(err) = dbus_server.await { + error!("failed to shutdown the dbus server: {err}"); + } + } } } } From 01edb80d634d1d3cb6d4ffd9454848e50548bf99 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 03:58:04 +0100 Subject: [PATCH 04/17] chore: update dependencies and librespot to 0.6 --- Cargo.lock | 1119 +++++++++++++++++++++++++++------------------------- Cargo.toml | 19 +- 2 files changed, 599 insertions(+), 539 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1c7ed54..f181859e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -100,43 +100,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arrayvec" @@ -152,7 +152,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -167,7 +167,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "libc", "winapi", ] @@ -180,21 +180,20 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d" +checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" dependencies = [ "aws-lc-sys", - "mirai-annotations", "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.22.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972" +checksum = "8478a5c29ead3f3be14aff8a202ad965cf7da6856860041bfca271becf8ba48b" dependencies = [ "bindgen 0.69.5", "cc", @@ -263,7 +262,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.82", + "syn 2.0.92", "which", ] @@ -282,7 +281,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -314,9 +313,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -326,15 +325,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.1.31" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" dependencies = [ "jobserver", "libc", @@ -364,9 +363,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -395,7 +394,7 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.5", + "libloading 0.8.6", ] [[package]] @@ -415,9 +414,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -451,9 +450,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -472,38 +471,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "cookie" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.20.0" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387461abbc748185c3a6e1673d826918b450b87ff22639429c694619a83b6cf6" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "cookie", - "idna 0.3.0", - "indexmap 1.9.3", - "log", - "serde", - "serde_derive", - "serde_json", - "time", - "url", + "core-foundation-sys", + "libc", ] [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ "core-foundation-sys", "libc", @@ -561,9 +542,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -617,7 +598,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -628,7 +609,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -714,7 +695,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -724,7 +705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -760,6 +741,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", +] + [[package]] name = "dunce" version = "1.0.5" @@ -774,30 +766,18 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] -[[package]] -name = "enum_dispatch" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.82", -] - [[package]] name = "env_filter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -805,9 +785,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", @@ -824,12 +804,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -853,15 +833,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fern" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" dependencies = [ "log", "syslog", @@ -950,7 +930,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -1036,14 +1016,13 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "governor" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7ecdc5898f6a43e08a7e2c9e2266beb98fd4dfbf2634182540fbb715245093" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" dependencies = [ "cfg-if", - "futures-sink", + "futures", "futures-timer", - "futures-util", "no-std-compat", "nonzero_ext", "parking_lot", @@ -1065,7 +1044,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap", "slab", "tokio", "tokio-util", @@ -1074,17 +1053,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "http 1.1.0", - "indexmap 2.6.0", + "http 1.2.0", + "indexmap", "slab", "tokio", "tokio-util", @@ -1093,15 +1072,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "headers" @@ -1112,7 +1085,7 @@ dependencies = [ "base64 0.21.7", "bytes", "headers-core", - "http 1.1.0", + "http 1.2.0", "httpdate", "mime", "sha1", @@ -1124,7 +1097,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" dependencies = [ - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1136,12 +1109,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - [[package]] name = "hermit-abi" version = "0.1.19" @@ -1151,12 +1118,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -1174,11 +1135,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1216,9 +1177,9 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1243,7 +1204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http 1.1.0", + "http 1.2.0", ] [[package]] @@ -1254,7 +1215,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", "pin-project-lite", ] @@ -1279,9 +1240,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.31" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -1303,15 +1264,15 @@ dependencies = [ [[package]] name = "hyper" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.6", - "http 1.1.0", + "h2 0.4.7", + "http 1.2.0", "http-body 1.0.1", "httparse", "httpdate", @@ -1331,8 +1292,8 @@ dependencies = [ "bytes", "futures-util", "headers", - "http 1.1.0", - "hyper 1.5.0", + "http 1.2.0", + "hyper 1.5.2", "hyper-rustls 0.26.0", "hyper-util", "pin-project-lite", @@ -1351,7 +1312,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.31", + "hyper 0.14.32", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -1364,8 +1325,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.5.0", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", "log", "rustls 0.22.4", @@ -1378,35 +1339,35 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.5.0", + "http 1.2.0", + "hyper 1.5.2", "hyper-util", "log", - "rustls 0.23.15", - "rustls-native-certs 0.8.0", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tower-service", ] [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", + "http 1.2.0", "http-body 1.0.1", - "hyper 1.5.0", + "hyper 1.5.2", "pin-project-lite", "socket2", "tokio", @@ -1437,6 +1398,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1445,22 +1524,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "idna" -version = "0.5.0" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1481,22 +1561,12 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown", ] [[package]] @@ -1540,9 +1610,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jack" @@ -1582,7 +1652,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] @@ -1604,18 +1674,19 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] [[package]] name = "keyring" -version = "3.5.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11351fce7c6e2b5f1871e3c8ed048d60d909ab6fea6b96bfe41a6409277a2ee5" +checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" dependencies = [ "log", ] @@ -1637,9 +1708,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libdbus-sys" @@ -1662,9 +1733,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -1672,9 +1743,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libmdns" @@ -1690,15 +1761,15 @@ dependencies = [ "multimap", "rand", "socket2", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "libpulse-binding" -version = "2.28.1" +version = "2.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3557a2dfc380c8f061189a01c6ae7348354e0c9886038dc6c171219c08eaff" +checksum = "b6b1040a6c4c4d1e9e852000f6202df1a02a4f074320de336ab21e4fd317b538" dependencies = [ "bitflags 1.3.2", "libc", @@ -1754,30 +1825,30 @@ dependencies = [ [[package]] name = "librespot-audio" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbda070a5598b32718e497f585f46891f7113e64aff20a13c0f2ba8fe7ccad9" +checksum = "7e07566fe7553042936c61bbdd9bedb524114a904aa7f9738e266c641468bab8" dependencies = [ "aes", "bytes", "ctr", "futures-util", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.2", "hyper-util", "librespot-core", "log", "parking_lot", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "librespot-connect" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "699745eaeff6f53b67e93fe973eb72c818cba58d10cfdbdd4c1bf7893f9b705b" +checksum = "67ce3a5634669ce051a425cff5437a474831111df045fd5a2bb37fabe316fa60" dependencies = [ "form_urlencoded", "futures-util", @@ -1789,16 +1860,16 @@ dependencies = [ "rand", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", ] [[package]] name = "librespot-core" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505a5ddd966231755994b60435607a1e8ae1d41c7f1169b078e0511bfb82d931" +checksum = "c4c76303efcf949a59f9380220ca420c4d72fa32dbb3641a0079f429cc5e44e7" dependencies = [ "aes", "base64 0.22.1", @@ -1810,12 +1881,12 @@ dependencies = [ "futures-util", "governor", "hmac", - "http 1.1.0", + "http 1.2.0", "http-body-util", "httparse", - "hyper 1.5.0", + "hyper 1.5.2", "hyper-proxy2", - "hyper-rustls 0.27.3", + "hyper-rustls 0.27.5", "hyper-util", "librespot-oauth", "librespot-protocol", @@ -1839,7 +1910,7 @@ dependencies = [ "sha1", "shannon", "sysinfo", - "thiserror", + "thiserror 1.0.69", "time", "tokio", "tokio-stream", @@ -1852,9 +1923,9 @@ dependencies = [ [[package]] name = "librespot-discovery" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abca1d9420179c0875189cee50b1cd75ad91c6180f38d079eae3a62a40b4745f" +checksum = "94a952d28c775562b9b6039102c0e3a834cb31157fccb2f2a68a26dc4397fea8" dependencies = [ "aes", "base64 0.22.1", @@ -1865,23 +1936,24 @@ dependencies = [ "futures-util", "hmac", "http-body-util", - "hyper 1.5.0", + "hyper 1.5.2", "hyper-util", "libmdns", "librespot-core", "log", "rand", "serde_json", + "serde_repr", "sha1", - "thiserror", + "thiserror 1.0.69", "tokio", ] [[package]] name = "librespot-metadata" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a10ab5a390f65281e763cd09c617b173f0e665994eae3d242526924625fdc66" +checksum = "7cf6d5c46a401b1dd3e062ebdce959aa694bbae1039841756545d2e9c4f8be5f" dependencies = [ "async-trait", "bytes", @@ -1891,27 +1963,27 @@ dependencies = [ "protobuf", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "uuid", ] [[package]] name = "librespot-oauth" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bda94233b358fb41c04ed15507c61136c80efe876c6e05a10ddb9a182b144e" +checksum = "00dcad779aa6c3b442e493e2a40ca83a5c5fcf38a65c05b026c3587bd4f8d14f" dependencies = [ "log", "oauth2", - "thiserror", + "thiserror 1.0.69", "url", ] [[package]] name = "librespot-playback" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1bcfe1d72c5ac14c798c7e3e1c20e1fb6af2b9c254794545cfcb1f2a4627e2" +checksum = "4ed1f776a04c8c9275407f8d4df034f2615ea729ec6c6d0fa69f423fc571df64" dependencies = [ "alsa", "cpal", @@ -1929,16 +2001,16 @@ dependencies = [ "rodio", "shell-words", "symphonia", - "thiserror", + "thiserror 1.0.69", "tokio", "zerocopy", ] [[package]] name = "librespot-protocol" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6f343f573e0469d3ff8a02b99bbd9789faa01e2ff167332542ac840a8b31e7" +checksum = "80802f52b5a1b3a2157454e6aca483a627fbf7b942e0a5fea037ebf3ed8b0546" dependencies = [ "protobuf", "protobuf-codegen", @@ -1950,6 +2022,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + [[package]] name = "lock_api" version = "0.4.12" @@ -1981,17 +2059,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" -[[package]] -name = "maybe-async" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.82", -] - [[package]] name = "memchr" version = "2.7.4" @@ -2021,22 +2088,15 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", ] -[[package]] -name = "mirai-annotations" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" - [[package]] name = "multimap" version = "0.10.0" @@ -2057,7 +2117,7 @@ dependencies = [ "log", "ndk-sys", "num_enum", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2159,7 +2219,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -2210,7 +2270,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -2238,7 +2298,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "sha2", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -2362,14 +2422,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2415,9 +2475,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "portaudio-rs" @@ -2457,12 +2517,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -2473,17 +2533,16 @@ checksum = "714c75db297bc88a63783ffc6ab9f830698a6705aa0201416931759ef4c8183d" dependencies = [ "autocfg", "equivalent", - "indexmap 2.6.0", + "indexmap", ] [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "toml_edit", ] [[package]] @@ -2512,9 +2571,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -2527,7 +2586,7 @@ checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72" dependencies = [ "once_cell", "protobuf-support", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2542,7 +2601,7 @@ dependencies = [ "protobuf-parse", "regex", "tempfile", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2552,12 +2611,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322330e133eab455718444b4e033ebfac7c6528972c784fcde28d2cc783c6257" dependencies = [ "anyhow", - "indexmap 2.6.0", + "indexmap", "log", "protobuf", "protobuf-support", "tempfile", - "thiserror", + "thiserror 1.0.69", "which", ] @@ -2567,7 +2626,7 @@ version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2582,9 +2641,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -2631,9 +2690,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -2646,14 +2705,14 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2663,9 +2722,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2692,7 +2751,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.31", + "hyper 0.14.32", "hyper-rustls 0.24.2", "ipnet", "js-sys", @@ -2741,14 +2800,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" dependencies = [ "cpal", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -2764,60 +2823,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rspotify" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71aa4a990ef1bacbed874fbab621e16c61a8b5a56854ada6b2bcccf19acb5795" -dependencies = [ - "base64 0.22.1", - "chrono", - "getrandom", - "log", - "maybe-async", - "rspotify-http", - "rspotify-macros", - "rspotify-model", - "serde", - "serde_json", - "sha2", - "thiserror", - "url", -] - -[[package]] -name = "rspotify-http" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a193f73ee55ab66aeb0337170d120bc73ec4963b150d9c66d68b28d14bc5ac5f" -dependencies = [ - "log", - "maybe-async", - "serde_json", - "thiserror", - "ureq", -] - -[[package]] -name = "rspotify-macros" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78387b0ebb8da6d4c72e728496b09701b7054c0ef88ea2f4f40e46b9107a6de" - -[[package]] -name = "rspotify-model" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6ce0f0ecf4eb3b0b8ab7c6932328d03040dd77169b1c533a3ead1308985af6" -dependencies = [ - "chrono", - "enum_dispatch", - "serde", - "serde_json", - "strum", - "thiserror", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2832,15 +2837,15 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2871,9 +2876,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "aws-lc-rs", "log", @@ -2894,20 +2899,19 @@ dependencies = [ "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", ] [[package]] name = "rustls-native-certs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile 2.2.0", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.1.0", ] [[package]] @@ -2930,9 +2934,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -2958,9 +2962,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -2979,9 +2983,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ "windows-sys 0.59.0", ] @@ -3009,7 +3013,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-foundation-sys", "libc", "security-framework-sys", @@ -3017,9 +3034,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -3027,29 +3044,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "itoa", "memchr", @@ -3067,6 +3084,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", +] + [[package]] name = "serde_spanned" version = "0.6.8" @@ -3187,25 +3215,14 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", ] -[[package]] -name = "socks" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" -dependencies = [ - "byteorder", - "libc", - "winapi", -] - [[package]] name = "spin" version = "0.9.8" @@ -3258,12 +3275,11 @@ dependencies = [ "librespot-playback", "log", "pledge", - "rspotify", "serde", "sha-1", "structopt", "syslog", - "thiserror", + "thiserror 2.0.9", "time", "tokio", "tokio-stream", @@ -3272,6 +3288,12 @@ dependencies = [ "whoami", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.8.0" @@ -3301,35 +3323,13 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck 0.3.3", + "heck", "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.82", -] - [[package]] name = "subtle" version = "2.6.1" @@ -3433,9 +3433,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.82" +version = "2.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" dependencies = [ "proc-macro2", "quote", @@ -3448,6 +3448,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", +] + [[package]] name = "sysinfo" version = "0.31.4" @@ -3481,7 +3492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -3497,9 +3508,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -3519,22 +3530,42 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc" +dependencies = [ + "thiserror-impl 2.0.9", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ - "thiserror-impl", + "proc-macro2", + "quote", + "syn 2.0.92", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -3591,25 +3622,20 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.8.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.40.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -3631,7 +3657,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -3657,20 +3683,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.15", - "rustls-pki-types", + "rustls 0.23.20", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3685,19 +3710,19 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.15", - "rustls-native-certs 0.8.0", + "rustls 0.23.20", + "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls 0.26.1", "tungstenite", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3715,7 +3740,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -3727,28 +3752,17 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.6.0", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.20", + "winnow", ] [[package]] @@ -3759,9 +3773,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -3769,9 +3783,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -3779,9 +3793,9 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", "tracing-subscriber", @@ -3789,9 +3803,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "sharded-slab", "thread_local", @@ -3813,14 +3827,14 @@ dependencies = [ "byteorder", "bytes", "data-encoding", - "http 1.1.0", + "http 1.2.0", "httparse", "log", "rand", - "rustls 0.23.15", + "rustls 0.23.20", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.69", "utf-8", ] @@ -3830,26 +3844,11 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -3869,34 +3868,14 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" -dependencies = [ - "base64 0.21.7", - "cookie", - "cookie_store", - "log", - "once_cell", - "rustls 0.21.12", - "rustls-webpki 0.101.7", - "serde", - "serde_json", - "socks", - "url", - "webpki-roots", -] - [[package]] name = "url" -version = "2.5.2" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna", "percent-encoding", "serde", ] @@ -3907,6 +3886,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -3937,9 +3928,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "9.0.1" +version = "9.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349ed9e45296a581f455bc18039878f409992999bc1d5da12a6800eb18c8752f" +checksum = "31f25fc8f8f05df455c7941e87f093ad22522a9ff33d7a027774815acf6f0639" dependencies = [ "anyhow", "derive_builder", @@ -3950,9 +3941,9 @@ dependencies = [ [[package]] name = "vergen-gitcl" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a3a7f91caabecefc3c249fd864b11d4abe315c166fbdb568964421bccfd2b7a" +checksum = "0227006d09f98ab00ea69e9a5e055e676a813cfbed4232986176c86a6080b997" dependencies = [ "anyhow", "derive_builder", @@ -3964,9 +3955,9 @@ dependencies = [ [[package]] name = "vergen-lib" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229eaddb0050920816cf051e619affaf18caa3dd512de8de5839ccbc8e53abb0" +checksum = "c0c767e6751c09fc85cde58722cf2f1007e80e4c8d5a4321fc90d83dc54ca147" dependencies = [ "anyhow", "derive_builder", @@ -4012,9 +4003,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -4023,36 +4014,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4060,28 +4051,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4226,7 +4217,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -4237,7 +4228,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", ] [[package]] @@ -4463,15 +4454,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.20" @@ -4491,6 +4473,42 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4509,7 +4527,28 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.92", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", + "synstructure", ] [[package]] @@ -4517,3 +4556,25 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.92", +] diff --git a/Cargo.toml b/Cargo.toml index 7bbd8005..fba33363 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,30 +14,29 @@ chrono = "0.4" dbus = { version = "0.9", optional = true } dbus-tokio = { version = "0.7.3", optional = true } dbus-crossroads = { version = "0.5.0", optional = true } -fern = { version = "0.6.0", features = ["syslog-6"] } +fern = { version = "0.7.0", features = ["syslog-6"] } futures = "0.3.15" gethostname = "0.5.0" hex = "0.4" keyring = { version = "3.5", optional = true } libc = "0.2.82" log = "0.4.6" -rspotify = { version = "0.13.0", features = ["client-ureq", "ureq-rustls-tls"], default-features = false, optional = true } serde = { version = "1.0.115", features = ["derive"] } sha-1 = "0.10" structopt = "0.3.17" tokio = {version = "1.26.0", features = ["signal", "rt-multi-thread", "process", "io-std"] } tokio-stream = "0.1.7" url = "2.2.2" -librespot-audio = { version = "0.5", default-features = false } -librespot-playback = { version = "0.5", default-features = false } -librespot-core = { version = "0.5" } -librespot-discovery = { version = "0.5" } -librespot-connect = { version = "0.5" } -librespot-metadata = "0.5.0" +librespot-audio = { version = "0.6", default-features = false } +librespot-playback = { version = "0.6", default-features = false } +librespot-core = "0.6" +librespot-discovery = "0.6" +librespot-connect = "0.6" +librespot-metadata = "0.6" toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" -thiserror = "1.0.64" +thiserror = "2.0" time = { version = "0.3.37", default-features = false, features = ["formatting"] } [target."cfg(unix)".dependencies] @@ -56,7 +55,7 @@ env_logger = "0.11" [features] alsa_backend = ["librespot-playback/alsa-backend", "alsa"] dbus_keyring = ["keyring"] -dbus_mpris = ["dbus", "dbus-tokio", "dbus-crossroads", "rspotify"] +dbus_mpris = ["dbus", "dbus-tokio", "dbus-crossroads"] pipe_backend = [] default = ["alsa_backend", "pipe_backend"] portaudio_backend = ["librespot-playback/portaudio-backend"] From 2f6666f9120d3d876006259c4662636d86fab2ac Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 04:26:19 +0100 Subject: [PATCH 05/17] clippy: fix warnings --- src/config.rs | 2 +- src/dbus_mpris.rs | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/config.rs b/src/config.rs index 53c2ae5f..9c635777 100644 --- a/src/config.rs +++ b/src/config.rs @@ -56,7 +56,7 @@ pub enum Backend { } fn default_backend() -> Backend { - return Backend::from_str(BACKEND_VALUES.first().unwrap()).unwrap(); + Backend::from_str(BACKEND_VALUES.first().unwrap()).unwrap() } impl FromStr for Backend { diff --git a/src/dbus_mpris.rs b/src/dbus_mpris.rs index 7e71d207..313379b3 100644 --- a/src/dbus_mpris.rs +++ b/src/dbus_mpris.rs @@ -21,16 +21,19 @@ use std::convert::TryFrom; use std::{ collections::HashMap, pin::Pin, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, RwLock}, }; use thiserror::Error; use time::format_description::well_known::Iso8601; -use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; +use tokio::sync::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + Mutex, +}; type DbusMap = HashMap>>; -const MPRIS_PATH: &'static str = "/org/mpris/MediaPlayer2"; -const CONTROLS_PATH: &'static str = "/rs/spotifyd/Controls"; +const MPRIS_PATH: &str = "/org/mpris/MediaPlayer2"; +const CONTROLS_PATH: &str = "/rs/spotifyd/Controls"; pub enum ControlMessage { SetSpirc(Arc), @@ -97,7 +100,7 @@ enum PlaybackStatus { } impl PlaybackStatus { - fn to_mpris(&self) -> &'static str { + fn to_mpris(self) -> &'static str { match self { PlaybackStatus::Playing => "Playing", PlaybackStatus::Paused => "Paused", @@ -137,7 +140,7 @@ enum RepeatState { } impl RepeatState { - fn to_mpris(&self) -> &'static str { + fn to_mpris(self) -> &'static str { match self { RepeatState::None => "None", // RepeatState::Track => "Track", @@ -427,8 +430,10 @@ async fn create_dbus_server( conn.start_receive( MatchRule::new_method_call(), Box::new(move |msg, conn| { - let mut cr = cr.lock().unwrap(); - cr.handle_message(msg, conn).unwrap(); + tokio::task::block_in_place(|| { + let mut cr = cr.blocking_lock(); + cr.handle_message(msg, conn).unwrap(); + }); true }), ); @@ -449,7 +454,7 @@ async fn create_dbus_server( let event = event.expect("event channel was unexpectedly closed"); if let PlayerEvent::SessionConnected { connection_id, .. } = event { - let mut cr = crossroads.lock().unwrap(); + let mut cr = crossroads.lock().await; let spirc = spirc.clone().unwrap(); register_player_interface(&mut cr, spirc, current_state.clone(), quit_tx.clone()); if cur_conn_id.is_none() { @@ -459,7 +464,7 @@ async fn create_dbus_server( } else if let PlayerEvent::SessionDisconnected { connection_id, .. } = event { // if this message isn't outdated yet, we vanish from the bus if cur_conn_id == Some(connection_id) { - let mut cr = crossroads.lock().unwrap(); + let mut cr = crossroads.lock().await; conn.release_name(&mpris_name).await?; cr.remove::<()>(&MPRIS_PATH.into()); cur_conn_id = None; @@ -509,12 +514,12 @@ async fn create_dbus_server( break; }, ControlMessage::SetSpirc(new_spirc) => { - let mut cr = crossroads.lock().unwrap(); + let mut cr = crossroads.lock().await; register_controls_interface(&mut cr, new_spirc.clone()); spirc = Some(new_spirc); } ControlMessage::DropSpirc => { - let mut cr = crossroads.lock().unwrap(); + let mut cr = crossroads.lock().await; conn.release_name(&mpris_name).await?; cr.remove::<()>(&MPRIS_PATH.into()); cr.remove::<()>(&CONTROLS_PATH.into()); From 97846e73cf34e50411ca61dbbe0b551529815772 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 15:47:41 +0100 Subject: [PATCH 06/17] add seeked signal to interface Co-Authored-By: dotandl --- src/dbus_mpris.rs | 49 +++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/dbus_mpris.rs b/src/dbus_mpris.rs index 313379b3..4dbed434 100644 --- a/src/dbus_mpris.rs +++ b/src/dbus_mpris.rs @@ -439,7 +439,12 @@ async fn create_dbus_server( ); let mut spirc: Option> = None; - let mut cur_conn_id: Option = None; + + struct ConnectionData { + conn_id: String, + seeked_fn: SeekedSignal, + } + let mut cur_conn: Option = None; loop { tokio::select! { @@ -456,18 +461,23 @@ async fn create_dbus_server( if let PlayerEvent::SessionConnected { connection_id, .. } = event { let mut cr = crossroads.lock().await; let spirc = spirc.clone().unwrap(); - register_player_interface(&mut cr, spirc, current_state.clone(), quit_tx.clone()); - if cur_conn_id.is_none() { + let seeked_fn = register_player_interface( + &mut cr, + spirc, + current_state.clone(), + quit_tx.clone(), + ); + if cur_conn.is_none() { conn.request_name(&mpris_name, true, true, true).await?; } - cur_conn_id = Some(connection_id); + cur_conn = Some(ConnectionData { conn_id: connection_id, seeked_fn }); } else if let PlayerEvent::SessionDisconnected { connection_id, .. } = event { // if this message isn't outdated yet, we vanish from the bus - if cur_conn_id == Some(connection_id) { + if cur_conn.as_ref().is_some_and(|d| d.conn_id == connection_id) { let mut cr = crossroads.lock().await; conn.release_name(&mpris_name).await?; cr.remove::<()>(&MPRIS_PATH.into()); - cur_conn_id = None; + cur_conn = None; } } else { let (changed, seeked) = current_state @@ -476,19 +486,17 @@ async fn create_dbus_server( .handle_event(event); if seeked { - if let Some(position) = current_state + let position = current_state .read() .expect("state has been poisoned") - .get_position() + .get_position(); + if let Some((ConnectionData { seeked_fn, .. }, position)) = + Option::zip(cur_conn.as_ref(), position) { - let msg = dbus::message::Message::signal( - &dbus::Path::new(MPRIS_PATH).unwrap(), - &dbus::strings::Interface::new("org.mpris.MediaPlayer2.Player") - .unwrap(), - &dbus::strings::Member::new("Seeked").unwrap(), - ) - // position should be in microseconds - .append1(position.num_microseconds().unwrap_or_default()); + let msg = seeked_fn( + &MPRIS_PATH.into(), + &(position.num_microseconds().unwrap_or_default(),), + ); conn.send(msg).unwrap(); } } @@ -534,12 +542,14 @@ async fn create_dbus_server( Ok(()) } +type SeekedSignal = Box dbus::Message + Send + Sync + 'static>; + fn register_player_interface( cr: &mut Crossroads, spirc: Arc, current_state: Arc, quit_tx: tokio::sync::mpsc::UnboundedSender<()>, -) { +) -> SeekedSignal { // The following methods and properties are part of the MediaPlayer2 interface. // https://specifications.freedesktop.org/mpris-spec/latest/Media_Player.html let media_player2_interface = cr.register("org.mpris.MediaPlayer2", move |b| { @@ -578,7 +588,10 @@ fn register_player_interface( // The following methods and properties are part of the MediaPlayer2.Player interface. // https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html + let mut seeked_signal = None; + let player_interface: IfaceToken<()> = cr.register("org.mpris.MediaPlayer2.Player", |b| { + seeked_signal = Some(b.signal::<(i64,), _>("Seeked", ("Position",)).msg_fn()); let local_spirc = spirc.clone(); b.method("VolumeUp", (), (), move |_, _, (): ()| { local_spirc.volume_up().map_err(|e| MethodErr::failed(&e)) @@ -771,6 +784,8 @@ fn register_player_interface( }); cr.insert(MPRIS_PATH, &[media_player2_interface, player_interface], ()); + + seeked_signal.expect("player interface has not been registered") } fn register_controls_interface(cr: &mut Crossroads, spirc: Arc) { From 25ee03dd7d3267ba61fa4fbe1c7d768b62cbe481 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 19:33:36 +0100 Subject: [PATCH 07/17] keyring: re-enable real backends --- Cargo.lock | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f181859e..5501070f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -646,6 +646,19 @@ dependencies = [ "dbus", ] +[[package]] +name = "dbus-secret-service" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +dependencies = [ + "dbus", + "futures-util", + "num", + "once_cell", + "rand", +] + [[package]] name = "dbus-tokio" version = "0.7.6" @@ -1688,7 +1701,12 @@ version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" dependencies = [ + "byteorder", + "dbus-secret-service", "log", + "security-framework 2.11.1", + "security-framework 3.1.0", + "windows-sys 0.59.0", ] [[package]] @@ -2166,6 +2184,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -2194,6 +2226,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2242,6 +2283,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" diff --git a/Cargo.toml b/Cargo.toml index fba33363..7cb77b34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ fern = { version = "0.7.0", features = ["syslog-6"] } futures = "0.3.15" gethostname = "0.5.0" hex = "0.4" -keyring = { version = "3.5", optional = true } +keyring = { version = "3.5", optional = true, features = ["apple-native", "windows-native", "sync-secret-service"] } libc = "0.2.82" log = "0.4.6" serde = { version = "1.0.115", features = ["derive"] } From aa4cdb97ca7e554bfe0c7aa47142f7b5afb03de2 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 19:35:49 +0100 Subject: [PATCH 08/17] chore: bump MSRV to 1.81 --- .github/workflows/ci.yml | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a9ce99a..d551d6e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,7 +55,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - rust: [stable, 1.67] + rust: [stable, 1.81] os: [macos-latest, ubuntu-latest] include: - os: macos-latest diff --git a/Cargo.toml b/Cargo.toml index 7cb77b34..87330619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "A Spotify daemon" repository = "https://github.com/Spotifyd/spotifyd" license = "GPL-3.0-only" version = "0.3.5" -rust-version = "1.74" +rust-version = "1.81" [dependencies] alsa = { version = "0.9.1", optional = true } From f6dabd278629050fd8d9ace69b407c7e99ad98e2 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 20:14:30 +0100 Subject: [PATCH 09/17] discovery: shutdown server properly on abort --- src/main.rs | 2 +- src/main_loop.rs | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index deb36d88..52dcdd17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -209,7 +209,7 @@ fn main() -> eyre::Result<()> { let runtime = Runtime::new().unwrap(); runtime.block_on(async { - let mut initial_state = setup::initial_state(internal_config); + let initial_state = setup::initial_state(internal_config); initial_state.run().await; }); diff --git a/src/main_loop.rs b/src/main_loop.rs index 61dbac7f..073fc0e6 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -62,7 +62,7 @@ impl CredentialsProvider { pub(crate) struct MainLoop { pub(crate) spotifyd_state: SpotifydState, - pub(crate) mixer: Box Arc>, + pub(crate) mixer: Arc, pub(crate) session: Session, pub(crate) player: Arc, pub(crate) has_volume_ctrl: bool, @@ -92,12 +92,12 @@ impl MainLoop { self.session.clone(), creds, self.player.clone(), - (self.mixer)(), + self.mixer.clone(), ) .await } - pub(crate) async fn run(&mut self) { + pub(crate) async fn run(mut self) { tokio::pin! { let ctrl_c = tokio::signal::ctrl_c(); // we don't necessarily have a dbus server @@ -116,6 +116,9 @@ impl MainLoop { 'mainloop: loop { let (spirc, spirc_task) = tokio::select!( _ = &mut ctrl_c => { + if let CredentialsProvider::Discovery(stream) = self.credentials_provider { + let _ = stream.into_inner().shutdown().await; + } break 'mainloop; } spirc = self.get_connection() => { From 748fdf6a3d15304f70d945bbf306d653b03dbb7d Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 20:15:36 +0100 Subject: [PATCH 10/17] audio: fix volume control by only creating one mixer --- src/setup.rs | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/setup.rs b/src/setup.rs index 8f2f3d6b..82086c0e 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -18,12 +18,11 @@ use log::{debug, error, info, warn}; use std::{str::FromStr, sync::Arc, thread, time::Duration}; pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLoop { - let mut mixer = { + let mixer: Arc = { match config.volume_controller { config::VolumeController::None => { info!("Using no volume controller."); - Box::new(|| Arc::new(crate::no_mixer::NoMixer) as Arc) - as Box Arc> + Arc::new(crate::no_mixer::NoMixer) } #[cfg(feature = "alsa_backend")] config::VolumeController::Alsa | config::VolumeController::AlsaLinear => { @@ -35,23 +34,18 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo config.volume_controller, config::VolumeController::AlsaLinear ); - Box::new(move || { - Arc::new(alsa_mixer::AlsaMixer { - device: control_device - .clone() - .or_else(|| audio_device.clone()) - .unwrap_or_else(|| "default".to_string()), - mixer: mixer.clone().unwrap_or_else(|| "Master".to_string()), - linear_scaling: linear, - }) as Arc - }) as Box Arc> + Arc::new(alsa_mixer::AlsaMixer { + device: control_device + .clone() + .or_else(|| audio_device.clone()) + .unwrap_or_else(|| "default".to_string()), + mixer: mixer.clone().unwrap_or_else(|| "Master".to_string()), + linear_scaling: linear, + }) } _ => { info!("Using software volume controller."); - Box::new(move || { - Arc::new(mixer::softmixer::SoftMixer::open(MixerConfig::default())) - as Arc - }) as Box Arc> + Arc::new(mixer::softmixer::SoftMixer::open(MixerConfig::default())) } } }; @@ -134,7 +128,7 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo Player::new( player_config, session.clone(), - mixer().get_soft_volume(), + mixer.get_soft_volume(), move || backend(audio_device, audio_format), ) }; From f70574d26c10ecd51f8f69216680f25c78a28fb0 Mon Sep 17 00:00:00 2001 From: eladyn Date: Fri, 27 Dec 2024 20:38:08 +0100 Subject: [PATCH 11/17] log: silence symphonia info logs --- src/main.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 52dcdd17..a61068c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,9 +43,18 @@ fn setup_logger(log_target: LogTarget, verbose: bool) -> eyre::Result<()> { let mut logger = fern::Dispatch::new().level(log_level); - if cfg!(feature = "dbus_mpris") && !verbose { - logger = logger.level_for("rspotify_http", LevelFilter::Warn); - } + logger = if verbose { + logger.format(|out, message, record| { + out.finish(format_args!( + "[{} {}] {}", + record.level(), + record.target(), + message + )) + }) + } else { + logger.level_for("symphonia_format_ogg::demuxer", LevelFilter::Warn) + }; let logger = match log_target { LogTarget::Terminal => logger.chain(std::io::stdout()), From 310a0faf4d4c2eb3436b4a9b7e5a84f7ab677d1e Mon Sep 17 00:00:00 2001 From: eladyn Date: Sun, 29 Dec 2024 18:19:26 +0100 Subject: [PATCH 12/17] mpris: always return at least mpris:trackid --- src/dbus_mpris.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/dbus_mpris.rs b/src/dbus_mpris.rs index 4dbed434..342e57d8 100644 --- a/src/dbus_mpris.rs +++ b/src/dbus_mpris.rs @@ -238,9 +238,7 @@ impl CurrentStateInner { self.audio_item = Some(audio_item); insert_attr(&mut changed, "Metadata", self.to_metadata()); } - PlayerEvent::Loading { track_id, .. } | PlayerEvent::Preloading { track_id } => { - current_track_id = Some(track_id) - } + PlayerEvent::Loading { track_id, .. } => current_track_id = Some(track_id), PlayerEvent::PositionCorrection { track_id, position_ms, @@ -271,7 +269,8 @@ impl CurrentStateInner { self.repeat.to_mpris().to_string(), ) } - PlayerEvent::TimeToPreloadNextTrack { .. } + PlayerEvent::Preloading { .. } + | PlayerEvent::TimeToPreloadNextTrack { .. } | PlayerEvent::EndOfTrack { .. } | PlayerEvent::Unavailable { .. } | PlayerEvent::PlayRequestIdChanged { .. } @@ -296,13 +295,18 @@ impl CurrentStateInner { fn to_metadata(&self) -> DbusMap { let mut m = HashMap::new(); - if let Some(audio_item) = self.audio_item.as_deref() { - insert_attr( - &mut m, - "mpris:trackid", - uri_to_object_path(audio_item.track_id.to_uri().as_deref().unwrap_or_default()), - ); + insert_attr( + &mut m, + "mpris:trackid", + uri_to_object_path( + self.audio_item + .as_deref() + .and_then(|item| item.track_id.to_uri().ok()) + .as_deref(), + ), + ); + if let Some(audio_item) = self.audio_item.as_deref() { if let Some(length) = Duration::milliseconds(audio_item.duration_ms as i64).num_microseconds() { @@ -808,7 +812,10 @@ fn register_controls_interface(cr: &mut Crossroads, spirc: Arc) { cr.insert(CONTROLS_PATH, &[spotifyd_ctrls_interface], ()); } -fn uri_to_object_path(uri: &str) -> dbus::Path<'static> { +fn uri_to_object_path(uri: Option<&str>) -> dbus::Path<'static> { + let Some(uri) = uri else { + return dbus::Path::new("/org/mpris/MediaPlayer2/TrackList/NoTrack").unwrap(); + }; let mut path = String::with_capacity(uri.len() + 1); for element in uri.split(':') { path.push('/'); From 3bf08791b254063d8e86688d231b4581384abfb0 Mon Sep 17 00:00:00 2001 From: eladyn Date: Sun, 29 Dec 2024 22:12:58 +0100 Subject: [PATCH 13/17] mpris: implement OpenUri for all supported types --- Cargo.lock | 75 +++++++++++++------------- Cargo.toml | 1 + src/dbus_mpris.rs | 131 ++++++++++++++++++++++++++++++++++++++++------ src/main_loop.rs | 3 +- 4 files changed, 156 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5501070f..6b177e3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,7 +152,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -262,7 +262,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.92", + "syn 2.0.93", "which", ] @@ -281,7 +281,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -331,9 +331,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" dependencies = [ "jobserver", "libc", @@ -598,7 +598,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -609,7 +609,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -708,7 +708,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -718,7 +718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -762,7 +762,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -943,7 +943,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -1023,9 +1023,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "governor" @@ -1526,7 +1526,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -2260,7 +2260,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -2322,7 +2322,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -2574,7 +2574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3096,22 +3096,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.216" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3144,7 +3144,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3325,6 +3325,7 @@ dependencies = [ "librespot-discovery", "librespot-metadata", "librespot-playback", + "librespot-protocol", "log", "pledge", "serde", @@ -3485,9 +3486,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.92" +version = "2.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" +checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" dependencies = [ "proc-macro2", "quote", @@ -3508,7 +3509,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3606,7 +3607,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3617,7 +3618,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -3709,7 +3710,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -4074,7 +4075,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", "wasm-bindgen-shared", ] @@ -4109,7 +4110,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4269,7 +4270,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -4280,7 +4281,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -4557,7 +4558,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", "synstructure", ] @@ -4579,7 +4580,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] [[package]] @@ -4599,7 +4600,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", "synstructure", ] @@ -4628,5 +4629,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.92", + "syn 2.0.93", ] diff --git a/Cargo.toml b/Cargo.toml index 87330619..66d3e156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ librespot-core = "0.6" librespot-discovery = "0.6" librespot-connect = "0.6" librespot-metadata = "0.6" +librespot-protocol = "0.6" toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" diff --git a/src/dbus_mpris.rs b/src/dbus_mpris.rs index 342e57d8..84ac7c6c 100644 --- a/src/dbus_mpris.rs +++ b/src/dbus_mpris.rs @@ -13,9 +13,11 @@ use futures::{ task::{Context, Poll}, Future, }; -use librespot_connect::spirc::Spirc; +use librespot_connect::spirc::{Spirc, SpircLoadCommand}; +use librespot_core::{spotify_id::SpotifyItemType, Session, SpotifyId}; use librespot_metadata::audio::AudioItem; use librespot_playback::player::PlayerEvent; +use librespot_protocol::spirc::TrackRef; use log::{error, warn}; use std::convert::TryFrom; use std::{ @@ -25,9 +27,12 @@ use std::{ }; use thiserror::Error; use time::format_description::well_known::Iso8601; -use tokio::sync::{ - mpsc::{UnboundedReceiver, UnboundedSender}, - Mutex, +use tokio::{ + runtime::Handle, + sync::{ + mpsc::{UnboundedReceiver, UnboundedSender}, + Mutex, + }, }; type DbusMap = HashMap>>; @@ -47,9 +52,13 @@ pub(crate) struct DbusServer { } impl DbusServer { - pub fn new(event_rx: UnboundedReceiver, dbus_type: DBusType) -> DbusServer { + pub fn new( + event_rx: UnboundedReceiver, + dbus_type: DBusType, + session: Session, + ) -> DbusServer { let (control_tx, control_rx) = tokio::sync::mpsc::unbounded_channel(); - let dbus_future = Box::pin(create_dbus_server(event_rx, control_rx, dbus_type)); + let dbus_future = Box::pin(create_dbus_server(event_rx, control_rx, dbus_type, session)); DbusServer { dbus_future, control_tx, @@ -149,6 +158,25 @@ impl RepeatState { } } +impl From for bool { + fn from(repeat: RepeatState) -> Self { + match repeat { + RepeatState::None => false, + RepeatState::All => true, + } + } +} + +impl From for RepeatState { + fn from(repeat: bool) -> Self { + if repeat { + RepeatState::All + } else { + RepeatState::None + } + } +} + #[derive(Debug)] struct CurrentStateInner { status: PlaybackStatus, @@ -258,11 +286,7 @@ impl CurrentStateInner { insert_attr(&mut changed, "Shuffle", self.shuffle); } PlayerEvent::RepeatChanged { repeat } => { - self.repeat = if repeat { - RepeatState::All - } else { - RepeatState::None - }; + self.repeat = repeat.into(); insert_attr( &mut changed, "LoopStatus", @@ -392,6 +416,7 @@ async fn create_dbus_server( mut event_rx: UnboundedReceiver, mut control_rx: UnboundedReceiver, dbus_type: DBusType, + session: Session, ) -> Result<(), DbusError> { let (resource, conn) = match dbus_type { DBusType::Session => connection::new_session_sync(), @@ -468,6 +493,7 @@ async fn create_dbus_server( let seeked_fn = register_player_interface( &mut cr, spirc, + session.clone(), current_state.clone(), quit_tx.clone(), ); @@ -551,6 +577,7 @@ type SeekedSignal = Box dbus::Message + Send + S fn register_player_interface( cr: &mut Crossroads, spirc: Arc, + session: Session, current_state: Arc, quit_tx: tokio::sync::mpsc::UnboundedSender<()>, ) -> SeekedSignal { @@ -688,11 +715,83 @@ fn register_player_interface( }, ); - b.method("OpenUri", ("uri",), (), move |_, _, (_,): (String,)| { - warn!("OpenUri is currently not implemented"); - Err::<(), _>(dbus::MethodErr::no_method( - "this method is currently not implemented", - )) + let local_spirc = spirc.clone(); + let local_state = current_state.clone(); + b.method("OpenUri", ("uri",), (), move |_, _, (uri,): (String,)| { + let id = SpotifyId::from_uri(&uri).map_err(|e| MethodErr::invalid_arg(&e))?; + let CurrentStateInner { + shuffle, repeat, .. + } = *local_state.read()?; + + fn id_to_trackref(id: &SpotifyId) -> TrackRef { + let mut trackref = TrackRef::new(); + if let Ok(uri) = id.to_uri() { + trackref.set_uri(uri); + } else { + trackref.set_gid(id.to_raw().to_vec()); + } + trackref + } + + let session = session.clone(); + + let (playing_track_index, context_uri, tracks) = Handle::current() + .block_on(async move { + use librespot_metadata::*; + Ok::<_, librespot_core::Error>(match id.item_type { + SpotifyItemType::Album => { + let album = Album::get(&session, &id).await?; + (0, uri, album.tracks().map(id_to_trackref).collect()) + } + SpotifyItemType::Artist => { + let artist = Artist::get(&session, &id).await?; + ( + 0, + uri, + artist + .top_tracks + .for_country(&session.country()) + .iter() + .map(id_to_trackref) + .collect(), + ) + } + SpotifyItemType::Playlist => { + let playlist = Playlist::get(&session, &id).await?; + (0, uri, playlist.tracks().map(id_to_trackref).collect()) + } + SpotifyItemType::Track => { + let track = Track::get(&session, &id).await?; + ( + track.number as u32, + track.album.id.to_uri()?, + vec![id_to_trackref(&track.id)], + ) + } + SpotifyItemType::Episode => (0, uri, vec![id_to_trackref(&id)]), + SpotifyItemType::Show => { + let show = Show::get(&session, &id).await?; + (0, uri, show.episodes.iter().map(id_to_trackref).collect()) + } + SpotifyItemType::Local | SpotifyItemType::Unknown => { + return Err(librespot_core::Error::unimplemented( + "this type of uri is not supported", + )); + } + }) + }) + .map_err(|e| MethodErr::failed(&e))?; + + local_spirc + .load(SpircLoadCommand { + context_uri, + start_playing: true, + shuffle, + repeat: repeat.into(), + playing_track_index, + tracks, + }) + .map_err(|e| MethodErr::failed(&e)) }); let local_state = current_state.clone(); diff --git a/src/main_loop.rs b/src/main_loop.rs index 073fc0e6..26aa5686 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -107,7 +107,8 @@ impl MainLoop { #[cfg(feature = "dbus_mpris")] let mpris_event_tx = if self.use_mpris { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - *dbus_server.as_mut() = Either::Left(DbusServer::new(rx, self.dbus_type)); + *dbus_server.as_mut() = + Either::Left(DbusServer::new(rx, self.dbus_type, self.session.clone())); Some(tx) } else { None From 83f477f140eb73e0b999b25e710cd7e0ae22a189 Mon Sep 17 00:00:00 2001 From: eladyn Date: Sat, 28 Dec 2024 02:56:43 +0100 Subject: [PATCH 14/17] config: refactor and replace structopt by clap This greatly refactors and simplifies the config parsing. Also, it removes the possiblity to specify user and password, since this has been phased out by Spotify and will be replaced by OAuth. --- Cargo.lock | 226 +++------------ Cargo.toml | 4 +- src/config.rs | 700 +++++++++++++---------------------------------- src/main.rs | 24 +- src/main_loop.rs | 18 +- src/process.rs | 18 -- src/setup.rs | 110 ++------ 7 files changed, 276 insertions(+), 824 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b177e3f..0fc9fc82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,15 +74,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" version = "0.6.18" @@ -161,17 +152,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.4.0" @@ -399,19 +379,44 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", ] +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.93", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + [[package]] name = "cmake" version = "0.1.52" @@ -597,7 +602,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn 2.0.93", ] @@ -646,19 +651,6 @@ dependencies = [ "dbus", ] -[[package]] -name = "dbus-secret-service" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" -dependencies = [ - "dbus", - "futures-util", - "num", - "once_cell", - "rand", -] - [[package]] name = "dbus-tokio" version = "0.7.6" @@ -1115,21 +1107,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hex" @@ -1695,20 +1675,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "keyring" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833" -dependencies = [ - "byteorder", - "dbus-secret-service", - "log", - "security-framework 2.11.1", - "security-framework 3.1.0", - "windows-sys 0.59.0", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -2184,20 +2150,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -2226,15 +2178,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -2283,17 +2226,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -2597,30 +2529,6 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.92" @@ -3306,6 +3214,7 @@ version = "0.3.5" dependencies = [ "alsa", "chrono", + "clap", "color-eyre", "daemonize", "dbus", @@ -3317,7 +3226,6 @@ dependencies = [ "futures", "gethostname", "hex", - "keyring", "libc", "librespot-audio", "librespot-connect", @@ -3330,7 +3238,6 @@ dependencies = [ "pledge", "serde", "sha-1", - "structopt", "syslog", "thiserror 2.0.9", "time", @@ -3347,42 +3254,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "subtle" version = "2.6.1" @@ -3572,15 +3449,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -3903,18 +3771,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "untrusted" version = "0.9.0" @@ -3973,12 +3829,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "vergen" version = "9.0.2" diff --git a/Cargo.toml b/Cargo.toml index 66d3e156..ffd56cee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,10 @@ fern = { version = "0.7.0", features = ["syslog-6"] } futures = "0.3.15" gethostname = "0.5.0" hex = "0.4" -keyring = { version = "3.5", optional = true, features = ["apple-native", "windows-native", "sync-secret-service"] } libc = "0.2.82" log = "0.4.6" serde = { version = "1.0.115", features = ["derive"] } sha-1 = "0.10" -structopt = "0.3.17" tokio = {version = "1.26.0", features = ["signal", "rt-multi-thread", "process", "io-std"] } tokio-stream = "0.1.7" url = "2.2.2" @@ -39,6 +37,7 @@ color-eyre = "0.6" directories = "5.0.1" thiserror = "2.0" time = { version = "0.3.37", default-features = false, features = ["formatting"] } +clap = { version = "4.5.23", features = ["derive"] } [target."cfg(unix)".dependencies] daemonize = "0.5" @@ -55,7 +54,6 @@ env_logger = "0.11" [features] alsa_backend = ["librespot-playback/alsa-backend", "alsa"] -dbus_keyring = ["keyring"] dbus_mpris = ["dbus", "dbus-tokio", "dbus-crossroads"] pipe_backend = [] default = ["alsa_backend", "pipe_backend"] diff --git a/src/config.rs b/src/config.rs index 9c635777..b4035afe 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,147 +1,39 @@ -use crate::{ - error::{Error as CrateError, ParseError}, - process::run_program, - utils, +use crate::utils; +use clap::{ + builder::{IntoResettable, PossibleValuesParser, TypedValueParser, ValueParser}, + Args, Parser, ValueEnum, }; use color_eyre::Report; +use directories::ProjectDirs; use gethostname::gethostname; use librespot_core::{cache::Cache, config::DeviceType as LSDeviceType, config::SessionConfig}; use librespot_playback::{ + audio_backend, config::{AudioFormat as LSAudioFormat, Bitrate as LSBitrate, PlayerConfig}, dither::{mk_ditherer, DithererBuilder, TriangularDitherer}, }; use log::{error, info, warn}; use serde::{de::Error, de::Unexpected, Deserialize, Deserializer}; use sha1::{Digest, Sha1}; -use std::{fmt, fs, path::Path, path::PathBuf, str::FromStr}; -use structopt::{clap::AppSettings, StructOpt}; +use std::{fs, path::Path, path::PathBuf}; use url::Url; const CONFIG_FILE_NAME: &str = "spotifyd.conf"; -#[cfg(not(any( - feature = "pulseaudio_backend", - feature = "portaudio_backend", - feature = "alsa_backend", - feature = "pipe_backend", - feature = "rodio_backend", - feature = "rodiojack_backend", -)))] -compile_error!("At least one of the backend features is required!"); -static BACKEND_VALUES: &[&str] = &[ - #[cfg(feature = "alsa_backend")] - "alsa", - #[cfg(feature = "pulseaudio_backend")] - "pulseaudio", - #[cfg(feature = "portaudio_backend")] - "portaudio", - #[cfg(feature = "rodio_backend")] - "rodio", - #[cfg(feature = "pipe_backend")] - "pipe", - #[cfg(feature = "rodiojack_backend")] - "rodiojack", -]; - -/// The backend used by librespot -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, StructOpt)] -#[serde(rename_all = "lowercase")] -pub enum Backend { - Alsa, - PortAudio, - PulseAudio, - Rodio, - Pipe, - RodioJack, -} - -fn default_backend() -> Backend { - Backend::from_str(BACKEND_VALUES.first().unwrap()).unwrap() -} - -impl FromStr for Backend { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - match s { - "alsa" => Ok(Backend::Alsa), - "portaudio" => Ok(Backend::PortAudio), - "pulseaudio" => Ok(Backend::PulseAudio), - "rodio" => Ok(Backend::Rodio), - "pipe" => Ok(Backend::Pipe), - "rodiojack" => Ok(Backend::RodioJack), - _ => unreachable!(), - } - } -} - -impl fmt::Display for Backend { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Backend::Alsa => write!(f, "alsa"), - Backend::PortAudio => write!(f, "portaudio"), - Backend::PulseAudio => write!(f, "pulseaudio"), - Backend::Rodio => write!(f, "rodio"), - Backend::Pipe => write!(f, "pipe"), - Backend::RodioJack => write!(f, "rodiojack"), - } - } -} - -static VOLUME_CONTROLLER_VALUES: &[&str] = &[ - "softvol", - #[cfg(feature = "alsa_backend")] - "alsa", - #[cfg(feature = "alsa_backend")] - "alsa_linear", - "none", -]; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, StructOpt)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, ValueEnum)] #[serde(rename_all = "snake_case")] pub enum VolumeController { + #[cfg(feature = "alsa_backend")] Alsa, + #[cfg(feature = "alsa_backend")] AlsaLinear, #[serde(rename = "softvol")] SoftVolume, None, } -impl FromStr for VolumeController { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - match s { - "alsa" => Ok(VolumeController::Alsa), - "alsa_linear" => Ok(VolumeController::AlsaLinear), - "softvol" => Ok(VolumeController::SoftVolume), - "none" => Ok(VolumeController::None), - _ => unreachable!(), - } - } -} - -static DEVICETYPE_VALUES: &[&str] = &[ - "computer", - "tablet", - "smartphone", - "speaker", - "tv", - "avr", - "stb", - "audiodongle", - "gameconsole", - "castaudio", - "castvideo", - "automobile", - "smartwatch", - "chromebook", - "carthing", - "homething", -]; - // Spotify's device type (copied from it's config.rs) -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, StructOpt)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, ValueEnum)] #[serde(rename_all = "snake_case")] pub enum DeviceType { Unknown, @@ -168,34 +60,8 @@ pub enum DeviceType { HomeThing, } -impl From for DeviceType { - fn from(item: LSDeviceType) -> Self { - match item { - LSDeviceType::Unknown => DeviceType::Unknown, - LSDeviceType::Computer => DeviceType::Computer, - LSDeviceType::Tablet => DeviceType::Tablet, - LSDeviceType::Smartphone => DeviceType::Smartphone, - LSDeviceType::Speaker => DeviceType::Speaker, - LSDeviceType::Tv => DeviceType::Tv, - LSDeviceType::Avr => DeviceType::Avr, - LSDeviceType::Stb => DeviceType::Stb, - LSDeviceType::AudioDongle => DeviceType::AudioDongle, - LSDeviceType::GameConsole => DeviceType::GameConsole, - LSDeviceType::CastAudio => DeviceType::CastAudio, - LSDeviceType::CastVideo => DeviceType::CastVideo, - LSDeviceType::Automobile => DeviceType::Automobile, - LSDeviceType::Smartwatch => DeviceType::Smartwatch, - LSDeviceType::Chromebook => DeviceType::Chromebook, - LSDeviceType::UnknownSpotify => DeviceType::UnknownSpotify, - LSDeviceType::CarThing => DeviceType::CarThing, - LSDeviceType::Observer => DeviceType::Observer, - LSDeviceType::HomeThing => DeviceType::HomeThing, - } - } -} - -impl From<&DeviceType> for LSDeviceType { - fn from(item: &DeviceType) -> Self { +impl From for LSDeviceType { + fn from(item: DeviceType) -> Self { match item { DeviceType::Unknown => LSDeviceType::Unknown, DeviceType::Computer => LSDeviceType::Computer, @@ -220,26 +86,18 @@ impl From<&DeviceType> for LSDeviceType { } } -impl FromStr for DeviceType { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - let dt = LSDeviceType::from_str(s).unwrap(); - Ok(dt.into()) - } +fn bitrate_parser() -> impl IntoResettable { + let possible_values: PossibleValuesParser = ["96", "160", "320"].into(); + possible_values.map(|val| match val.as_str() { + "96" => Bitrate::Bitrate96, + "160" => Bitrate::Bitrate160, + "320" => Bitrate::Bitrate320, + _ => unreachable!(), + }) } -impl fmt::Display for DeviceType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let dt: LSDeviceType = self.into(); - write!(f, "{dt}") - } -} - -static BITRATE_VALUES: &[&str] = &["96", "160", "320"]; - /// Spotify's audio bitrate -#[derive(Clone, Copy, Debug, PartialEq, Eq, StructOpt)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)] pub enum Bitrate { Bitrate96, Bitrate160, @@ -261,19 +119,6 @@ impl<'de> Deserialize<'de> for Bitrate { } } -impl FromStr for Bitrate { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - match s { - "96" => Ok(Bitrate::Bitrate96), - "160" => Ok(Bitrate::Bitrate160), - "320" => Ok(Bitrate::Bitrate320), - _ => unreachable!(), - } - } -} - impl From for LSBitrate { fn from(bitrate: Bitrate) -> Self { match bitrate { @@ -284,41 +129,14 @@ impl From for LSBitrate { } } -#[cfg(feature = "dbus_mpris")] -static DBUSTYPE_VALUES: &[&str] = &["session", "system"]; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, StructOpt)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, ValueEnum)] #[serde(rename_all = "snake_case")] pub enum DBusType { Session, System, } -impl FromStr for DBusType { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - match s { - "session" => Ok(DBusType::Session), - "system" => Ok(DBusType::System), - _ => unreachable!(), - } - } -} - -impl fmt::Display for DBusType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - DBusType::Session => write!(f, "session"), - DBusType::System => write!(f, "system"), - } - } -} - -/// LibreSpot supported audio formats -static AUDIO_FORMAT_VALUES: &[&str] = &["F32", "S32", "S24", "S24_3", "S16"]; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, StructOpt)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, ValueEnum)] pub enum AudioFormat { F32, S32, @@ -327,33 +145,6 @@ pub enum AudioFormat { S16, } -impl FromStr for AudioFormat { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - match s { - "F32" => Ok(AudioFormat::F32), - "S32" => Ok(AudioFormat::S32), - "S24" => Ok(AudioFormat::S24), - "S24_3" => Ok(AudioFormat::S24_3), - "S16" => Ok(AudioFormat::S16), - _ => unreachable!(), - } - } -} - -impl fmt::Display for AudioFormat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - AudioFormat::F32 => write!(f, "F32"), - AudioFormat::S32 => write!(f, "S32"), - AudioFormat::S24 => write!(f, "S24"), - AudioFormat::S24_3 => write!(f, "S24_3"), - AudioFormat::S16 => write!(f, "S16"), - } - } -} - impl From for LSAudioFormat { fn from(audio_format: AudioFormat) -> Self { match audio_format { @@ -366,177 +157,176 @@ impl From for LSAudioFormat { } } -#[derive(Debug, Default, StructOpt)] -#[structopt( - about = "A Spotify daemon", - author, - name = "spotifyd", - setting(AppSettings::ColoredHelp) -)] +fn possible_backends() -> Vec<&'static str> { + audio_backend::BACKENDS.iter().map(|b| b.0).collect() +} + +#[derive(Debug, Default, Parser)] +#[command(version, about, long_about = None)] pub struct CliConfig { /// The path to the config file to use - #[structopt(long, value_name = "string")] + #[arg(long, value_name = "PATH")] pub config_path: Option, /// If set, starts spotifyd without detaching - #[structopt(long)] + #[arg(long)] pub no_daemon: bool, /// Prints more verbose output - #[structopt(long)] - pub verbose: bool, + #[arg(short, long, action = clap::ArgAction::Count)] + pub verbose: u8, /// Path to PID file. - #[structopt(long)] + #[cfg(unix)] + #[arg(long, value_name = "PATH")] pub pid: Option, - #[structopt(flatten)] + #[command(flatten)] pub shared_config: SharedConfigValues, } // A struct that holds all allowed config fields. // The actual config file is made up of two sections, spotifyd and global. -#[derive(Clone, Default, Deserialize, PartialEq, StructOpt)] +#[derive(Clone, Default, Debug, Deserialize, PartialEq, Args)] pub struct SharedConfigValues { - /// The Spotify account user name - #[structopt(conflicts_with = "username_cmd", long, short, value_name = "string")] - username: Option, - - /// A command that can be used to retrieve the Spotify account username - #[structopt( - conflicts_with = "username", - long, - short = "U", - value_name = "string", - visible_alias = "username_cmd" - )] - username_cmd: Option, - - /// The Spotify account password - #[structopt(conflicts_with = "password_cmd", long, short, value_name = "string")] - password: Option, - - /// Enables keyring password access - #[cfg_attr( - feature = "dbus_keyring", - structopt(long), - serde(alias = "use-keyring", default) - )] - #[cfg_attr(not(feature = "dbus_keyring"), structopt(skip), serde(skip))] - use_keyring: bool, - - /// Enables the MPRIS interface - #[cfg_attr( - feature = "dbus_mpris", - structopt(long), - serde(alias = "use-mpris", default) - )] - #[cfg_attr(not(feature = "dbus_mpris"), structopt(skip), serde(skip))] - use_mpris: Option, - - /// The Bus-type to use for the MPRIS interface - #[cfg_attr( - feature = "dbus_mpris", - structopt(long, possible_values = &DBUSTYPE_VALUES, value_name = "string") - )] - #[cfg_attr(not(feature = "dbus_mpris"), structopt(skip), serde(skip))] - dbus_type: Option, - - /// A command that can be used to retrieve the Spotify account password - #[structopt( - conflicts_with = "password", - long, - short = "P", - value_name = "string", - visible_alias = "password_cmd" - )] - password_cmd: Option, - - /// Whether the credentials should be debugged. - #[structopt(long)] - #[serde(skip)] - debug_credentials: bool, - /// A script that gets evaluated in the user's shell when the song changes - #[structopt(visible_alias = "onevent", long, value_name = "string")] + #[arg(visible_alias = "onevent", long, value_name = "CMD")] #[serde(alias = "onevent")] on_song_change_hook: Option, /// The cache path used to store credentials and music file artifacts - #[structopt(long, parse(from_os_str), short, value_name = "string")] + #[arg(long, short, value_name = "PATH")] cache_path: Option, /// The maximal cache size in bytes - #[structopt(long)] + #[arg(long, value_name = "BYTES")] max_cache_size: Option, /// Disable the use of audio cache - #[structopt(long)] - #[serde(default)] - no_audio_cache: bool, + #[arg( + long, + default_missing_value("true"), + require_equals = true, + num_args(0..=1), + value_name = "BOOL" + )] + no_audio_cache: Option, /// The audio backend to use - #[structopt(long, short, possible_values = &BACKEND_VALUES, value_name = "string")] - backend: Option, + #[arg(long, short, value_parser = possible_backends())] + backend: Option, /// The volume controller to use - #[structopt(long, short, possible_values = &VOLUME_CONTROLLER_VALUES, visible_alias = "volume-control")] + #[arg(value_enum, long, visible_alias = "volume-control")] #[serde(alias = "volume-control")] volume_controller: Option, - /// The audio device (or file handle if using pipe backend) - #[structopt(long, value_name = "string")] + /// The audio device (or pipe file) + #[arg(long)] device: Option, - /// The control device - #[structopt(long, value_name = "string")] - control: Option, - - /// The mixer to use - #[structopt(long, value_name = "string")] - mixer: Option, - /// The device name displayed in Spotify - #[structopt(long, short, value_name = "string")] + #[arg(long, short)] device_name: Option, /// The bitrate of the streamed audio data - #[structopt(long, short = "B", possible_values = &BITRATE_VALUES, value_name = "number")] + #[arg(long, short = 'B', value_parser = bitrate_parser())] bitrate: Option, /// The audio format of the streamed audio data - #[structopt(long, possible_values = &AUDIO_FORMAT_VALUES, value_name = "string")] + #[arg(value_enum, long)] audio_format: Option, /// Initial volume between 0 and 100 - #[structopt(long, value_name = "initial_volume")] - initial_volume: Option, + #[arg(long)] + initial_volume: Option, /// Enable to normalize the volume during playback - #[structopt(long)] - #[serde(default)] - volume_normalisation: bool, + #[arg( + long, + default_missing_value("true"), + require_equals = true, + num_args(0..=1), + value_name = "BOOL" + )] + volume_normalisation: Option, /// A custom pregain applied before sending the audio to the output device - #[structopt(long, value_name = "number")] + #[arg(long)] normalisation_pregain: Option, + #[arg( + long, + default_missing_value("true"), + require_equals = true, + num_args(0..=1), + value_name = "BOOL" + )] + disable_discovery: Option, + /// The port used for the Spotify Connect discovery - #[structopt(long, value_name = "number")] + #[arg(long)] zeroconf_port: Option, /// The proxy used to connect to spotify's servers - #[structopt(long, value_name = "string")] + #[arg(long, value_name = "URL")] proxy: Option, /// The device type shown to clients - #[structopt(long, possible_values = &DEVICETYPE_VALUES, value_name = "string")] + #[arg(value_enum, long)] device_type: Option, /// Start playing similar songs after your music has ended - #[structopt(long)] + #[arg( + long, + default_missing_value("true"), + require_equals = true, + num_args(0..=1), + value_name = "BOOL" + )] #[serde(default)] - autoplay: bool, + autoplay: Option, + + #[cfg(feature = "alsa_backend")] + #[command(flatten)] + #[serde(flatten)] + alsa_config: AlsaConfig, + + #[cfg(feature = "dbus_mpris")] + #[command(flatten)] + #[serde(flatten)] + mpris_config: MprisConfig, +} + +#[cfg(feature = "dbus_mpris")] +#[derive(Debug, Default, Clone, Deserialize, Args, PartialEq, Eq)] +pub struct MprisConfig { + /// Enables the MPRIS interface + #[arg( + long, + default_missing_value("true"), + require_equals = true, + num_args(0..=1), + value_name = "BOOL" + )] + #[serde(alias = "use-mpris")] + pub(crate) use_mpris: Option, + + /// The Bus-type to use for the MPRIS interface + #[arg(value_enum, long)] + pub(crate) dbus_type: Option, +} + +#[cfg(feature = "alsa_backend")] +#[derive(Debug, Default, Clone, Deserialize, Args, PartialEq, Eq)] +pub struct AlsaConfig { + /// The control device + #[arg(long)] + pub(crate) control: Option, + + /// The mixer to use + #[arg(long)] + pub(crate) mixer: Option, } #[derive(Debug, Default, Deserialize)] @@ -547,84 +337,13 @@ pub struct FileConfig { impl FileConfig { pub fn get_merged_sections(self) -> Option { - let global_config_section = self.global; - let spotifyd_config_section = self.spotifyd; - - let merged_config: Option; - // First merge the two sections together. The spotifyd has priority over global - // section. - if let Some(mut spotifyd_section) = spotifyd_config_section { - // spotifyd section exists. Try to merge it with global section. - #[allow(clippy::branches_sharing_code)] - if let Some(global_section) = global_config_section { - spotifyd_section.merge_with(global_section); - merged_config = Some(spotifyd_section); - } else { - // There is no global section. Just use the spotifyd section. - merged_config = Some(spotifyd_section); + match (self.global, self.spotifyd) { + (Some(global), Some(mut spotifyd)) => { + spotifyd.merge_with(global); + Some(spotifyd) } - } else { - // No spotifyd config available. Check for global and use that, if both are - // none, use none. - merged_config = global_config_section; - } - - merged_config - } -} - -impl fmt::Debug for SharedConfigValues { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let placeholder = "taken out for privacy"; - - macro_rules! extract_credential { - ( $e:expr ) => { - match $e { - Some(s) => match self.debug_credentials { - true => Some(s.as_str()), - false => Some(placeholder), - }, - None => None, - } - }; + (global, spotifyd) => global.or(spotifyd), } - - let password_value = extract_credential!(&self.password); - - let password_cmd_value = extract_credential!(&self.password_cmd); - - let username_value = extract_credential!(&self.username); - - let username_cmd_value = extract_credential!(&self.username_cmd); - - f.debug_struct("SharedConfigValues") - .field("username", &username_value) - .field("username_cmd", &username_cmd_value) - .field("password", &password_value) - .field("password_cmd", &password_cmd_value) - .field("use_keyring", &self.use_keyring) - .field("use_mpris", &self.use_mpris) - .field("dbus_type", &self.dbus_type) - .field("on_song_change_hook", &self.on_song_change_hook) - .field("cache_path", &self.cache_path) - .field("no-audio-cache", &self.no_audio_cache) - .field("backend", &self.backend) - .field("volume_controller", &self.volume_controller) - .field("device", &self.device) - .field("control", &self.control) - .field("mixer", &self.mixer) - .field("device_name", &self.device_name) - .field("bitrate", &self.bitrate) - .field("audio_format", &self.audio_format) - .field("initial_volume", &self.initial_volume) - .field("volume_normalisation", &self.volume_normalisation) - .field("normalisation_pregain", &self.normalisation_pregain) - .field("zeroconf_port", &self.zeroconf_port) - .field("proxy", &self.proxy) - .field("device_type", &self.device_type) - .field("autoplay", &self.autoplay) - .field("max_cache_size", &self.max_cache_size) - .finish() } } @@ -659,52 +378,46 @@ impl CliConfig { } impl SharedConfigValues { - pub fn merge_with(&mut self, other: SharedConfigValues) { + pub fn merge_with(&mut self, mut other: SharedConfigValues) { macro_rules! merge { - ($($x:ident),+) => { - $(self.$x = self.$x.clone().or_else(|| other.$x.clone());)+ + ($a:expr; and $b:expr => {$($x:ident),+}) => { + $($a.$x = $a.$x.take().or_else(|| $b.$x.take());)+ } } // Handles Option merging. - merge!( + merge!(self; and other => { backend, - username, - username_cmd, - password, - password_cmd, + volume_normalisation, normalisation_pregain, bitrate, initial_volume, device_name, - mixer, - control, device, volume_controller, cache_path, + no_audio_cache, on_song_change_hook, + disable_discovery, zeroconf_port, proxy, device_type, - use_mpris, max_cache_size, - dbus_type, - audio_format - ); - - // Handles boolean merging. - self.use_keyring |= other.use_keyring; - self.volume_normalisation |= other.volume_normalisation; - self.no_audio_cache |= other.no_audio_cache; - self.autoplay |= other.autoplay; + audio_format, + autoplay + }); + + #[cfg(feature = "dbus_mpris")] + merge!(self.mpris_config; and other.mpris_config => {use_mpris, dbus_type}); + #[cfg(feature = "alsa_backend")] + merge!(self.alsa_config; and other.alsa_config => {mixer, control}); } } pub(crate) fn get_config_file() -> Option { let etc_conf = format!("/etc/{}", CONFIG_FILE_NAME); - let dirs = directories::BaseDirs::new()?; + let dirs = directories::ProjectDirs::from("", "", "spotifyd")?; let mut path = dirs.config_dir().to_path_buf(); - path.push("spotifyd"); path.push(CONFIG_FILE_NAME); if path.exists() { @@ -722,41 +435,42 @@ fn device_id(name: &str) -> String { } pub(crate) struct SpotifydConfig { - pub(crate) username: Option, - pub(crate) password: Option, - #[allow(unused)] - pub(crate) use_keyring: bool, - pub(crate) use_mpris: bool, - pub(crate) dbus_type: DBusType, pub(crate) cache: Option, pub(crate) backend: Option, pub(crate) audio_device: Option, pub(crate) audio_format: LSAudioFormat, - #[allow(unused)] - pub(crate) control_device: Option, - #[allow(unused)] - pub(crate) mixer: Option, - #[allow(unused)] pub(crate) volume_controller: VolumeController, pub(crate) initial_volume: Option, pub(crate) device_name: String, pub(crate) player_config: PlayerConfig, pub(crate) session_config: SessionConfig, pub(crate) onevent: Option, - #[allow(unused)] + #[cfg(unix)] pub(crate) pid: Option, pub(crate) shell: String, + pub(crate) discovery: bool, pub(crate) zeroconf_port: Option, - pub(crate) device_type: String, + pub(crate) device_type: LSDeviceType, + #[cfg(feature = "dbus_mpris")] + pub(crate) mpris: MprisConfig, + #[cfg(feature = "alsa_backend")] + pub(crate) alsa_config: AlsaConfig, } pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { - let audio_cache = !config.shared_config.no_audio_cache; + let audio_cache = !config.shared_config.no_audio_cache.unwrap_or(false); let size_limit = config.shared_config.max_cache_size; let cache = config .shared_config .cache_path + .or_else(|| { + ProjectDirs::from("", "", "spotifyd").map(|dirs| dirs.cache_dir().to_path_buf()) + }) + .or_else(|| { + warn!("failed to determine cache directory, please specify one manually!"); + None + }) .map(|path| { Cache::new( Some(&path), @@ -783,12 +497,6 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { .unwrap_or(AudioFormat::S16) .into(); - let backend = config - .shared_config - .backend - .unwrap_or_else(default_backend) - .to_string(); - let volume_controller = config .shared_config .volume_controller @@ -797,14 +505,15 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { let initial_volume: Option = config .shared_config .initial_volume - .and_then(|input| match input.parse::() { - Ok(v) if (0..=100).contains(&v) => Some(v), - _ => { - warn!("Could not parse initial_volume (must be in the range 0-100)"); - None + .filter(|val| { + if (0..=100).contains(val) { + true + } else { + warn!("initial_volume must be in range 0..100"); + false } }) - .map(|volume| (volume as i32 * 0xFFFF / 100) as u16); + .map(|volume| (volume as i32 * (u16::MAX as i32) / 100) as u16); let device_name = config .shared_config @@ -816,15 +525,13 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { let normalisation_pregain = config.shared_config.normalisation_pregain.unwrap_or(0.0); - let dbus_type = config.shared_config.dbus_type.unwrap_or(DBusType::Session); - let autoplay = config.shared_config.autoplay; - let device_type = config .shared_config .device_type .unwrap_or(DeviceType::Speaker) - .to_string(); + .into(); + #[cfg(unix)] let pid = config.pid.map(|f| { f.into_os_string() .into_string() @@ -836,30 +543,6 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { "sh".to_string() }); - let mut username = config.shared_config.username; - if username.is_none() { - info!("No username specified. Checking username_cmd"); - match config.shared_config.username_cmd { - Some(ref cmd) => match run_program(&shell, cmd) { - Ok(s) => username = Some(s.trim().to_string()), - Err(e) => error!("{}", CrateError::subprocess_with_err(&shell, cmd, e)), - }, - None => info!("No username_cmd specified"), - } - } - - let mut password = config.shared_config.password; - if password.is_none() { - info!("No password specified. Checking password_cmd"); - - match config.shared_config.password_cmd { - Some(ref cmd) => match run_program(&shell, cmd) { - Ok(s) => password = Some(s.trim().to_string()), - Err(e) => error!("{}", CrateError::subprocess_with_err(&shell, cmd, e)), - }, - None => info!("No password_cmd specified"), - } - } let mut proxy_url = None; match config.shared_config.proxy { Some(s) => match Url::parse(&s) { @@ -888,7 +571,7 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { // should consider adding them to Spotifyd's config system. let pc = PlayerConfig { bitrate, - normalisation: config.shared_config.volume_normalisation, + normalisation: config.shared_config.volume_normalisation.unwrap_or(false), normalisation_pregain_db: normalisation_pregain, gapless: true, ditherer, @@ -896,33 +579,32 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { }; SpotifydConfig { - username, - password, - use_keyring: config.shared_config.use_keyring, - use_mpris: config.shared_config.use_mpris.unwrap_or(true), - dbus_type, cache, - backend: Some(backend), + backend: config.shared_config.backend, audio_device: config.shared_config.device, audio_format, - control_device: config.shared_config.control, - mixer: config.shared_config.mixer, volume_controller, initial_volume, device_name, player_config: pc, session_config: SessionConfig { - autoplay: Some(autoplay), + autoplay: config.shared_config.autoplay, device_id, proxy: proxy_url, ap_port: Some(443), ..Default::default() }, onevent: config.shared_config.on_song_change_hook, - pid, shell, + discovery: !config.shared_config.disable_discovery.unwrap_or(false), zeroconf_port: config.shared_config.zeroconf_port, device_type, + #[cfg(unix)] + pid, + #[cfg(feature = "dbus_mpris")] + mpris: config.shared_config.mpris_config, + #[cfg(feature = "alsa_backend")] + alsa_config: config.shared_config.alsa_config, } } @@ -933,12 +615,12 @@ mod tests { #[test] fn test_section_merging() { let mut spotifyd_section = SharedConfigValues { - password: Some("123456".to_string()), + device_type: Some(DeviceType::Computer), ..Default::default() }; let global_section = SharedConfigValues { - username: Some("testUserName".to_string()), + device_name: Some("spotifyd-test".to_string()), ..Default::default() }; @@ -952,15 +634,7 @@ mod tests { let merged_config = file_config.get_merged_sections().unwrap(); // Add the new field to spotifyd section. - spotifyd_section.username = Some("testUserName".to_string()); + spotifyd_section.device_name = Some("spotifyd-test".to_string()); assert_eq!(merged_config, spotifyd_section); } - #[test] - fn test_default_backend() { - let spotifyd_config = get_internal_config(CliConfig::default()); - assert_eq!( - spotifyd_config.backend.unwrap(), - default_backend().to_string() - ); - } } diff --git a/src/main.rs b/src/main.rs index a61068c1..941f2e6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use crate::config::CliConfig; +use clap::Parser; #[cfg(unix)] use color_eyre::eyre::eyre; use color_eyre::{ @@ -14,7 +15,6 @@ use log::{info, trace, LevelFilter}; use pledge::pledge; #[cfg(windows)] use std::fs; -use structopt::StructOpt; use tokio::runtime::Runtime; #[cfg(feature = "alsa_backend")] @@ -34,16 +34,15 @@ enum LogTarget { Syslog, } -fn setup_logger(log_target: LogTarget, verbose: bool) -> eyre::Result<()> { - let log_level = if verbose { - LevelFilter::Trace - } else { - LevelFilter::Info +fn setup_logger(log_target: LogTarget, verbose: u8) -> eyre::Result<()> { + let log_level = match verbose { + 0 => LevelFilter::Info, + 1 => LevelFilter::Debug, + 2.. => LevelFilter::Trace, }; - let mut logger = fern::Dispatch::new().level(log_level); - logger = if verbose { + logger = if verbose > 0 { logger.format(|out, message, record| { out.finish(format_args!( "[{} {}] {}", @@ -107,7 +106,7 @@ fn main() -> eyre::Result<()> { color_eyre::install().wrap_err("Couldn't initialize error reporting")?; - let mut cli_config: CliConfig = CliConfig::from_args(); + let mut cli_config = CliConfig::parse(); let is_daemon = !cli_config.no_daemon; @@ -218,9 +217,8 @@ fn main() -> eyre::Result<()> { let runtime = Runtime::new().unwrap(); runtime.block_on(async { - let initial_state = setup::initial_state(internal_config); + let initial_state = setup::initial_state(internal_config)?; initial_state.run().await; - }); - - Ok(()) + Ok(()) + }) } diff --git a/src/main_loop.rs b/src/main_loop.rs index 26aa5686..b629831c 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -1,4 +1,5 @@ -use crate::config::DBusType; +#[cfg(feature = "dbus_mpris")] +use crate::config::{DBusType, MprisConfig}; #[cfg(feature = "dbus_mpris")] use crate::dbus_mpris::DbusServer; use crate::process::spawn_program_on_event; @@ -69,11 +70,9 @@ pub(crate) struct MainLoop { pub(crate) initial_volume: Option, pub(crate) shell: String, pub(crate) device_type: DeviceType, - #[cfg_attr(not(feature = "dbus_mpris"), allow(unused))] - pub(crate) use_mpris: bool, - #[cfg_attr(not(feature = "dbus_mpris"), allow(unused))] - pub(crate) dbus_type: DBusType, pub(crate) credentials_provider: CredentialsProvider, + #[cfg(feature = "dbus_mpris")] + pub(crate) mpris_config: MprisConfig, } impl MainLoop { @@ -105,10 +104,13 @@ impl MainLoop { } #[cfg(feature = "dbus_mpris")] - let mpris_event_tx = if self.use_mpris { + let mpris_event_tx = if self.mpris_config.use_mpris.unwrap_or(true) { let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - *dbus_server.as_mut() = - Either::Left(DbusServer::new(rx, self.dbus_type, self.session.clone())); + *dbus_server.as_mut() = Either::Left(DbusServer::new( + rx, + self.mpris_config.dbus_type.unwrap_or(DBusType::Session), + self.session.clone(), + )); Some(tx) } else { None diff --git a/src/process.rs b/src/process.rs index 39d92ac4..3d781e6c 100644 --- a/src/process.rs +++ b/src/process.rs @@ -8,24 +8,6 @@ use tokio::{ process::{self, Command}, }; -/// Blocks while provided command is run in a subprocess using the provided -/// shell. If successful, returns the contents of the subprocess's `stdout` as a -/// `String`. -pub(crate) fn run_program(shell: &str, cmd: &str) -> Result { - info!("Running {:?} using {:?}", cmd, shell); - let output = std::process::Command::new(shell) - .arg("-c") - .arg(cmd) - .output() - .map_err(|e| Error::subprocess_with_err(shell, cmd, e))?; - if !output.status.success() { - let s = std::str::from_utf8(&output.stderr).map_err(|_| Error::subprocess(shell, cmd))?; - return Err(Error::subprocess_with_str(shell, cmd, s)); - } - let s = String::from_utf8(output.stdout).map_err(|_| Error::subprocess(shell, cmd))?; - Ok(s) -} - /// Spawns provided command in a subprocess using the provided shell. fn spawn_program(shell: &str, cmd: &str, env: HashMap<&str, String>) -> Result { info!( diff --git a/src/setup.rs b/src/setup.rs index 82086c0e..5fe5b2aa 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -4,20 +4,23 @@ use crate::{ config, main_loop::{self, CredentialsProvider}, }; -#[cfg(feature = "dbus_keyring")] -use keyring::Entry; -use librespot_core::{authentication::Credentials, cache::Cache, config::DeviceType, Session}; +use color_eyre::{ + eyre::{eyre, Context}, + Section, +}; +use librespot_core::Session; use librespot_playback::{ - audio_backend::{Sink, BACKENDS}, - config::AudioFormat, + audio_backend::{self}, mixer::{self, Mixer}, }; use librespot_playback::{mixer::MixerConfig, player::Player}; #[allow(unused_imports)] // cfg use log::{debug, error, info, warn}; -use std::{str::FromStr, sync::Arc, thread, time::Duration}; +use std::{sync::Arc, thread, time::Duration}; -pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLoop { +pub(crate) fn initial_state( + config: config::SpotifydConfig, +) -> color_eyre::Result { let mixer: Arc = { match config.volume_controller { config::VolumeController::None => { @@ -27,8 +30,8 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo #[cfg(feature = "alsa_backend")] config::VolumeController::Alsa | config::VolumeController::AlsaLinear => { let audio_device = config.audio_device.clone(); - let control_device = config.control_device.clone(); - let mixer = config.mixer.clone(); + let control_device = config.alsa_config.control.clone(); + let mixer = config.alsa_config.mixer.clone(); info!("Using alsa volume controller."); let linear = matches!( config.volume_controller, @@ -59,34 +62,10 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo let zeroconf_port = config.zeroconf_port.unwrap_or(0); - let device_type: DeviceType = DeviceType::from_str(&config.device_type).unwrap_or_default(); - - let username = config.username; - #[allow(unused_mut)] // mut is needed behind the dbus_keyring flag. - let mut password = config.password; - - #[cfg(feature = "dbus_keyring")] - if config.use_keyring { - match (&username, &password) { - (None, _) => warn!("Can't query the keyring without a username"), - (Some(_), Some(_)) => { - info!("Keyring is ignored, since you already configured a password") - } - (Some(username), None) => { - info!("Checking keyring for password"); - let entry = Entry::new("spotifyd", username); - match entry.and_then(|e| e.get_password()) { - Ok(retrieved_password) => password = Some(retrieved_password), - Err(e) => error!("Keyring did not return any results: {e}"), - } - } - } - } - let credentials_provider = - if let Some(credentials) = get_credentials(&cache, &username, &password) { + if let Some(credentials) = cache.as_ref().and_then(|c| c.credentials()) { CredentialsProvider::SpotifyCredentials(credentials) - } else { + } else if config.discovery { info!("no usable credentials found, enabling discovery"); debug!("Using device id '{}'", session_config.device_id); const RETRY_MAX: u8 = 4; @@ -98,7 +77,7 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo session_config.client_id.clone(), ) .name(config.device_name.clone()) - .device_type(device_type) + .device_type(config.device_type) .port(zeroconf_port) .launch() { @@ -106,7 +85,9 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo Err(err) => { error!("failed to enable discovery: {err}"); if retry_counter >= RETRY_MAX { - panic!("failed to enable discovery (and no credentials provided)"); + return Err(err).with_context(|| { + "failed to enable discovery (and no credentials provided)" + }); } info!("retrying discovery in {} seconds", backoff.as_secs()); thread::sleep(backoff); @@ -117,9 +98,14 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo } }; discovery_stream.into() + } else { + return Err(eyre!( + "no cached credentials available and discovery disabled" + )) + .with_suggestion(|| "consider enabling discovery or authenticating via OAuth"); }; - let backend = find_backend(backend.as_ref().map(String::as_ref)); + let backend = audio_backend::find(backend).expect("available backends should match ours"); let session = Session::new(session_config, cache); let player = { @@ -133,7 +119,7 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo ) }; - main_loop::MainLoop { + Ok(main_loop::MainLoop { credentials_provider, mixer, spotifyd_state: main_loop::SpotifydState { @@ -145,46 +131,8 @@ pub(crate) fn initial_state(config: config::SpotifydConfig) -> main_loop::MainLo initial_volume: config.initial_volume, has_volume_ctrl, shell: config.shell, - device_type, - use_mpris: config.use_mpris, - dbus_type: config.dbus_type, - } -} - -fn get_credentials( - cache: &Option, - username: &Option, - password: &Option, -) -> Option { - if let Some(credentials) = cache.as_ref().and_then(Cache::credentials) { - if Option::zip(username.as_deref(), credentials.username.as_deref()) - .is_some_and(|(user_config, user_cached)| user_config == user_cached) - { - return Some(credentials); - } - } - - Some(Credentials::with_password( - username.as_ref()?, - password.as_ref()?, - )) -} - -fn find_backend(name: Option<&str>) -> fn(Option, AudioFormat) -> Box { - match name { - Some(name) => { - BACKENDS - .iter() - .find(|backend| name == backend.0) - .unwrap_or_else(|| panic!("Unknown backend: {}.", name)) - .1 - } - None => { - let &(name, back) = BACKENDS - .first() - .expect("No backends were enabled at build time"); - info!("No backend specified, defaulting to: {}.", name); - back - } - } + device_type: config.device_type, + #[cfg(feature = "dbus_mpris")] + mpris_config: config.mpris, + }) } From f93a6f31f3c25ed0eb72f417c176eeabf97c98e1 Mon Sep 17 00:00:00 2001 From: eladyn Date: Mon, 30 Dec 2024 02:03:43 +0100 Subject: [PATCH 15/17] config: allow both number and string for initial_volume --- src/config.rs | 184 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 53 deletions(-) diff --git a/src/config.rs b/src/config.rs index b4035afe..83d6550a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,12 @@ use crate::utils; use clap::{ builder::{IntoResettable, PossibleValuesParser, TypedValueParser, ValueParser}, - Args, Parser, ValueEnum, + Args, Parser, Subcommand, ValueEnum, +}; +use color_eyre::{ + eyre::{bail, Context}, + Report, }; -use color_eyre::Report; use directories::ProjectDirs; use gethostname::gethostname; use librespot_core::{cache::Cache, config::DeviceType as LSDeviceType, config::SessionConfig}; @@ -12,10 +15,19 @@ use librespot_playback::{ config::{AudioFormat as LSAudioFormat, Bitrate as LSBitrate, PlayerConfig}, dither::{mk_ditherer, DithererBuilder, TriangularDitherer}, }; -use log::{error, info, warn}; -use serde::{de::Error, de::Unexpected, Deserialize, Deserializer}; +use log::{debug, error, info, warn}; +use serde::{ + de::{self, Error, Unexpected}, + Deserialize, Deserializer, +}; use sha1::{Digest, Sha1}; -use std::{fs, path::Path, path::PathBuf}; +use std::{ + borrow::Cow, + convert::TryInto, + fs, + path::{Path, PathBuf}, + str::FromStr, +}; use url::Url; const CONFIG_FILE_NAME: &str = "spotifyd.conf"; @@ -161,30 +173,71 @@ fn possible_backends() -> Vec<&'static str> { audio_backend::BACKENDS.iter().map(|b| b.0).collect() } +fn number_or_string<'de, D>(de: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let Some(val) = Option::::deserialize(de)? else { + return Ok(None); + }; + + let unexpected = match val { + toml::Value::Integer(num) => { + let num: u8 = num.try_into().map_err(de::Error::custom)?; + return Ok(Some(num)); + } + toml::Value::String(num) => { + return u8::from_str(&num) + .map(Some) + .inspect(|_| warn!("Configuration Warning: `initial_volume` should be a number rather than a string, this will become a hard error in the future")) + .map_err(de::Error::custom) + } + toml::Value::Float(f) => Unexpected::Float(f), + toml::Value::Boolean(b) => Unexpected::Bool(b), + toml::Value::Datetime(_) => Unexpected::Other("datetime"), + toml::Value::Array(_) => Unexpected::Seq, + toml::Value::Table(_) => Unexpected::Map, + }; + Err(de::Error::invalid_type(unexpected, &"number")) +} + #[derive(Debug, Default, Parser)] -#[command(version, about, long_about = None)] +#[command(version, about, long_about = None, args_conflicts_with_subcommands = true)] pub struct CliConfig { /// The path to the config file to use - #[arg(long, value_name = "PATH")] + #[arg(long, value_name = "PATH", global = true)] pub config_path: Option, + /// Prints more verbose output + #[arg(short, long, action = clap::ArgAction::Count, global = true)] + pub verbose: u8, + /// If set, starts spotifyd without detaching #[arg(long)] pub no_daemon: bool, - /// Prints more verbose output - #[arg(short, long, action = clap::ArgAction::Count)] - pub verbose: u8, - /// Path to PID file. #[cfg(unix)] #[arg(long, value_name = "PATH")] pub pid: Option, + #[command(subcommand)] + pub mode: Option, + #[command(flatten)] pub shared_config: SharedConfigValues, } +#[derive(Debug, Subcommand)] +pub enum ExecutionMode { + #[command(visible_alias = "auth")] + Authenticate { + /// The port to use for the OAuth redirect + #[arg(long, default_value_t = 8000)] + oauth_port: u16, + }, +} + // A struct that holds all allowed config fields. // The actual config file is made up of two sections, spotifyd and global. #[derive(Clone, Default, Debug, Deserialize, PartialEq, Args)] @@ -195,7 +248,7 @@ pub struct SharedConfigValues { on_song_change_hook: Option, /// The cache path used to store credentials and music file artifacts - #[arg(long, short, value_name = "PATH")] + #[arg(long, short, value_name = "PATH", global = true)] cache_path: Option, /// The maximal cache size in bytes @@ -239,6 +292,7 @@ pub struct SharedConfigValues { /// Initial volume between 0 and 100 #[arg(long)] + #[serde(deserialize_with = "number_or_string")] initial_volume: Option, /// Enable to normalize the volume during playback @@ -378,6 +432,56 @@ impl CliConfig { } impl SharedConfigValues { + pub fn get_cache(&self, for_oauth: bool) -> color_eyre::Result { + let Some(cache_path) = self.cache_path.as_deref().map(Cow::Borrowed).or_else(|| { + ProjectDirs::from("", "", "spotifyd") + .map(|dirs| Cow::Owned(dirs.cache_dir().to_path_buf())) + }) else { + bail!("Failed to determine cache directory, please specify one manually"); + }; + + if for_oauth { + let mut creds_path = cache_path.into_owned(); + creds_path.push("oauth"); + Cache::new(Some(creds_path), None, None, None) + } else { + let audio_cache = !self.no_audio_cache.unwrap_or(false); + + let mut creds_path = cache_path.to_path_buf(); + creds_path.push("zeroconf"); + Cache::new( + Some(creds_path.as_path()), + Some(cache_path.as_ref()), + audio_cache.then_some(cache_path.as_ref()), + self.max_cache_size, + ) + } + .wrap_err("Failed to initialize cache") + } + + pub fn proxy_url(&self) -> Option { + match &self.proxy { + Some(s) => match Url::parse(s) { + Ok(url) => { + if url.scheme() != "http" { + error!("Only HTTP proxies are supported!"); + None + } else { + Some(url) + } + } + Err(err) => { + error!("Invalid proxy URL: {}", err); + None + } + }, + None => { + debug!("No proxy specified"); + None + } + } + } + pub fn merge_with(&mut self, mut other: SharedConfigValues) { macro_rules! merge { ($a:expr; and $b:expr => {$($x:ident),+}) => { @@ -436,6 +540,7 @@ fn device_id(name: &str) -> String { pub(crate) struct SpotifydConfig { pub(crate) cache: Option, + pub(crate) oauth_cache: Option, pub(crate) backend: Option, pub(crate) audio_device: Option, pub(crate) audio_format: LSAudioFormat, @@ -458,32 +563,19 @@ pub(crate) struct SpotifydConfig { } pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { - let audio_cache = !config.shared_config.no_audio_cache.unwrap_or(false); - - let size_limit = config.shared_config.max_cache_size; - let cache = config - .shared_config - .cache_path - .or_else(|| { - ProjectDirs::from("", "", "spotifyd").map(|dirs| dirs.cache_dir().to_path_buf()) - }) - .or_else(|| { - warn!("failed to determine cache directory, please specify one manually!"); - None - }) - .map(|path| { - Cache::new( - Some(&path), - Some(&path), - audio_cache.then_some(&path), - size_limit, - ) - }) - .transpose() - .unwrap_or_else(|e| { - warn!("Cache couldn't be initialized: {e}"); - None - }); + let (cache, oauth_cache) = match ( + config.shared_config.get_cache(false), + config.shared_config.get_cache(true), + ) { + (Ok(cache), Ok(oauth_cache)) => (Some(cache), Some(oauth_cache)), + (a, b) => { + // at least one of the results are err + let err = a.or(b).map(|_| ()).unwrap_err(); + warn!("{err}"); + (None, None) + } + }; + let proxy_url = config.shared_config.proxy_url(); let bitrate: LSBitrate = config .shared_config @@ -543,21 +635,6 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { "sh".to_string() }); - let mut proxy_url = None; - match config.shared_config.proxy { - Some(s) => match Url::parse(&s) { - Ok(url) => { - if url.scheme() != "http" { - error!("Only HTTP proxies are supported!"); - } else { - proxy_url = Some(url); - } - } - Err(err) => error!("Invalid proxy URL: {}", err), - }, - None => info!("No proxy specified"), - } - // choose default ditherer the same way librespot does let ditherer: Option = match audio_format { LSAudioFormat::S16 | LSAudioFormat::S24 | LSAudioFormat::S24_3 => { @@ -580,6 +657,7 @@ pub(crate) fn get_internal_config(config: CliConfig) -> SpotifydConfig { SpotifydConfig { cache, + oauth_cache, backend: config.shared_config.backend, audio_device: config.shared_config.device, audio_format, From 836fbfa107c5a20f1dd7db3b2327aed1f0f1f2f4 Mon Sep 17 00:00:00 2001 From: eladyn Date: Mon, 30 Dec 2024 02:06:19 +0100 Subject: [PATCH 16/17] auth: implement oauth support --- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 28 ++++++------ src/main_loop.rs | 35 +++++++++------ src/oauth.rs | 75 +++++++++++++++++++++++++++++++ src/setup.rs | 112 ++++++++++++++++++++++++++++------------------- 6 files changed, 178 insertions(+), 74 deletions(-) create mode 100644 src/oauth.rs diff --git a/Cargo.lock b/Cargo.lock index 0fc9fc82..7310f5d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3232,6 +3232,7 @@ dependencies = [ "librespot-core", "librespot-discovery", "librespot-metadata", + "librespot-oauth", "librespot-playback", "librespot-protocol", "log", diff --git a/Cargo.toml b/Cargo.toml index ffd56cee..360bb895 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ librespot-discovery = "0.6" librespot-connect = "0.6" librespot-metadata = "0.6" librespot-protocol = "0.6" +librespot-oauth = "0.6" toml = "0.8.19" color-eyre = "0.6" directories = "5.0.1" diff --git a/src/main.rs b/src/main.rs index 941f2e6b..f041ab91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,14 @@ use crate::config::CliConfig; use clap::Parser; #[cfg(unix)] use color_eyre::eyre::eyre; -use color_eyre::{ - eyre::{self, Context}, - Help, SectionExt, -}; +use color_eyre::eyre::{self, Context}; +use config::ExecutionMode; #[cfg(unix)] use daemonize::Daemonize; #[cfg(unix)] use log::error; use log::{info, trace, LevelFilter}; +use oauth::run_oauth; #[cfg(target_os = "openbsd")] use pledge::pledge; #[cfg(windows)] @@ -25,6 +24,7 @@ mod dbus_mpris; mod error; mod main_loop; mod no_mixer; +mod oauth; mod process; mod setup; mod utils; @@ -63,7 +63,7 @@ fn setup_logger(log_target: LogTarget, verbose: u8) -> eyre::Result<()> { facility: syslog::Facility::LOG_DAEMON, hostname: None, process: "spotifyd".to_owned(), - pid: 0, + pid: std::process::id(), }; logger.chain( syslog::unix(log_format) @@ -106,8 +106,15 @@ fn main() -> eyre::Result<()> { color_eyre::install().wrap_err("Couldn't initialize error reporting")?; - let mut cli_config = CliConfig::parse(); + let cli_config = CliConfig::parse(); + match cli_config.mode { + None => run_daemon(cli_config), + Some(ExecutionMode::Authenticate { oauth_port }) => run_oauth(cli_config, oauth_port), + } +} + +fn run_daemon(mut cli_config: CliConfig) -> eyre::Result<()> { let is_daemon = !cli_config.no_daemon; let log_target = if is_daemon { @@ -138,14 +145,7 @@ fn main() -> eyre::Result<()> { cli_config .load_config_file_values() - .wrap_err("could not load the config file") - .with_section(|| { - concat!( - "the config format should be valid TOML\n", - "we recently changed the config format, see https://github.com/Spotifyd/spotifyd/issues/765" - ) - .header("note:") - })?; + .wrap_err("could not load the config file")?; trace!("{:?}", &cli_config); // Returns the old SpotifydConfig struct used within the rest of the daemon. diff --git a/src/main_loop.rs b/src/main_loop.rs index b629831c..b68c9706 100644 --- a/src/main_loop.rs +++ b/src/main_loop.rs @@ -29,28 +29,35 @@ pub struct SpotifydState { } pub(crate) enum CredentialsProvider { - Discovery(Peekable), - SpotifyCredentials(Credentials), -} - -impl From for CredentialsProvider { - fn from(stream: Discovery) -> Self { - CredentialsProvider::Discovery(stream.peekable()) - } + Discovery { + stream: Peekable, + last_credentials: Option, + }, + CredentialsOnly(Credentials), } impl CredentialsProvider { async fn get_credentials(&mut self) -> Credentials { match self { - CredentialsProvider::Discovery(stream) => stream.next().await.unwrap(), - CredentialsProvider::SpotifyCredentials(creds) => creds.clone(), + CredentialsProvider::Discovery { + stream, + last_credentials, + } => { + let new_creds = match last_credentials.take() { + Some(creds) => stream.next().now_or_never().flatten().unwrap_or(creds), + None => stream.next().await.unwrap(), + }; + *last_credentials = Some(new_creds.clone()); + new_creds + } + CredentialsProvider::CredentialsOnly(creds) => creds.clone(), } } // wait for an incoming connection if the underlying provider is a discovery stream async fn incoming_connection(&mut self) { match self { - CredentialsProvider::Discovery(stream) => { + CredentialsProvider::Discovery { stream, .. } => { let peeked = Pin::new(stream).peek().await; if peeked.is_none() { future::pending().await @@ -119,9 +126,6 @@ impl MainLoop { 'mainloop: loop { let (spirc, spirc_task) = tokio::select!( _ = &mut ctrl_c => { - if let CredentialsProvider::Discovery(stream) = self.credentials_provider { - let _ = stream.into_inner().shutdown().await; - } break 'mainloop; } spirc = self.get_connection() => { @@ -215,6 +219,9 @@ impl MainLoop { } } } + if let CredentialsProvider::Discovery { stream, .. } = self.credentials_provider { + let _ = stream.into_inner().shutdown().await; + } #[cfg(feature = "dbus_mpris")] if let Either::Left(dbus_server) = Either::as_pin_mut(dbus_server.as_mut()) { if dbus_server.shutdown() { diff --git a/src/oauth.rs b/src/oauth.rs new file mode 100644 index 00000000..1effeee7 --- /dev/null +++ b/src/oauth.rs @@ -0,0 +1,75 @@ +use color_eyre::{ + eyre::{self, Context as _}, + Section as _, +}; +use librespot_core::SessionConfig; +use librespot_core::{authentication::Credentials, Session}; +use log::info; +use tokio::runtime::Runtime; + +use crate::{config::CliConfig, setup_logger, LogTarget}; + +pub(crate) fn run_oauth(mut cli_config: CliConfig, oauth_port: u16) -> eyre::Result<()> { + setup_logger(LogTarget::Terminal, cli_config.verbose)?; + + cli_config + .load_config_file_values() + .wrap_err("failed to read config file")?; + + let cache = cli_config + .shared_config + .get_cache(true) + .with_note(|| "The result of the authentication needs to be cached to be usable later.")?; + + const OAUTH_SCOPES: &[&str] = &[ + "app-remote-control", + "playlist-modify", + "playlist-modify-private", + "playlist-modify-public", + "playlist-read", + "playlist-read-collaborative", + "playlist-read-private", + "streaming", + "ugc-image-upload", + "user-follow-modify", + "user-follow-read", + "user-library-modify", + "user-library-read", + "user-modify", + "user-modify-playback-state", + "user-modify-private", + "user-personalized", + "user-read-birthdate", + "user-read-currently-playing", + "user-read-email", + "user-read-play-history", + "user-read-playback-position", + "user-read-playback-state", + "user-read-private", + "user-read-recently-played", + "user-top-read", + ]; + + let session_config = SessionConfig { + proxy: cli_config.shared_config.proxy_url(), + ..Default::default() + }; + + let token = librespot_oauth::get_access_token( + &session_config.client_id, + &format!("http://127.0.0.1:{oauth_port}/login"), + OAUTH_SCOPES.to_vec(), + ) + .wrap_err("token retrieval failed")?; + + let creds = Credentials::with_access_token(token.access_token); + + Runtime::new().unwrap().block_on(async move { + let session = Session::new(session_config, Some(cache)); + session.connect(creds, true).await + })?; + + info!("\nLogin successful! You are now ready to run spotifyd."); + + Ok(()) +} diff --git a/src/setup.rs b/src/setup.rs index 5fe5b2aa..ca0abc30 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -4,10 +4,8 @@ use crate::{ config, main_loop::{self, CredentialsProvider}, }; -use color_eyre::{ - eyre::{eyre, Context}, - Section, -}; +use color_eyre::{eyre::eyre, Section}; +use futures::StreamExt as _; use librespot_core::Session; use librespot_playback::{ audio_backend::{self}, @@ -53,7 +51,6 @@ pub(crate) fn initial_state( } }; - let cache = config.cache; let player_config = config.player_config; let session_config = config.session_config; let backend = config.backend.clone(); @@ -62,52 +59,75 @@ pub(crate) fn initial_state( let zeroconf_port = config.zeroconf_port.unwrap_or(0); - let credentials_provider = - if let Some(credentials) = cache.as_ref().and_then(|c| c.credentials()) { - CredentialsProvider::SpotifyCredentials(credentials) - } else if config.discovery { - info!("no usable credentials found, enabling discovery"); - debug!("Using device id '{}'", session_config.device_id); - const RETRY_MAX: u8 = 4; - let mut retry_counter = 0; - let mut backoff = Duration::from_secs(5); - let discovery_stream = loop { - match librespot_discovery::Discovery::builder( - session_config.device_id.clone(), - session_config.client_id.clone(), - ) - .name(config.device_name.clone()) - .device_type(config.device_type) - .port(zeroconf_port) - .launch() - { - Ok(discovery_stream) => break discovery_stream, - Err(err) => { - error!("failed to enable discovery: {err}"); - if retry_counter >= RETRY_MAX { - return Err(err).with_context(|| { - "failed to enable discovery (and no credentials provided)" - }); - } - info!("retrying discovery in {} seconds", backoff.as_secs()); - thread::sleep(backoff); - retry_counter += 1; - backoff *= 2; - info!("trying to enable discovery (retry {retry_counter}/{RETRY_MAX})"); + let creds = if let Some(creds) = config.oauth_cache.as_ref().and_then(|c| c.credentials()) { + info!( + "Login via OAuth as user {}.", + creds.username.as_deref().unwrap_or("unknown") + ); + Some(creds) + } else if let Some(creds) = config.cache.as_ref().and_then(|c| c.credentials()) { + info!( + "Restoring previous login as user {}.", + creds.username.as_deref().unwrap_or("unknown") + ); + Some(creds) + } else { + None + }; + + let discovery = if config.discovery { + info!("Starting zeroconf server to advertise on local network."); + debug!("Using device id '{}'", session_config.device_id); + const RETRY_MAX: u8 = 4; + let mut retry_counter = 0; + let mut backoff = Duration::from_secs(5); + loop { + match librespot_discovery::Discovery::builder( + session_config.device_id.clone(), + session_config.client_id.clone(), + ) + .name(config.device_name.clone()) + .device_type(config.device_type) + .port(zeroconf_port) + .launch() + { + Ok(discovery_stream) => break Some(discovery_stream), + Err(err) => { + error!("failed to enable discovery: {err}"); + if retry_counter >= RETRY_MAX { + error!("maximum amount of retries exceeded"); + break None; } + info!("retrying discovery in {} seconds", backoff.as_secs()); + thread::sleep(backoff); + retry_counter += 1; + backoff *= 2; + info!("trying to enable discovery (retry {retry_counter}/{RETRY_MAX})"); } - }; - discovery_stream.into() - } else { - return Err(eyre!( - "no cached credentials available and discovery disabled" - )) - .with_suggestion(|| "consider enabling discovery or authenticating via OAuth"); - }; + } + } + } else { + None + }; + + let credentials_provider = match (discovery, creds) { + (Some(stream), creds) => CredentialsProvider::Discovery { + stream: stream.peekable(), + last_credentials: creds, + }, + (None, Some(creds)) => CredentialsProvider::CredentialsOnly(creds), + (None, None) => { + return Err( + eyre!("Discovery unavailable and no credentials found.").with_suggestion(|| { + "Try enabling discovery or logging in first with `spotifyd authenticate`." + }), + ); + } + }; let backend = audio_backend::find(backend).expect("available backends should match ours"); - let session = Session::new(session_config, cache); + let session = Session::new(session_config, config.cache); let player = { let audio_device = config.audio_device; let audio_format = config.audio_format; From 41ef38246a693d13662ab7f57084d3c13706dfc0 Mon Sep 17 00:00:00 2001 From: eladyn Date: Mon, 30 Dec 2024 02:43:26 +0100 Subject: [PATCH 17/17] chore: properly remove any references to `dbus_keyring` feature --- .github/ISSUE_TEMPLATE/bug-report.md | 1 - .github/workflows/cd.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- Cargo.toml | 2 +- hooks/pre-commit | 8 ++++---- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index c5c9d79d..6d967fdf 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -33,7 +33,6 @@ assignees: '' **Compilation flags** - [ ] dbus_mpris -- [ ] dbus_keyring - [x] alsa_backend - [ ] portaudio_backend - [ ] pulseaudio_backend diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 787cce72..a87b7d6d 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -18,9 +18,9 @@ jobs: - artifact_type: 'slim' # Slim version has no features enabled by default. feature: '' - artifact_type: 'default' - feature: 'dbus_keyring,dbus_mpris' # Default version has all extra features enabled + feature: 'dbus_mpris' # Default version has all extra features enabled - artifact_type: 'full' - feature: 'dbus_keyring,dbus_mpris' # Full version has all extra features and audio backends enabled + feature: 'dbus_mpris' # Full version has all extra features and audio backends enabled - build_target: macos os: macos-latest artifact_prefix: macos diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d551d6e8..4b089568 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,9 +59,9 @@ jobs: os: [macos-latest, ubuntu-latest] include: - os: macos-latest - features: portaudio_backend,rodio_backend,dbus_keyring + features: portaudio_backend,rodio_backend - os: ubuntu-latest - features: alsa_backend,rodio_backend,dbus_keyring,dbus_mpris + features: alsa_backend,rodio_backend,dbus_mpris steps: - name: Installing Rust toolchain diff --git a/Cargo.toml b/Cargo.toml index 360bb895..142d0704 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,7 +65,7 @@ rodiojack_backend = ["librespot-playback/rodiojack-backend"] [package.metadata.deb] depends = "$auto, systemd, pulseaudio" -features = ["pulseaudio_backend", "dbus_keyring", "dbus_mpris"] +features = ["pulseaudio_backend", "dbus_mpris"] assets = [ ["target/release/spotifyd", "usr/bin/", "755"], ["README.md", "usr/share/doc/spotifyd/README", "644"], diff --git a/hooks/pre-commit b/hooks/pre-commit index c07342f9..e43d760e 100755 --- a/hooks/pre-commit +++ b/hooks/pre-commit @@ -34,16 +34,16 @@ for path in $(git diff --name-only --cached); do done echo "→ Building pre-commit build artifacts..." -cargo check --quiet --no-default-features --features "rodio_backend,dbus_keyring" +cargo check --quiet --no-default-features --features "rodio_backend" if [ $? -ne 0 ]; then exit 1 fi -cargo build --quiet --no-default-features --features "rodio_backend,dbus_keyring" +cargo build --quiet --no-default-features --features "rodio_backend" # Linting is only done with the rodio backend and the keyring feature as those should be # compilable for every supported platform without external library needs. echo "→ Linting Rust code..." -cargo clippy --no-default-features --features "rodio_backend,dbus_keyring" -- -D warnings +cargo clippy --no-default-features --features "rodio_backend" -- -D warnings echo "→ Testing Rust code..." -cargo test --no-default-features --features "rodio_backend,dbus_keyring" +cargo test --no-default-features --features "rodio_backend"