From 29338f32e3e0587828116c81c152369b755aef98 Mon Sep 17 00:00:00 2001 From: Ivan Bushchik Date: Mon, 26 Aug 2024 20:08:19 +0300 Subject: [PATCH] 0.7.0: Playlists, Vorbis, ALAC and more - XSPF playlists support - Modernization of error handling and server-client communications - Vorbis and ALAC transcoding - All transcoders are now optional but enabled on default - lonelyradio_types crate is now exported through monolib Signed-off-by: Ivan Bushchik --- .gitignore | 1 - Cargo.lock | 1856 +++++++---------- Cargo.toml | 32 +- README.md | 53 +- lonelyradio_types/Cargo.toml | 11 +- lonelyradio_types/src/lib.rs | 74 +- microserve/Cargo.lock | 886 -------- microserve/Cargo.toml | 24 - microserve/src/main.rs | 96 - monoclient-s/Cargo.toml | 12 +- monoclient-s/src/app.rs | 227 -- monoclient-s/src/lib.rs | 7 - monoclient-s/src/main.rs | 264 ++- monoclient-x/monoclient-x/Metadata.swift | 2 +- monoclient-x/monoclient-x/Player.swift | 329 +-- .../monoclient-x/monoclient_xApp.swift | 3 +- monoclient/Cargo.toml | 10 +- monoclient/src/main.rs | 27 +- monolib/Cargo.toml | 23 +- monolib/src/c.rs | 33 +- monolib/src/decode.rs | 99 + monolib/src/lib.rs | 194 +- monolib/src/monolib.h | 60 +- monolib/src/target | 1 - monoloader/Cargo.toml | 5 +- monoloader/src/main.rs | 37 +- src/decode.rs | 59 +- src/encode.rs | 131 +- src/main.rs | 226 +- 29 files changed, 2002 insertions(+), 2780 deletions(-) delete mode 100644 microserve/Cargo.lock delete mode 100644 microserve/Cargo.toml delete mode 100644 microserve/src/main.rs delete mode 100644 monoclient-s/src/app.rs delete mode 100644 monoclient-s/src/lib.rs create mode 100644 monolib/src/decode.rs delete mode 120000 monolib/src/target diff --git a/.gitignore b/.gitignore index 0222fdc..5cdfc31 100644 --- a/.gitignore +++ b/.gitignore @@ -50,7 +50,6 @@ fastlane/test_output ### SwiftPackageManager ### Packages xcuserdata -*.xcodeproj ### Xcode ### # Xcode diff --git a/Cargo.lock b/Cargo.lock index 9e538aa..3028887 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,15 +20,15 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "accesskit" -version = "0.12.3" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a4b14f3d99c1255dcba8f45621ab1a2e7540a0009652d33989005a4d0bfc6b" +checksum = "e4700bdc115b306d6c43381c344dc307f03b7f0460c304e4892c309930322bd7" [[package]] name = "accesskit_atspi_common" -version = "0.2.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9357ba093d0c8c234840f126efa71d09b848027b2963f553940021fb07bbf076" +checksum = "a1de72dc7093910a1284cef784b6b143bab0a34d67f6178e4fc3aaaf29a09f8b" dependencies = [ "accesskit", "accesskit_consumer", @@ -40,31 +40,33 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.17.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6114c157d5b02e24b38e929afe99324f2f9cc116ce7d49fdbf3fea111369c14" +checksum = "fe3a07a32ab5837ad83db3230ac490c8504c2cd5b90ac8c00db6535f6ed65d0b" dependencies = [ "accesskit", + "immutable-chunkmap", ] [[package]] name = "accesskit_macos" -version = "0.11.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded5f12ee8af8d8dae8de4ef96bc6abdd94735973ba97bbd426da41005252553" +checksum = "a189d159c153ae0fce5f9eefdcfec4a27885f453ce5ef0ccf078f72a73c39d34" dependencies = [ "accesskit", "accesskit_consumer", - "icrate 0.1.2", - "objc2 0.5.2", + "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", ] [[package]] name = "accesskit_unix" -version = "0.7.5" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "454040abdc130ca45d9142cc6ea0b196fb53119f62600d88665ae6090d597f3e" +checksum = "b76c448cfd96d16131a9ad3ab786d06951eb341cdac1db908978ab010245a19d" dependencies = [ "accesskit", "accesskit_atspi_common", @@ -74,36 +76,34 @@ dependencies = [ "atspi", "futures-lite 1.13.0", "futures-util", - "once_cell", "serde", "zbus", ] [[package]] name = "accesskit_windows" -version = "0.16.4" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b698c3561514806519d28c63b6a2b1f5797f5ae3042a9caa4d64b7b928ff69" +checksum = "682d8c4fb425606f97408e7577793f32e96310b646fa77662eb4216293eddc7f" dependencies = [ "accesskit", "accesskit_consumer", - "once_cell", "paste", "static_assertions", - "windows", + "windows 0.54.0", ] [[package]] name = "accesskit_winit" -version = "0.18.7" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d80d7aa92a9334120580e9fe2028670f48f2b1a30cdf8bfd3d038c2f430345" +checksum = "9afbd6d598b7c035639ad2b664aa0edc94c93dc1fc3ebb4b40d8a95fcd43ffac" dependencies = [ "accesskit", "accesskit_macos", "accesskit_unix", "accesskit_windows", - "raw-window-handle 0.6.2", + "raw-window-handle", "winit", ] @@ -122,6 +122,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -145,10 +151,13 @@ dependencies = [ ] [[package]] -name = "aligned-vec" -version = "0.5.0" +name = "alac-encoder" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +checksum = "0a32a4e6eec2ede679898711c25120685f4cd472be57be0b98642312232b9f29" +dependencies = [ + "log", +] [[package]] name = "allocator-api2" @@ -158,12 +167,13 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alsa" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", "bitflags 2.6.0", + "cfg-if", "libc", ] @@ -177,27 +187,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "android-activity" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" -dependencies = [ - "android-properties", - "bitflags 2.6.0", - "cc", - "cesu8", - "jni", - "jni-sys", - "libc", - "log", - "ndk 0.8.0", - "ndk-context", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror", -] - [[package]] name = "android-activity" version = "0.6.0" @@ -242,9 +231,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -257,33 +246,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -296,33 +285,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] -name = "arbitrary" -version = "1.3.2" +name = "aotuv_lancer_vorbis_sys" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +checksum = "495ea2c3cc8dc08e9fb6ff470c9c90e44d4fbc648882a0bfaba13216daea4c3c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", + "cc", + "ogg_next_sys", ] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "as-raw-xcb-connection" @@ -354,13 +336,13 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" +checksum = "d7ebdfa2ebdab6b1760375fa7d6f382b9f486eac35fc994625a00e89280bdbb7" dependencies = [ "async-task", "concurrent-queue", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-lite 2.3.0", "slab", ] @@ -399,9 +381,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock 3.4.0", "cfg-if", @@ -409,11 +391,11 @@ dependencies = [ "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.7.2", + "polling 3.7.3", "rustix 0.38.34", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -461,16 +443,16 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ - "async-io 2.3.3", + "async-io 2.3.4", "async-lock 3.4.0", "atomic-waker", "cfg-if", @@ -479,7 +461,7 @@ dependencies = [ "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -501,7 +483,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -518,7 +500,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -577,14 +559,14 @@ dependencies = [ [[package]] name = "auto_enums" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1899bfcfd9340ceea3533ea157360ba8fa864354eccbceab58e1006ecab35393" +checksum = "459b77b7e855f875fd15f101064825cd79eb83185a961d66e6298560126facfb" dependencies = [ "derive_utils", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -593,29 +575,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "av1-grain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" -dependencies = [ - "arrayvec", -] - [[package]] name = "backtrace" version = "0.3.73" @@ -626,7 +585,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -646,7 +605,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools", + "itertools 0.12.1", "lazy_static", "lazycell", "log", @@ -656,16 +615,10 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.71", + "syn 2.0.76", "which", ] -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" version = "1.3.2" @@ -678,12 +631,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "bitstream-io" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499" - [[package]] name = "block" version = "0.1.6" @@ -699,33 +646,13 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - [[package]] name = "block2" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "block-sys", - "objc2 0.4.1", -] - -[[package]] -name = "block2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f" -dependencies = [ - "block-sys", - "objc2 0.5.2", + "objc2", ] [[package]] @@ -761,22 +688,22 @@ checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -793,9 +720,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "calloop" @@ -805,7 +732,21 @@ checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ "bitflags 2.6.0", "log", - "polling 3.7.2", + "polling 3.7.3", + "rustix 0.38.34", + "slab", + "thiserror", +] + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.6.0", + "log", + "polling 3.7.3", "rustix 0.38.34", "slab", "thiserror", @@ -813,11 +754,11 @@ dependencies = [ [[package]] name = "calloop-wayland-source" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop", + "calloop 0.13.0", "rustix 0.38.34", "wayland-backend", "wayland-client", @@ -825,13 +766,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.1" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907d8581360765417f8f2e0e7d602733bbed60156b4465b7617243689ef9b83d" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "jobserver", "libc", - "once_cell", + "shlex", ] [[package]] @@ -849,28 +790,12 @@ dependencies = [ "nom", ] -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cfg_aliases" version = "0.2.1" @@ -908,14 +833,14 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.4", + "libloading", ] [[package]] name = "clap" -version = "4.5.9" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -923,9 +848,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.9" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", @@ -935,21 +860,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "claxon" @@ -975,9 +900,9 @@ checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "cmake" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -1036,9 +961,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "combine" @@ -1077,7 +1002,7 @@ checksum = "5387f5bbc9e9e6c96436ea125afa12614cebf8ac67f49abc08c1e7a891466c90" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1112,9 +1037,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -1198,7 +1123,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows", + "windows 0.54.0", ] [[package]] @@ -1221,7 +1146,7 @@ dependencies = [ "lazy_static", "proc-macro2", "regex", - "syn 2.0.71", + "syn 2.0.76", "unicode-xid", ] @@ -1233,7 +1158,7 @@ checksum = "3e1a2532e4ed4ea13031c13bc7bc0dbca4aae32df48e9d77f0d1e743179f2ea1" dependencies = [ "lazy_static", "proc-macro2", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1248,14 +1173,14 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -1286,28 +1211,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] +checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "crossbeam-utils" @@ -1317,15 +1223,15 @@ checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" -version = "0.27.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags 2.6.0", "crossterm_winapi", - "libc", "mio", "parking_lot", + "rustix 0.38.34", "signal-hook", "signal-hook-mio", "winapi", @@ -1340,12 +1246,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "crypto-common" version = "0.1.6" @@ -1356,15 +1256,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "css-color-parser2" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8ed1639f4b56ec6f31d007ff66ce4a13099dce5a9995d48368a30d62bf04bd" -dependencies = [ - "lazy_static", -] - [[package]] name = "ctor-lite" version = "0.1.0" @@ -1416,18 +1307,18 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "derive_utils" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61bb5a1014ce6dfc2a378578509abe775a5aa06bff584a547555d9efdb81b926" +checksum = "65f152f4b8559c4da5d574bafc7af85454d706b4c5fe8b530d508cacbb6807ea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1452,7 +1343,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.4", + "libloading", ] [[package]] @@ -1461,6 +1352,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + [[package]] name = "drm" version = "0.9.0" @@ -1546,7 +1443,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1612,22 +1509,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "exr" -version = "1.72.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" -dependencies = [ - "bit_field", - "flume", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - [[package]] name = "extended" version = "0.1.0" @@ -1645,9 +1526,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" @@ -1667,12 +1548,12 @@ dependencies = [ "bitflags 2.6.0", "fnv", "glow", - "image 0.25.1", + "image 0.25.2", "imgref", "log", "lru", "rgb", - "rustybuzz 0.14.1", + "rustybuzz", "slotmap", "unicode-bidi", "unicode-segmentation", @@ -1692,14 +1573,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox 0.1.3", + "windows-sys 0.59.0", ] [[package]] @@ -1719,12 +1600,12 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1733,15 +1614,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1750,35 +1622,35 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fontconfig-parser" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a595cb550439a117696039dfc69830492058211b771a2a165379f2a1a53d84d" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" dependencies = [ "roxmltree", ] [[package]] name = "fontdb" -version = "0.16.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" dependencies = [ "fontconfig-parser", "log", "memmap2 0.9.4", "slotmap", "tinyvec", - "ttf-parser 0.20.0", + "ttf-parser 0.21.1", ] [[package]] name = "fontdue" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9099a2f86b8e674b75d03ff154b3fe4c5208ed249ced8d69cc313a9fa40bb488" +checksum = "efe23d02309319171d00d794c9ff48d4f903c0e481375b1b04b017470838af04" dependencies = [ "hashbrown", - "ttf-parser 0.20.0", + "ttf-parser 0.21.1", ] [[package]] @@ -1799,7 +1671,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1850,7 +1722,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-core", "futures-io", "parking", @@ -1865,7 +1737,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -1929,16 +1801,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "gethostname" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -1960,16 +1822,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gimli" version = "0.29.0" @@ -2007,55 +1859,56 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.3" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" +checksum = "2491aa3090f682ddd920b184491844440fdd14379c7eef8f5bc10ef7fb3242fd" dependencies = [ "bitflags 2.6.0", - "cfg_aliases 0.1.1", + "cfg_aliases", "cgl", "core-foundation", "dispatch", "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "icrate 0.0.4", - "libloading 0.8.4", - "objc2 0.4.1", + "libloading", + "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", - "raw-window-handle 0.5.2", + "raw-window-handle", "wayland-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", ] [[package]] name = "glutin-winit" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" dependencies = [ - "cfg_aliases 0.1.1", + "cfg_aliases", "glutin", - "raw-window-handle 0.5.2", + "raw-window-handle", "winit", ] [[package]] name = "glutin_egl_sys" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" +checksum = "cae99fff4d2850dbe6fb8c1fa8e4fead5525bab715beaacfccf3fb994e01c827" dependencies = [ "gl_generator", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "glutin_glx_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" +checksum = "9c2b2d3918e76e18e08796b55eb64e8fe6ec67d5a6b2e2a7e2edce224ad24c63" dependencies = [ "gl_generator", "x11-dl", @@ -2063,23 +1916,13 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" dependencies = [ "gl_generator", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hash32" version = "0.3.1" @@ -2109,12 +1952,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -2154,28 +1991,14 @@ version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" -[[package]] -name = "i-slint-backend-android-activity" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f3bdf1a87abe3db01c09da598d42c5638cca30a8503d9e9610d2a3261aea95" -dependencies = [ - "android-activity 0.5.2", - "android-activity 0.6.0", - "i-slint-core", - "i-slint-renderer-skia", - "jni", - "ndk 0.9.0", - "raw-window-handle 0.5.2", -] - [[package]] name = "i-slint-backend-linuxkms" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734d8fb9fe4ec1e16b037fed68da4d41f2a61ac4114f7cff22c4df242771fb08" +checksum = "59745188ee04a8afd65887a0386a1e5272cea18c435493c20be1eaf42cb1da70" dependencies = [ - "calloop", + "bytemuck", + "calloop 0.12.4", "drm", "gbm", "gbm-sys", @@ -2184,16 +2007,17 @@ dependencies = [ "i-slint-core", "i-slint-renderer-femtovg", "input", + "memmap2 0.9.4", "nix 0.27.1", - "raw-window-handle 0.5.2", + "raw-window-handle", "xkbcommon", ] [[package]] name = "i-slint-backend-qt" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39bdf955542e1ae8ebb0f7f5bd88d310d4f375cc84d9ca77db8d897b8f00d2f9" +checksum = "8f9b499754d17f42b31fd3315c76c3824c3a2d6156b799a78aec3968cd89027f" dependencies = [ "const-field-offset", "cpp", @@ -2211,9 +2035,9 @@ dependencies = [ [[package]] name = "i-slint-backend-selector" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb82314416726feb9b4b67e369df1f9ca5a2286a57a3a8ba1101ac59dc047b9a" +checksum = "cbf8c0da7b5a493e224acd3a15fced7ce5dcfbf838717fae4a142be10c6a0318" dependencies = [ "cfg-if", "i-slint-backend-linuxkms", @@ -2225,15 +2049,15 @@ dependencies = [ [[package]] name = "i-slint-backend-winit" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714c7d4f0f7536dd278f935b3aa57224b8f4458ebc96ecdf02aa916d11dbb63d" +checksum = "3e6a2ce764e057fc22693b193448f195b3c7e801c19342ddbfd6c9c6e298f5c3" dependencies = [ "accesskit", "accesskit_winit", "bytemuck", "cfg-if", - "cfg_aliases 0.2.1", + "cfg_aliases", "cocoa", "const-field-offset", "copypasta", @@ -2249,7 +2073,7 @@ dependencies = [ "lyon_path", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", + "raw-window-handle", "rgb", "scoped-tls-hkt", "scopeguard", @@ -2261,29 +2085,28 @@ dependencies = [ [[package]] name = "i-slint-common" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98770ce4f006a76efa0c728857a29fdca2dcad5dc0442f0aa786a28bbf9dcab1" +checksum = "eeb81f124038f7ea8a4b95c725a5dffbd17dd87e0e652a79cee1f14b856e69b7" dependencies = [ "cfg-if", "derive_more", "fontdb", - "libloading 0.8.4", + "libloading", ] [[package]] name = "i-slint-compiler" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2f6ebf56a7c2845868e01e111558b0e2e8164a3514a7fd54ab3edc2b6c3a83" +checksum = "18e9203a41a378ccf9b97df080bdcda7c613186b0889a4f6a6f1a5ea8adcb34d" dependencies = [ "by_address", "codemap", "codemap-diagnostic", - "css-color-parser2", "derive_more", "i-slint-common", - "itertools", + "itertools 0.13.0", "linked_hash_set", "lyon_extra", "lyon_path", @@ -2300,14 +2123,15 @@ dependencies = [ [[package]] name = "i-slint-core" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e40b1c61efe0fc5fbccdb68b23381d312ff6bf0a5cbdd72a6c7e9a669277240d" +checksum = "d20ae1c8d0de028db0ec1decf0a869436e19ff4bf489a87c35aeb1000fd4a365" dependencies = [ "auto_enums", "bitflags 2.6.0", "bytemuck", "cfg-if", + "chrono", "clru", "const-field-offset", "derive_more", @@ -2326,10 +2150,10 @@ dependencies = [ "pin-project", "pin-weak", "portable-atomic", - "raw-window-handle 0.6.2", + "raw-window-handle", "resvg", "rgb", - "rustybuzz 0.13.0", + "rustybuzz", "scoped-tls-hkt", "scopeguard", "slab", @@ -2341,24 +2165,24 @@ dependencies = [ "vtable", "wasm-bindgen", "web-sys", - "web-time 1.1.0", + "web-time", ] [[package]] name = "i-slint-core-macros" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed18eb2f3910f85ce4a4bb4c0d770147e76c072a48c845d86ad59c169c24b" +checksum = "096799ce16264fcb7f99b0e9e49b8d0d1a6181807f05e499c821edc60af60649" dependencies = [ "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "i-slint-renderer-femtovg" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8c32b7651861322f39d730bf116e9a585a77d6c66fc63a4377c16bf37c869d" +checksum = "6c7ecc7713bc6d074b1ea10a3bba71ca006f0de6159ca7662c9a91a5e63d1be5" dependencies = [ "cfg-if", "const-field-offset", @@ -2375,10 +2199,9 @@ dependencies = [ "lyon_path", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", "rgb", "scoped-tls-hkt", - "ttf-parser 0.20.0", + "ttf-parser 0.21.1", "unicode-script", "unicode-segmentation", "wasm-bindgen", @@ -2388,13 +2211,13 @@ dependencies = [ [[package]] name = "i-slint-renderer-skia" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b923fc4cff196bc6cd9f32f34b8b73957d0aecd1c43fabb174481eb57cc9b08" +checksum = "83e58cc4e96d47273b916711da9e962b2f220204b1b481733a1f418711228b11" dependencies = [ "bytemuck", "cfg-if", - "cfg_aliases 0.2.1", + "cfg_aliases", "cocoa", "const-field-offset", "core-foundation", @@ -2411,13 +2234,13 @@ dependencies = [ "objc", "once_cell", "pin-weak", - "raw-window-handle 0.5.2", + "raw-window-handle", "scoped-tls-hkt", "skia-safe", "softbuffer", "unicode-segmentation", "vtable", - "windows", + "windows 0.56.0", ] [[package]] @@ -2443,27 +2266,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icrate" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" -dependencies = [ - "block2 0.3.0", - "dispatch", - "objc2 0.4.1", -] - -[[package]] -name = "icrate" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb69199826926eb864697bddd27f73d9fddcffc004f5733131e15b465e30642" -dependencies = [ - "block2 0.4.0", - "objc2 0.5.2", -] - [[package]] name = "idna" version = "0.5.0" @@ -2490,37 +2292,18 @@ dependencies = [ [[package]] name = "image" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" dependencies = [ "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "image-webp", + "byteorder-lite", "num-traits", "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", "zune-core", "zune-jpeg", ] -[[package]] -name = "image-webp" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d" -dependencies = [ - "byteorder-lite", - "thiserror", -] - [[package]] name = "imagesize" version = "0.12.0" @@ -2534,10 +2317,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" [[package]] -name = "indexmap" -version = "2.2.6" +name = "immutable-chunkmap" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "4419f022e55cc63d5bbd6b44b71e1d226b9c9480a47824c706e9d54e5c40c5eb" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", "hashbrown", @@ -2581,17 +2373,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] - [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2605,9 +2386,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -2618,22 +2399,21 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[package]] -name = "java-locator" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd" -dependencies = [ - "glob", - "lazy_static", -] - [[package]] name = "jni" version = "0.21.1" @@ -2643,9 +2423,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "java-locator", "jni-sys", - "libloading 0.7.4", "log", "thiserror", "walkdir", @@ -2660,9 +2438,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -2675,9 +2453,9 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -2716,44 +2494,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" -dependencies = [ - "arbitrary", - "cc", - "once_cell", -] +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -2776,6 +2527,17 @@ dependencies = [ "redox_syscall 0.4.1", ] +[[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", + "redox_syscall 0.5.3", +] + [[package]] name = "libsamplerate-sys" version = "0.1.12" @@ -2855,7 +2617,7 @@ checksum = "764b60e1ddd07e5665a6a17636a95cd7d8f3b86c73503a69c32979d05f72f3cf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -2866,15 +2628,15 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lonelyradio" -version = "0.6.1" +version = "0.7.0" dependencies = [ + "alac-encoder", "async-stream", - "cc", "chrono", "clap", "flacenc", "futures-util", - "image 0.25.1", + "image 0.25.2", "lofty", "lonelyradio_types", "once_cell", @@ -2885,31 +2647,25 @@ dependencies = [ "symphonia", "tokio", "tokio-stream", + "url", + "vorbis_rs", "walkdir", + "xspf", ] [[package]] name = "lonelyradio_types" -version = "0.6.0" +version = "0.7.0" dependencies = [ "serde", "serde_bytes", ] -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" [[package]] name = "lyon_algorithms" @@ -2970,16 +2726,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "md-5" version = "0.10.6" @@ -3064,32 +2810,40 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.8.11" +name = "miniz_oxide" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", "libc", "log", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "monoclient" -version = "0.6.1" +version = "0.7.0" dependencies = [ "clap", "crossterm", - "lonelyradio_types", "monolib", ] [[package]] name = "monoclient-s" -version = "0.6.0" +version = "0.7.0" dependencies = [ - "lonelyradio_types", "monolib", "slint", "zune-jpeg", @@ -3097,22 +2851,25 @@ dependencies = [ [[package]] name = "monolib" -version = "0.6.0" +version = "0.7.0" dependencies = [ + "anyhow", "byteorder", "claxon", "lonelyradio_types", "rmp-serde", "rodio", + "symphonia-codec-alac", + "symphonia-core", + "vorbis_rs", ] [[package]] name = "monoloader" -version = "0.6.0" +version = "0.7.0" dependencies = [ "clap", "hound", - "lonelyradio_types", "monolib", ] @@ -3127,8 +2884,6 @@ dependencies = [ "log", "ndk-sys 0.5.0+25.2.9519653", "num_enum", - "raw-window-handle 0.5.2", - "raw-window-handle 0.6.2", "thiserror", ] @@ -3143,7 +2898,7 @@ dependencies = [ "log", "ndk-sys 0.6.0+11769913", "num_enum", - "raw-window-handle 0.5.2", + "raw-window-handle", "thiserror", ] @@ -3171,12 +2926,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - [[package]] name = "nix" version = "0.26.4" @@ -3210,22 +2959,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-complex" version = "0.4.6" @@ -3243,7 +2976,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -3255,17 +2988,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" @@ -3276,35 +2998,25 @@ dependencies = [ "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.9", - "libc", -] - [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -3334,16 +3046,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" -[[package]] -name = "objc2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" -dependencies = [ - "objc-sys", - "objc2-encode 3.0.0", -] - [[package]] name = "objc2" version = "0.5.2" @@ -3351,14 +3053,84 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", - "objc2-encode 4.0.3", + "objc2-encode", ] [[package]] -name = "objc2-encode" -version = "3.0.0" +name = "objc2-app-kit" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] [[package]] name = "objc2-encode" @@ -3366,6 +3138,111 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", + "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -3386,9 +3263,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.1" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -3416,6 +3293,15 @@ dependencies = [ "cc", ] +[[package]] +name = "ogg_next_sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4af25868786f6ab24956a8496a1eca4b010f860b449596f523d19ee9f956ae" +dependencies = [ + "cc", +] + [[package]] name = "ogg_pager" version = "0.6.1" @@ -3441,7 +3327,7 @@ version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox", + "libredox 0.0.2", ] [[package]] @@ -3460,7 +3346,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90" dependencies = [ - "ttf-parser 0.24.0", + "ttf-parser 0.24.1", ] [[package]] @@ -3487,7 +3373,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.5.3", "smallvec", "windows-targets 0.52.6", ] @@ -3527,7 +3413,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -3550,12 +3436,12 @@ checksum = "b330c9d1b92dfe68442ca20b009c717d5f0b1e3cf4965e62f704c3c6e95a1305" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand 2.1.0", + "fastrand 2.1.1", "futures-io", ] @@ -3575,7 +3461,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]] @@ -3596,9 +3482,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", @@ -3606,32 +3492,35 @@ dependencies = [ "pin-project-lite", "rustix 0.38.34", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" dependencies = [ "critical-section", ] [[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", +] [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -3671,34 +3560,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "profiling" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" -dependencies = [ - "quote", - "syn 2.0.71", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - [[package]] name = "qttypes" version = "0.2.11" @@ -3710,12 +3571,6 @@ dependencies = [ "semver", ] -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quick-xml" version = "0.34.0" @@ -3727,9 +3582,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3764,97 +3619,12 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "system-deps", - "thiserror", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ba61c28ba24c0cf8406e025cb29a742637e3f70776e61c27a8a8b72a042d12" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3866,18 +3636,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -3904,9 +3674,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resvg" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2327ced609dadeed3e9702fec3e6b2ddd208758a9268d13e06566c6101ba533" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" dependencies = [ "log", "pico-args", @@ -3918,9 +3688,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.44" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aee83dc281d5a3200d37b299acd13b81066ea126a7f16f0eae70fc9aed241d9" +checksum = "0f86ae463694029097b846d8f99fd5536740602ae00022c0c50c5600720b2f71" dependencies = [ "bytemuck", ] @@ -3949,31 +3719,31 @@ dependencies = [ [[package]] name = "rodio" -version = "0.17.3" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1bb7b48ee48471f55da122c0044fcc7600cfcc85db88240b89cb832935e611" +checksum = "6006a627c1a38d37f3d3a85c6575418cfe34a5392d60a686d0071e1c8d427acb" dependencies = [ "cpal", + "thiserror", ] [[package]] name = "rowan" -version = "0.15.15" +version = "0.15.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49" +checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d" dependencies = [ "countme", "hashbrown", - "memoffset 0.9.1", "rustc-hash", "text-size", ] [[package]] name = "roxmltree" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" [[package]] name = "rustc-demangle" @@ -4044,22 +3814,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" -[[package]] -name = "rustybuzz" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88117946aa1bfb53c2ae0643ceac6506337f44887f8c9fbfb43587b1cc52ba49" -dependencies = [ - "bitflags 2.6.0", - "bytemuck", - "smallvec", - "ttf-parser 0.20.0", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - [[package]] name = "rustybuzz" version = "0.14.1" @@ -4120,9 +3874,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "ab_glyph", "log", @@ -4145,9 +3899,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -4163,22 +3917,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -4191,14 +3946,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -4232,9 +3987,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", "mio", @@ -4256,15 +4011,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - [[package]] name = "simplecss" version = "0.2.1" @@ -4282,14 +4028,14 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "skia-bindings" -version = "0.72.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace7c5359ccb009880e65958eaf1e2fa68ee19ada6931300c2f1942f84abf2c3" +checksum = "c06e19e97660b09a381c6eb566849b63556b1a90b8e2c6ba2d146b3f5066847b" dependencies = [ "bindgen", "cc", "flate2", - "heck 0.4.1", + "heck", "lazy_static", "regex", "serde_json", @@ -4299,14 +4045,14 @@ dependencies = [ [[package]] name = "skia-safe" -version = "0.72.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a4a3df502b317456a34df181ac67a7a6443b0f2e4b883ac220dba1dcb3ce38" +checksum = "ad6e6f369522471b585c99427720b53aad04016fa4314e0a8cf23f17083a4e4c" dependencies = [ "bitflags 2.6.0", "lazy_static", "skia-bindings", - "windows", + "windows 0.56.0", ] [[package]] @@ -4320,12 +4066,11 @@ dependencies = [ [[package]] name = "slint" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0296f559dca60687e5a4208f94ae462f8b410c8e46288b6052747fe34bd7365a" +checksum = "b07c20ca1e15b15a998b7e6aa9b160f1857238cdd0ce5536ce40dcc175dcae62" dependencies = [ "const-field-offset", - "i-slint-backend-android-activity", "i-slint-backend-qt", "i-slint-backend-selector", "i-slint-core", @@ -4339,9 +4084,9 @@ dependencies = [ [[package]] name = "slint-macros" -version = "1.6.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd7a3c3bd28d9f5dc8632183d14abccd99985a125a842f991907635485b6768" +checksum = "f342d53e220a0431b277c4d82b7f3b98e8dc555d7a70cc7da80476a1b2e19079" dependencies = [ "i-slint-compiler", "proc-macro2", @@ -4366,12 +4111,12 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay-client-toolkit" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ "bitflags 2.6.0", - "calloop", + "calloop 0.13.0", "calloop-wayland-source", "cursor-icon", "libc", @@ -4391,9 +4136,9 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ "libc", "smithay-client-toolkit", @@ -4431,23 +4176,25 @@ dependencies = [ [[package]] name = "softbuffer" -version = "0.3.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f266ce2aa23eaaaa4e758ed44495d505d00fb79f359d46f6c1900cb053123b62" +checksum = "d623bff5d06f60d738990980d782c8c866997d9194cfe79ecad00aa2f76826dd" dependencies = [ "as-raw-xcb-connection", "bytemuck", - "cfg_aliases 0.1.1", - "cocoa", + "cfg_aliases", "core-graphics", - "fastrand 2.1.0", + "fastrand 2.1.1", "foreign-types", "js-sys", "log", "memmap2 0.9.4", - "objc", - "raw-window-handle 0.5.2", - "redox_syscall 0.4.1", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-quartz-core", + "raw-window-handle", + "redox_syscall 0.5.3", "rustix 0.38.34", "tiny-xlib", "wasm-bindgen", @@ -4455,17 +4202,8 @@ dependencies = [ "wayland-client", "wayland-sys", "web-sys", - "windows-sys 0.48.0", - "x11rb 0.12.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", + "windows-sys 0.52.0", + "x11rb", ] [[package]] @@ -4525,18 +4263,18 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] name = "svgtypes" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fae3064df9b89391c9a76a0425a69d124aee9c5c28455204709e72c39868a43c" +checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" dependencies = [ "kurbo", "siphasher", @@ -4751,28 +4489,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - [[package]] name = "tar" version = "0.4.41" @@ -4784,22 +4509,17 @@ dependencies = [ "xattr", ] -[[package]] -name = "target-lexicon" -version = "0.12.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" - [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", - "fastrand 2.1.0", + "fastrand 2.1.1", + "once_cell", "rustix 0.38.34", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4819,33 +4539,22 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", -] - -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", + "syn 2.0.76", ] [[package]] @@ -4882,7 +4591,7 @@ checksum = "1d52f22673960ad13af14ff4025997312def1223bfa7c8e4949d099e6b3d5d1c" dependencies = [ "as-raw-xcb-connection", "ctor-lite", - "libloading 0.8.4", + "libloading", "pkg-config", "tracing", ] @@ -4904,30 +4613,28 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", - "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2 0.5.7", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -4957,21 +4664,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.15", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -5000,15 +4707,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.15" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.18", ] [[package]] @@ -5030,7 +4737,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -5052,12 +4759,6 @@ dependencies = [ "strength_reduce", ] -[[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - [[package]] name = "ttf-parser" version = "0.21.1" @@ -5066,9 +4767,9 @@ checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" [[package]] name = "ttf-parser" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "typenum" @@ -5139,9 +4840,9 @@ dependencies = [ [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" [[package]] name = "unicode-script" @@ -5163,9 +4864,9 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "url" @@ -5180,9 +4881,9 @@ dependencies = [ [[package]] name = "usvg" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c704361d822337cfc00387672c7b59eaa72a1f0744f62b2a68aa228a0c6927d" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" dependencies = [ "base64", "data-url", @@ -5193,7 +4894,7 @@ dependencies = [ "log", "pico-args", "roxmltree", - "rustybuzz 0.13.0", + "rustybuzz", "simplecss", "siphasher", "strict-num", @@ -5211,28 +4912,25 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "v_frame" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vorbis_rs" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513beb7a94438399e404b297592dad39e99dd5e39515ab66dfe9caa6fd18897a" +dependencies = [ + "aotuv_lancer_vorbis_sys", + "errno", + "getrandom", + "ogg_next_sys", + "thiserror", + "tinyvec", +] [[package]] name = "vtable" @@ -5254,7 +4952,7 @@ checksum = "68c1b85ec843d3bc60e9d65fa7e00ce6549416a25c267b5ea93e6c81e3aa66e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -5281,34 +4979,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" dependencies = [ "cfg-if", "js-sys", @@ -5318,9 +5017,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5328,28 +5027,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wayland-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269c04f203640d0da2092d1b8d89a2d081714ae3ac2f1b53e99f205740517198" +checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993" dependencies = [ "cc", "downcast-rs", @@ -5361,9 +5060,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bd0f46c069d3382a36c8666c1b9ccef32b8b04f41667ca1fef06a1adcc2982" +checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943" dependencies = [ "bitflags 2.6.0", "rustix 0.38.34", @@ -5384,9 +5083,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09414bcf0fd8d9577d73e9ac4659ebc45bcc9cff1980a350543ad8e50ee263b2" +checksum = "6ef9489a8df197ebf3a8ce8a7a7f0a2320035c3743f3c1bd0bdbccf07ce64f95" dependencies = [ "rustix 0.38.34", "wayland-client", @@ -5395,9 +5094,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "62989625a776e827cc0f15d41444a3cea5205b963c3a25be48ae1b52d6b4daaa" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -5407,9 +5106,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "f79f2d57c7fcc6ab4d602adba364bf59a5c24de57bd194486bf9b8360e06bfc4" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -5420,9 +5119,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -5433,9 +5132,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.3" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6" +checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6" dependencies = [ "proc-macro2", "quick-xml", @@ -5444,9 +5143,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.3" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6754825230fa5b27bafaa28c30b3c9e72c55530581220cef401fa422c0fae7" +checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148" dependencies = [ "dlib", "log", @@ -5456,19 +5155,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -5484,12 +5173,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - [[package]] name = "which" version = "4.4.2" @@ -5520,20 +5203,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eafc5f679c576995526e81635d0cf9695841736712b4e892f87abbe6fed3f28" -dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -5549,8 +5223,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ "windows-core 0.54.0", - "windows-implement", - "windows-interface", + "windows-implement 0.53.0", + "windows-interface 0.53.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", "windows-targets 0.52.6", ] @@ -5573,6 +5257,18 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface 0.56.0", + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-implement" version = "0.53.0" @@ -5581,7 +5277,18 @@ checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", +] + +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", ] [[package]] @@ -5592,7 +5299,18 @@ checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.76", ] [[package]] @@ -5631,6 +5349,15 @@ 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]] name = "windows-targets" version = "0.42.2" @@ -5811,38 +5538,41 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.29.15" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" dependencies = [ "ahash", - "android-activity 0.5.2", + "android-activity", "atomic-waker", "bitflags 2.6.0", + "block2", "bytemuck", - "calloop", - "cfg_aliases 0.1.1", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", "core-foundation", "core-graphics", "cursor-icon", - "icrate 0.0.4", + "dpi", "js-sys", "libc", - "log", "memmap2 0.9.4", - "ndk 0.8.0", - "ndk-sys 0.5.0+25.2.9519653", - "objc2 0.4.1", - "once_cell", + "ndk 0.9.0", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", "orbclient", "percent-encoding", - "raw-window-handle 0.5.2", - "raw-window-handle 0.6.2", - "redox_syscall 0.3.5", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", "rustix 0.38.34", "sctk-adwaita", "smithay-client-toolkit", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -5851,10 +5581,10 @@ dependencies = [ "wayland-protocols", "wayland-protocols-plasma", "web-sys", - "web-time 0.2.4", - "windows-sys 0.48.0", + "web-time", + "windows-sys 0.52.0", "x11-dl", - "x11rb 0.13.1", + "x11rb", "xkbcommon-dl", ] @@ -5869,9 +5599,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -5892,7 +5622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98785a09322d7446e28a13203d2cae1059a0dd3dfb32cb06d0a225f023d8286" dependencies = [ "libc", - "x11rb 0.13.1", + "x11rb", ] [[package]] @@ -5906,23 +5636,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" -dependencies = [ - "as-raw-xcb-connection", - "gethostname 0.3.0", - "libc", - "libloading 0.7.4", - "nix 0.26.4", - "once_cell", - "winapi", - "winapi-wsapoll", - "x11rb-protocol 0.12.0", -] - [[package]] name = "x11rb" version = "0.13.1" @@ -5930,21 +5643,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "as-raw-xcb-connection", - "gethostname 0.4.3", + "gethostname", "libc", - "libloading 0.8.4", + "libloading", "once_cell", "rustix 0.38.34", - "x11rb-protocol 0.13.1", -] - -[[package]] -name = "x11rb-protocol" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix 0.26.4", + "x11rb-protocol", ] [[package]] @@ -5966,18 +5670,18 @@ dependencies = [ [[package]] name = "xcursor" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6011,10 +5715,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] -name = "xml-rs" +name = "xml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "ede1c99c55b4b3ad0349018ef0eccbe954ce9c342334410707ee87177fcf2ab4" +dependencies = [ + "xml-rs", +] + +[[package]] +name = "xml-rs" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "539a77ee7c0de333dcc6da69b177380a0b81e0dacfa4f7344c465a36871ee601" [[package]] name = "xmlwriter" @@ -6022,6 +5735,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "xspf" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17166c19b5513724d4b2d60d8c9aa0576b0d15e078671551fb1bae4c46df22fa" +dependencies = [ + "xml", +] + [[package]] name = "zbus" version = "3.15.2" @@ -6094,6 +5816,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -6105,7 +5828,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.76", ] [[package]] @@ -6114,20 +5837,11 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - [[package]] name = "zune-jpeg" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 943e991..978e296 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,20 +10,17 @@ members = [ [package] name = "lonelyradio" description = "TCP radio for lonely ones" -version = "0.6.1" +version = "0.7.0" edition = "2021" license = "MIT" authors = ["Ivan Bushchik "] repository = "https://github.com/ivabus/lonelyradio" [dependencies] -lonelyradio_types = { version = "0.6.0", path = "./lonelyradio_types" } +lonelyradio_types = { version = "0.7.0", path = "./lonelyradio_types" } rand = "0.8.5" clap = { version = "4.4.18", features = ["derive"] } tokio = { version = "1.35.1", features = [ - "sync", - "fs", - "io-util", "net", "rt-multi-thread", "rt", @@ -42,14 +39,27 @@ lofty = "0.18.2" async-stream = "0.3.5" tokio-stream = { version = "0.1.15", features = ["sync"] } futures-util = "0.3.30" -samplerate = "0.2.4" once_cell = "1.19.0" -flacenc = { version = "0.4.0", default-features = false } -image = "0.25.1" +image = { version = "0.25.1", default-features = false, features = ["png", "jpeg", "bmp"]} +xspf = "0.4.0" +url = "2.5.2" +samplerate = "0.2.4" -[build-dependencies] -cc = "1.0.98" +# Optional encoders +flacenc = { version = "0.4.0", default-features = false, optional = true } +alac-encoder = { version = "0.3.0", optional = true } +vorbis_rs = {version = "0.5.4", optional = true } -[profile.release] +[features] +default = ["all-lossless", "all-lossy"] +all-lossless = ["alac", "flac"] +all-lossy = ["vorbis"] +alac = ["dep:alac-encoder"] +flac = ["dep:flacenc"] +vorbis = ["dep:vorbis_rs"] + +[profile.distribute] +inherits = "release" opt-level = 3 strip = true +lto = "fat" diff --git a/README.md b/README.md index 7b07175..8439e90 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,33 @@ -# lonelyradio +# lonelyradio Music Streamer -Broadcast lossless audio over the internet. +Shuffles through your [XSPF playlists](https://www.xspf.org) or your entire library. -Decodes audio streams using [symphonia](https://github.com/pdeljanov/Symphonia). +Decodes audio streams using [symphonia](https://github.com/pdeljanov/Symphonia) (supported [decoders](https://github.com/pdeljanov/Symphonia?tab=readme-ov-file#codecs-decoders) and [demuxers](https://github.com/pdeljanov/Symphonia?tab=readme-ov-file#formats-demuxers)) -Optionally transcodes audio into and from FLAC using [flacenc-rs](https://github.com/yotarok/flacenc-rs/) and [claxon](https://github.com/ruuda/claxon). +Streams music using [FLAC](https://crates.io/crates/flacenc), [ALAC](https://crates.io/crates/alac-encoder), [Vorbis](https://crates.io/crates/vorbis_rs) or raw PCM on client’s requests. -## Install server +### Install server ```shell -cargo install --git https://github.com/ivabus/lonelyradio --tag 0.6.1 lonelyradio +cargo install --git https://github.com/ivabus/lonelyradio --tag 0.7.0 lonelyradio ``` -## Run +### Run ``` lonelyradio ``` -All files (recursively) will be shuffled and played back. Public log will be displayed to stdout, private to stderr. +All files (recursively) will be shuffled and played back. Log will be displayed to stdout. Look into `--help` for detailed info +#### Playlists + +Specify a directory with playlists with `--playlist-dir`. lonelyradio will scan them on startup and play them on clients’ requests. + +Only the `` and (playlist's) element would be used and only `file://` is supported. + ### Clients #### monoclient-x @@ -37,42 +43,37 @@ Look into `--help` for detailed info [monoclient-s](./monoclient-s) is a GUI player for lonelyradio built with [Slint](https://slint.dev) - ##### Install ```shell -cargo install --git https://github.com/ivabus/lonelyradio --tag 0.6.1 monoclient-s +cargo install --git https://github.com/ivabus/lonelyradio --tag 0.7.0 monoclient-s ``` You may need to install some dependencies for Slint. Desktop integration will be added later. -##### Build - -``` -cargo build -p monoclient-s -``` - -You may need to install some dependencies for Slint. - #### monoclient [monoclient](./monoclient) is a CLI player for lonelyradio that uses [monolib](./monolib) +##### Install monoclient + +```shell +cargo install --git https://github.com/ivabus/lonelyradio --tag 0.7.0 monoclient +``` + +#### Usage + ```shell monoclient : ``` -##### Install monoclient - -```shell -cargo install --git https://github.com/ivabus/lonelyradio --tag 0.6.1 monoclient -``` +Look into `--help` for detailed info on usage. # Other things -[monoloader](./monoloader) is a tool, that allows you to download individual audio tracks from lonelyradio-compatible servers. +[monoloader](./monoloader) is a tool that allows you to download individual audio tracks from lonelyradio-compatible servers. [monolib](./monolib) provides a C API compatible with lonelyradio for creating custom clients. @@ -82,10 +83,6 @@ The full protocol specification will be available later. If you would like to le As lonelyradio has not yet reached its first major release, the API may (and will) break at any point. -### Microphone server - -Experimental (and uncompatible with versions 0.6+) server (lonelyradio-compatible) for streaming audio from your microphone is available in the [microserve](./microserve) crate. - ## License lonelyradio, monolib and monoclient, as well as all other crates in this repository, are licensed under the terms of the [MIT license](./LICENSE). diff --git a/lonelyradio_types/Cargo.toml b/lonelyradio_types/Cargo.toml index 327931c..00a235d 100644 --- a/lonelyradio_types/Cargo.toml +++ b/lonelyradio_types/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "lonelyradio_types" +edition = "2021" +version = "0.7.0" +authors = ["Ivan Bushchik "] description = "Shared types for lonelyradio" license = "MIT" -version = "0.6.0" -edition = "2021" -authors = ["Ivan Bushchik "] repository = "https://github.com/ivabus/lonelyradio" + [dependencies] -serde = { version = "1.0.197", features = ["derive"] } -serde_bytes = "0.11.15" +serde = {version = "1.0.209", features = ["derive"]} +serde_bytes = {version = "0.11.15"} diff --git a/lonelyradio_types/src/lib.rs b/lonelyradio_types/src/lib.rs index a6bbc09..8e40613 100644 --- a/lonelyradio_types/src/lib.rs +++ b/lonelyradio_types/src/lib.rs @@ -1,9 +1,39 @@ use serde::{Deserialize, Serialize}; -pub const HELLO_MAGIC: u64 = 0x104e1374d10; +pub const HELLO_MAGIC: &[u8; 8] = b"lonelyra"; #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] -pub enum Message { +pub enum Request { + // Just play what server wants you to give + #[serde(rename = "p", alias = "Play")] + Play(Settings), + #[serde(rename = "lpl", alias = "ListPlaylist")] + ListPlaylist, + #[serde(rename = "ppl", alias = "PlayPlaylist")] + PlayPlaylist(String, Settings), +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub struct PlaylistResponce { + pub playlists: Vec, +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub enum RequestResult { + Ok, + Playlist(PlaylistResponce), + Error(RequestError), +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub enum RequestError { + NoSuchPlaylist, + WrongCoverSize, + UnsupportedEncoder, +} + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] +pub enum PlayMessage { T(TrackMetadata), F(FragmentMetadata), } @@ -11,10 +41,10 @@ pub enum Message { #[repr(C)] #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct Settings { - #[serde(rename = "e")] + #[serde(rename = "e", alias = "encoder")] pub encoder: Encoder, - #[serde(rename = "co")] + #[serde(rename = "co", alias = "cover")] pub cover: i32, } @@ -22,6 +52,9 @@ pub struct Settings { pub struct ServerCapabilities { #[serde(rename = "e")] pub encoders: Vec, + // Will be used in the next updates + //#[serde(rename = "ar")] + //pub available_requests: Vec, } #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] @@ -42,22 +75,47 @@ pub struct TrackMetadata { pub album: String, #[serde(rename = "mar")] pub artist: String, - #[serde(rename = "co")] - #[serde(with = "serde_bytes")] + + #[serde( + rename = "co", + skip_serializing_if = "Option::is_none", + with = "serde_bytes", + default = "none" + )] pub cover: Option>, + + pub id: u8, } +// WavPack, Opus and Aac are currently unimplemented. #[repr(u8)] #[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq)] pub enum Encoder { Pcm16 = 0, PcmFloat = 1, Flac = 2, + Alac = 3, + WavPack = 4, + Opus = 5, + Aac = 6, + Vorbis = 7, } #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] pub struct FragmentMetadata { - // In bytes - #[serde(rename = "l")] + // In bytes or samples, depends on encoder: Pcm* - samples, any compressed - bytes + #[serde(rename = "le")] pub length: u64, + + #[serde( + rename = "mc", + skip_serializing_if = "Option::is_none", + with = "serde_bytes", + default = "none" + )] + pub magic_cookie: Option>, +} + +fn none() -> Option> { + None } diff --git a/microserve/Cargo.lock b/microserve/Cargo.lock deleted file mode 100644 index 58cb0cf..0000000 --- a/microserve/Cargo.lock +++ /dev/null @@ -1,886 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alsa" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" -dependencies = [ - "alsa-sys", - "bitflags 2.5.0", - "libc", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.5.0", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - -[[package]] -name = "cc" -version = "1.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" -dependencies = [ - "jobserver", - "libc", - "once_cell", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "coreaudio-rs" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2", - "ndk", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows", -] - -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "either" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets 0.52.5", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "lonelyradio_types" -version = "0.4.0" -dependencies = [ - "serde", -] - -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "microserve" -version = "0.1.0" -dependencies = [ - "cpal", - "lonelyradio_types", -] - -[[package]] -name = "microserve-session" -version = "0.1.0" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.5.0", - "jni-sys", - "log", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[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", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "serde" -version = "1.0.202" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.202" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "syn" -version = "2.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "toml_datetime" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "windows" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" -dependencies = [ - "windows-core", - "windows-targets 0.52.5", -] - -[[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.5", -] - -[[package]] -name = "windows-result" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" -dependencies = [ - "windows-targets 0.52.5", -] - -[[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.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.5", -] - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", -] - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[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.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] diff --git a/microserve/Cargo.toml b/microserve/Cargo.toml deleted file mode 100644 index ee4a4e7..0000000 --- a/microserve/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "microserve" -version = "0.5.0" -license = "MIT" -edition = "2021" -authors = ["Ivan Bushchik "] -repository = "https://github.com/ivabus/lonelyradio" - - -[dependencies] -cpal = "0.15.3" -lonelyradio_types = { path = "../lonelyradio_types" } -once_cell = "1.19.0" -queues = "1.1.0" -rmp-serde = "1.3.0" -tokio = { version = "1.35.1", features = [ - "sync", - "fs", - "io-util", - "net", - "rt-multi-thread", - "rt", - "macros", -] } diff --git a/microserve/src/main.rs b/microserve/src/main.rs deleted file mode 100644 index 19c1c18..0000000 --- a/microserve/src/main.rs +++ /dev/null @@ -1,96 +0,0 @@ -use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use lonelyradio_types::{FragmentMetadata, TrackMetadata}; -use once_cell::sync::Lazy; -use std::collections::VecDeque; -use std::io::Write; -use std::sync::Arc; -use std::sync::Mutex; -use std::sync::RwLock; -use std::time::Duration; -use tokio::net::TcpListener; - -static QUEUE: Lazy>>>> = - Lazy::new(|| Arc::new(RwLock::new(VecDeque::new()))); - -static START_INDEX: Mutex = Mutex::new(0); - -#[tokio::main] -async fn main() { - tokio::spawn(listen_mic()); - println!("Started buffering"); - let listener = TcpListener::bind("0.0.0.0:5894").await.unwrap(); - std::thread::sleep(Duration::from_secs(5)); - tokio::spawn(update_start()); - println!("Accepting connections"); - loop { - let (socket, _) = listener.accept().await.unwrap(); - let socket = socket.into_std().unwrap(); - tokio::spawn(stream(socket)); - } -} - -async fn update_start() { - loop { - std::thread::sleep(Duration::from_secs(1)); - *START_INDEX.lock().unwrap() = QUEUE.read().unwrap().len() - 5; - } -} - -async fn stream(mut s: std::net::TcpStream) { - println!("Playing for {}", s.peer_addr().unwrap()); - let md = lonelyradio_types::Message::T(TrackMetadata { - cover: None, - encoder: lonelyradio_types::Encoder::Pcm, - track_length_secs: 0, - track_length_frac: 0.0, - channels: 1, - sample_rate: 44100, - title: "microserve instance".to_string(), - album: "".to_string(), - artist: "".to_string(), - }); - s.write_all(rmp_serde::to_vec(&md).unwrap().as_slice()).unwrap(); - let mut ind = *START_INDEX.lock().unwrap(); - dbg!(ind); - loop { - let front = QUEUE.read().unwrap()[ind].clone(); - ind += 1; - let md = lonelyradio_types::Message::F(FragmentMetadata { - length: front.len() as u64, - }); - s.write_all(rmp_serde::to_vec(&md).unwrap().as_slice()).unwrap(); - - if s.write_all(unsafe { front.as_slice().align_to::().1 }).is_err() { - return; - }; - while ind >= QUEUE.read().unwrap().len() - 5 { - std::thread::sleep(Duration::from_millis(100)) - } - } -} - -async fn listen_mic() { - let host = cpal::default_host(); - - let device = host.default_input_device().unwrap(); - let config = device.default_input_config().unwrap(); - let stream = match config.sample_format() { - cpal::SampleFormat::F32 => device.build_input_stream( - &config.into(), - move |data: &[f32], _: &_| { - let samples = data.iter().map(|x| (*x * 32767.0) as i16).collect(); - QUEUE.write().unwrap().push_back(samples); - }, - |e| eprintln!("Error while reading: {}", e), - None, - ), - _ => { - unimplemented!() - } - } - .unwrap(); - loop { - stream.play().unwrap(); - std::thread::sleep(Duration::from_millis(100)); - } -} diff --git a/monoclient-s/Cargo.toml b/monoclient-s/Cargo.toml index 4accef0..b06ea91 100644 --- a/monoclient-s/Cargo.toml +++ b/monoclient-s/Cargo.toml @@ -1,17 +1,13 @@ [package] name = "monoclient-s" description = "Client for lonelyradio built with Slint" -version = "0.6.0" +version = "0.7.0" edition = "2021" [dependencies] -slint = { version = "1.6", features = ["backend-android-activity-06"] } -monolib = { path = "../monolib", version = "0.6.0" } -lonelyradio_types = { version = "0.6.0", path = "../lonelyradio_types" } -zune-jpeg = "0.4.11" - -[lib] -crate-type = [ "cdylib" ] +slint = { version = "1.6" } +monolib = { path = "../monolib", version = "0.7.0" } +zune-jpeg = "0.4.13" [package.metadata.bundle] name = "monoclient-s" diff --git a/monoclient-s/src/app.rs b/monoclient-s/src/app.rs deleted file mode 100644 index e08b3f3..0000000 --- a/monoclient-s/src/app.rs +++ /dev/null @@ -1,227 +0,0 @@ -use std::time::Duration; - -use monolib::State; -use slint::{Image, Rgb8Pixel, Rgba8Pixel, SharedPixelBuffer, Weak}; - -slint::slint! { - import { AboutSlint, Button, VerticalBox, GroupBox, Slider } from "std-widgets.slint"; -export component MainWindow inherits Window { - max-height: self.preferred-height; - callback play; - callback stop; - callback next; - callback change_volume(float); - callback text_edited; - - in-out property addr: address.text; - in-out property mtitle: ""; - in-out property malbum: ""; - in-out property martist: ""; - in-out property volume: svolume.value; - in-out property start_enabled: false; - in-out property playing: false; - in-out property paused: false; - in property cover: @image-url("lonelyradio.png"); - - title: "monoclient-s"; - min-width: 192px; - max-width: 768px; - VerticalBox { - alignment: center; - spacing: 0px; - - Image { - source: cover; - max-height: 192px; - max-width: 192px; - min-height: 192px; - min-width: 192px; - } - - GroupBox{ - max-width: 768px; - address := TextInput { - text: ""; - horizontal-alignment: center; - height: 1.25rem; - - accepted => { - self.clear_focus() - } - - edited => { - text_edited() - } - } - } - - VerticalLayout { - max-width: 512px; - - VerticalLayout { - spacing: 4px; - Button { - max-width: 256px; - text: playing ? (paused ? "Play" : "Pause") : "Start"; - enabled: start_enabled || playing; - clicked => { - play() - } - } - HorizontalLayout { - spacing: 4px; - max-width: 256px; - Button { - text: "Stop"; - enabled: playing && !paused; - clicked => { - stop() - } - } - Button { - text: "Next"; - enabled: playing && !paused; - clicked => { - next() - } - } - } - svolume := Slider { - value: 255; - maximum: 255; - changed(f) => { - change_volume(f) - } - } - } - } - - VerticalLayout { - padding: 4px; - tartist := Text { - height: 1.25rem; - font-weight: 600; - text: martist; - overflow: elide; - } - talbum := Text { - height: 1.25rem; - text: malbum; - overflow: elide; - } - ttitle := Text { - height: 1.25rem; - text: mtitle; - overflow: elide; - } - } - } -} -} - -fn start_playback(window_weak: Weak) { - let window = window_weak.upgrade().unwrap(); - let addr = window.get_addr().to_string(); - let handle = std::thread::spawn(move || { - monolib::run( - &addr, - lonelyradio_types::Settings { - encoder: lonelyradio_types::Encoder::Flac, - cover: 512, - }, - ) - }); - std::thread::sleep(Duration::from_millis(166)); - if handle.is_finished() { - window.set_playing(false); - return; - } - window.set_playing(true); - window.set_paused(false); - while monolib::get_metadata().is_none() {} - monolib::set_volume(window.get_volume() as u8); -} - -pub fn _main() { - let window = MainWindow::new().unwrap(); - - let window_weak = window.as_weak(); - window.on_text_edited(move || { - let window = window_weak.upgrade().unwrap(); - let addr = window.get_addr().to_string(); - window.set_start_enabled(addr.contains(':')); - }); - - let window_weak = window.as_weak(); - window.on_play(move || match monolib::get_state() { - State::NotStarted => start_playback(window_weak.clone()), - State::Paused => { - let window = window_weak.upgrade().unwrap(); - window.set_paused(false); - monolib::toggle(); - } - State::Resetting => {} - State::Playing => { - let window = window_weak.upgrade().unwrap(); - window.set_paused(true); - monolib::toggle() - } - }); - - let window_weak = window.as_weak(); - window.on_next(move || { - monolib::stop(); - start_playback(window_weak.clone()) - }); - let window_weak = window.as_weak(); - window.on_stop(move || { - let window = window_weak.upgrade().unwrap(); - window.set_playing(false); - window.set_martist("".into()); - window.set_malbum("".into()); - window.set_mtitle("".into()); - window.set_cover(Image::from_rgba8(SharedPixelBuffer::::new(1, 1))); - monolib::stop(); - }); - window.on_change_volume(move |vol| monolib::set_volume(vol as u8)); - let window_weak = window.as_weak(); - std::thread::spawn(move || loop { - let window = window_weak.clone(); - while monolib::get_metadata().is_none() { - std::thread::sleep(Duration::from_millis(25)) - } - let md = monolib::get_metadata().unwrap(); - let _md = md.clone(); - if let Some(jpeg) = md.cover { - let mut decoder = zune_jpeg::JpegDecoder::new(jpeg); - decoder.decode_headers().unwrap(); - let (w, h) = decoder.dimensions().unwrap(); - let decoded = decoder.decode().unwrap(); - let mut pixel_buffer = SharedPixelBuffer::::new(w as u32, h as u32); - pixel_buffer.make_mut_bytes().copy_from_slice(&decoded); - window - .upgrade_in_event_loop(|win| { - let image = Image::from_rgb8(pixel_buffer); - win.set_cover(image); - }) - .unwrap(); - } else { - window - .upgrade_in_event_loop(|win| { - win.set_cover(Image::from_rgba8(SharedPixelBuffer::::new(1, 1))); - }) - .unwrap(); - } - slint::invoke_from_event_loop(move || { - let window = window.unwrap(); - window.set_martist(md.artist.clone().into()); - window.set_malbum(md.album.clone().into()); - window.set_mtitle(md.title.clone().into()); - }) - .unwrap(); - while monolib::get_metadata() == Some(_md.clone()) { - std::thread::sleep(Duration::from_millis(100)) - } - }); - window.run().unwrap(); -} diff --git a/monoclient-s/src/lib.rs b/monoclient-s/src/lib.rs deleted file mode 100644 index 87bfb0e..0000000 --- a/monoclient-s/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod app; -#[cfg(target_os = "andoid")] -#[no_mangle] -fn android_main(app: slint::android::AndroidApp) { - slint::android::init(app).unwrap(); - app::_main(); -} diff --git a/monoclient-s/src/main.rs b/monoclient-s/src/main.rs index fb31ded..b7c5f59 100644 --- a/monoclient-s/src/main.rs +++ b/monoclient-s/src/main.rs @@ -1,4 +1,262 @@ -mod app; -fn main() { - app::_main() +use std::time::Duration; + +use monolib::State; +use slint::{ + Image, ModelRc, Rgb8Pixel, Rgba8Pixel, SharedPixelBuffer, SharedString, VecModel, Weak, +}; + +slint::slint! { + import { ComboBox, Button, VerticalBox, GroupBox, Slider } from "std-widgets.slint"; +export component MainWindow inherits Window { + max-height: self.preferred-height; + callback play; + callback stop; + callback next; + callback refreshp; + callback change_volume(float); + callback text_edited; + + in-out property addr: address.text; + in-out property mtitle: ""; + in-out property malbum: ""; + in-out property martist: ""; + in-out property volume: svolume.value; + in-out property start_enabled: false; + in-out property playing: false; + in-out property paused: false; + in property cover: @image-url("lonelyradio.png"); + in property <[string]> playlists: ["All tracks"]; + in-out property selected_playlist: selected.current-value; + + title: "monoclient-s"; + min-width: 192px; + max-width: 768px; + VerticalBox { + alignment: center; + spacing: 0px; + + Image { + source: cover; + max-height: 192px; + max-width: 192px; + min-height: 192px; + min-width: 192px; + } + + GroupBox{ + max-width: 768px; + address := TextInput { + text: ""; + horizontal-alignment: center; + height: 1.25rem; + + accepted => { + self.clear_focus() + } + + edited => { + text_edited(); + } + } + } + + VerticalLayout { + max-width: 512px; + + VerticalLayout { + spacing: 4px; + Button { + max-width: 256px; + text: playing ? (paused ? "Play" : "Pause") : "Start"; + enabled: start_enabled || playing; + clicked => { + play() + } + } + HorizontalLayout { + spacing: 4px; + max-width: 256px; + Button { + text: "Stop"; + enabled: playing && !paused; + clicked => { + stop() + } + } + Button { + text: "Next"; + enabled: playing && !paused; + clicked => { + next() + } + } + } + HorizontalLayout { + selected := ComboBox { + model: playlists; + current-value: "All tracks"; + selected() => { + self.clear_focus() + } + } + + } + svolume := Slider { + value: 255; + maximum: 255; + changed(f) => { + change_volume(f) + } + } + } + } + + VerticalLayout { + padding: 4px; + tartist := Text { + height: 1.25rem; + font-weight: 600; + text: martist; + overflow: elide; + } + talbum := Text { + height: 1.25rem; + text: malbum; + overflow: elide; + } + ttitle := Text { + height: 1.25rem; + text: mtitle; + overflow: elide; + } + } + } +} +} + +#[allow(dead_code)] +fn start_playback(window_weak: Weak) { + let window = window_weak.upgrade().unwrap(); + let addr = window.get_addr().to_string(); + let playlist = window.get_selected_playlist(); + let handle = std::thread::spawn(move || { + monolib::run( + &addr, + lonelyradio_types::Settings { + encoder: lonelyradio_types::Encoder::Flac, + cover: 512, + }, + if playlist == "All tracks" { + "" + } else { + &playlist + }, + ) + }); + std::thread::sleep(Duration::from_millis(166)); + if handle.is_finished() { + window.set_playing(false); + return; + } + window.set_playing(true); + window.set_paused(false); + while monolib::get_metadata().is_none() {} + monolib::set_volume(window.get_volume() as u8); +} + +pub fn main() { + let window = MainWindow::new().unwrap(); + + let window_weak = window.as_weak(); + window.on_text_edited(move || { + let window = window_weak.upgrade().unwrap(); + let addr = window.get_addr().to_string(); + if addr.contains(':') { + window.set_start_enabled(true); + + let playlists = match monolib::list_playlists(&window.get_addr()) { + Some(v) => [vec!["All tracks".to_string()], v].concat(), + None => vec!["All tracks".to_string()], + }; + window.set_playlists(ModelRc::new(VecModel::from( + playlists.iter().map(SharedString::from).collect::>(), + ))); + } else { + window.set_start_enabled(false); + } + }); + + let window_weak = window.as_weak(); + window.on_play(move || match monolib::get_state() { + State::NotStarted => start_playback(window_weak.clone()), + State::Paused => { + let window = window_weak.upgrade().unwrap(); + window.set_paused(false); + monolib::toggle(); + } + State::Resetting => {} + State::Playing => { + let window = window_weak.upgrade().unwrap(); + window.set_paused(true); + monolib::toggle() + } + }); + + let window_weak = window.as_weak(); + window.on_next(move || { + monolib::stop(); + start_playback(window_weak.clone()) + }); + let window_weak = window.as_weak(); + window.on_stop(move || { + let window = window_weak.upgrade().unwrap(); + window.set_playing(false); + window.set_martist("".into()); + window.set_malbum("".into()); + window.set_mtitle("".into()); + window.set_cover(Image::from_rgba8(SharedPixelBuffer::::new(1, 1))); + monolib::stop(); + }); + window.on_change_volume(move |vol| monolib::set_volume(vol as u8)); + + let window_weak = window.as_weak(); + std::thread::spawn(move || loop { + let window = window_weak.clone(); + while monolib::get_metadata().is_none() { + std::thread::sleep(Duration::from_millis(25)) + } + let md = monolib::get_metadata().unwrap(); + let _md = md.clone(); + if let Some(jpeg) = md.cover { + let mut decoder = zune_jpeg::JpegDecoder::new(jpeg); + decoder.decode_headers().unwrap(); + let (w, h) = decoder.dimensions().unwrap(); + let decoded = decoder.decode().unwrap(); + let mut pixel_buffer = SharedPixelBuffer::::new(w as u32, h as u32); + pixel_buffer.make_mut_bytes().copy_from_slice(&decoded); + window + .upgrade_in_event_loop(|win| { + let image = Image::from_rgb8(pixel_buffer); + win.set_cover(image); + }) + .unwrap(); + } else { + window + .upgrade_in_event_loop(|win| { + win.set_cover(Image::from_rgba8(SharedPixelBuffer::::new(1, 1))); + }) + .unwrap(); + } + slint::invoke_from_event_loop(move || { + let window = window.unwrap(); + window.set_martist(md.artist.clone().into()); + window.set_malbum(md.album.clone().into()); + window.set_mtitle(md.title.clone().into()); + }) + .unwrap(); + while monolib::get_metadata() == Some(_md.clone()) { + std::thread::sleep(Duration::from_millis(100)) + } + }); + window.run().unwrap(); } diff --git a/monoclient-x/monoclient-x/Metadata.swift b/monoclient-x/monoclient-x/Metadata.swift index fad7c02..22baf63 100644 --- a/monoclient-x/monoclient-x/Metadata.swift +++ b/monoclient-x/monoclient-x/Metadata.swift @@ -47,7 +47,7 @@ struct Cover { self.cover = PlatformImage(cgImage: CGImage(jpegDataProviderSource: CGDataProvider(data: data)!, decode: nil, shouldInterpolate: false, intent: CGColorRenderingIntent.absoluteColorimetric)!).preparingForDisplay()! #endif // deallocating memory - c_drop(cov.bytes, Int(cov.length)) + c_drop(cov.bytes, UInt(Int(cov.length))) print(self.cover.size) } else { diff --git a/monoclient-x/monoclient-x/Player.swift b/monoclient-x/monoclient-x/Player.swift index 3183b76..6c21ced 100644 --- a/monoclient-x/monoclient-x/Player.swift +++ b/monoclient-x/monoclient-x/Player.swift @@ -29,6 +29,11 @@ enum EncoderType: UInt8 { case PCM16 = 0 case PCMFloat = 1 case FLAC = 2 + case Alac = 3 + //WavPack = 4, + //Opus = 5, + //Aac = 6, + case Vorbis = 7 } enum CoverSize: Int32 { @@ -40,110 +45,166 @@ enum CoverSize: Int32 { case NoCover = -1 } +struct PlayList: Identifiable, Hashable { + var id: Int + + var name: String +} + struct Settings { var encoder: EncoderType = EncoderType.FLAC var cover_size: CoverSize = CoverSize.High/* - init(enc: EncoderType, cov: CoverSize) { - encoder = enc - cover_size = cov - }*/ + init(enc: EncoderType, cov: CoverSize) { + encoder = enc + cover_size = cov + }*/ } +#if os(tvOS) +typealias MyStack = HStack +#else +typealias MyStack = VStack +#endif + struct Player: View { - let timer_state = Timer.publish(every: 0.25, on: .main, in: .common).autoconnect() - let timer_meta = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect() + let timer_playlists = Timer.publish(every: 5, on: .main, in: .common).autoconnect() @State var metadata: Metadata = Metadata(title: "", album: "", artist: "") @State var prev_meta: Metadata = Metadata(title: "", album: "", artist: "") @State var cover: Cover = Cover(cover: PlatformImage()) @State var state: PlayerState = PlayerState.NotStarted @State var settings: Settings = Settings.init() + @State var playlists: [PlayList] = [PlayList(id: 0, name: "All tracks")] + @State var playlist: PlayList = PlayList(id: 0, name: "All tracks") @AppStorage("ContentView.server") var server: String = "" var body: some View { - VStack(alignment: .center) { + + MyStack(alignment: .center) { + + VStack(alignment: .center) { + #if os(macOS) - Image(nsImage: cover.cover) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(minWidth: 256, maxWidth: 256, minHeight: 256, maxHeight: 256) - .frame(width: 256.0, height: 256.0) - .clipShape(.rect(cornerRadius: 24)) - .shadow(radius: 16) - .padding(16) + Image(nsImage: cover.cover) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(minWidth: 256, maxWidth: 256, minHeight: 256, maxHeight: 256) + .frame(width: 256.0, height: 256.0) + .clipShape(.rect(cornerRadius: 24)) + .shadow(radius: 16) + .padding(16) #else - Image(uiImage: cover.cover) - .resizable() - .aspectRatio(contentMode: .fit) - .frame(minWidth: 256, maxWidth: 256, minHeight: 256, maxHeight: 256) - .frame(width: 256.0, height: 256.0) - .clipShape(.rect(cornerRadius: 24)) - .shadow(radius: 16) - .padding(16) + Image(uiImage: cover.cover) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(minWidth: 256, maxWidth: 256, minHeight: 256, maxHeight: 256) + .frame(width: 256.0, height: 256.0) + .clipShape(.rect(cornerRadius: 24)) + .shadow(radius: 16) + .padding(16) #endif - - VStack(alignment: .center){ - Text(metadata.title).bold() - Text(metadata.album) - - Text(metadata.artist) - }.frame(minHeight: 64) - - TextField( - "Server", - text: $server, - onCommit: { -#if os(macOS) - DispatchQueue.main.async { - NSApp.keyWindow?.makeFirstResponder(nil) + VStack(alignment: .center){ + Text(metadata.title).bold() + + Text(metadata.album) + + Text(metadata.artist) + }.frame(minHeight: 64).onReceive(timer_state) { _ in + metadata.update() + if prev_meta != metadata { + prev_meta = metadata + cover.update() } + let image = cover.cover + let mediaArtwork = MPMediaItemArtwork(boundsSize: image.size) { (size: CGSize) -> PlatformImage in + return image + } + + +#if os(macOS) + MPNowPlayingInfoCenter.default().playbackState = state == PlayerState.Playing ? .playing : .paused #endif + + let nowPlayingInfo: [String: Any] = [ + MPMediaItemPropertyArtist: metadata.artist, + MPMediaItemPropertyAlbumTitle: metadata.album, + MPMediaItemPropertyTitle: metadata.title, + MPMediaItemPropertyArtwork: mediaArtwork, + MPNowPlayingInfoPropertyIsLiveStream: true, + MPMediaItemPropertyPlaybackDuration: c_get_metadata_length(), + + ] + MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo } - ) - .disableAutocorrection(true) - .frame(width: 256) - .textFieldStyle(.roundedBorder) - .padding(16) - .multilineTextAlignment(.center) - - HStack(spacing: 8) { - Button(action: stop){ - Image(systemName: "stop.fill").padding(4).frame(width: 32, height: 24) - } - .disabled(state == PlayerState.NotStarted) - .buttonStyle(.bordered) - .font(.system(size: 20)) - .buttonBorderShape(.capsule) - Button(action: play){ - Image(systemName: state == PlayerState.NotStarted ? "infinity.circle" : (state == PlayerState.Playing) ? "pause.circle.fill" : "play.circle" ) - .font(.system(size: 30)) - .padding(4) - } - .buttonStyle(.borderedProminent) - .buttonBorderShape(.capsule) + TextField( + "Server", + text: $server, + onCommit: { +#if os(macOS) + DispatchQueue.main.async { + NSApp.keyWindow?.makeFirstResponder(nil) + } +#endif + } + ) + .disableAutocorrection(true) + .frame(width: 256) + .textFieldStyle(.roundedBorder) + .padding(16) + .multilineTextAlignment(.center) - Button(action: next){ - Image(systemName: "forward.end.fill").padding(4).frame(width: 32, height: 24) - }.disabled(state == PlayerState.NotStarted) + HStack(spacing: 8) { + Button(action: stop){ + Image(systemName: "stop.fill").padding(4).frame(width: 32, height: 24) + } + .disabled(state == PlayerState.NotStarted) .buttonStyle(.bordered) .font(.system(size: 20)) .buttonBorderShape(.capsule) - } - Menu { - Picker("Encoder", selection: $settings.encoder) { - Text("PCM (s16)") - .tag(EncoderType.PCM16) - Text("PCM (f32)") - .tag(EncoderType.PCMFloat) - Text("FLAC (s24)") - .tag(EncoderType.FLAC) - }.pickerStyle(.menu) - - Picker("Cover size", selection: $settings.cover_size) { + + Button(action: play){ + Image(systemName: state == PlayerState.NotStarted ? "infinity.circle" : (state == PlayerState.Playing) ? "pause.circle.fill" : "play.circle" ) + .font(.system(size: 30)) + .padding(4) + } + .buttonStyle(.borderedProminent) + .buttonBorderShape(.capsule) + + Button(action: next){ + Image(systemName: "forward.end.fill").padding(4).frame(width: 32, height: 24) + }.disabled(state == PlayerState.NotStarted) + .buttonStyle(.bordered) + .font(.system(size: 20)) + .buttonBorderShape(.capsule) + }.onReceive(timer_state) { _ in + state.update() + } + Menu { + Picker("Playlist", selection: $playlist) { + ForEach ($playlists) { pl in + Text(pl.wrappedValue.name).tag(pl.wrappedValue) + } + + }.pickerStyle(.menu) + + Picker("Encoder", selection: $settings.encoder) { + Text("PCM (s16)") + .tag(EncoderType.PCM16) + Text("PCM (f32)") + .tag(EncoderType.PCMFloat) + Text("FLAC (s24)") + .tag(EncoderType.FLAC) + Text("ALAC (s16)") + .tag(EncoderType.Alac) + Text("Vorbis (lossy)") + .tag(EncoderType.Vorbis) + }.pickerStyle(.menu) + + Picker("Cover size", selection: $settings.cover_size) { Text("Original") .tag(CoverSize.Full) Text("High (768)") @@ -157,77 +218,58 @@ struct Player: View { Text("No cover") .tag(CoverSize.NoCover) }.pickerStyle(.menu) - } label: { - Label("Settings", systemImage: "gearshape") - .padding(16) - }.frame(maxWidth: 128) - } - .padding(32) - .onReceive(timer_state) { _ in - state.update() - - #if os(macOS) - MPNowPlayingInfoCenter.default().playbackState = state == PlayerState.Playing ? .playing : .paused - #endif - - } - .onReceive(timer_meta) { _ in - metadata.update() - if prev_meta != metadata || metadata.album == "" || cover.cover == PlatformImage() { - prev_meta = metadata - cover.update() - } - let image = cover.cover - let mediaArtwork = MPMediaItemArtwork(boundsSize: image.size) { (size: CGSize) -> PlatformImage in - return image + } label: { + Label("Settings", systemImage: "gearshape") + .padding(16) + }.frame(maxWidth: 128) } - let nowPlayingInfo: [String: Any] = [ - MPMediaItemPropertyArtist: metadata.artist, - MPMediaItemPropertyAlbumTitle: metadata.album, - MPMediaItemPropertyTitle: metadata.title, - MPMediaItemPropertyArtwork: mediaArtwork, - MPNowPlayingInfoPropertyIsLiveStream: true, - MPMediaItemPropertyPlaybackDuration: c_get_metadata_length(), - - ] - MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo - - } - .onAppear() { + .padding(32) + .onReceive(timer_playlists) { _ in + var id = -1 + playlists = (["All tracks"] + String(cString: c_list_playlists(server)).components(separatedBy: "\n")).map({elem in + if elem.isEmpty { + return PlayList(id: -1, name: elem) + } + id += 1; + return PlayList(id: id, name: elem) + }).filter({elem in elem.id != -1}) + } + .onAppear() { #if os(iOS) - UIApplication.shared.beginReceivingRemoteControlEvents() + UIApplication.shared.beginReceivingRemoteControlEvents() #endif - MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = false - MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = true - MPRemoteCommandCenter.shared().skipForwardCommand.isEnabled = false - MPRemoteCommandCenter.shared().skipBackwardCommand.isEnabled = false - MPRemoteCommandCenter.shared().pauseCommand.addTarget(handler: { _ in - if state != PlayerState.Paused { + MPRemoteCommandCenter.shared().previousTrackCommand.isEnabled = false + MPRemoteCommandCenter.shared().nextTrackCommand.isEnabled = true + MPRemoteCommandCenter.shared().skipForwardCommand.isEnabled = false + MPRemoteCommandCenter.shared().skipBackwardCommand.isEnabled = false + MPRemoteCommandCenter.shared().pauseCommand.addTarget(handler: { _ in + if state != PlayerState.Paused { + play() + } + return MPRemoteCommandHandlerStatus.success + }) + MPRemoteCommandCenter.shared().playCommand.addTarget(handler: { _ in + if state != PlayerState.Playing { + play() + } + return MPRemoteCommandHandlerStatus.success + }) + + MPRemoteCommandCenter.shared().togglePlayPauseCommand.addTarget(handler: {_ in play() - } - return MPRemoteCommandHandlerStatus.success - }) - MPRemoteCommandCenter.shared().playCommand.addTarget(handler: { _ in - if state != PlayerState.Playing { - play() - } - return MPRemoteCommandHandlerStatus.success - }) - - MPRemoteCommandCenter.shared().togglePlayPauseCommand.addTarget(handler: {_ in - play() - return MPRemoteCommandHandlerStatus.success - }) - - MPRemoteCommandCenter.shared().nextTrackCommand.addTarget(handler: {_ in - next() - return MPRemoteCommandHandlerStatus.success - }) - - + return MPRemoteCommandHandlerStatus.success + }) + + MPRemoteCommandCenter.shared().nextTrackCommand.addTarget(handler: {_ in + next() + return MPRemoteCommandHandlerStatus.success + }) + + + } + .animation(.spring, value: UUID()) } - .animation(.spring, value: UUID()) } @@ -236,7 +278,8 @@ struct Player: View { func play() { switch state { case PlayerState.NotStarted: do { -#if os(iOS) +/*#if os(macOS) +#else*/ let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory( @@ -246,9 +289,9 @@ struct Player: View { } catch { print("Failed to set the audio session configuration") } -#endif +/*#endif*/ Thread.detachNewThread { - c_start(server, CSettings(encoder: settings.encoder.rawValue, cover: settings.cover_size.rawValue)) + c_start(server, CSettings(encoder: settings.encoder.rawValue, cover: settings.cover_size.rawValue), playlist.name == "All tracks" ? "" : playlist.name) } } default: do { diff --git a/monoclient-x/monoclient-x/monoclient_xApp.swift b/monoclient-x/monoclient-x/monoclient_xApp.swift index 61da8ac..a0dbec0 100644 --- a/monoclient-x/monoclient-x/monoclient_xApp.swift +++ b/monoclient-x/monoclient-x/monoclient_xApp.swift @@ -25,11 +25,12 @@ struct monoclient_xApp: App { CommandGroup(replacing: CommandGroupPlacement.newItem) { } } + .defaultSize(width: 256, height: 512) #else WindowGroup { ContentView() } - .defaultSize(width: 256, height: 512) + #endif } } diff --git a/monoclient/Cargo.toml b/monoclient/Cargo.toml index d07c2bb..cd71dd4 100644 --- a/monoclient/Cargo.toml +++ b/monoclient/Cargo.toml @@ -1,14 +1,12 @@ [package] name = "monoclient" license = "MIT" -version = "0.6.1" +version = "0.7.0" edition = "2021" authors = ["Ivan Bushchik "] repository = "https://github.com/ivabus/lonelyradio" [dependencies] -monolib = { version = "0.6.0", path = "../monolib" } -clap = { version = "4.4.18", features = ["derive"] } -crossterm = "0.27.0" -lonelyradio_types = { version = "0.6.0", path = "../lonelyradio_types" } - +monolib = { version = "0.7.0", path = "../monolib" } +clap = { version = "4.5.16", features = ["derive"] } +crossterm = "0.28.1" diff --git a/monoclient/src/main.rs b/monoclient/src/main.rs index c1830ea..7bd0041 100644 --- a/monoclient/src/main.rs +++ b/monoclient/src/main.rs @@ -3,7 +3,7 @@ use crossterm::cursor::MoveToColumn; use crossterm::event::{poll, read, Event}; use crossterm::style::Print; use crossterm::terminal::{Clear, ClearType}; -use lonelyradio_types::{Encoder, Settings}; +use monolib::lonelyradio_types::{Encoder, Settings}; use std::io::stdout; use std::sync::OnceLock; use std::time::Instant; @@ -17,6 +17,12 @@ struct Args { #[arg(short, long)] verbose: bool, + + #[arg(short, long, default_value = "")] + playlist: String, + + #[arg(short, long)] + list: bool, } const HELP: &str = r#"Keybinds: @@ -37,17 +43,29 @@ macro_rules! verbose { fn main() { let args = Args::parse(); VERBOSE.set(args.verbose).unwrap(); + if args.list { + println!( + "Available playlists: {}", + match monolib::list_playlists(&args.address) { + Some(s) => format!("{:?}", s), + None => String::from("None"), + } + ); + return; + } std::thread::spawn(move || { monolib::run( &args.address, Settings { - encoder: Encoder::PcmFloat, + encoder: Encoder::Flac, cover: -1, }, + &args.playlist, ) }); while monolib::get_metadata().is_none() {} let mut md = monolib::get_metadata().unwrap(); + let mut next_md = md.clone(); verbose!("md: {:?}", md); let mut track_start = Instant::now(); let mut seconds_past = 0; @@ -63,7 +81,6 @@ fn main() { )) ) .unwrap(); - let mut next_md = md.clone(); crossterm::terminal::enable_raw_mode().unwrap(); loop { if let Ok(true) = poll(std::time::Duration::from_micros(1)) { @@ -116,8 +133,8 @@ fn main() { } } } - if monolib::get_metadata().unwrap() != md - //&& track_length <= (Instant::now() - track_start).as_secs_f64() + if next_md != md + && md.track_length_secs as f64 <= (Instant::now() - track_start).as_secs_f64() { md = next_md.clone(); verbose!("md: {:?}", md); diff --git a/monolib/Cargo.toml b/monolib/Cargo.toml index baedf10..58d8ee4 100644 --- a/monolib/Cargo.toml +++ b/monolib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "monolib" -version = "0.6.0" +version = "0.7.0" edition = "2021" license = "MIT" description = "A library implementing the lonely radio audio streaming protocol" @@ -12,11 +12,25 @@ name = "monolib" crate-type = ["cdylib", "staticlib", "rlib"] [dependencies] -rodio = { version = "0.17.3", default-features = false } +rodio = { version = "0.19.0", default-features = false } byteorder = "1.5.0" rmp-serde = "1.1.2" -lonelyradio_types = { version = "0.6.0", path = "../lonelyradio_types" } -claxon = "0.4.3" +lonelyradio_types = { version = "0.7.0", path = "../lonelyradio_types" } +anyhow = "1.0.86" + +# Optional decoders +claxon = { version = "0.4.3", optional = true } +symphonia-codec-alac = {version = "0.5.4", optional = true } +symphonia-core = {version = "0.5.4", optional = true } +vorbis_rs = {version = "0.5.4", optional = true } + +[features] +default = ["all-lossless", "all-lossy"] +all-lossless = ["alac", "flac"] +all-lossy = ["vorbis"] +alac = ["dep:symphonia-codec-alac", "dep:symphonia-core"] +flac = ["dep:claxon"] +vorbis = ["dep:vorbis_rs"] [package.metadata.xcframework] include-dir = "src" @@ -24,4 +38,5 @@ lib-type = "cdylib" zip = false macOS = true iOS = true +#tvOS = true simulators = true diff --git a/monolib/src/c.rs b/monolib/src/c.rs index adee145..7c4fc9f 100644 --- a/monolib/src/c.rs +++ b/monolib/src/c.rs @@ -11,39 +11,52 @@ pub struct CTrackMetadata { pub artist: *mut c_char, } -pub const ENCODER_PCM16: u8 = 0; -pub const ENCODER_PCMFLOAT: u8 = 1; -pub const ENCODER_FLAC: u8 = 2; - #[repr(C)] #[derive(Clone, Debug, PartialEq)] pub struct CSettings { - /// See lonelyradio_types -> Encoder + /// See lonelyradio_types for numeric representation -> Encoder pub encoder: u8, pub cover: i32, } #[no_mangle] #[allow(clippy::not_unsafe_ptr_arg_deref)] -pub extern "C" fn c_start(server: *const c_char, settings: CSettings) { +/// Starts audio playback using rodio +/// Play without playlist => playlist = "" +pub extern "C" fn c_start(server: *const c_char, settings: CSettings, playlist: *const c_char) { let serv = unsafe { CStr::from_ptr(server) }; + let playlist = unsafe { CStr::from_ptr(playlist) }; run( - match serv.to_str() { - Ok(s) => s, - _ => "", - }, + serv.to_str().unwrap_or_default(), Settings { encoder: match settings.encoder { 0 => Encoder::Pcm16, 1 => Encoder::PcmFloat, 2 => Encoder::Flac, + 3 => Encoder::Alac, + 7 => Encoder::Vorbis, _ => return, }, cover: settings.cover, }, + playlist.to_str().unwrap_or_default(), ) } +#[no_mangle] +#[allow(clippy::not_unsafe_ptr_arg_deref)] +/// Playlists separated by '\n' +pub extern "C" fn c_list_playlists(server: *const c_char) -> *mut c_char { + let serv = unsafe { CStr::from_ptr(server) }; + let playlists = list_playlists(serv.to_str().unwrap_or_default()); + CString::new(match playlists { + None => "".to_string(), + Some(s) => s.join("\n"), + }) + .unwrap() + .into_raw() +} + #[no_mangle] pub extern "C" fn c_toggle() { toggle() diff --git a/monolib/src/decode.rs b/monolib/src/decode.rs new file mode 100644 index 0000000..09bdcfc --- /dev/null +++ b/monolib/src/decode.rs @@ -0,0 +1,99 @@ +use std::io::{Cursor, Read}; + +use byteorder::{LittleEndian, ReadBytesExt}; +use lonelyradio_types::{Encoder, FragmentMetadata, TrackMetadata}; +use symphonia_core::{ + audio::SampleBuffer, + codecs::{Decoder, CODEC_TYPE_ALAC}, + formats::Packet, +}; + +pub(crate) fn decode( + mut stream: impl ReadBytesExt, + md: &TrackMetadata, + fmd: &FragmentMetadata, +) -> anyhow::Result> { + let mut samples = vec![]; + match md.encoder { + Encoder::Pcm16 => { + let mut samples_i16 = vec![0; fmd.length as usize / 2]; + stream.read_i16_into::(&mut samples_i16)?; + samples + .append(&mut samples_i16.iter().map(|sample| *sample as f32 / 32767.0).collect()); + } + Encoder::PcmFloat => { + let mut samples_f32 = vec![0f32; fmd.length as usize / 4]; + stream.read_f32_into::(&mut samples_f32)?; + samples.append(&mut samples_f32); + } + Encoder::Flac => { + #[cfg(feature = "alac")] + { + let take = std::io::Read::by_ref(&mut stream).take(fmd.length); + let mut reader = claxon::FlacReader::new(take)?; + samples.append( + &mut reader + .samples() + .map(|x| x.unwrap_or(0) as f32 / 32768.0 / 256.0) + .collect::>(), + ); + } + + #[cfg(not(feature = "flac"))] + { + unimplemented!("flac decoding is disabled in library") + } + } + Encoder::Alac => { + #[cfg(feature = "alac")] + { + let mut buf = vec![]; + std::io::Read::by_ref(&mut stream).take(fmd.length).read_to_end(&mut buf)?; + let mut reader = symphonia_codec_alac::AlacDecoder::try_new( + symphonia_core::codecs::CodecParameters::default() + .for_codec(CODEC_TYPE_ALAC) + .with_extra_data(fmd.magic_cookie.clone().unwrap().into_boxed_slice()), + &symphonia_core::codecs::DecoderOptions { + verify: false, + }, + )?; + let decoded = reader.decode(&Packet::new_from_slice(0, 0, 0, &buf))?; + let mut byte_buf = + SampleBuffer::::new(decoded.capacity() as u64, *decoded.spec()); + byte_buf.copy_interleaved_ref(decoded); + samples.extend(byte_buf.samples()); + } + #[cfg(not(feature = "alac"))] + { + unimplemented!("alac decoding is disabled in library") + } + } + Encoder::Vorbis => { + #[cfg(feature = "vorbis")] + { + let mut buf = vec![]; + std::io::Read::by_ref(&mut stream).take(fmd.length).read_to_end(&mut buf)?; + let mut decoder = vorbis_rs::VorbisDecoder::new(Cursor::new(buf))?; + let mut interleaved = vec![]; + + while let Some(decoded_block) = decoder.decode_audio_block()? { + let s = decoded_block.samples(); + interleaved.resize(s[0].len() * s.len(), 0f32); + for (ind, channel) in s.iter().enumerate() { + for (samind, sample) in channel.iter().enumerate() { + interleaved[ind + samind * md.channels as usize] = *sample; + } + } + samples.extend(interleaved); + interleaved = vec![]; + } + } + #[cfg(not(feature = "vorbis"))] + { + unimplemented!("vorbis decoding is disabled in library") + } + } + Encoder::Aac | Encoder::Opus | Encoder::WavPack => unimplemented!(), + }; + Ok(samples) +} diff --git a/monolib/src/lib.rs b/monolib/src/lib.rs index 1b9b0a9..88d7033 100644 --- a/monolib/src/lib.rs +++ b/monolib/src/lib.rs @@ -17,19 +17,36 @@ /// Functions, providing C-like API pub mod c; -use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -use lonelyradio_types::{Encoder, Message, ServerCapabilities, Settings, TrackMetadata}; +pub use lonelyradio_types; + +use anyhow::{bail, Context}; +use decode::decode; +use lonelyradio_types::{ + Encoder, PlayMessage, Request, RequestResult, ServerCapabilities, Settings, TrackMetadata, +}; use rodio::buffer::SamplesBuffer; use rodio::{OutputStream, Sink}; -use std::error::Error; -use std::io::{Read, Write}; +use std::io::Write; use std::net::TcpStream; use std::sync::atomic::AtomicU8; use std::sync::RwLock; use std::time::Instant; +mod decode; + const CACHE_SIZE_PCM: usize = 32; -const CACHE_SIZE_COMPRESSED: usize = 2; +const CACHE_SIZE_COMPRESSED: usize = 4; + +const SUPPORTED_DECODERS: &[Encoder] = &[ + Encoder::Pcm16, + Encoder::PcmFloat, + #[cfg(feature = "flac")] + Encoder::Flac, + #[cfg(feature = "alac")] + Encoder::Alac, + #[cfg(feature = "vorbis")] + Encoder::Vorbis, +]; static SINK: RwLock> = RwLock::new(None); static VOLUME: AtomicU8 = AtomicU8::new(255); @@ -144,139 +161,146 @@ pub fn set_volume(volume: u8) { } /// Download track as samples -pub fn get_track(server: &str, mut settings: Settings) -> Option<(TrackMetadata, Vec)> { - let mut connection = unwrap(TcpStream::connect(server))?; - unwrap(connection.write_u64::(lonelyradio_types::HELLO_MAGIC))?; - let capabilities: ServerCapabilities = unwrap(rmp_serde::from_read(&mut connection))?; +pub fn get_track( + server: &str, + mut settings: Settings, + playlist: &str, +) -> anyhow::Result<(TrackMetadata, Vec)> { + let mut connection = TcpStream::connect(server)?; + connection.write_all(lonelyradio_types::HELLO_MAGIC)?; + let capabilities: ServerCapabilities = rmp_serde::from_read(&mut connection)?; if !capabilities.encoders.contains(&settings.encoder) { settings.encoder = Encoder::Pcm16 } - unwrap(connection.write_all(&rmp_serde::to_vec_named(&settings).unwrap()))?; - let mut stream = connection; + let request = if playlist.is_empty() { + Request::Play(settings) + } else { + Request::PlayPlaylist(playlist.to_string(), settings) + }; + connection.write_all(&rmp_serde::to_vec_named(&request).unwrap())?; + + let response: RequestResult = rmp_serde::from_read(&connection)?; + if let RequestResult::Error(e) = response { + bail!("{e:?}") + } + let mut samples = vec![]; let mut md: Option = None; + loop { - let recv_md: Message = rmp_serde::from_read(&mut stream).expect("Failed to parse message"); + let recv_md: PlayMessage = rmp_serde::from_read(&mut connection)?; match recv_md { - Message::T(tmd) => { + PlayMessage::T(tmd) => { if md.is_some() { break; } md = Some(tmd); } - Message::F(fmd) => match md.as_ref().unwrap().encoder { - Encoder::Pcm16 => { - let mut buf = vec![0; fmd.length as usize]; - stream.read_i16_into::(&mut buf).unwrap(); - samples.append(&mut buf); - } - Encoder::PcmFloat => unimplemented!(), - Encoder::Flac => { - let take = std::io::Read::by_ref(&mut stream).take(fmd.length); - let mut reader = claxon::FlacReader::new(take).unwrap(); - samples.append( - &mut reader.samples().map(|x| x.unwrap_or(0) as i16).collect::>(), - ); - } - }, + PlayMessage::F(fmd) => { + samples.extend(decode(&mut connection, md.as_ref().unwrap(), &fmd)?) + } } } - md.map(|md| (md, samples)) + + if let Some(md) = md { + Ok((md, samples)) + } else { + bail!("No metadata") + } } -fn unwrap(thing: Result) -> Option { - if thing.is_err() { - *STATE.write().unwrap() = State::NotStarted; +pub fn list_playlists(server: &str) -> Option> { + let mut connection = TcpStream::connect(server).ok()?; + connection.write_all(lonelyradio_types::HELLO_MAGIC).ok()?; + let _: ServerCapabilities = rmp_serde::from_read(&mut connection).ok()?; + connection.write_all(&rmp_serde::to_vec_named(&Request::ListPlaylist).ok()?).ok()?; + let res: RequestResult = rmp_serde::from_read(connection).ok()?; + match res { + RequestResult::Playlist(plist) => Some(plist.playlists), + _ => None, } - thing.ok() } /// Starts playing at "server:port" -pub fn run(server: &str, settings: Settings) { - let _ = _run(server, settings); +pub fn run(server: &str, settings: Settings, playlist: &str) { + let result = _run(server, settings, playlist); + if let Err(e) = result { + println!("{:?}", e); + *STATE.write().unwrap() = State::NotStarted; + } } -pub fn _run(server: &str, settings: Settings) -> Option<()> { - let mut settings = settings; +pub(crate) fn _run(server: &str, mut settings: Settings, playlist: &str) -> anyhow::Result<()> { + if !SUPPORTED_DECODERS.contains(&settings.encoder) { + eprintln!( + "monolib was built without support for {:?}, falling back to Pcm16", + settings.encoder + ); + settings.encoder = Encoder::Pcm16 + } let mut state = STATE.write().unwrap(); if *state == State::Playing || *state == State::Paused { - return None; + return Ok(()); } *state = State::Playing; drop(state); - let mut connection = unwrap(TcpStream::connect(server))?; - unwrap(connection.write_u64::(lonelyradio_types::HELLO_MAGIC))?; - let capabilities: ServerCapabilities = unwrap(rmp_serde::from_read(&mut connection))?; + let mut connection = TcpStream::connect(server).context("failed to connect to the server")?; + connection.write_all(lonelyradio_types::HELLO_MAGIC)?; + let capabilities: ServerCapabilities = rmp_serde::from_read(&mut connection)?; if !capabilities.encoders.contains(&settings.encoder) { settings.encoder = Encoder::Pcm16 } - unwrap(connection.write_all(&rmp_serde::to_vec_named(&settings).unwrap()))?; + let request = if playlist.is_empty() { + Request::Play(settings) + } else { + Request::PlayPlaylist(playlist.to_string(), settings) + }; + connection.write_all(&rmp_serde::to_vec_named(&request).unwrap())?; + + let response: RequestResult = rmp_serde::from_read(&connection).unwrap(); + if let RequestResult::Error(e) = response { + bail!("{:?}", e) + } let mut stream = connection; let mut sink = SINK.write().unwrap(); - let (_stream, stream_handle) = unwrap(OutputStream::try_default())?; + let (_stream, stream_handle) = + OutputStream::try_default().context("failed to determine audio device")?; // Can't reuse old sink for some reason - let audio_sink = Sink::try_new(&stream_handle).unwrap(); + let audio_sink = Sink::try_new(&stream_handle).context("failed to create audio sink")?; *sink = Some(audio_sink); drop(sink); let mut samples = Vec::with_capacity(8192); loop { - let recv_md: Message = rmp_serde::from_read(&mut stream).expect("Failed to parse message"); + let recv_md: PlayMessage = + rmp_serde::from_read(&mut stream).expect("Failed to parse message"); match recv_md { - Message::T(tmd) => { + PlayMessage::T(tmd) => { // No metadata shift if watching_sleep_until_end() { _stop(); - return None; + return Ok(()); } let mut md = MD.write().unwrap(); *md = Some(tmd.clone()); + drop(md); } - Message::F(fmd) => { + PlayMessage::F(fmd) => { while *STATE.read().unwrap() == State::Paused { std::thread::sleep(std::time::Duration::from_secs_f32(0.25)) } if *STATE.read().unwrap() == State::Resetting { _stop(); - return None; + return Ok(()); } - match MD.read().unwrap().as_ref().unwrap().encoder { - Encoder::Pcm16 => { - let mut samples_i16 = vec![0; fmd.length as usize / 2]; - if stream.read_i16_into::(&mut samples_i16).is_err() { - return None; - }; - samples.append( - &mut samples_i16 - .iter() - .map(|sample| *sample as f32 / 32767.0) - .collect(), - ); - } - Encoder::PcmFloat => { - let mut samples_f32 = vec![0f32; fmd.length as usize / 4]; - if stream.read_f32_into::(&mut samples_f32).is_err() { - return None; - }; - samples.append(&mut samples_f32); - } - Encoder::Flac => { - let take = std::io::Read::by_ref(&mut stream).take(fmd.length); - let mut reader = claxon::FlacReader::new(take).unwrap(); - samples.append( - &mut reader - .samples() - .map(|x| x.unwrap_or(0) as f32 / 32768.0 / 256.0) - .collect::>(), - ); - } - }; + + samples.extend(decode(&mut stream, &MD.read().unwrap().clone().unwrap(), &fmd)?); // Synchronizing with sink let sink = SINK.read().unwrap(); @@ -284,8 +308,12 @@ pub fn _run(server: &str, settings: Settings) -> Option<()> { let md = _md.as_ref().unwrap().clone(); drop(_md); if let Some(sink) = sink.as_ref() { - while (sink.len() >= CACHE_SIZE_PCM && md.encoder != Encoder::Flac) - || (sink.len() >= CACHE_SIZE_COMPRESSED && md.encoder == Encoder::Flac) + while (sink.len() >= CACHE_SIZE_PCM + && md.encoder == Encoder::Pcm16 + && md.encoder == Encoder::PcmFloat) + || (sink.len() >= CACHE_SIZE_COMPRESSED + && md.encoder != Encoder::Pcm16 + && md.encoder != Encoder::PcmFloat) { // Sleeping exactly one buffer and watching for reset signal if watching_sleep( @@ -297,7 +325,7 @@ pub fn _run(server: &str, settings: Settings) -> Option<()> { / 4.0, ) { _stop(); - return None; + return Ok(()); } } sink.append(SamplesBuffer::new( diff --git a/monolib/src/monolib.h b/monolib/src/monolib.h index eaeadaa..54b62f9 100644 --- a/monolib/src/monolib.h +++ b/monolib/src/monolib.h @@ -1,23 +1,45 @@ #include #include -#include #include #include +typedef struct CSettings { + /** + * See lonelyradio_types for numeric representation -> Encoder + */ + uint8_t encoder; + int32_t cover; +} CSettings; + typedef struct CImageJpeg { uint32_t length; uint8_t *bytes; } CImageJpeg; -typedef struct CSettings { - /** - * See lonelyradio_types -> Encoder - */ - uint8_t encoder; - int32_t cover; -} CSettings; +/** + * Starts audio playback using rodio + * Play without playlist => playlist = "" + */ +void c_start(const char *server, struct CSettings settings, const char *playlist); -void c_drop(uint8_t *ptr, size_t count); +/** + * Playlists separated by '\n' + */ +char *c_list_playlists(const char *server); + +void c_toggle(void); + +void c_stop(void); + +char c_get_state(void); + +char *c_get_metadata_artist(void); + +char *c_get_metadata_album(void); + +char *c_get_metadata_title(void); + +float c_get_metadata_length(void); /** * # Safety @@ -25,18 +47,8 @@ void c_drop(uint8_t *ptr, size_t count); */ struct CImageJpeg c_get_cover_jpeg(void); -char *c_get_metadata_album(void); - -char *c_get_metadata_artist(void); - -float c_get_metadata_length(void); - -char *c_get_metadata_title(void); - -char c_get_state(void); - -void c_start(const char *server, struct CSettings settings); - -void c_stop(void); - -void c_toggle(void); +/** + * # Safety + * None + */ +void c_drop(uint8_t *ptr, uintptr_t count); diff --git a/monolib/src/target b/monolib/src/target deleted file mode 120000 index 78bc337..0000000 --- a/monolib/src/target +++ /dev/null @@ -1 +0,0 @@ -../target \ No newline at end of file diff --git a/monoloader/Cargo.toml b/monoloader/Cargo.toml index 1fa6af0..4a62a9b 100644 --- a/monoloader/Cargo.toml +++ b/monoloader/Cargo.toml @@ -1,12 +1,11 @@ [package] name = "monoloader" -version = "0.6.0" +version = "0.7.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -monolib = { path = "../monolib" } +monolib = { version = "0.7.0", path = "../monolib" } clap = { version = "4.4.18", features = ["derive"] } hound = "3.5.1" -lonelyradio_types = { version = "0.6.0", path = "../lonelyradio_types" } diff --git a/monoloader/src/main.rs b/monoloader/src/main.rs index 7c38b06..c689938 100644 --- a/monoloader/src/main.rs +++ b/monoloader/src/main.rs @@ -1,5 +1,5 @@ use clap::Parser; -use lonelyradio_types::Settings; +use monolib::lonelyradio_types::Settings; use std::path::PathBuf; #[derive(Parser)] @@ -9,34 +9,53 @@ struct Args { #[arg(long)] xor_key_file: Option, + + #[arg(short, long, default_value = "")] + playlist: String, + + #[arg(short, long)] + list: bool, } fn main() { let args = Args::parse(); + + if args.list { + println!( + "Available playlists: {}", + match monolib::list_playlists(&args.address) { + Some(s) => format!("{:?}", s), + None => String::from("None"), + } + ); + return; + } + let (md, samples) = monolib::get_track( &args.address, Settings { - encoder: lonelyradio_types::Encoder::Pcm16, + encoder: monolib::lonelyradio_types::Encoder::Flac, cover: -1, }, + &args.playlist, ) .unwrap(); println!( - "Downloaded: {} - {} - {} ({} MB)", + "Downloaded: {} - {} - {} ({:?}, {} MiB)", md.artist, md.album, md.title, - samples.len() as f32 * 2.0 / 1024.0 / 1024.0 + md.encoder, + samples.len() as f32 / 256.0 / 1024.0 ); let spec = hound::WavSpec { channels: md.channels, sample_rate: md.sample_rate, - bits_per_sample: 16, - sample_format: hound::SampleFormat::Int, + bits_per_sample: 32, + sample_format: hound::SampleFormat::Float, }; let mut writer = hound::WavWriter::create(format!("{} - {}.wav", md.artist, md.title), spec).unwrap(); - let mut writer_i16 = writer.get_i16_writer(samples.len() as u32); - samples.iter().for_each(|s| writer_i16.write_sample(*s)); - writer_i16.flush().unwrap(); + samples.iter().for_each(|s| writer.write_sample(*s).unwrap()); + writer.flush().unwrap(); } diff --git a/src/decode.rs b/src/decode.rs index 7d2804e..653221a 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -11,7 +11,7 @@ use symphonia::core::units::Time; use crate::Args; -pub async fn get_meta(file_path: &Path) -> (u16, u32, Time) { +pub async fn get_meta(file_path: &Path, encoder_wants: u32) -> (u16, u32, Time) { let file = Box::new(std::fs::File::open(file_path).unwrap()); let mut hint = Hint::new(); hint.with_extension(file_path.extension().unwrap().to_str().unwrap()); @@ -65,11 +65,26 @@ pub async fn get_meta(file_path: &Path) -> (u16, u32, Time) { } let args = Args::parse(); - (channels, get_resampling_rate(&sample_rate, &args.max_samplerate), track_length) + ( + channels, + if args.no_resampling && encoder_wants == 0 { + sample_rate + } else { + get_resampling_rate( + &sample_rate, + &if encoder_wants != 0 { + args.max_samplerate.min(encoder_wants) + } else { + args.max_samplerate + }, + ) + }, + track_length, + ) } /// Getting samples -pub fn decode_file_stream(file_path: PathBuf) -> impl Stream> { +pub fn decode_file_stream(file_path: PathBuf, encoder_wants: u32) -> impl Stream> { let args = Args::parse(); let file = Box::new(std::fs::File::open(&file_path).unwrap()); let mut hint = Hint::new(); @@ -93,7 +108,7 @@ pub fn decode_file_stream(file_path: PathBuf) -> impl Stream> { .expect("no supported audio tracks"); let mut decoder = symphonia::default::get_codecs() - .make(track.codec_params.clone().with_max_frames_per_packet(65536), &Default::default()) + .make(&track.codec_params, &Default::default()) .expect("unsupported codec"); let track_id = track.id; stream! { @@ -109,30 +124,30 @@ pub fn decode_file_stream(file_path: PathBuf) -> impl Stream> { match decoder.decode(&packet) { Ok(decoded) => { - if decoded.spec().rate > args.max_samplerate { + let output_rate = get_resampling_rate(&decoded.spec().rate, &if encoder_wants != 0 { + args.max_samplerate.min(encoder_wants) + } else { + args.max_samplerate + }); + if decoded.spec().rate > output_rate && (!args.no_resampling || encoder_wants != 0) { let spec = *decoded.spec(); let mut byte_buf = SampleBuffer::::new(decoded.capacity() as u64, *decoded.spec()); byte_buf.copy_interleaved_ref(decoded); - let output_rate = get_resampling_rate(&spec.rate,&args.max_samplerate); - // About Samplerate struct: // We are downsampling, not upsampling, so we should be fine - yield ( - if output_rate == spec.rate { - byte_buf.samples().to_vec() - } else { - samplerate::convert( - spec.rate, - args.max_samplerate, - spec.channels.count(), - samplerate::ConverterType::Linear, - byte_buf.samples(), - ) - .unwrap() - } - ); - + yield (if output_rate == spec.rate { + byte_buf.samples().to_vec() + } else { + samplerate::convert( + spec.rate, + output_rate, + spec.channels.count(), + samplerate::ConverterType::Linear, + byte_buf.samples(), + ) + .unwrap() + }); } else { let mut byte_buf = SampleBuffer::::new(decoded.capacity() as u64, *decoded.spec()); diff --git a/src/encode.rs b/src/encode.rs index 0d8e019..75b30c3 100644 --- a/src/encode.rs +++ b/src/encode.rs @@ -1,52 +1,133 @@ -use flacenc::{component::BitRepr, error::Verify, source::MemSource}; use lonelyradio_types::Encoder; +// Return: 0 - encoded bytes, 1 - magic cookie (for alac only) +#[allow(unused_variables)] pub fn encode( codec: Encoder, mut samples: Vec, sample_rate: u32, channels: u16, -) -> Option> { +) -> Option<(Vec, Option>)> { match codec { Encoder::Pcm16 => { + #[allow(unused_mut)] let mut samples = samples.iter_mut().map(|x| (*x * 32768.0) as i16).collect::>(); // Launching lonelyradio on the router moment - if cfg!(target_endian = "big") { + #[cfg(target_endian = "big")] + { samples.iter_mut().for_each(|sample| { *sample = sample.to_le(); }); } // Sowwy about that let (_, samples, _) = unsafe { samples.align_to::() }; - Some(samples.to_vec()) + Some((samples.to_vec(), None)) } Encoder::PcmFloat => { - // Launching lonelyradio on the router moment // Sowwy about that - let samples = samples.iter().map(|x| x.to_bits()).collect::>(); let (_, samples, _) = unsafe { samples.align_to::() }; - Some(samples.to_vec()) + Some((samples.to_vec(), None)) } Encoder::Flac => { - let encoded = flacenc::encode_with_fixed_block_size( - &flacenc::config::Encoder::default().into_verified().unwrap(), - MemSource::from_samples( - // I'm crying (It's just a burning memory) - &samples - .iter() - .map(|x| (*x as f64 * 32768.0 * 256.0) as i32) - .collect::>(), - channels as usize, - 24, - sample_rate as usize, - ), - 256, - ) - .unwrap(); + #[cfg(feature = "flac")] + { + use flacenc::{component::BitRepr, error::Verify, source::MemSource}; - let mut sink = flacenc::bitsink::ByteSink::new(); - encoded.write(&mut sink).unwrap(); - Some(sink.as_slice().to_vec()) + let encoded = flacenc::encode_with_fixed_block_size( + &flacenc::config::Encoder::default().into_verified().unwrap(), + MemSource::from_samples( + &samples + .iter() + .map(|x| (*x as f64 * 32768.0 * 256.0) as i32) + .collect::>(), + channels as usize, + 24, + sample_rate as usize, + ), + 256, + ) + .unwrap(); + + let mut sink = flacenc::bitsink::ByteSink::new(); + encoded.write(&mut sink).unwrap(); + Some((sink.as_slice().to_vec(), None)) + } + + #[cfg(not(feature = "flac"))] + { + unimplemented!() + } } + Encoder::Alac => { + #[cfg(feature = "alac")] + { + use alac_encoder::{AlacEncoder, FormatDescription}; + + let samples = samples.iter_mut().map(|x| (*x * 32768.0) as i16).collect::>(); + let (_, samples, _) = unsafe { samples.align_to::() }; + + let input_format = + FormatDescription::pcm::(sample_rate as f64, channels as u32); + let output_format = FormatDescription::alac( + sample_rate as f64, + samples.len() as u32, + channels as u32, + ); + + // Initialize the encoder + let mut encoder = AlacEncoder::new(&output_format); + + // Allocate a buffer for the encoder to write chunks to. + let mut output = vec![0u8; output_format.max_packet_size()]; + let size = encoder.encode(&input_format, samples, &mut output); + + // Here you can do whatever you want with the result: + Some((Vec::from(&output[0..size]), Some(encoder.magic_cookie()))) + } + #[cfg(not(feature = "alac"))] + { + unimplemented!() + } + } + Encoder::Vorbis => { + #[cfg(feature = "vorbis")] + { + use std::num::{NonZeroU32, NonZeroU8}; + let out: Vec = vec![]; + let mut encoder = vorbis_rs::VorbisEncoderBuilder::new( + NonZeroU32::new(sample_rate).unwrap(), + NonZeroU8::new(channels as u8).unwrap(), + out, + ) + .unwrap() + .bitrate_management_strategy( + vorbis_rs::VorbisBitrateManagementStrategy::ConstrainedAbr { + // I will think about clients asking about bitrate later, now it's just + // "enough" 128 kib/s + maximum_bitrate: NonZeroU32::new(192 * 1024).unwrap(), + }, + ) + .build() + .unwrap(); + let mut samples_channels = vec![]; + for i in 0..channels as usize { + samples_channels.push( + samples[i..] + .iter() + .step_by(channels as usize) + .copied() + .collect::>(), + ); + } + encoder.encode_audio_block(samples_channels).unwrap(); + Some((encoder.finish().unwrap(), None)) + } + + #[cfg(not(feature = "vorbis"))] + { + unimplemented!() + } + } + Encoder::Aac | Encoder::Opus | Encoder::WavPack => unimplemented!(), } } diff --git a/src/main.rs b/src/main.rs index 31b5f5c..f383b90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,9 @@ mod decode; mod encode; +use std::collections::HashMap; use std::io::Cursor; use std::io::Read; -use std::net::TcpStream; use std::path::Path; use std::path::PathBuf; use std::sync::Arc; @@ -13,18 +13,22 @@ use clap::Parser; use encode::encode; use futures_util::pin_mut; use futures_util::StreamExt; -use image::io::Reader as ImageReader; +use image::ImageReader; use lofty::Accessor; use lofty::TaggedFileExt; use lonelyradio_types::Encoder; +use lonelyradio_types::Request; +use lonelyradio_types::RequestResult; use lonelyradio_types::ServerCapabilities; use lonelyradio_types::Settings; -use lonelyradio_types::{FragmentMetadata, Message, TrackMetadata}; +use lonelyradio_types::{FragmentMetadata, PlayMessage, TrackMetadata}; use rand::prelude::*; use std::io::Write; use tokio::net::TcpListener; use tokio_stream::Stream; +use url::Url; use walkdir::DirEntry; +use xspf::Playlist; use crate::decode::decode_file_stream; use crate::decode::get_meta; @@ -38,14 +42,6 @@ struct Args { #[arg(short, default_value = "0.0.0.0:5894")] address: String, - /// Enable "public" log (without sensitive information) - #[arg(short, long)] - public_log: bool, - - /// Process all samples to -1 or 1 - #[arg(short, long)] - war: bool, - /// Resample all tracks, which samplerate exceeds N #[arg(short, long, default_value = "96000")] max_samplerate: u32, @@ -57,54 +53,65 @@ struct Args { /// Size of artwork (-1 for no artwork, 0 for original, N for NxN) #[arg(long, default_value = "96000")] artwork: i32, + + #[arg(long)] + playlist_dir: Option, } -const SUPPORTED_ENCODERS: [Encoder; 3] = [Encoder::Pcm16, Encoder::PcmFloat, Encoder::Flac]; +const SUPPORTED_ENCODERS: &[Encoder] = &[ + Encoder::Pcm16, + Encoder::PcmFloat, + #[cfg(feature = "flac")] + Encoder::Flac, + #[cfg(feature = "alac")] + Encoder::Alac, + #[cfg(feature = "vorbis")] + Encoder::Vorbis, +]; async fn stream_track( samples_stream: impl Stream>, - war: bool, md: TrackMetadata, - s: &mut TcpStream, + mut s: impl Write, ) -> bool { pin_mut!(samples_stream); let _md = md.clone(); - if s.write_all(rmp_serde::encode::to_vec_named(&Message::T(_md)).unwrap().as_slice()).is_err() { + if s.write_all(rmp_serde::encode::to_vec_named(&PlayMessage::T(_md)).unwrap().as_slice()) + .is_err() + { return true; }; // Why chunks? - // flacenc is broken on low amount of samples (Symphonia's AIFF decoder returns - // ~2304 samples per packet (on bo en's tracks), instead of usual ~8192 on any - // other lossless decoder) + // Different codecs have different quality on different audio lenghts while let Some(mut _samples) = samples_stream .as_mut() .chunks(match md.encoder { Encoder::Pcm16 => 1, Encoder::PcmFloat => 1, Encoder::Flac => 16, + Encoder::Alac => 32, + Encoder::Vorbis => 64, + Encoder::Aac | Encoder::Opus | Encoder::WavPack => unimplemented!(), }) .next() .await { let mut _samples = _samples.concat(); - if war { - _samples.iter_mut().for_each(|sample| { - *sample = sample.signum(); - }); - } + match md.encoder { Encoder::Pcm16 => { - let _md = Message::F(FragmentMetadata { + let _md = PlayMessage::F(FragmentMetadata { length: _samples.len() as u64 * 2, + magic_cookie: None, }); if s.write_all(rmp_serde::to_vec(&_md).unwrap().as_slice()).is_err() { return true; } if s.write_all( - &encode(Encoder::Pcm16, _samples, md.sample_rate, md.channels).unwrap(), + &encode(Encoder::Pcm16, _samples, md.sample_rate, md.channels).unwrap().0, ) .is_err() { @@ -112,24 +119,27 @@ async fn stream_track( } } Encoder::PcmFloat => { - let _md = Message::F(FragmentMetadata { + let _md = PlayMessage::F(FragmentMetadata { length: _samples.len() as u64 * 4, + magic_cookie: None, }); if s.write_all(rmp_serde::to_vec(&_md).unwrap().as_slice()).is_err() { return true; } if s.write_all( - &encode(Encoder::PcmFloat, _samples, md.sample_rate, md.channels).unwrap(), + &encode(Encoder::PcmFloat, _samples, md.sample_rate, md.channels).unwrap().0, ) .is_err() { return true; } } - Encoder::Flac => { - let encoded = encode(Encoder::Flac, _samples, md.sample_rate, md.channels).unwrap(); - let _md = Message::F(FragmentMetadata { + Encoder::Flac | Encoder::Alac | Encoder::Vorbis => { + let (encoded, magic_cookie) = + encode(md.encoder, _samples, md.sample_rate, md.channels).unwrap(); + let _md = PlayMessage::F(FragmentMetadata { length: encoded.as_slice().len() as u64, + magic_cookie, }); if s.write_all(rmp_serde::to_vec(&_md).unwrap().as_slice()).is_err() { return true; @@ -138,11 +148,39 @@ async fn stream_track( return true; } } + Encoder::Aac | Encoder::Opus | Encoder::WavPack => unimplemented!(), } } false } +fn get_playlists(dir: impl AsRef) -> Option>>> { + let mut map: HashMap>> = HashMap::new(); + for playlist in walkdir::WalkDir::new(dir) + .into_iter() + .filter_entry(is_not_hidden) + .filter_map(|v| v.ok()) + .map(|x| x.into_path()) + .filter(|x| x.is_file()) + { + let mut name = playlist.file_name().unwrap().to_str().unwrap().to_string(); + let parsed = Playlist::read_file(playlist).unwrap(); + if let Some(ref n) = parsed.title { + name = n.clone(); + } + let tracklist = parsed + .track_list + .iter() + .flat_map(|x| x.location.iter().flat_map(|l| Url::parse(l.as_str()).ok())) + .filter(|x| x.scheme() == "file") + .map(|x| x.to_file_path().unwrap()) + .filter(|x| track_valid(x)) + .collect(); + map.insert(name, Arc::new(tracklist)); + } + Some(map) +} + #[tokio::main] async fn main() { let args = Args::parse(); @@ -156,17 +194,24 @@ async fn main() { .filter(|x| track_valid(x)) .collect::>(), ); + let playlists: Option>>> = match args.playlist_dir.as_ref() { + None => None, + Some(dir) => get_playlists(dir), + }; loop { let (socket, _) = listener.accept().await.unwrap(); let mut s = socket.into_std().unwrap(); s.set_nonblocking(false).unwrap(); + let mut hello = [0u8; 8]; if s.read_exact(&mut hello).is_err() { continue; } - if hello != lonelyradio_types::HELLO_MAGIC.to_le_bytes() { + + if &hello != lonelyradio_types::HELLO_MAGIC { continue; } + if s.write_all( &rmp_serde::to_vec_named(&ServerCapabilities { encoders: SUPPORTED_ENCODERS.to_vec(), @@ -177,17 +222,82 @@ async fn main() { { continue; }; - let settings: Settings = match rmp_serde::from_read(&s) { - Ok(s) => s, - _ => continue, + s.flush().unwrap(); + + let request: Request = match rmp_serde::from_read(&s) { + Ok(r) => r, + Err(_) => { + continue; + } }; - if settings.cover < -1 { - continue; + + match request { + Request::Play(settings) => { + if s.write_all(&rmp_serde::to_vec_named(&check_settings(&settings)).unwrap()) + .is_err() + { + continue; + } + tokio::spawn(stream(s, tracklist.clone(), settings)); + } + Request::ListPlaylist => match playlists { + None => { + s.write_all( + &rmp_serde::to_vec_named(&RequestResult::Playlist( + lonelyradio_types::PlaylistResponce { + playlists: vec![], + }, + )) + .unwrap(), + ) + .unwrap(); + } + Some(ref playlists) => { + s.write_all( + &rmp_serde::to_vec_named(&RequestResult::Playlist( + lonelyradio_types::PlaylistResponce { + playlists: playlists.keys().cloned().collect(), + }, + )) + .unwrap(), + ) + .unwrap(); + } + }, + + Request::PlayPlaylist(playlist, settings) => { + if playlists.is_none() || playlists.as_ref().unwrap().get(&playlist).is_none() { + s.write_all( + &rmp_serde::to_vec_named(&RequestResult::Error( + lonelyradio_types::RequestError::NoSuchPlaylist, + )) + .unwrap(), + ) + .unwrap(); + continue; + } + if s.write_all(&rmp_serde::to_vec_named(&check_settings(&settings)).unwrap()) + .is_err() + { + continue; + } + let tracklist = playlists.as_ref().unwrap().get(&playlist).unwrap().clone(); + tokio::spawn(stream(s, tracklist, settings)); + } } - tokio::spawn(stream(s, tracklist.clone(), settings)); } } +fn check_settings(settings: &Settings) -> RequestResult { + if settings.cover < -1 { + return RequestResult::Error(lonelyradio_types::RequestError::WrongCoverSize); + } + if !SUPPORTED_ENCODERS.contains(&settings.encoder) { + return RequestResult::Error(lonelyradio_types::RequestError::UnsupportedEncoder); + } + RequestResult::Ok +} + fn is_not_hidden(entry: &DirEntry) -> bool { entry.file_name().to_str().map(|s| entry.depth() == 0 || !s.starts_with('.')).unwrap_or(false) } @@ -212,9 +322,13 @@ fn track_valid(track: &Path) -> bool { } } -async fn stream(mut s: TcpStream, tracklist: Arc>, settings: Settings) { +async fn stream(mut s: impl Write, tracklist: Arc>, settings: Settings) { let args = Args::parse(); - + let encoder_wants = match settings.encoder { + Encoder::Opus | Encoder::Vorbis | Encoder::Aac => 48000, + Encoder::Flac => 96000, + _ => 0, + }; loop { let track = tracklist.choose(&mut thread_rng()).unwrap().clone(); @@ -255,43 +369,19 @@ async fn stream(mut s: TcpStream, tracklist: Arc>, settings: Settin }; }; let track_message = format!("{} - {} - {}", &artist, &album, &title); - eprintln!( - "[{}] {} to {}:{}{} ({:?})", - Local::now().to_rfc3339(), - track_message, - s.peer_addr().unwrap().ip(), - s.peer_addr().unwrap().port(), - if args.war { - " with WAR.rs" - } else { - "" - }, - settings.encoder - ); + println!("[{}] {} ({:?})", Local::now().to_rfc3339(), track_message, settings.encoder); - if args.public_log { - println!( - "[{}] {} to {}{}", - Local::now().to_rfc3339(), - track.to_str().unwrap(), - s.peer_addr().unwrap().port(), - if args.war { - " with WAR.rs" - } else { - "" - } - ); - } - let (channels, sample_rate, time) = get_meta(track.as_path()).await; - let stream = decode_file_stream(track); + let (channels, sample_rate, time) = get_meta(track.as_path(), encoder_wants).await; + let stream = decode_file_stream(track, encoder_wants); + let id = thread_rng().gen(); if stream_track( stream, - args.war, TrackMetadata { track_length_frac: time.frac as f32, track_length_secs: time.seconds, encoder: settings.encoder, cover: cover.join().unwrap(), + id, album, artist, title,