From cec5cdb6aeb4bbae56b13a9c95b982d4ea33b2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ja=C5=ADhien=20Lavon=C4=87je=C5=AD?= Date: Mon, 4 May 2026 05:52:25 +0200 Subject: [PATCH] deps: Update dependencies and remove once_cell dependency - Change Rust edition to 2024 - Update gnome runtime to gnome 50 - Update pipewire from 0.7.1 to 0.9.2 - Update adwaita from 0.5 to 0.9.1 - Update glib from 0.18 to 0.22.7 - Replace once_cell dependency with std::cell::OnceCell --- .gitignore | 1 + Cargo.lock | 658 ++++++++++++++--------------- Cargo.toml | 22 +- build-aux/org.pipewire.Helvum.json | 8 +- meson.build | 4 +- src/application.rs | 22 +- src/graph_manager.rs | 46 +- src/main.rs | 10 +- src/pipewire_connection/mod.rs | 292 ++++++------- src/ui/graph/graph_view.rs | 52 ++- src/ui/graph/link.rs | 11 +- src/ui/graph/node.rs | 13 +- src/ui/graph/port.rs | 19 +- src/ui/graph/port_handle.rs | 4 +- src/ui/graph/zoomentry.rs | 24 +- src/ui/window.rs | 3 +- 16 files changed, 586 insertions(+), 603 deletions(-) diff --git a/.gitignore b/.gitignore index 08bf5da..37e070b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /.vscode /_build /target +/repo diff --git a/Cargo.lock b/Cargo.lock index 4876527..c209b73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,79 +1,86 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] [[package]] -name = "anyhow" -version = "1.0.75" +name = "annotate-snippets" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bindgen" -version = "0.66.1" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.4.0", + "annotate-snippets", + "bitflags", "cexpr", "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", + "itertools", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", - "syn 2.0.37", + "syn", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "cairo-rs" -version = "0.18.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c0466dfa8c0ee78deef390c274ad756801e0a6dbb86c5ef0924a298c5761c4d" +checksum = "5cc8d9aa793480744cd9a0524fef1a2e197d9eaa0f739cde19d16aba530dcb95" dependencies = [ - "bitflags 2.4.0", + "bitflags", "cairo-sys-rs", "glib", "libc", - "once_cell", - "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.18.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +checksum = "f8b4985713047f5faee02b8db6a6ef32bbb50269ff53c1aee716d1d195b76d54" dependencies = [ "glib-sys", "libc", @@ -82,11 +89,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ - "libc", + "find-msvc-tools", + "shlex", ] [[package]] @@ -95,14 +103,14 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] name = "cfg-expr" -version = "0.15.5" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" +checksum = "3c6b04e07d8080154ed4ac03546d9a2b303cc2fe1901ba0b35b301516e289368" dependencies = [ "smallvec", "target-lexicon", @@ -110,15 +118,21 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -127,24 +141,30 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" dependencies = [ "unicode-segmentation", ] [[package]] name = "cookie-factory" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396de984970346b0d9e93d1415082923c679e5ae5c3ee3dcbd104f5610af126b" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "field-offset" @@ -152,30 +172,52 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset 0.9.0", + "memoffset", "rustc_version", ] [[package]] -name = "futures-channel" -version = "0.3.28" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -184,59 +226,67 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn", ] [[package]] -name = "futures-task" -version = "0.3.28" +name = "futures-sink" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", - "pin-utils", "slab", ] [[package]] name = "gdk-pixbuf" -version = "0.18.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc9c2ed73a81d556b65d08879ba4ee58808a6b1927ce915262185d6d547c6f3" +checksum = "25f420376dbee041b2db374ce4573892a36222bb3f6c0c43e24f0d67eae9b646" dependencies = [ "gdk-pixbuf-sys", "gio", "glib", "libc", - "once_cell", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.18.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +checksum = "48f31b37b1fc4b48b54f6b91b7ef04c18e00b4585d98359dd7b998774bbd91fb" dependencies = [ "gio-sys", "glib-sys", @@ -247,9 +297,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.7.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edb019ad581f8ecf8ea8e4baa6df7c483a95b5a59be3140be6a9c3b0c632af6" +checksum = "fd42fdbbf48612c6e8f47c65fb92d2e8f39c25aecd6af047e83897c1a22d2a4e" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -262,9 +312,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.7.2" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0" +checksum = "9d974ac4f15e67472c3a9728daf612590b4a5762a4b33f0edd298df0b80d043c" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -279,9 +329,9 @@ dependencies = [ [[package]] name = "gio" -version = "0.18.2" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57052f84e8e5999b258e8adf8f5f2af0ac69033864936b8b6838321db2f759b1" +checksum = "e3848bcba3a35cc0a71df8ba8ecfd799d6bfb862342a53a4a915fb62213aa4e6" dependencies = [ "futures-channel", "futures-core", @@ -290,32 +340,30 @@ dependencies = [ "gio-sys", "glib", "libc", - "once_cell", "pin-project-lite", "smallvec", - "thiserror", ] [[package]] name = "gio-sys" -version = "0.18.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +checksum = "64729ba2772c080448f9f966dba8f4456beeb100d8c28a865ef8a0f2ef4987e1" dependencies = [ "glib-sys", "gobject-sys", "libc", "system-deps", - "winapi", + "windows-sys", ] [[package]] name = "glib" -version = "0.18.2" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c316afb01ce8067c5eaab1fc4f2cd47dc21ce7b6296358605e2ffab23ccbd19" +checksum = "c207e04e51605dcf7b2924c41591b3a10e1438eaac5bcf448fb91f325381104a" dependencies = [ - "bitflags 2.4.0", + "bitflags", "futures-channel", "futures-core", "futures-executor", @@ -328,30 +376,26 @@ dependencies = [ "libc", "log", "memchr", - "once_cell", "smallvec", - "thiserror", ] [[package]] name = "glib-macros" -version = "0.18.2" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8da903822b136d42360518653fcf154455defc437d3e7a81475bf9a95ff1e47" +checksum = "506d23499707c7142898429757e8d9a3871d965239a2cb66dfa05052be6d6f19" dependencies = [ "heck", - "proc-macro-crate", - "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.37", + "syn", ] [[package]] name = "glib-sys" -version = "0.18.1" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +checksum = "5f7fbac234ed5bc2a28359b7bde8e1b9cdf1441cc2d7f068e4824672d7db9445" dependencies = [ "libc", "system-deps", @@ -359,15 +403,15 @@ dependencies = [ [[package]] name = "glob" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "gobject-sys" -version = "0.18.0" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +checksum = "22a861859b887a79cf461359c192c97a57d8fb0229dd291232e57aa11f6fa72c" dependencies = [ "glib-sys", "libc", @@ -376,9 +420,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.18.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2228cda1505613a7a956cca69076892cfbda84fc2b7a62b94a41a272c0c401" +checksum = "c7d1b7881f96869f49808b6adfe906a93a57a34204952253444d68c3208d71f1" dependencies = [ "glib", "graphene-sys", @@ -387,9 +431,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.18.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4144cee8fc8788f2a9b73dc5f1d4e1189d1f95305c4cb7bd9c1af1cfa31f59" +checksum = "517f062f3fd6b7fd3e57a3f038a74b3c23ca32f51199ff028aa704609943f79c" dependencies = [ "glib-sys", "libc", @@ -399,9 +443,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.7.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e" +checksum = "53c912dfcbd28acace5fc99c40bb9f25e1dcb73efb1f2608327f66a99acdcb62" dependencies = [ "cairo-rs", "gdk4", @@ -414,9 +458,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.7.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55" +checksum = "d7d54bbc7a9d8b6ffe4f0c95eede15ccfb365c8bf521275abe6bcfb57b18fb8a" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -430,9 +474,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.7.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb51aa3e9728575a053e1f43543cd9992ac2477e1b186ad824fd4adfb70842" +checksum = "7181b837f04cbe93f79441475f7a00560a92cba7a72e38cc1a68b6f8b78eaae2" dependencies = [ "cairo-rs", "field-offset", @@ -451,23 +495,21 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.7.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d57ec49cf9b657f69a05bca8027cff0a8dfd0c49e812be026fc7311f2163832f" +checksum = "3581b242ba62fdff122ebb626ea641582ec326031622bd19d60f85029c804a87" dependencies = [ - "anyhow", "proc-macro-crate", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "gtk4-sys" -version = "0.7.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54d8c4aa23638ce9faa2caf7e2a27d4a1295af2155c8e8d28c4d4eeca7a65eb8" +checksum = "20ba8e695e2640455561274e65e45f0a151619e450746007667f4b23ceae4e1b" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -484,57 +526,54 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "helvum" version = "0.5.1" dependencies = [ + "futures", "glib", + "gtk4", "libadwaita", "libc", "log", - "once_cell", "pipewire", ] [[package]] name = "indexmap" -version = "2.0.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad227c3af19d4914570ad36d30409928b75967c298feb9ea1969db3a610bb14e" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "itertools" +version = "0.13.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" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] [[package]] name = "libadwaita" -version = "0.5.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fe7e70c06507ed10a16cda707f358fbe60fe0dc237498f78c686ade92fd979c" +checksum = "bc0da4e27b20d3e71f830e5b0f0188d22c257986bf421c02cfde777fe07932a4" dependencies = [ - "gdk-pixbuf", "gdk4", "gio", "glib", @@ -546,9 +585,9 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.5.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e10aaa38de1d53374f90deeb4535209adc40cc5dba37f9704724169bceec69a" +checksum = "aaee067051c5d3c058d050d167688b80b67de1950cfca77730549aa761fc5d7d" dependencies = [ "gdk4-sys", "gio-sys", @@ -562,42 +601,42 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "winapi", + "windows-link", ] [[package]] name = "libspa" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0434617020ddca18b86067912970c55410ca654cdafd775480322f50b857a8c4" +checksum = "b6b8cfa2a7656627b4c92c6b9ef929433acd673d5ab3708cda1b18478ac00df4" dependencies = [ - "bitflags 2.4.0", + "bitflags", "cc", "convert_case", "cookie-factory", "libc", "libspa-sys", "nix", - "nom", + "nom 8.0.0", "system-deps", ] [[package]] name = "libspa-sys" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e70ca3f3e70f858ef363046d06178c427b4e0b63d210c95fd87d752679d345" +checksum = "901049455d2eb6decf9058235d745237952f4804bc584c5fcb41412e6adcc6e0" dependencies = [ "bindgen", "cc", @@ -606,30 +645,21 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "memchr" -version = "2.6.3" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" -version = "0.7.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] @@ -642,15 +672,14 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "nix" -version = "0.26.4" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if", + "cfg_aliases", "libc", - "memoffset 0.7.1", - "pin-utils", ] [[package]] @@ -664,29 +693,37 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.18.0" +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "pango" -version = "0.18.0" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06a9e54b831d033206160096b825f2070cf5fda7e35167b1c01e9e774f9202d1" +checksum = "251bdc6e6487b811be0e406a21e301e07e45c0aa8fa39e00c0c8e12a91752438" dependencies = [ "gio", "glib", "libc", - "once_cell", "pango-sys", ] [[package]] name = "pango-sys" -version = "0.18.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +checksum = "bbd111a20ca90fedf03e09c59783c679c00900f1d8491cca5399f5e33609d5d6" dependencies = [ "glib-sys", "gobject-sys", @@ -694,32 +731,20 @@ dependencies = [ "system-deps", ] -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pipewire" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d009c8dd65e890b515a71950f7e4c801523b8894ff33863a40830bf762e9e9" +checksum = "9688b89abf11d756499f7c6190711d6dbe5a3acdb30c8fbf001d6596d06a8d44" dependencies = [ "anyhow", - "bitflags 2.4.0", + "bitflags", "libc", "libspa", "libspa-sys", @@ -731,9 +756,9 @@ dependencies = [ [[package]] name = "pipewire-sys" -version = "0.7.2" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890c084e7b737246cb4799c86b71a0e4da536031ff7473dd639eba9f95039f64" +checksum = "cb028afee0d6ca17020b090e3b8fa2d7de23305aef975c7e5192a5050246ea36" dependencies = [ "bindgen", "libspa-sys", @@ -742,67 +767,42 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "once_cell", "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -812,9 +812,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -823,97 +823,83 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "semver" -version = "1.0.19" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] -name = "serde" -version = "1.0.188" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.11.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -922,9 +908,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.1" +version = "7.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" dependencies = [ "cfg-expr", "heck", @@ -935,115 +921,125 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" [[package]] name = "thiserror" -version = "1.0.49" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn", ] [[package]] name = "toml" -version = "0.7.8" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", - "serde", + "serde_core", "serde_spanned", "toml_datetime", + "toml_parser", + "toml_writer", "winnow", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "version-compare" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" [[package]] -name = "version_check" -version = "0.9.4" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-link", ] -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "winnow" -version = "0.5.15" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index e72f4fd..9d7c57e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,11 @@ [package] name = "helvum" version = "0.5.1" -authors = ["Tom Wagner "] -edition = "2021" -rust-version = "1.70" +authors = [ + "Tom Wagner ", + "Jaŭhien Lavonćjeŭ " +] +edition = "2024" license = "GPL-3.0-only" description = "A GTK patchbay for pipewire" repository = "https://gitlab.freedesktop.org/pipewire/helvum" @@ -14,12 +16,10 @@ categories = ["gui", "multimedia"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -pipewire = "0.7.1" -adw = { version = "0.5", package = "libadwaita", features = ["v1_4"] } -glib = { version = "0.18", features = ["log"] } - -log = "0.4.11" - -once_cell = "1.7.2" - +pipewire = "0.9.2" +adw = { version = "0.9.1", package = "libadwaita", features = ["v1_9"] } +gtk = { package = "gtk4", version = "0.11.2", features = ["gnome_50"] } +glib = { version = "0.22.7", features = ["log"] } +futures = "0.3.32" +log = "0.4.29" libc = "0.2" diff --git a/build-aux/org.pipewire.Helvum.json b/build-aux/org.pipewire.Helvum.json index 8716d17..1144ac4 100644 --- a/build-aux/org.pipewire.Helvum.json +++ b/build-aux/org.pipewire.Helvum.json @@ -1,11 +1,11 @@ { "id": "org.pipewire.Helvum", "runtime": "org.gnome.Platform", - "runtime-version": "45", + "runtime-version": "50", "sdk": "org.gnome.Sdk", "sdk-extensions": [ "org.freedesktop.Sdk.Extension.rust-stable", - "org.freedesktop.Sdk.Extension.llvm16" + "org.freedesktop.Sdk.Extension.llvm22" ], "command": "helvum", "finish-args": [ @@ -16,8 +16,8 @@ "--filesystem=xdg-run/pipewire-0" ], "build-options": { - "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm16/bin", - "prepend-ld-library-path": "/usr/lib/sdk/llvm16/lib", + "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm22/bin", + "prepend-ld-library-path": "/usr/lib/sdk/llvm22/lib", "build-args": [ "--share=network" ] diff --git a/meson.build b/meson.build index 34bf0fa..8d2e6b9 100644 --- a/meson.build +++ b/meson.build @@ -11,8 +11,8 @@ gnome = import('gnome') base_id = 'org.pipewire.Helvum' dependency('glib-2.0', version: '>= 2.66') -dependency('gtk4', version: '>= 4.4.0') -dependency('libadwaita-1', version: '>= 1.4') +dependency('gtk4', version: '>= 4.22.0') +dependency('libadwaita-1', version: '>= 1.9') dependency('libpipewire-0.3') desktop_file_validate = find_program('desktop-file-validate', required: false) diff --git a/src/application.rs b/src/application.rs index 0e4dbc0..3998caa 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,14 +15,17 @@ // // SPDX-License-Identifier: GPL-3.0-only +use std::cell::OnceCell; +use futures::channel::mpsc::UnboundedReceiver; +use pipewire::channel::Sender; + use adw::{ gio, - glib::{self, clone, Receiver}, + glib::{self, clone}, gtk, prelude::*, subclass::prelude::*, }; -use pipewire::channel::Sender; use crate::{graph_manager::GraphManager, ui, GtkMessage, PipewireMessage}; @@ -33,9 +37,6 @@ static AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); mod imp { use super::*; - use adw::subclass::prelude::AdwApplicationImpl; - use once_cell::unsync::OnceCell; - #[derive(Default)] pub struct Application { pub(super) window: ui::Window, @@ -60,7 +61,7 @@ mod imp { let zoom_set_action = gio::SimpleAction::new("set-zoom", Some(&f64::static_variant_type())); - zoom_set_action.connect_activate(clone!(@weak graphview => move|_, param| { + zoom_set_action.connect_activate(clone!(#[weak] graphview, move|_, param| { let zoom_factor = param.unwrap().get::().unwrap(); graphview.set_zoom_factor(zoom_factor, None) })); @@ -97,7 +98,7 @@ mod imp { // Add shortcut for quitting the application. let quit = gtk::gio::SimpleAction::new("quit", None); - quit.connect_activate(clone!(@weak obj => move |_, _| { + quit.connect_activate(clone!(#[weak] obj, move |_, _| { obj.quit(); })); obj.set_accels_for_action("app.quit", &["Q"]); @@ -116,8 +117,7 @@ mod imp { let window = obj.active_window().unwrap(); let authors: Vec<&str> = AUTHORS.split(':').collect(); - let about_window = adw::AboutWindow::builder() - .transient_for(&window) + let about_dialog = adw::AboutDialog::builder() .application_icon(APP_ID) .application_name("Helvum") .developer_name("Tom Wagner") @@ -128,7 +128,7 @@ mod imp { .license_type(gtk::License::Gpl30Only) .build(); - about_window.present(); + about_dialog.present(Some(&window)); } } } @@ -143,7 +143,7 @@ impl Application { /// Create the view. /// This will set up the entire user interface and prepare it for being run. pub(super) fn new( - gtk_receiver: Receiver, + gtk_receiver: UnboundedReceiver, pw_sender: Sender, ) -> Self { let app: Application = glib::Object::builder() diff --git a/src/graph_manager.rs b/src/graph_manager.rs index 34b2868..d7c4d21 100644 --- a/src/graph_manager.rs +++ b/src/graph_manager.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,31 +15,34 @@ // // SPDX-License-Identifier: GPL-3.0-only -use adw::{glib, prelude::*, subclass::prelude::*}; +use std::{cell::{RefCell, OnceCell}, collections::HashMap}; +use futures::{prelude::*, channel::mpsc::UnboundedReceiver}; -use pipewire::channel::Sender as PwSender; +use adw::{glib::clone, prelude::*, subclass::prelude::*}; -use crate::{ui::graph::GraphView, GtkMessage, PipewireMessage}; +use pipewire::{ + spa::{ + param::format::MediaType, + utils::Direction + }, + channel::Sender +}; + +use crate::{ui::graph, ui::graph::GraphView, GtkMessage, PipewireMessage, NodeType}; mod imp { use super::*; - use std::{cell::RefCell, collections::HashMap}; - - use once_cell::unsync::OnceCell; - - use crate::{ui::graph, MediaType, NodeType}; - #[derive(Default, glib::Properties)] #[properties(wrapper_type = super::GraphManager)] pub struct GraphManager { #[property(get, set, construct_only)] - pub graph: OnceCell, + pub graph: OnceCell, #[property(get, set, construct_only)] pub connection_banner: OnceCell, - pub pw_sender: OnceCell>, + pub pw_sender: OnceCell>, pub items: RefCell>, } @@ -53,10 +57,9 @@ mod imp { impl ObjectImpl for GraphManager {} impl GraphManager { - pub fn attach_receiver(&self, receiver: glib::Receiver) { - receiver.attach(None, glib::clone!( - @weak self as imp => @default-return glib::ControlFlow::Continue, - move |msg| { + pub fn attach_receiver(&self, mut receiver: UnboundedReceiver) { + glib::MainContext::default().spawn_local(clone!(#[weak(rename_to = imp)] self, async move { + while let Some(msg) = receiver.next().await { match msg { PipewireMessage::NodeAdded { id, name, node_type } => imp.add_node(id, name.as_str(), node_type), PipewireMessage::NodeNameChanged { id, name, media_name } => imp.node_name_changed(id, &name, &media_name), @@ -80,9 +83,8 @@ mod imp { imp.clear(); }, }; - glib::ControlFlow::Continue } - )); + })); } /// Add a new node to the view. @@ -130,7 +132,7 @@ mod imp { } /// Add a new port to the view. - fn add_port(&self, id: u32, name: &str, node_id: u32, direction: pipewire::spa::Direction) { + fn add_port(&self, id: u32, name: &str, node_id: u32, direction: Direction) { log::info!("Adding port to graph: id {}", id); let mut items = self.items.borrow_mut(); @@ -150,7 +152,7 @@ mod imp { port.connect_local( "port_toggled", false, - glib::clone!(@weak self as app => @default-return None, move |args| { + glib::clone!(#[weak(rename_to = app)] self, #[upgrade_or] None, move |args| { // Args always look like this: &[widget, id_port_from, id_port_to] let port_from = args[1].get::().unwrap(); let port_to = args[2].get::().unwrap(); @@ -273,7 +275,7 @@ mod imp { link.set_active(active); } - fn link_format_changed(&self, id: u32, media_type: pipewire::spa::format::MediaType) { + fn link_format_changed(&self, id: u32, media_type: MediaType) { let items = self.items.borrow(); let Some(link) = items.get(&id) else { @@ -326,8 +328,8 @@ impl GraphManager { pub fn new( graph: &GraphView, connection_banner: &adw::Banner, - sender: PwSender, - receiver: glib::Receiver, + sender: Sender, + receiver: UnboundedReceiver, ) -> Self { let res: Self = glib::Object::builder() .property("graph", graph) diff --git a/src/main.rs b/src/main.rs index 610c175..fa20009 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -19,8 +20,10 @@ mod graph_manager; mod pipewire_connection; mod ui; +use futures::channel::mpsc::unbounded; +use pipewire::spa::{utils::Direction, param::format::MediaType}; + use adw::{gtk, prelude::*}; -use pipewire::spa::{format::MediaType, Direction}; /// Messages sent by the GTK thread to notify the pipewire thread. #[derive(Debug, Clone)] @@ -120,10 +123,9 @@ fn main() -> Result<(), Box> { // Start the pipewire thread with channels in both directions. - let (gtk_sender, gtk_receiver) = glib::MainContext::channel(glib::Priority::DEFAULT); + let (gtk_sender, gtk_receiver) = unbounded::(); let (pw_sender, pw_receiver) = pipewire::channel::channel(); - let pw_thread = - std::thread::spawn(move || pipewire_connection::thread_main(gtk_sender, pw_receiver)); + let pw_thread = std::thread::spawn(move || pipewire_connection::thread_main(gtk_sender, pw_receiver)); let app = application::Application::new(gtk_receiver, pw_sender.clone()); diff --git a/src/pipewire_connection/mod.rs b/src/pipewire_connection/mod.rs index 768f737..8a8f73c 100644 --- a/src/pipewire_connection/mod.rs +++ b/src/pipewire_connection/mod.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -23,22 +24,22 @@ use std::{ time::Duration, }; -use adw::glib::{self, clone}; +use futures::channel::mpsc::UnboundedSender; +use glib::clone; use log::{debug, error, info, warn}; use pipewire::{ + context::ContextRc, + channel::Receiver, + core::{CoreRc, PW_ID_CORE}, keys, - link::{Link, LinkChangeMask, LinkInfo, LinkListener, LinkState}, - node::{Node, NodeInfo, NodeListener}, - port::{Port, PortChangeMask, PortInfo, PortListener}, - prelude::*, - properties, - registry::{GlobalObject, Registry}, - spa::{ - param::{ParamInfoFlags, ParamType}, - ForeignDict, SpaResult, - }, - types::ObjectType, - Context, Core, MainLoop, + link::{Link, LinkChangeMask, LinkInfoRef, LinkListener, LinkState}, + main_loop::{MainLoopRc}, + node::{Node, NodeInfoRef, NodeListener}, + port::{Port, PortChangeMask, PortInfoRef, PortListener}, + properties::properties, + registry::{GlobalObject, RegistryRc}, + spa::{param::{ParamInfoFlags, ParamType}, utils::{dict::DictRef, result::SpaResult}}, + types::ObjectType }; use crate::{GtkMessage, MediaType, NodeType, PipewireMessage}; @@ -61,70 +62,63 @@ enum ProxyItem { /// The "main" function of the pipewire thread. pub(super) fn thread_main( - gtk_sender: glib::Sender, - mut pw_receiver: pipewire::channel::Receiver, + gtk_sender: UnboundedSender, + mut pw_receiver: Receiver, ) { - let mainloop = MainLoop::new().expect("Failed to create mainloop"); - let context = Rc::new(Context::new(&mainloop).expect("Failed to create context")); + let mainloop = MainLoopRc::new(None).expect("Failed to create mainloop"); + let context = ContextRc::new(&mainloop, None).expect("Failed to create context"); let is_stopped = Rc::new(Cell::new(false)); let mut is_connecting = false; while !is_stopped.get() { // Try to connect - let core = match context.connect(Some(properties! { + let Ok(core) = context.connect_rc(Some(properties! { "media.category" => "Manager" - })) { - Ok(core) => Rc::new(core), - Err(_) => { - if !is_connecting { - is_connecting = true; - gtk_sender - .send(PipewireMessage::Connecting) - .expect("Failed to send message"); - } - - // If connection is failed, try to connect again in 200ms - let interval = Some(Duration::from_millis(200)); - - let timer = mainloop.add_timer(clone!(@strong mainloop => move |_| { - mainloop.quit(); - })); - - timer.update_timer(interval, None).into_result().unwrap(); - - let receiver = pw_receiver.attach(&mainloop, { - clone!(@strong mainloop, @strong is_stopped => move |msg| - if let GtkMessage::Terminate = msg { - // main thread requested stop - is_stopped.set(true); - mainloop.quit(); - } - ) - }); - - mainloop.run(); - pw_receiver = receiver.deattach(); - - continue; + })) else { + if !is_connecting { + is_connecting = true; + gtk_sender.unbounded_send(PipewireMessage::Connecting).expect("Failed to send message"); } + + // If connection is failed, try to connect again in 200ms + let interval = Some(Duration::from_millis(200)); + + let timer = mainloop.loop_().add_timer(clone!(#[strong] mainloop, move |_| { + mainloop.quit(); + })); + + timer.update_timer(interval, None).into_result().unwrap(); + + let receiver = pw_receiver.attach(&mainloop.loop_(), { + clone!(#[strong] mainloop, #[strong] is_stopped, move |msg| + if let GtkMessage::Terminate = msg { + // main thread requested stop + is_stopped.set(true); + mainloop.quit(); + } + ) + }); + + mainloop.run(); + pw_receiver = receiver.deattach(); + + continue; }; if is_connecting { is_connecting = false; - gtk_sender - .send(PipewireMessage::Connected) - .expect("Failed to send message"); + gtk_sender.unbounded_send(PipewireMessage::Connected).expect("Failed to send message"); } - let registry = Rc::new(core.get_registry().expect("Failed to get registry")); + let registry = core.get_registry_rc().expect("Failed to get registry"); // Keep proxies and their listeners alive so that we can receive info events. let proxies = Rc::new(RefCell::new(HashMap::new())); let state = Rc::new(RefCell::new(State::new())); - let receiver = pw_receiver.attach(&mainloop, { - clone!(@strong mainloop, @weak core, @weak registry, @strong state, @strong is_stopped => move |msg| match msg { - GtkMessage::ToggleLink { port_from, port_to } => toggle_link(port_from, port_to, &core, ®istry, &state), + let receiver = pw_receiver.attach(&mainloop.loop_(), { + clone!(#[strong] mainloop, #[strong] core, #[strong] registry, #[strong] state, #[strong] is_stopped, move |msg| match msg { + GtkMessage::ToggleLink { port_from, port_to } => toggle_link(port_from, port_to, &core, ®istry, &state.borrow()), GtkMessage::Terminate => { // main thread requested stop is_stopped.set(true); @@ -135,14 +129,13 @@ pub(super) fn thread_main( let gtk_sender = gtk_sender.clone(); let _listener = core.add_listener_local() - .error(clone!(@strong mainloop, @strong gtk_sender, @strong is_stopped => move |id, _seq, res, message| { - if id != pipewire::PW_ID_CORE { + .error(clone!(#[strong] mainloop, #[strong] gtk_sender, move |id, _seq, res, message| { + if id != PW_ID_CORE { return; } if res == -libc::EPIPE { - gtk_sender.send(PipewireMessage::Disconnected) - .expect("Failed to send message"); + gtk_sender.unbounded_send(PipewireMessage::Disconnected).expect("Failed to send message"); mainloop.quit(); } else { let serr = SpaResult::from_c(res).into_result().unwrap_err(); @@ -153,19 +146,19 @@ pub(super) fn thread_main( let _listener = registry .add_listener_local() - .global(clone!(@strong gtk_sender, @weak registry, @strong proxies, @strong state => + .global(clone!(#[strong] gtk_sender, #[strong] registry, #[strong] proxies, #[strong] state, move |global| match global.type_ { - ObjectType::Node => handle_node(global, >k_sender, ®istry, &proxies, &state), + ObjectType::Node => handle_node(global, >k_sender, ®istry, &proxies, &mut state.borrow_mut()), ObjectType::Port => handle_port(global, >k_sender, ®istry, &proxies, &state), - ObjectType::Link => handle_link(global, >k_sender, ®istry, &proxies, &state), + ObjectType::Link => handle_link(global, >k_sender, ®istry, &mut proxies.borrow_mut(), &state), _ => { // Other objects are not interesting to us } } )) - .global_remove(clone!(@strong proxies, @strong state => move |id| { + .global_remove(clone!(#[strong] proxies, #[strong] state, move |id| { if let Some(item) = state.borrow_mut().remove(id) { - gtk_sender.send(match item { + gtk_sender.unbounded_send(match item { Item::Node { .. } => PipewireMessage::NodeRemoved {id}, Item::Port { node_id } => PipewireMessage::PortRemoved {id, node_id}, Item::Link { .. } => PipewireMessage::LinkRemoved {id}, @@ -187,21 +180,22 @@ pub(super) fn thread_main( } /// Get the nicest possible name for the node, using a fallback chain of possible name attributes -fn get_node_name(props: &ForeignDict) -> &str { +fn get_node_name(props: &DictRef) -> String { props .get(&keys::NODE_DESCRIPTION) .or_else(|| props.get(&keys::NODE_NICK)) .or_else(|| props.get(&keys::NODE_NAME)) .unwrap_or_default() + .to_string() } /// Handle a new node being added fn handle_node( - node: &GlobalObject, - sender: &glib::Sender, - registry: &Rc, + node: &GlobalObject<&DictRef>, + sender: &UnboundedSender, + registry: &RegistryRc, proxies: &Rc>>, - state: &Rc>, + state: &mut State, ) { let props = node .props @@ -230,21 +224,19 @@ fn handle_node( }) .or_else(|| props.get("media.class").and_then(media_class)); - state.borrow_mut().insert(node.id, Item::Node); + state.insert(node.id, Item::Node); - sender - .send(PipewireMessage::NodeAdded { - id: node.id, - name, - node_type, - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::NodeAdded { + id: node.id, + name, + node_type, + }).expect("Failed to send message"); let proxy: Node = registry.bind(node).expect("Failed to bind to node proxy"); let listener = proxy .add_listener_local() - .info(clone!(@strong sender, @strong proxies => move |info| { - handle_node_info(info, &sender, &proxies); + .info(clone!(#[strong] sender, #[strong] proxies, move |info| { + handle_node_info(info, &sender, &proxies.borrow()); })) .register(); @@ -258,14 +250,13 @@ fn handle_node( } fn handle_node_info( - info: &NodeInfo, - sender: &glib::Sender, - proxies: &Rc>>, + info: &NodeInfoRef, + sender: &UnboundedSender, + proxies: &HashMap, ) { debug!("Received node info: {:?}", info); let id = info.id(); - let proxies = proxies.borrow(); let Some(ProxyItem::Node { .. }) = proxies.get(&id) else { error!("Received info on unknown node with id {id}"); return; @@ -275,21 +266,19 @@ fn handle_node_info( if let Some(media_name) = props.get(&keys::MEDIA_NAME) { let name = get_node_name(props).to_string(); - sender - .send(PipewireMessage::NodeNameChanged { - id, - name, - media_name: media_name.to_string(), - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::NodeNameChanged { + id, + name, + media_name: media_name.to_string(), + }).expect("Failed to send message"); } } /// Handle a new port being added fn handle_port( - port: &GlobalObject, - sender: &glib::Sender, - registry: &Rc, + port: &GlobalObject<&DictRef>, + sender: &UnboundedSender, + registry: &RegistryRc, proxies: &Rc>>, state: &Rc>, ) { @@ -298,11 +287,11 @@ fn handle_port( let listener = proxy .add_listener_local() .info( - clone!(@strong proxies, @strong state, @strong sender => move |info| { - handle_port_info(info, &proxies, &state, &sender); + clone!(#[strong] proxies, #[strong] state, #[strong] sender, move |info| { + handle_port_info(info, &proxies.borrow(), &mut state.borrow_mut(), &sender); }), ) - .param(clone!(@strong sender => move |_, param_id, _, _, param| { + .param(clone!(#[strong] sender, move |_, param_id, _, _, param| { if param_id == ParamType::EnumFormat { handle_port_enum_format(port_id, param, &sender) } @@ -319,22 +308,19 @@ fn handle_port( } fn handle_port_info( - info: &PortInfo, - proxies: &Rc>>, - state: &Rc>, - sender: &glib::Sender, + info: &PortInfoRef, + proxies: &HashMap, + state: &mut State, + sender: &UnboundedSender, ) { debug!("Received port info: {:?}", info); let id = info.id(); - let proxies = proxies.borrow(); let Some(ProxyItem::Port { proxy, .. }) = proxies.get(&id) else { log::error!("Received info on unknown port with id {id}"); return; }; - let mut state = state.borrow_mut(); - if let Some(Item::Port { .. }) = state.get(id) { // Info was an update, figure out if we should notify the GTK thread if info.change_mask().contains(PortChangeMask::PARAMS) { @@ -362,41 +348,37 @@ fn handle_port_info( } } - sender - .send(PipewireMessage::PortAdded { - id, - node_id, - name, - direction: info.direction(), - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::PortAdded { + id, + node_id, + name, + direction: info.direction(), + }).expect("Failed to send message"); } } fn handle_port_enum_format( port_id: u32, param: Option<&pipewire::spa::pod::Pod>, - sender: &glib::Sender, + sender: &UnboundedSender, ) { let media_type = param .and_then(|param| pipewire::spa::param::format_utils::parse_format(param).ok()) .map(|(media_type, _media_subtype)| media_type) .unwrap_or(MediaType::Unknown); - sender - .send(PipewireMessage::PortFormatChanged { - id: port_id, - media_type, - }) - .expect("Failed to send message") + sender.unbounded_send(PipewireMessage::PortFormatChanged { + id: port_id, + media_type, + }).expect("Failed to send message"); } /// Handle a new link being added fn handle_link( - link: &GlobalObject, - sender: &glib::Sender, - registry: &Rc, - proxies: &Rc>>, + link: &GlobalObject<&DictRef>, + sender: &UnboundedSender, + registry: &RegistryRc, + proxies: &mut HashMap, state: &Rc>, ) { debug!( @@ -407,12 +389,12 @@ fn handle_link( let proxy: Link = registry.bind(link).expect("Failed to bind to link proxy"); let listener = proxy .add_listener_local() - .info(clone!(@strong state, @strong sender => move |info| { - handle_link_info(info, &state, &sender); + .info(clone!(#[strong] state, #[strong] sender, move |info| { + handle_link_info(info, &mut state.borrow_mut(), &sender); })) .register(); - proxies.borrow_mut().insert( + proxies.insert( link.id, ProxyItem::Link { _proxy: proxy, @@ -422,32 +404,27 @@ fn handle_link( } fn handle_link_info( - info: &LinkInfo, - state: &Rc>, - sender: &glib::Sender, + info: &LinkInfoRef, + state: &mut State, + sender: &UnboundedSender, ) { debug!("Received link info: {:?}", info); let id = info.id(); - let mut state = state.borrow_mut(); if let Some(Item::Link { .. }) = state.get(id) { // Info was an update - figure out if we should notify the gtk thread if info.change_mask().contains(LinkChangeMask::STATE) { - sender - .send(PipewireMessage::LinkStateChanged { - id, - active: matches!(info.state(), LinkState::Active), - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::LinkStateChanged { + id, + active: matches!(info.state(), LinkState::Active), + }).expect("Failed to send message"); } if info.change_mask().contains(LinkChangeMask::FORMAT) { - sender - .send(PipewireMessage::LinkFormatChanged { - id, - media_type: get_link_media_type(info), - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::LinkFormatChanged { + id, + media_type: get_link_media_type(info), + }).expect("Failed to send message"); } } else { // First time we get info. We can now notify the gtk thread of a new link. @@ -456,15 +433,13 @@ fn handle_link_info( state.insert(id, Item::Link { port_from, port_to }); - sender - .send(PipewireMessage::LinkAdded { - id, - port_from, - port_to, - active: matches!(info.state(), LinkState::Active), - media_type: get_link_media_type(info), - }) - .expect("Failed to send message"); + sender.unbounded_send(PipewireMessage::LinkAdded { + id, + port_from, + port_to, + active: matches!(info.state(), LinkState::Active), + media_type: get_link_media_type(info), + }).expect("Failed to send message"); } } @@ -472,11 +447,10 @@ fn handle_link_info( fn toggle_link( port_from: u32, port_to: u32, - core: &Rc, - registry: &Rc, - state: &Rc>, + core: &CoreRc, + registry: &RegistryRc, + state: &State, ) { - let state = state.borrow_mut(); if let Some(id) = state.get_link_id(port_from, port_to) { info!("Requesting removal of link with id {}", id); @@ -495,7 +469,7 @@ fn toggle_link( .get_node_of_port(port_to) .expect("Requested port not in state"); - if let Err(e) = core.create_object::( + if let Err(e) = core.create_object::( "link-factory", &properties! { "link.output.node" => node_from.to_string(), @@ -510,7 +484,7 @@ fn toggle_link( } } -fn get_link_media_type(link_info: &LinkInfo) -> MediaType { +fn get_link_media_type(link_info: &LinkInfoRef) -> MediaType { let media_type = link_info .format() .and_then(|format| pipewire::spa::param::format_utils::parse_format(format).ok()) diff --git a/src/ui/graph/graph_view.rs b/src/ui/graph/graph_view.rs index 5825dae..2b8c3c7 100644 --- a/src/ui/graph/graph_view.rs +++ b/src/ui/graph/graph_view.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,19 +15,24 @@ // // SPDX-License-Identifier: GPL-3.0-only +use std::{ + cmp::Ordering, + sync::LazyLock, + cell::{Cell, RefCell}, + collections::{HashMap, HashSet} +}; + +use pipewire::spa::{utils::Direction, param::format::MediaType}; + +use gtk::{self, cairo, gsk, gdk, graphene::{self, Point}}; use adw::{ gio, glib::{self, clone}, - gtk::{ - self, cairo, - graphene::{self, Point}, - gsk, - }, prelude::*, subclass::prelude::*, }; -use std::cmp::Ordering; +use log::warn; use super::{Link, Node, Port}; use crate::NodeType; @@ -36,15 +42,6 @@ const CANVAS_SIZE: f64 = 5000.0; mod imp { use super::*; - use std::cell::{Cell, RefCell}; - use std::collections::{HashMap, HashSet}; - - use adw::gtk::gdk::{self}; - use log::warn; - use once_cell::sync::Lazy; - use pipewire::spa::format::MediaType; - use pipewire::spa::Direction; - pub struct Colors { audio: gdk::RGBA, video: gdk::RGBA, @@ -151,7 +148,7 @@ mod imp { } fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: LazyLock> = LazyLock::new(|| { vec![ glib::ParamSpecOverride::for_interface::("hadjustment"), glib::ParamSpecOverride::for_interface::("vadjustment"), @@ -276,6 +273,7 @@ mod imp { drag_controller.connect_drag_begin(|drag_controller, x, y| { let widget = drag_controller .widget() + .unwrap() .dynamic_cast::() .expect("drag-begin event is not on the GraphView"); let mut dragged_node = widget.imp().dragged_node.borrow_mut(); @@ -315,6 +313,7 @@ mod imp { drag_controller.connect_drag_update(|drag_controller, x, y| { let widget = drag_controller .widget() + .unwrap() .dynamic_cast::() .expect("drag-update event is not on the GraphView"); let dragged_node = widget.imp().dragged_node.borrow(); @@ -348,6 +347,7 @@ mod imp { controller.connect_enter(|controller, x, y| { let graph = controller .widget() + .unwrap() .downcast::() .expect("Widget should be a graphview"); @@ -357,6 +357,7 @@ mod imp { controller.connect_motion(|controller, x, y| { let graph = controller .widget() + .unwrap() .downcast::() .expect("Widget should be a graphview"); @@ -366,6 +367,7 @@ mod imp { controller.connect_leave(|controller| { let graph = controller .widget() + .unwrap() .downcast::() .expect("Widget should be a graphview"); @@ -386,7 +388,7 @@ mod imp { Port::static_type(), glib::Priority::DEFAULT, Option::<&gio::Cancellable>::None, - clone!(@weak self as imp => move|value| { + clone!(#[weak(rename_to = imp)] self, move|value| { let Ok(value) = value else { return; }; @@ -430,6 +432,7 @@ mod imp { { let widget = eventcontroller .widget() + .unwrap() .downcast::() .unwrap(); widget.set_zoom_factor(widget.zoom_factor() + (0.1 * -delta_y), None); @@ -445,7 +448,7 @@ mod imp { fn setup_zoom_gesture(&self) { let zoom_gesture = gtk::GestureZoom::new(); zoom_gesture.connect_begin(|gesture, _| { - let widget = gesture.widget().downcast::().unwrap(); + let widget = gesture.widget().unwrap().downcast::().unwrap(); widget .imp() @@ -457,7 +460,7 @@ mod imp { .set(gesture.bounding_box_center()); }); zoom_gesture.connect_scale_changed(move |gesture, delta| { - let widget = gesture.widget().downcast::().unwrap(); + let widget = gesture.widget().unwrap().downcast::().unwrap(); let initial_zoom = widget .imp() @@ -480,6 +483,7 @@ mod imp { drag_controller.connect_drag_begin(|drag_controller, _, _| { let widget = drag_controller .widget() + .unwrap() .downcast::() .unwrap(); @@ -489,6 +493,7 @@ mod imp { drag_controller.connect_drag_update(|drag_controller, x, y| { let widget = drag_controller .widget() + .unwrap() .downcast::() .unwrap(); @@ -689,7 +694,7 @@ mod imp { if let Some(adjustment) = adjustment { adjustment - .connect_value_changed(clone!(@weak obj => move |_| obj.queue_allocate() )); + .connect_value_changed(clone!(#[weak] obj, move |_| obj.queue_allocate() )); } } @@ -720,7 +725,8 @@ mod imp { glib::wrapper! { pub struct GraphView(ObjectSubclass) - @extends gtk::Widget; + @extends gtk::Widget, + @implements gtk::Accessible, gtk::ConstraintTarget, gtk::Buildable, gtk::Scrollable; } impl GraphView { @@ -822,13 +828,13 @@ impl GraphView { pub fn add_link(&self, link: Link) { link.connect_notify_local( Some("active"), - glib::clone!(@weak self as graph => move |_, _| { + glib::clone!(#[weak(rename_to = graph)] self, move |_, _| { graph.queue_draw(); }), ); link.connect_notify_local( Some("media-type"), - glib::clone!(@weak self as graph => move |_, _| { + glib::clone!(#[weak(rename_to = graph)] self, move |_, _| { graph.queue_draw(); }), ); diff --git a/src/ui/graph/link.rs b/src/ui/graph/link.rs index 140c74c..f9d98a5 100644 --- a/src/ui/graph/link.rs +++ b/src/ui/graph/link.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,18 +15,16 @@ // // SPDX-License-Identifier: GPL-3.0-only +use std::{cell::Cell, sync::LazyLock}; +use pipewire::spa::param::format::MediaType; + use adw::{glib, prelude::*, subclass::prelude::*}; -use pipewire::spa::format::MediaType; use super::Port; mod imp { use super::*; - use std::cell::Cell; - - use once_cell::sync::Lazy; - pub struct Link { pub output_port: glib::WeakRef, pub input_port: glib::WeakRef, @@ -53,7 +52,7 @@ mod imp { impl ObjectImpl for Link { fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: LazyLock> = LazyLock::new(|| { vec![ glib::ParamSpecObject::builder::("output-port") .flags(glib::ParamFlags::READWRITE) diff --git a/src/ui/graph/node.rs b/src/ui/graph/node.rs index a3f1afb..8ceaf2e 100644 --- a/src/ui/graph/node.rs +++ b/src/ui/graph/node.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,19 +15,16 @@ // // SPDX-License-Identifier: GPL-3.0-only +use std::{cell::{Cell, RefCell}, collections::HashSet}; +use pipewire::spa::utils::Direction; + use adw::{glib, gtk, prelude::*, subclass::prelude::*}; -use pipewire::spa::Direction; use super::Port; mod imp { use super::*; - use std::{ - cell::{Cell, RefCell}, - collections::HashSet, - }; - #[derive(glib::Properties, gtk::CompositeTemplate, Default)] #[properties(wrapper_type = super::Node)] #[template(file = "node.ui")] @@ -149,7 +147,8 @@ mod imp { glib::wrapper! { pub struct Node(ObjectSubclass) - @extends gtk::Widget; + @extends gtk::Widget, + @implements gtk::Accessible, gtk::ConstraintTarget, gtk::Buildable; } impl Node { diff --git a/src/ui/graph/port.rs b/src/ui/graph/port.rs index 13a5d9b..90da895 100644 --- a/src/ui/graph/port.rs +++ b/src/ui/graph/port.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -14,6 +15,9 @@ // // SPDX-License-Identifier: GPL-3.0-only +use std::{cell::{Cell, OnceCell}, sync::LazyLock}; +use pipewire::spa::{utils::Direction, param::format::MediaType}; + use adw::{ gdk, glib::{self, subclass::Signal}, @@ -21,18 +25,12 @@ use adw::{ prelude::*, subclass::prelude::*, }; -use pipewire::spa::Direction; use super::PortHandle; mod imp { use super::*; - use std::cell::Cell; - - use once_cell::{sync::Lazy, unsync::OnceCell}; - use pipewire::spa::{format::MediaType, Direction}; - /// Graphical representation of a pipewire port. #[derive(gtk::CompositeTemplate, glib::Properties)] #[properties(wrapper_type = super::Port)] @@ -112,7 +110,7 @@ mod imp { } fn signals() -> &'static [Signal] { - static SIGNALS: Lazy> = Lazy::new(|| { + static SIGNALS: LazyLock> = LazyLock::new(|| { vec![Signal::builder("port-toggled") // Provide id of output port and input port to signal handler. .param_types([::static_type(), ::static_type()]) @@ -218,6 +216,7 @@ mod imp { drag_src.connect_drag_begin(|drag_source, _| { let port = drag_source .widget() + .unwrap() .dynamic_cast::() .expect("Widget should be a Port"); @@ -226,6 +225,7 @@ mod imp { drag_src.connect_drag_cancel(|drag_source, _, _| { let port = drag_source .widget() + .unwrap() .dynamic_cast::() .expect("Widget should be a Port"); @@ -241,6 +241,7 @@ mod imp { drop_target.connect_value_notify(|drop_target| { let port = drop_target .widget() + .unwrap() .dynamic_cast::() .expect("Widget should be a Port"); @@ -260,6 +261,7 @@ mod imp { drop_target.connect_drop(|drop_target, val, _, _| { let port = drop_target .widget() + .unwrap() .dynamic_cast::() .expect("Widget should be a Port"); let other_port = val @@ -328,7 +330,8 @@ mod imp { glib::wrapper! { pub struct Port(ObjectSubclass) - @extends gtk::Widget; + @extends gtk::Widget, + @implements gtk::Accessible, gtk::ConstraintTarget, gtk::Buildable; } impl Port { diff --git a/src/ui/graph/port_handle.rs b/src/ui/graph/port_handle.rs index a9ca8cc..e360c96 100644 --- a/src/ui/graph/port_handle.rs +++ b/src/ui/graph/port_handle.rs @@ -1,4 +1,5 @@ // Copyright 2021 Tom A. Wagner +// Copyright 2026 Jaŭhien Lavonćjeŭ // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License version 3 as published by @@ -61,7 +62,8 @@ mod imp { glib::wrapper! { pub struct PortHandle(ObjectSubclass) - @extends gtk::Widget; + @extends gtk::Widget, + @implements gtk::Accessible, gtk::ConstraintTarget, gtk::Buildable; } impl PortHandle { diff --git a/src/ui/graph/zoomentry.rs b/src/ui/graph/zoomentry.rs index 667236b..cbcab06 100644 --- a/src/ui/graph/zoomentry.rs +++ b/src/ui/graph/zoomentry.rs @@ -1,15 +1,12 @@ -use adw::{glib, gtk, prelude::*, subclass::prelude::*}; +use std::{cell::RefCell, sync::LazyLock}; + +use adw::{glib::{self, clone}, gtk, prelude::*, subclass::prelude::*, gio}; use super::GraphView; mod imp { - use std::cell::RefCell; - use super::*; - use gtk::{gio, glib::clone}; - use once_cell::sync::Lazy; - #[derive(gtk::CompositeTemplate)] #[template(file = "zoomentry.ui")] pub struct ZoomEntry { @@ -66,7 +63,7 @@ mod imp { self.parent_constructed(); self.zoom_out_button - .connect_clicked(clone!(@weak self as imp => move |_| { + .connect_clicked(clone!(#[weak(rename_to = imp)] self, move |_| { let graphview = imp.graphview.borrow(); if let Some(ref graphview) = *graphview { graphview.set_zoom_factor(graphview.zoom_factor() - 0.1, None); @@ -74,7 +71,7 @@ mod imp { })); self.zoom_in_button - .connect_clicked(clone!(@weak self as imp => move |_| { + .connect_clicked(clone!(#[weak(rename_to = imp)] self, move |_| { let graphview = imp.graphview.borrow(); if let Some(ref graphview) = *graphview { graphview.set_zoom_factor(graphview.zoom_factor() + 0.1, None); @@ -82,7 +79,7 @@ mod imp { })); self.entry - .connect_activate(clone!(@weak self as imp => move |entry| { + .connect_activate(clone!(#[weak(rename_to = imp)] self, move |entry| { if let Ok(zoom_factor) = entry.text().trim_matches('%').parse::() { let graphview = imp.graphview.borrow(); if let Some(ref graphview) = *graphview { @@ -91,7 +88,7 @@ mod imp { } })); self.entry - .connect_icon_press(clone!(@weak self as imp => move |_, pos| { + .connect_icon_press(clone!(#[weak(rename_to = imp)] self, move |_, pos| { if pos == gtk::EntryIconPosition::Secondary { imp.popover.show(); } @@ -109,7 +106,7 @@ mod imp { } fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: LazyLock> = LazyLock::new(|| { vec![glib::ParamSpecObject::builder::("zoomed-widget") .flags(glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT) .build()] @@ -132,7 +129,7 @@ mod imp { if let Some(ref widget) = widget { widget.connect_notify_local( Some("zoom-factor"), - clone!(@weak self as imp => move |graphview, _| { + clone!(#[weak(rename_to = imp)] self, move |graphview, _| { imp.update_zoom_factor_text(graphview.zoom_factor()); }), ); @@ -161,7 +158,8 @@ mod imp { glib::wrapper! { pub struct ZoomEntry(ObjectSubclass) - @extends gtk::Box, gtk::Widget; + @extends gtk::Box, gtk::Widget, + @implements gtk::Accessible, gtk::ConstraintTarget, gtk::Buildable; } impl ZoomEntry { diff --git a/src/ui/window.rs b/src/ui/window.rs index e1e410b..22bd8fb 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -49,7 +49,8 @@ mod imp { glib::wrapper! { pub struct Window(ObjectSubclass) @extends adw::ApplicationWindow, gtk::ApplicationWindow, gtk::Window, gtk::Widget, - @implements gio::ActionGroup, gio::ActionMap; + @implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable, + gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager; } impl Window {