diff --git a/Linux/.vscode/settings.json b/Linux/.vscode/settings.json index bf73d85..61efbd3 100644 --- a/Linux/.vscode/settings.json +++ b/Linux/.vscode/settings.json @@ -1,5 +1,6 @@ { "nixEnvSelector.nixFile": "${workspaceFolder}/shell.nix", "files.trimTrailingWhitespace": true, - "rust-analyzer.imports.granularity.group": "item" + "rust-analyzer.imports.granularity.group": "item", + "rust-analyzer.check.command": "clippy" } \ No newline at end of file diff --git a/Linux/Cargo.lock b/Linux/Cargo.lock index 0dc4150..d5f9bb5 100644 --- a/Linux/Cargo.lock +++ b/Linux/Cargo.lock @@ -2,40 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "MassiveKnob" -version = "0.1.0" -dependencies = [ - "anyhow", - "env_logger", - "log", - "min-rs", - "platform-dirs", - "regex", - "relm4", - "relm4-icons", - "rust-i18n", - "serde", - "serde_json", - "serialport", - "tracker", -] - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "aho-corasick" version = "1.1.3" @@ -112,21 +78,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -135,9 +86,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bstr" @@ -149,12 +100,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - [[package]] name = "byteorder" version = "1.5.0" @@ -163,34 +108,27 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cairo-rs" -version = "0.19.4" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ac2a4d0e69036cf0062976f6efcba1aaee3e448594e6514bb2ddf87acce562" +checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cairo-sys-rs", "glib", "libc", - "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64" +checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" dependencies = [ "glib-sys", "libc", "system-deps", ] -[[package]] -name = "cc" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" - [[package]] name = "cfg-expr" version = "0.15.8" @@ -219,15 +157,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -313,49 +242,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "spin", -] - -[[package]] -name = "fragile" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.30" @@ -363,7 +249,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -397,15 +282,9 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - [[package]] name = "futures-task" version = "0.3.30" @@ -418,13 +297,9 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ - "futures-channel", "futures-core", - "futures-io", "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", @@ -432,9 +307,9 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6a23f8a0b5090494fd04924662d463f8386cc678dd3915015a838c1a3679b92" +checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" dependencies = [ "gdk-pixbuf-sys", "gio", @@ -444,9 +319,9 @@ dependencies = [ [[package]] name = "gdk-pixbuf-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fdbf021f8b9d19e30fb9ea6d6e5f2b6a712fe4645417c69f86f6ff1e1444a8f" +checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" dependencies = [ "gio-sys", "glib-sys", @@ -457,9 +332,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db265c9dd42d6a371e09e52deab3a84808427198b86ac792d75fd35c07990a07" +checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -472,9 +347,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9418fb4e8a67074919fe7604429c45aa74eb9df82e7ca529767c6d4e9dc66dd" +checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -494,23 +369,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "gio" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be548be810e45dd31d3bbb89c6210980bb7af9bca3ea1292b5f16b75f8e394a7" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" dependencies = [ "futures-channel", "futures-core", @@ -521,14 +388,13 @@ dependencies = [ "libc", "pin-project-lite", "smallvec", - "thiserror", ] [[package]] name = "gio-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4bdbef451b0f0361e7f762987cc6bebd5facab1d535e85a3cf1115dfb08db40" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" dependencies = [ "glib-sys", "gobject-sys", @@ -539,11 +405,11 @@ dependencies = [ [[package]] name = "glib" -version = "0.19.7" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52355166df21c7ed16b6a01f615669c7911ed74e27ef60eba339c0d2da12490" +checksum = "b19429cb83fcbf1f00b31ae3a123fab5cd3761bdd15b0cc07905804742f0d0e4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "futures-channel", "futures-core", "futures-executor", @@ -556,27 +422,26 @@ dependencies = [ "libc", "memchr", "smallvec", - "thiserror", ] [[package]] name = "glib-macros" -version = "0.19.7" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70025dbfa1275cf7d0531c3317ba6270dae15d87e63342229d638246ff45202e" +checksum = "960349f56469b75794157e93bf04f0bc8a622d0a6612d6a8f8d7eac41e0e1ee1" dependencies = [ "heck", - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] name = "glib-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767d23ead9bbdfcbb1c2242c155c8128a7d13dde7bf69c176f809546135e2282" +checksum = "44edae63bea922f18f7e63977ee60a257ec27c4613aff1a6a9bb572ad0d88269" dependencies = [ "libc", "system-deps", @@ -614,9 +479,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3787b0bfacca12bb25f8f822b0dbee9f7e4a86e6469a29976d332d2c14c945b" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" dependencies = [ "glib-sys", "libc", @@ -625,9 +490,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.19.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4d388e96c5f29e2b2f67045d229ddf826d0a8d6d282f94ed3b34452222c91" +checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" dependencies = [ "glib", "graphene-sys", @@ -636,9 +501,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60e7381afdd7be43bd10a89d3b6741d162aabbca3a8db73505afb6a3aea59d" +checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" dependencies = [ "glib-sys", "libc", @@ -648,9 +513,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7563884bf6939f4468e5d94654945bdd9afcaf8c3ba4c5dd17b5342b747221be" +checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" dependencies = [ "cairo-rs", "gdk4", @@ -663,9 +528,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23024bf2636c38bbd1f822f58acc9d1c25b28da896ff0f291a1a232d4272b3dc" +checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -679,9 +544,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b04e11319b08af11358ab543105a9e49b0c491faca35e2b8e7e36bfba8b671ab" +checksum = "eaffc6c743c9160514cc9b67eace364e5dc5798369fa809cdb04e035c21c5c5d" dependencies = [ "cairo-rs", "field-offset", @@ -700,21 +565,21 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec655a7ef88d8ce9592899deb8b2d0fa50bab1e6dd69182deb764e643c522408" +checksum = "188211f546ce5801f6d0245c37b6249143a2cb4fa040e54829ca1e76796e9f09" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] name = "gtk4-sys" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c8aa86b7f85ea71d66ea88c1d4bae1cfacf51ca4856274565133838d77e57b5" +checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -729,22 +594,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "gvdb" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb9136c388a1e7b3017d18fe7c2f263b0a2b13f215c48e8eb44935d413ce0f9" -dependencies = [ - "byteorder", - "flate2", - "quick-xml", - "safe-transmute", - "serde", - "serde_json", - "walkdir", - "zvariant", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -763,12 +612,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "humantime" version = "2.1.0" @@ -833,15 +676,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" -[[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" @@ -860,7 +694,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] @@ -870,16 +704,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.21" @@ -895,11 +719,41 @@ dependencies = [ "libc", ] +[[package]] +name = "massiveknob_backend" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "min-rs", + "platform-dirs", + "regex", + "rust-i18n", + "serde", + "serde_json", + "serialport", + "tracker", + "uuid", +] + +[[package]] +name = "massiveknob_ui_gtk" +version = "0.1.0" +dependencies = [ + "env_logger", + "gtk4", + "log", + "massiveknob_backend", + "rust-i18n", + "serialport", + "tracker", +] + [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -918,24 +772,6 @@ dependencies = [ "log", ] -[[package]] -name = "miniz_oxide" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" -dependencies = [ - "adler", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "nix" version = "0.26.4" @@ -956,25 +792,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -983,9 +800,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "pango" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504ce6e805439ea2c6791168fe7ef8e3da0c1b2ef82c44bc450dbc330592920d" +checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" dependencies = [ "gio", "glib", @@ -995,9 +812,9 @@ dependencies = [ [[package]] name = "pango-sys" -version = "0.19.5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4829555bdbb83692ddeaf5a6927fb2d025c8131e5ecaa4f7619fff6985d3505" +checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" dependencies = [ "glib-sys", "gobject-sys", @@ -1033,13 +850,12 @@ dependencies = [ ] [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "ppv-lite86" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "zerocopy", ] [[package]] @@ -1060,16 +876,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-xml" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "quote" version = "1.0.36" @@ -1079,6 +885,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_users" version = "0.4.5" @@ -1119,45 +955,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "relm4" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e0e187b58db367305e8486d3228158251da1c8ba1e18baa9de61894e822649" -dependencies = [ - "flume", - "fragile", - "futures", - "gtk4", - "once_cell", - "relm4-macros", - "tokio", - "tracing", -] - -[[package]] -name = "relm4-icons" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5738f52d978a211bd4b3ec3b37f1593297ad34f0f1789d8115eabe1df7958a8" -dependencies = [ - "gtk4", - "gvdb", - "serde", - "toml 0.8.14", -] - -[[package]] -name = "relm4-macros" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0774e846889823aa5766f5b62cface3189a5b36280e65b2faaa6df0319da1726" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "rust-i18n" version = "3.0.1" @@ -1186,7 +983,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "syn 2.0.66", + "syn", ] [[package]] @@ -1209,12 +1006,6 @@ dependencies = [ "triomphe", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustc_version" version = "0.4.0" @@ -1230,12 +1021,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "safe-transmute" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944826ff8fa8093089aba3acb4ef44b9446a99a16f3bf4e74af3f77d340ab7d" - [[package]] name = "same-file" version = "1.0.6" @@ -1274,7 +1059,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -1315,7 +1100,7 @@ version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de7c4f0cce25b9b3518eea99618112f9ee4549f974480c8f43d3c06f03c131a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "core-foundation-sys", "io-kit-sys", @@ -1342,43 +1127,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "syn" -version = "1.0.109" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -1387,22 +1146,22 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.2" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +checksum = "6c81f13d9a334a6c242465140bd262fae382b752ff2011c4f7419919a9c97922" dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 0.8.14", + "toml 0.8.15", "version-compare", ] [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "thiserror" @@ -1421,18 +1180,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", -] - -[[package]] -name = "tokio" -version = "1.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", + "syn", ] [[package]] @@ -1449,21 +1197,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.14", + "toml_edit 0.22.16", ] [[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", ] @@ -1494,46 +1242,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", + "winnow 0.6.18", ] [[package]] @@ -1553,7 +1270,7 @@ checksum = "dc19eb2373ccf3d1999967c26c3d44534ff71ae5d8b9dacf78f4b13132229e48" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn", ] [[package]] @@ -1588,6 +1305,28 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "getrandom", + "rand", + "uuid-macro-internal", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1cd046f83ea2c4e920d6ee9f7c3537ef928d75dce5d84a87c2c5d6b3999a3a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "version-compare" version = "0.2.0" @@ -1610,60 +1349,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[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 2.0.66", - "wasm-bindgen-shared", -] - -[[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 2.0.66", - "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 = "winapi" version = "0.3.9" @@ -1779,9 +1464,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", ] @@ -1796,38 +1481,22 @@ dependencies = [ ] [[package]] -name = "zvariant" -version = "3.15.2" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "libc", - "serde", - "static_assertions", - "zvariant_derive", + "zerocopy-derive", ] [[package]] -name = "zvariant_derive" -version = "3.15.2" +name = "zerocopy-derive" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] diff --git a/Linux/Cargo.toml b/Linux/Cargo.toml index cbe35ba..e3fac45 100644 --- a/Linux/Cargo.toml +++ b/Linux/Cargo.toml @@ -1,22 +1,6 @@ -[package] -name = "MassiveKnob" -version = "0.1.0" -edition = "2021" -build = "build.rs" - -[dependencies] -anyhow = "1.0.86" -env_logger = "0.11.3" -log = "0.4.21" -platform-dirs = "0.3.0" -regex = "1.10.5" -relm4 = "0.8.1" -relm4-icons = "0.8.3" -rust-i18n = "3.0.1" -serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.117" -serialport = { version = "4.4.0", default-features = false } -tracker = "0.2.2" - -[dependencies.min-rs] -git = "https://github.com/MvRens/min-rs.git" +[workspace] +resolver = "2" +members = [ + "backend", + "ui-gtk" +] diff --git a/Linux/backend/Cargo.toml b/Linux/backend/Cargo.toml new file mode 100644 index 0000000..e48d3b5 --- /dev/null +++ b/Linux/backend/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "massiveknob_backend" +version = "0.1.0" +edition = "2021" +build = "build.rs" + +[dependencies] +anyhow = "1.0.86" +log = "0.4.21" +platform-dirs = "0.3.0" +regex = "1.10.5" +rust-i18n = "3.0.1" +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1.0.117" +serialport = { version = "4.4.0", default-features = false } +tracker = "0.2.2" + +[dependencies.uuid] +version = "1.10.0" +features = [ "v4", "fast-rng", "macro-diagnostics" ] + +[dependencies.min-rs] +git = "https://github.com/MvRens/min-rs.git" diff --git a/Linux/build.rs b/Linux/backend/build.rs similarity index 100% rename from Linux/build.rs rename to Linux/backend/build.rs diff --git a/Linux/icons.toml b/Linux/backend/icons.toml similarity index 100% rename from Linux/icons.toml rename to Linux/backend/icons.toml diff --git a/Linux/backend/locales/actions/pipewire.yaml b/Linux/backend/locales/actions/pipewire.yaml new file mode 100644 index 0000000..ccc779d --- /dev/null +++ b/Linux/backend/locales/actions/pipewire.yaml @@ -0,0 +1,9 @@ +_version: 2 + +actions: + pipewire: + group_name: + en: Pipewire + set_volume: + name: + en: Set volume \ No newline at end of file diff --git a/Linux/locales/devices/emulator.yaml b/Linux/backend/locales/devices/emulator.yaml similarity index 100% rename from Linux/locales/devices/emulator.yaml rename to Linux/backend/locales/devices/emulator.yaml diff --git a/Linux/backend/locales/devices/serial_min.yaml b/Linux/backend/locales/devices/serial_min.yaml new file mode 100644 index 0000000..a1d1455 --- /dev/null +++ b/Linux/backend/locales/devices/serial_min.yaml @@ -0,0 +1,6 @@ +_version: 2 + +devices: + serial_min: + name: + en: Serial device using MIN protocol \ No newline at end of file diff --git a/Linux/backend/src/actions/mod.rs b/Linux/backend/src/actions/mod.rs new file mode 100644 index 0000000..0067be9 --- /dev/null +++ b/Linux/backend/src/actions/mod.rs @@ -0,0 +1,42 @@ +pub mod pipewire; + + +use crate::util::unique_id::UniqueId; + + +pub enum ActionGroup +{ + Pipewire(pipewire::PipewireActionGroupInfo) +} + + + +pub trait ActionGroupInfo +{ + /// The unique ID of the group. This should remain stable across releases for + /// the purpose of storing it in the user's configuration. + fn unique_id(&self) -> UniqueId; + + /// The name of the group for display purposes. + fn name(&self) -> String + { + t!(format!("actions.{}.name", self.unique_id().as_str()).as_str()).to_string() + } +} + + +pub trait ActionInfo +{ + /// The unique ID of the item. This should remain stable across releases for + /// the purpose of storing it in the user's configuration. + fn unique_id(&self) -> UniqueId; + + /// The unique ID of the group this action belongs to. + fn group_id(&self) -> UniqueId; + + /// The name of the item for display purposes. + fn name(&self) -> String + { + t!(format!("actions.{}.{}.name", self.group_id().as_str(), self.unique_id().as_str()).as_str()).to_string() + } +} diff --git a/Linux/backend/src/actions/pipewire/mod.rs b/Linux/backend/src/actions/pipewire/mod.rs new file mode 100644 index 0000000..bf43e60 --- /dev/null +++ b/Linux/backend/src/actions/pipewire/mod.rs @@ -0,0 +1,23 @@ +use crate::util::unique_id::UniqueId; + +use super::ActionGroupInfo; + +pub mod set_volume; + + + +pub enum PipewireAction +{ + SetVolume(set_volume::PipewireSetVolumeActionInfo) +} + + +pub struct PipewireActionGroupInfo +{ +} + + +impl ActionGroupInfo for PipewireActionGroupInfo +{ + fn unique_id(&self) -> UniqueId { UniqueId::from("pipewire") } +} \ No newline at end of file diff --git a/Linux/backend/src/actions/pipewire/set_volume.rs b/Linux/backend/src/actions/pipewire/set_volume.rs new file mode 100644 index 0000000..827f2c7 --- /dev/null +++ b/Linux/backend/src/actions/pipewire/set_volume.rs @@ -0,0 +1,13 @@ +use crate::actions::ActionInfo; +use crate::util::unique_id::UniqueId; + +pub struct PipewireSetVolumeActionInfo +{ +} + + +impl ActionInfo for PipewireSetVolumeActionInfo +{ + fn unique_id(&self) -> crate::util::unique_id::UniqueId { UniqueId::from("set_volume") } + fn group_id(&self) -> crate::util::unique_id::UniqueId { UniqueId::from("pipewire") } +} \ No newline at end of file diff --git a/Linux/src/config/json.rs b/Linux/backend/src/config/json.rs similarity index 100% rename from Linux/src/config/json.rs rename to Linux/backend/src/config/json.rs diff --git a/Linux/src/config/mod.rs b/Linux/backend/src/config/mod.rs similarity index 97% rename from Linux/src/config/mod.rs rename to Linux/backend/src/config/mod.rs index 19793dd..eea4e3d 100644 --- a/Linux/src/config/mod.rs +++ b/Linux/backend/src/config/mod.rs @@ -19,6 +19,7 @@ pub struct ConfigManager impl ConfigManager { + #![allow(clippy::new_without_default)] pub fn new() -> Self { let appdirs = AppDirs::new(Some("massiveknob"), false).unwrap(); @@ -37,7 +38,7 @@ impl ConfigManager { return OptionResult::None; } - + match std::fs::File::open(path) { Ok(v) => OptionResult::Some(v), @@ -62,7 +63,7 @@ impl ConfigManager } } } - + std::fs::File::create(path) } } diff --git a/Linux/backend/src/devices/emulator.rs b/Linux/backend/src/devices/emulator.rs new file mode 100644 index 0000000..04af054 --- /dev/null +++ b/Linux/backend/src/devices/emulator.rs @@ -0,0 +1,18 @@ +use uuid::Uuid; + +use super::DeviceContext; + +pub struct EmulatorDevice +{ +} + + +impl EmulatorDevice +{ + pub fn new(_context: DeviceContext, _instance_id: Uuid) -> Self + { + Self + { + } + } +} \ No newline at end of file diff --git a/Linux/backend/src/devices/mod.rs b/Linux/backend/src/devices/mod.rs new file mode 100644 index 0000000..01835d7 --- /dev/null +++ b/Linux/backend/src/devices/mod.rs @@ -0,0 +1,87 @@ +pub mod emulator; +pub mod serial_min; + + +use emulator::EmulatorDevice; +use serial_min::SerialMinDevice; +use uuid::Uuid; + +use crate::util::unique_id::UniqueId; + +// TODO use a procedural macro to build the registry based on attributes in the Device enum? + +pub enum Device +{ + Emulator(emulator::EmulatorDevice), + SerialMin(serial_min::SerialMinDevice) +} + + +pub struct DeviceInfo +{ + /// The unique ID of the item. This should remain stable across releases for + /// the purpose of storing it in the user's configuration. + pub unique_id: UniqueId, + + pub factory: fn(DeviceContext, Uuid) -> Device +} + + +pub struct DeviceRegistry +{ + info: Vec +} + + +pub struct DeviceContext +{ + // Arc +} + + +impl DeviceRegistry +{ + #![allow(clippy::new_without_default)] + pub fn new() -> Self + { + Self + { + info: vec!( + DeviceInfo + { + unique_id: UniqueId::from("emulator"), + factory: |context, instance_id| Device::Emulator(EmulatorDevice::new(context, instance_id)) + }, + + DeviceInfo + { + unique_id: UniqueId::from("serial_min"), + factory: |context, instance_id| Device::SerialMin(SerialMinDevice::new(context, instance_id)) + } + ) + } + } + + + pub fn iter(&self) -> impl Iterator + { + self.info.iter() + } + + + pub fn by_id(&self, id: &UniqueId) -> Option<&DeviceInfo> + { + self.info.iter().find(|v| &v.unique_id == id) + } +} + + + +impl DeviceInfo +{ + /// The name of the item for display purposes. + pub fn name(&self) -> String + { + t!(format!("devices.{}.name", self.unique_id.as_str()).as_str()).to_string() + } +} diff --git a/Linux/backend/src/devices/serial_min.rs b/Linux/backend/src/devices/serial_min.rs new file mode 100644 index 0000000..474ab8f --- /dev/null +++ b/Linux/backend/src/devices/serial_min.rs @@ -0,0 +1,19 @@ +use uuid::Uuid; + +use super::DeviceContext; + + +pub struct SerialMinDevice +{ +} + + +impl SerialMinDevice +{ + pub fn new(_context: DeviceContext, _instance_id: Uuid) -> Self + { + Self + { + } + } +} \ No newline at end of file diff --git a/Linux/backend/src/lib.rs b/Linux/backend/src/lib.rs new file mode 100644 index 0000000..898d171 --- /dev/null +++ b/Linux/backend/src/lib.rs @@ -0,0 +1,12 @@ +#[macro_use] +extern crate rust_i18n; + +i18n!("locales"); + + +pub mod util; +pub mod devices; +pub mod actions; + +pub mod config; +pub mod orchestrator; \ No newline at end of file diff --git a/Linux/src/mainwindow.rs b/Linux/backend/src/mainwindow.rs similarity index 95% rename from Linux/src/mainwindow.rs rename to Linux/backend/src/mainwindow.rs index 4d387ff..b82847b 100644 --- a/Linux/src/mainwindow.rs +++ b/Linux/backend/src/mainwindow.rs @@ -129,12 +129,16 @@ impl MainWindow { if initial { - self.orchestrator.with_active_device(|device_instance, cookie| { widget = device_instance.create_settings_widget(cookie) }); + if let Some(active_device) = self.orchestrator.active_device() + { + active_device + } + self.orchestrator.with_active_device(|device_instance| { widget = device_instance.create_settings_widget() }); } else { let device_id = self.devices_sorted[index].unique_id.clone(); - self.orchestrator.set_active_device_id(&device_id, |device_instance, cookie| { widget = device_instance.create_settings_widget(cookie) }); + self.orchestrator.set_active_device_id(&device_id, |device_instance| { widget = device_instance.create_settings_widget() }); } } diff --git a/Linux/src/orchestrator/mod.rs b/Linux/backend/src/orchestrator/mod.rs similarity index 50% rename from Linux/src/orchestrator/mod.rs rename to Linux/backend/src/orchestrator/mod.rs index 9ff4325..9141ee7 100644 --- a/Linux/src/orchestrator/mod.rs +++ b/Linux/backend/src/orchestrator/mod.rs @@ -1,13 +1,14 @@ -use std::borrow::{Borrow, BorrowMut}; use std::sync::Arc; -use crate::actions; -//use crate::actions::ActionRegistryItem; +use uuid::Uuid; + use crate::config::json::JsonConfigManager; -use crate::config::{ConfigManager, ConfigName}; -use crate::devices::{self, Device}; -use crate::devices::DeviceRegistryItem; -use crate::registry::Registry; +use crate::config::ConfigName; +use crate::config::ConfigManager; +use crate::devices::DeviceContext; +use crate::devices::DeviceInfo; +use crate::devices::DeviceRegistry; +use crate::devices::Device; use crate::util::unique_id::UniqueId; @@ -19,44 +20,30 @@ pub struct Orchestrator config_manager: ConfigManager, settings_name: ConfigName, - device_registry: Registry, - //action_registry: Registry, + device_registry: DeviceRegistry, -// current_device_instance: Option> active_device: Option } impl Orchestrator { + #![allow(clippy::new_without_default)] pub fn new() -> Self { let config_manager = ConfigManager::new(); let settings_name = ConfigName::new("settings"); - let settings = match config_manager.read_json(&settings_name).expect("Error reading settings") - { - None => settings::Settings::default(), - Some(v) => v - }; + let settings = config_manager.read_json(&settings_name).expect("Error reading settings").unwrap_or_default(); - let mut device_registry = Registry::new(); - let mut action_registry = Registry::new(); - - devices::register(&mut device_registry); - actions::register(&mut action_registry); - let mut instance = Self { config_manager, settings_name, - device_registry, - //action_registry, - + device_registry: DeviceRegistry::new(), //settings, - active_device: None }; @@ -75,7 +62,7 @@ impl Orchestrator } - pub fn devices(&self) -> impl Iterator + pub fn devices(&self) -> impl Iterator { self.device_registry.iter() } @@ -87,38 +74,31 @@ impl Orchestrator Some(active_device.id.clone()) } - /* - - pub fn current_device(&self) -> Option<&DeviceRegistryItem> + pub fn active_device(&self) -> Option { - let Some(device_id) = self.current_device_id() else { return None }; - self.device_registry.by_id(device_id) - } - */ - - - pub fn with_active_device(&self, callback: F) where F: FnOnce(&dyn Device) - { - let Some(active_device) = self.active_device else { return }; + let Some(active_device) = &self.active_device else { return None }; let instance = active_device.instance.clone(); - callback(instance.as_ref().as_ref()); - - self.active_device.as_ref().map(|device| callback(&*device.instance.clone())); + Some(instance) } - - pub fn set_active_device_id(&mut self, id: &UniqueId, on_changed: F) where F: FnOnce(&dyn Device) + pub fn set_active_device_id(&mut self, id: &UniqueId) -> DeviceReference { - let id = Some(id.clone()); - if id == self.active_device_id() { return } + if let Some(active_device) = &self.active_device + { + if *id == active_device.id + { + return active_device.instance.clone(); + } + } - self.set_active_device(id); + + let active_device = self.set_active_device(Some(id.clone())).unwrap_or_else(|| panic!("Invalid device ID: {}", id.as_str())); self.store_settings(); - self.with_active_device(on_changed); + active_device } @@ -127,11 +107,7 @@ impl Orchestrator { let settings = settings::Settings { - device_id: match &self.active_device - { - None => None, - Some(v) => Some(v.id.clone().into()) - } + device_id: self.active_device.as_ref().map(|v| v.id.clone().into()) }; if let Err(e) = self.config_manager.write_json(&self.settings_name, &settings) @@ -142,9 +118,9 @@ impl Orchestrator - fn set_active_device(&mut self, id: Option) + fn set_active_device(&mut self, id: Option) -> Option { - self.active_device = match id + let new_device = match id { None => None, Some(v) => @@ -153,14 +129,25 @@ impl Orchestrator None => None, Some(d) => { + let context = DeviceContext + { + }; + + let instance_id = Uuid::new_v4(); + Some(ActiveDevice { id: v.clone(), - instance: Arc::new((d.factory)()) + instance: Arc::new((d.factory)(context, instance_id)) }) } } }; + + let result = new_device.as_ref().map(|v| v.instance.clone()); + + self.active_device = new_device; + result } } @@ -175,8 +162,11 @@ impl Drop for Orchestrator +pub type DeviceReference = Arc; + + struct ActiveDevice { id: UniqueId, - instance: Arc> + instance: DeviceReference } \ No newline at end of file diff --git a/Linux/backend/src/orchestrator/settings.rs b/Linux/backend/src/orchestrator/settings.rs new file mode 100644 index 0000000..7b7a690 --- /dev/null +++ b/Linux/backend/src/orchestrator/settings.rs @@ -0,0 +1,7 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Default, Serialize, Deserialize)] +pub struct Settings +{ + pub device_id: Option +} diff --git a/Linux/src/ui/mod.rs b/Linux/backend/src/ui/mod.rs similarity index 100% rename from Linux/src/ui/mod.rs rename to Linux/backend/src/ui/mod.rs diff --git a/Linux/src/util/mod.rs b/Linux/backend/src/util/mod.rs similarity index 100% rename from Linux/src/util/mod.rs rename to Linux/backend/src/util/mod.rs diff --git a/Linux/src/util/option_result.rs b/Linux/backend/src/util/option_result.rs similarity index 100% rename from Linux/src/util/option_result.rs rename to Linux/backend/src/util/option_result.rs diff --git a/Linux/src/util/unique_id.rs b/Linux/backend/src/util/unique_id.rs similarity index 100% rename from Linux/src/util/unique_id.rs rename to Linux/backend/src/util/unique_id.rs diff --git a/Linux/src/util/validated_string.rs b/Linux/backend/src/util/validated_string.rs similarity index 91% rename from Linux/src/util/validated_string.rs rename to Linux/backend/src/util/validated_string.rs index eb0314d..106a345 100644 --- a/Linux/src/util/validated_string.rs +++ b/Linux/backend/src/util/validated_string.rs @@ -68,11 +68,11 @@ impl From for ValidatedString } -impl Into for ValidatedString +impl From> for String { - fn into(self) -> String + fn from(val: ValidatedString) -> Self { - self.inner.clone() + val.inner.clone() } } diff --git a/Linux/src/actions/mod.rs b/Linux/src/actions/mod.rs deleted file mode 100644 index 2fdd83a..0000000 --- a/Linux/src/actions/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -pub mod pipewire; - -use crate::registry::Registry; -use crate::registry::RegistryItem; -use crate::util::unique_id::UniqueId; - - -pub struct ActionRegistryItem -{ - pub unique_id: UniqueId -} - - -pub trait Action -{ -} - - -impl RegistryItem for ActionRegistryItem -{ - fn unique_id(&self) -> UniqueId - { - self.unique_id.clone() - } - - fn name(&self) -> String - { - t!(format!("actions.{}.name", self.unique_id.as_str()).as_str()).to_string() - } -} - - - -pub fn register(registry: &mut Registry) -{ - pipewire::register(registry); -} \ No newline at end of file diff --git a/Linux/src/actions/pipewire/mod.rs b/Linux/src/actions/pipewire/mod.rs deleted file mode 100644 index b300aa7..0000000 --- a/Linux/src/actions/pipewire/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::registry::Registry; -use crate::util::unique_id::UniqueId; -use super::ActionRegistryItem; - -pub mod set_volume; - - -pub fn register(registry: &mut Registry) -{ - registry.register(ActionRegistryItem - { - unique_id: UniqueId::from("pipewire.set_volume") - }); -} \ No newline at end of file diff --git a/Linux/src/actions/pipewire/set_volume.rs b/Linux/src/actions/pipewire/set_volume.rs deleted file mode 100644 index e69de29..0000000 diff --git a/Linux/src/devices/emulator/emulatorwindow.rs b/Linux/src/devices/emulator/emulatorwindow.rs deleted file mode 100644 index 93c68ca..0000000 --- a/Linux/src/devices/emulator/emulatorwindow.rs +++ /dev/null @@ -1,48 +0,0 @@ -use gtk::prelude::*; -use relm4::prelude::*; - -pub struct EmulatorWindow -{ -} - - -#[derive(Debug)] -pub enum EmulatorWindowMessage -{ -} - - -#[relm4::component(pub)] -impl SimpleComponent for EmulatorWindow -{ - type Init = (); - type Input = EmulatorWindowMessage; - type Output = (); - - view! - { - gtk::Window - { - set_title: Some(&t!("emulatorwindow.title")), - set_default_size: (300, 500) - } - } - - - fn init(_data: Self::Init, root: Self::Root, _sender: ComponentSender, ) -> ComponentParts - { - let model = EmulatorWindow {}; - let widgets = view_output!(); - - root.set_visible(true); - ComponentParts { model, widgets } - } - - - fn update(&mut self, msg: Self::Input, _sender: ComponentSender) - { - match msg - { - } - } -} \ No newline at end of file diff --git a/Linux/src/devices/emulator/mod.rs b/Linux/src/devices/emulator/mod.rs deleted file mode 100644 index 63d828d..0000000 --- a/Linux/src/devices/emulator/mod.rs +++ /dev/null @@ -1,58 +0,0 @@ -use emulatorwindow::EmulatorWindow; -use relm4::component::Connector; -use relm4::Component; -use relm4::gtk::prelude::*; -use relm4::ComponentController; - -use crate::registry::Registry; -use crate::util::unique_id::UniqueId; -use super::Device; -use super::DeviceRegistryItem; - - -pub mod emulatorwindow; - - -pub struct EmulatorWindowDevice -{ - window: Connector -} - - -impl EmulatorWindowDevice -{ - fn new() -> Self - { - let builder = EmulatorWindow::builder(); - let window = builder.launch({}); - - EmulatorWindowDevice - { - window - } - } -} - - -impl Device for EmulatorWindowDevice -{ -} - - -impl Drop for EmulatorWindowDevice -{ - fn drop(&mut self) - { - self.window.widget().close(); - } -} - - -pub fn register(registry: &mut Registry) -{ - registry.register(DeviceRegistryItem { - unique_id: UniqueId::from("emulator"), - factory: || Box::new(EmulatorWindowDevice::new()), - settings_widget_factory: || None - }); -} \ No newline at end of file diff --git a/Linux/src/devices/mod.rs b/Linux/src/devices/mod.rs deleted file mode 100644 index f21a6a1..0000000 --- a/Linux/src/devices/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -pub mod emulator; -pub mod serial_min; - - -use crate::registry::Registry; -use crate::registry::RegistryItem; -use crate::ui::EmbeddedWidgetConnector; -use crate::util::unique_id::UniqueId; - - -pub struct DeviceRegistryItem -{ - pub unique_id: UniqueId, - pub factory: fn() -> Box, - pub settings_widget_factory: fn() -> Option> -} - - -pub trait Device -{ -} - - -impl RegistryItem for DeviceRegistryItem -{ - fn unique_id(&self) -> UniqueId - { - self.unique_id.clone() - } - - fn name(&self) -> String - { - t!(format!("devices.{}.name", self.unique_id.as_str()).as_str()).to_string() - } -} - - - -pub fn register(registry: &mut Registry) -{ - emulator::register(registry); - serial_min::register(registry); -} \ No newline at end of file diff --git a/Linux/src/devices/serial_min/mod.rs b/Linux/src/devices/serial_min/mod.rs deleted file mode 100644 index 7238162..0000000 --- a/Linux/src/devices/serial_min/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -use relm4::Component; -use settingswidget::SerialMinSettingsInit; -use settingswidget::SerialMinSettingsWidget; - -use crate::registry::Registry; -use crate::util::unique_id::UniqueId; -use super::Device; -use super::DeviceRegistryItem; - - -pub mod settingswidget; - - -pub struct SerialMinDevice -{ - -} - - -impl Device for SerialMinDevice -{ -} - - -pub fn register(registry: &mut Registry) -{ - registry.register(DeviceRegistryItem { - unique_id: UniqueId::from("serial_min"), - factory: || Box::new(SerialMinDevice {}), - settings_widget_factory: || - { - let builder = SerialMinSettingsWidget::builder(); - Some(Box::new(builder.launch(SerialMinSettingsInit - { - }))) - } - }); -} \ No newline at end of file diff --git a/Linux/src/main.rs b/Linux/src/main.rs deleted file mode 100644 index 6b76d81..0000000 --- a/Linux/src/main.rs +++ /dev/null @@ -1,30 +0,0 @@ -use env_logger::Env; -use relm4::prelude::*; - -#[macro_use] -extern crate rust_i18n; - -i18n!("locales"); - - -pub mod util; -pub mod ui; -pub mod registry; -pub mod devices; -pub mod actions; - -pub mod config; -pub mod orchestrator; -pub mod mainwindow; - -fn main() -{ - env_logger::Builder::from_env(Env::default().default_filter_or("info")) -// .format_timestamp(None) - .init(); - - relm4_icons::initialize_icons(); - - let app = RelmApp::new("com.github.mvrens.massiveknob"); - app.run::(()); -} \ No newline at end of file diff --git a/Linux/src/orchestrator/settings.rs b/Linux/src/orchestrator/settings.rs deleted file mode 100644 index 874f6c6..0000000 --- a/Linux/src/orchestrator/settings.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde::{Serialize, Deserialize}; - -#[derive(Serialize, Deserialize)] -pub struct Settings -{ - pub device_id: Option -} - - -impl Default for Settings -{ - fn default() -> Self - { - Self - { - device_id: None - } - } -} \ No newline at end of file diff --git a/Linux/src/registry/mod.rs b/Linux/src/registry/mod.rs deleted file mode 100644 index f2cf89b..0000000 --- a/Linux/src/registry/mod.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::collections::HashMap; -use log; - -use crate::util::unique_id::UniqueId; - - -pub trait RegistryItem -{ - /// The unique ID of the item. This should remain stable across releases for - /// the purpose of storing it in the user's configuration. - fn unique_id(&self) -> UniqueId; - - /// The name of the item for display purposes. - fn name(&self) -> String; -} - - - -pub struct Registry where T: RegistryItem -{ - items: HashMap -} - - - -impl Registry where T: RegistryItem -{ - pub fn new() -> Self - { - Self - { - items: HashMap::new() - } - } - - - pub fn register(&mut self, device: T) - { - let device_id = device.unique_id(); - - log::debug!("Registered device: [{}] {}", device_id.as_str(), device.name()); - self.items.insert(String::from(device_id.as_str()), device); - } - - - pub fn iter(&self) -> impl Iterator - { - self.items.values() - } - - - pub fn by_id(&self, id: &UniqueId) -> Option<&T> - { - self.items.get(id.as_str()) - } -} \ No newline at end of file diff --git a/Linux/ui-gtk/Cargo.toml b/Linux/ui-gtk/Cargo.toml new file mode 100644 index 0000000..1d479de --- /dev/null +++ b/Linux/ui-gtk/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "massiveknob_ui_gtk" +version = "0.1.0" +edition = "2021" +build = "build.rs" + +[dependencies] +env_logger = "0.11.3" +gtk = { version = "0.9.0", package = "gtk4", features = ["v4_14"] } +log = "0.4.21" +rust-i18n = "3.0.1" +serialport = { version = "4.4.0", default-features = false } +tracker = "0.2.2" + +[dependencies.massiveknob_backend] +path = "../backend" \ No newline at end of file diff --git a/Linux/ui-gtk/build.rs b/Linux/ui-gtk/build.rs new file mode 100644 index 0000000..652c975 --- /dev/null +++ b/Linux/ui-gtk/build.rs @@ -0,0 +1,4 @@ +fn main() +{ + println!("cargo:rerun-if-changed=locales"); +} \ No newline at end of file diff --git a/Linux/ui-gtk/icons.toml b/Linux/ui-gtk/icons.toml new file mode 100644 index 0000000..45a4dd1 --- /dev/null +++ b/Linux/ui-gtk/icons.toml @@ -0,0 +1,2 @@ +base_resource_path = "/com/github/mvrens/massiveknob/" +icons = [] \ No newline at end of file diff --git a/Linux/locales/actions/pipewire.yaml b/Linux/ui-gtk/locales/actions/pipewire.yaml similarity index 100% rename from Linux/locales/actions/pipewire.yaml rename to Linux/ui-gtk/locales/actions/pipewire.yaml diff --git a/Linux/ui-gtk/locales/devices/emulator.yaml b/Linux/ui-gtk/locales/devices/emulator.yaml new file mode 100644 index 0000000..34a0e1f --- /dev/null +++ b/Linux/ui-gtk/locales/devices/emulator.yaml @@ -0,0 +1,6 @@ +_version: 2 + +devices: + emulator: + name: + en: Emulator \ No newline at end of file diff --git a/Linux/locales/devices/serial_min.yaml b/Linux/ui-gtk/locales/devices/serial_min.yaml similarity index 100% rename from Linux/locales/devices/serial_min.yaml rename to Linux/ui-gtk/locales/devices/serial_min.yaml diff --git a/Linux/locales/emulatorwindow.yml b/Linux/ui-gtk/locales/emulatorwindow.yml similarity index 100% rename from Linux/locales/emulatorwindow.yml rename to Linux/ui-gtk/locales/emulatorwindow.yml diff --git a/Linux/locales/mainwindow.yml b/Linux/ui-gtk/locales/mainwindow.yml similarity index 100% rename from Linux/locales/mainwindow.yml rename to Linux/ui-gtk/locales/mainwindow.yml diff --git a/Linux/ui-gtk/src/devices/emulator_settings_ui.rs b/Linux/ui-gtk/src/devices/emulator_settings_ui.rs new file mode 100644 index 0000000..ced5591 --- /dev/null +++ b/Linux/ui-gtk/src/devices/emulator_settings_ui.rs @@ -0,0 +1,101 @@ +use massiveknob_backend::orchestrator::DeviceReference; + +use crate::ui::uicomponent::UiComponent; +use crate::ui::uicomponent::UiComponentState; + + +pub struct EmulatorSettingsUiInit +{ + pub device: DeviceReference +} + + + +pub struct EmulatorSettingsUi +{ +} + + +pub struct EmulatorSettingsUiWidgets +{ + +} + + +impl UiComponent for EmulatorSettingsUi +{ + type Root = gtk::Box; + type Widgets = EmulatorSettingsUiWidgets; + type Init = EmulatorSettingsUiInit; + type State = Self; + + + fn build_root(_init: &Self::Init) -> Self::Root + { + gtk::Box::builder() + .hexpand(true) + .orientation(gtk::Orientation::Vertical) + .spacing(8) + .build() + } + + fn build_widgets(_root: &Self::Root, _init: &Self::Init) -> Self::Widgets + { + Self::Widgets + { + } + } + + fn init(_root: &Self::Root, _state: &std::rc::Rc>) + { + } +} + + +impl UiComponentState for EmulatorSettingsUi +{ + fn new(_init: (), _widgets: EmulatorSettingsUiWidgets) -> Self + { + Self + { + } + } +} + + +/* +#[relm4::component(pub)] +impl SimpleComponent for EmulatorWindow +{ + type Init = (); + type Input = EmulatorWindowMessage; + type Output = (); + + view! + { + gtk::Window + { + set_title: Some(&t!("emulatorwindow.title")), + set_default_size: (300, 500) + } + } + + + fn init(_data: Self::Init, root: Self::Root, _sender: ComponentSender, ) -> ComponentParts + { + let model = EmulatorWindow {}; + let widgets = view_output!(); + + root.set_visible(true); + ComponentParts { model, widgets } + } + + + fn update(&mut self, msg: Self::Input, _sender: ComponentSender) + { + match msg + { + } + } +} + */ \ No newline at end of file diff --git a/Linux/ui-gtk/src/devices/mod.rs b/Linux/ui-gtk/src/devices/mod.rs new file mode 100644 index 0000000..3add4dd --- /dev/null +++ b/Linux/ui-gtk/src/devices/mod.rs @@ -0,0 +1,30 @@ +use emulator_settings_ui::EmulatorSettingsUi; +use emulator_settings_ui::EmulatorSettingsUiInit; +use massiveknob_backend::devices::Device; +use massiveknob_backend::orchestrator::DeviceReference; +use serial_min_settings_ui::SerialMinSettingsUi; +use serial_min_settings_ui::SerialMinSettingsUiInit; + +use crate::ui::uicomponent::UiComponent; +use crate::ui::uicomponent::UiComponentConnectorWidget; + +pub mod emulator_settings_ui; +pub mod serial_min_settings_ui; + + +pub struct DeviceSettingsUiBuilder +{ +} + + +impl DeviceSettingsUiBuilder +{ + pub fn build(device: DeviceReference) -> Box + { + match device.as_ref() + { + Device::Emulator(_) => Box::new(EmulatorSettingsUi::builder().build(EmulatorSettingsUiInit { device })), + Device::SerialMin(_) => Box::new(SerialMinSettingsUi::builder().build(SerialMinSettingsUiInit { device })) + } + } +} \ No newline at end of file diff --git a/Linux/src/devices/serial_min/settingswidget.rs b/Linux/ui-gtk/src/devices/serial_min_settings_ui.rs similarity index 70% rename from Linux/src/devices/serial_min/settingswidget.rs rename to Linux/ui-gtk/src/devices/serial_min_settings_ui.rs index a08580e..5990e78 100644 --- a/Linux/src/devices/serial_min/settingswidget.rs +++ b/Linux/ui-gtk/src/devices/serial_min_settings_ui.rs @@ -1,15 +1,13 @@ -use gtk::StringList; use gtk::glib::clone; -use relm4::component::Connector; -use relm4::prelude::*; -use relm4::gtk::prelude::*; -use serialport::SerialPortInfo; - -use crate::ui::EmbeddedWidgetConnector; +use gtk::prelude::*; +use gtk::StringList; +use massiveknob_backend::orchestrator::DeviceReference; +use crate::ui::uicomponent::UiComponent; +use crate::ui::uicomponent::UiComponentState; #[tracker::track] -pub struct SerialMinSettingsWidget +pub struct SerialMinSettingsUi { #[do_not_track] ports: Vec, @@ -19,28 +17,130 @@ pub struct SerialMinSettingsWidget } -#[derive(Debug)] -pub enum SerialMinSettingsWidgetMessage +pub struct SerialMinSettingsUiInit { - PortChanged(usize), - CustomPortChanged(String) + pub device: DeviceReference } -pub struct SerialMinSettingsInit -{ - // this needs a good design - we need to be able to modify the device instance, but - // we can't pass the reference or an Rc to the device due to the design of create_settings_widget. - // Either seperate the UI from the Device, or pass a middle man (sender/receiver style perhaps?) -} - - -pub struct SerialMinSettingsWidgets +pub struct SerialMinSettingsUiWidgets { custom_port_input: gtk::Entry } + +impl UiComponent for SerialMinSettingsUi +{ + type Root = gtk::Box; + type Widgets = SerialMinSettingsUiWidgets; + type Init = SerialMinSettingsUiInit; + type State = Self; + + + fn build_root(_init: &Self::Init) -> Self::Root + { + gtk::Box::builder() + .hexpand(true) + .orientation(gtk::Orientation::Vertical) + .spacing(8) + .build() + } + + fn build_widgets(root: &Self::Root, init: &Self::Init) -> Self::Widgets + { + let port_label = gtk::Label::builder() + .label(t!("serial_min.settings.port.label")) + .halign(gtk::Align::Start) + .build(); + + root.append(&port_label); + + + + let port_model_vec: Vec<&str> = ports.iter().map(|p| p.as_str()).collect(); + let port_model = StringList::new(&port_model_vec); + + port_model.append(t!("serial_min.settings.port.custom").as_ref()); + + let port_select = gtk::DropDown::builder() + .model(&port_model) + .build(); + + root.append(&port_select); + + + let port_select_cloned = port_select.clone(); + port_select.connect_selected_notify(clone!( + move |_| + { + let active_index = port_select_cloned.selected(); + if active_index == gtk::ffi::GTK_INVALID_LIST_POSITION { return }; + + if let Ok(active_index_usize) = usize::try_from(active_index) + { + //sender.input(SerialMinSettingsWidgetMessage::PortChanged(active_index_usize)); + } + })); + + + let custom_port_input = gtk::Entry::builder() + .hexpand(true) + .placeholder_text(t!("serial_min.settings.custom_port_placeholder")) + .build(); + + root.append(&custom_port_input); + + + let custom_port_input_cloned = custom_port_input.clone(); + /* + custom_port_input.connect_changed(clone!( + @strong sender => move |_| + { + sender.input(SerialMinSettingsWidgetMessage::CustomPortChanged(String::from(custom_port_input_cloned.text().as_str()))); + } + )); + */ + + Self::Widgets + { + custom_port_input + } + } + + + fn init(root: &Self::Root, state: &std::rc::Rc>) + { + + .selected(ports.len().try_into().unwrap_or(gtk::ffi::GTK_INVALID_LIST_POSITION)) + } +} + + +impl UiComponentState for SerialMinSettingsUi +{ + fn new(_init: ::Init, _widgets: ::Widgets) -> Self + { + let ports_list = serialport::available_ports().unwrap_or_default(); + let ports: Vec = ports_list.iter().map(|p| p.port_name.clone()).collect(); + + + // TODO read settings + + Self + { + ports, + custom_port: String::default(), + custom_port_visible: false, + tracker: 0 + } + } +} + + + + +/* impl SimpleComponent for SerialMinSettingsWidget { type Init = SerialMinSettingsInit; @@ -62,81 +162,7 @@ impl SimpleComponent for SerialMinSettingsWidget fn init(_data: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { - let port_label = gtk::Label::builder() - .label(t!("serial_min.settings.port.label")) - .halign(gtk::Align::Start) - .build(); - root.append(&port_label); - - - let ports_list = serialport::available_ports().unwrap_or(Vec::::new()); - let ports: Vec = ports_list.iter().map(|p| p.port_name.clone()).collect(); - - let port_model_vec: Vec<&str> = ports.iter().map(|p| p.as_str()).collect(); - let port_model = StringList::new(&port_model_vec); - - port_model.append(t!("serial_min.settings.port.custom").as_ref()); - - let port_select = gtk::DropDown::builder() - .model(&port_model) - .selected(ports.len().try_into().unwrap_or(gtk::ffi::GTK_INVALID_LIST_POSITION)) - .build(); - - root.append(&port_select); - - - let port_select_cloned = port_select.clone(); - port_select.connect_selected_notify(clone!( - @strong sender => move |_| - { - let active_index = port_select_cloned.selected(); - if active_index == gtk::ffi::GTK_INVALID_LIST_POSITION { return }; - - if let Ok(active_index_usize) = usize::try_from(active_index) - { - sender.input(SerialMinSettingsWidgetMessage::PortChanged(active_index_usize)); - } - })); - - - let custom_port_input = gtk::Entry::builder() - .hexpand(true) - .placeholder_text(t!("serial_min.settings.custom_port_placeholder")) - .build(); - - root.append(&custom_port_input); - - - let custom_port_input_cloned = custom_port_input.clone(); - custom_port_input.connect_changed(clone!( - @strong sender => move |_| - { - sender.input(SerialMinSettingsWidgetMessage::CustomPortChanged(String::from(custom_port_input_cloned.text().as_str()))); - } - )); - - - let model = SerialMinSettingsWidget - { - ports, - - custom_port: String::new(), - custom_port_visible: true, - - tracker: 0 - }; - - - // TODO load settings - - - let widgets = SerialMinSettingsWidgets - { - custom_port_input - }; - - ComponentParts { model, widgets } } @@ -180,4 +206,4 @@ impl EmbeddedWidgetConnector for Connector { self.widget().as_ref() } -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/Linux/ui-gtk/src/main.rs b/Linux/ui-gtk/src/main.rs new file mode 100644 index 0000000..d9b4a72 --- /dev/null +++ b/Linux/ui-gtk/src/main.rs @@ -0,0 +1,53 @@ +use std::sync::Arc; +use std::sync::Mutex; + +use env_logger::Env; +use gtk::glib; +use gtk::prelude::*; +use mainwindow::MainWindow; +use mainwindow::MainWindowInit; +use massiveknob_backend::orchestrator::Orchestrator; +use ui::uicomponent::UiComponent; + + +const APP_ID: &str = "com.github.mvrens.massiveknob"; + + +#[macro_use] +extern crate rust_i18n; + +i18n!("locales"); + + +pub mod ui; +pub mod devices; + +pub mod mainwindow; + +fn main() -> glib::ExitCode +{ + env_logger::Builder::from_env(Env::default().default_filter_or("info")) +// .format_timestamp(None) + .init(); + + + let app = gtk::Application::builder() + .application_id(APP_ID) + .build(); + + app.connect_activate(activate); + app.run() +} + + +fn activate(app: >k::Application) +{ + let orchestrator = Arc::new(Mutex::new(Orchestrator::new())); + let mainwindow = MainWindow::builder().build(MainWindowInit + { + app: app.clone(), + orchestrator: orchestrator.clone() + }); + + mainwindow.root.present(); +} \ No newline at end of file diff --git a/Linux/ui-gtk/src/mainwindow.rs b/Linux/ui-gtk/src/mainwindow.rs new file mode 100644 index 0000000..6435dcc --- /dev/null +++ b/Linux/ui-gtk/src/mainwindow.rs @@ -0,0 +1,257 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::Arc; +use std::sync::Mutex; + +use gtk::glib; +use gtk::glib::clone; +use gtk::prelude::*; +use massiveknob_backend::orchestrator::Orchestrator; +use massiveknob_backend::util::unique_id::UniqueId; + +use crate::devices::DeviceSettingsUiBuilder; +use crate::ui::uicomponent::UiComponent; +use crate::ui::uicomponent::UiComponentState; + + + +pub struct MainWindowInit +{ + pub app: gtk::Application, + pub orchestrator: Arc> +} + + +pub struct MainWindow +{ + orchestrator: Arc>, + devices_sorted: Vec, + widgets: MainWindowWidgets, + + device_settings_widget: Option +} + + +pub struct MainWindowWidgets +{ + device: MainWindowDeviceWidgets +} + + +pub struct MainWindowDeviceWidgets +{ + devices_dropdown: gtk::DropDown, + settings_container: gtk::Box +} + + +impl UiComponent for MainWindow +{ + type Root = gtk::ApplicationWindow; + type Widgets = MainWindowWidgets; + type Init = MainWindowInit; + type State = Self; + + + fn build_root(init: &Self::Init) -> Self::Root + { + gtk::ApplicationWindow::builder() + .application(&init.app) + .title(t!("mainwindow.title")) + .default_width(500) + .default_height(500) + .build() + } + + fn build_widgets(root: &Self::Root, _init: &Self::Init) -> Self::Widgets + { + let tabs = gtk::Notebook::builder().build(); + root.set_child(Some(&tabs)); + + Self::Widgets + { + device: Self::build_device_tab(&tabs) + } + } + + + fn init(_root: &Self::Root, state: &Rc>) + { + { + let state_borrowed = state.borrow(); + let devices_dropdown = state_borrowed.widgets.device.devices_dropdown.clone(); + let orchestrator = state_borrowed.orchestrator.lock().unwrap(); + + let active_device_id = orchestrator.active_device_id(); + let mut active_device_index = gtk::ffi::GTK_INVALID_LIST_POSITION; + let devices_dropdown_list = gtk::StringList::default(); + + for (index, device) in state_borrowed.devices_sorted.iter().enumerate() + { + devices_dropdown_list.append(device.name.as_str()); + + if let Some(device_id) = &active_device_id + { + if *device_id == device.unique_id + { + active_device_index = index as u32; + } + } + } + + devices_dropdown.set_model(Some(&devices_dropdown_list)); + devices_dropdown.set_selected(active_device_index); + + devices_dropdown.connect_selected_notify(clone!( + #[weak] + state, + + move |_| + { + let mut state = state.borrow_mut(); + state.update_active_device(true); + } + )); + } + + let mut state = state.borrow_mut(); + state.update_active_device(false); + } +} + + +impl UiComponentState for MainWindow +{ + fn new(init: MainWindowInit, widgets: MainWindowWidgets) -> Self + { + let mut devices_sorted: Vec; + { + let orchestrator = init.orchestrator.lock().unwrap(); + + devices_sorted = orchestrator.devices() + .map(|device| SortedDevice + { + unique_id: device.unique_id.clone(), + name: device.name() + }) + .collect(); + + devices_sorted.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + } + + + Self + { + orchestrator: init.orchestrator.clone(), + devices_sorted, + widgets, + + device_settings_widget: None + } + } +} + + +impl MainWindow +{ + fn build_device_tab(tabs: >k::Notebook) -> MainWindowDeviceWidgets + { + //let sender = self.sender; + let tab = Self::build_box_tab(tabs, "mainwindow.tab.device"); + + let label = gtk::Label::builder() + .label(t!("mainwindow.deviceType.label")) + .halign(gtk::Align::Start) + .build(); + + tab.append(&label); + + + let devices_dropdown = gtk::DropDown::builder().build(); + tab.append(&devices_dropdown); + + + let settings_container = gtk::Box::builder().build(); + tab.append(&settings_container); + + + MainWindowDeviceWidgets + { + devices_dropdown, + settings_container + } + } + + + fn build_box_tab(notebook: >k::Notebook, title_key: &str) -> gtk::Box + { + let tab = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .spacing(8) + .margin_start(8) + .margin_end(8) + .margin_top(8) + .margin_bottom(8) + .build(); + + let tab_label = gtk::Label::builder() + .label(t!(title_key)) + .build(); + + notebook.append_page(&tab, Some(&tab_label)); + + tab + } + + + fn update_active_device(&mut self, set_active: bool) + { + log::info!("update_active_device"); + + let active_index = self.widgets.device.devices_dropdown.selected(); + if active_index == gtk::ffi::GTK_INVALID_LIST_POSITION { return }; + + let Ok(active_index_usize) = usize::try_from(active_index) else { return }; + let selected_device = &self.devices_sorted[active_index_usize]; + let device; + + { + let mut orchestrator = self.orchestrator.lock().unwrap(); + + if set_active + { + device = Some(orchestrator.set_active_device_id(&selected_device.unique_id)); + } + else + { + device = orchestrator.active_device(); + } + } + + if let Some(prev_widget) = &self.device_settings_widget + { + self.widgets.device.settings_container.remove(prev_widget); + } + + if let Some(device) = device + { + let widget = DeviceSettingsUiBuilder::build(device.clone()); + + self.widgets.device.settings_container.append(&widget); + self.device_settings_widget = Some(widget); + } + else + { + self.device_settings_widget = None; + } + } +} + + + +#[derive(Clone)] +struct SortedDevice +{ + unique_id: UniqueId, + name: String +} \ No newline at end of file diff --git a/Linux/ui-gtk/src/ui/mod.rs b/Linux/ui-gtk/src/ui/mod.rs new file mode 100644 index 0000000..39ff711 --- /dev/null +++ b/Linux/ui-gtk/src/ui/mod.rs @@ -0,0 +1,8 @@ +pub mod uicomponent; + + +#[deprecated] +pub trait EmbeddedWidgetConnector +{ + fn root(&self) -> gtk::Widget; +} \ No newline at end of file diff --git a/Linux/ui-gtk/src/ui/uicomponent.rs b/Linux/ui-gtk/src/ui/uicomponent.rs new file mode 100644 index 0000000..fc1e3fb --- /dev/null +++ b/Linux/ui-gtk/src/ui/uicomponent.rs @@ -0,0 +1,104 @@ +// Much credit to Relm4 for the inspiration. I initially used it, but felt +// like I wasn't using much of the abstractions it provided. But some parts +// are still very useful and I recommend giving it a try for your project! + +use gtk::prelude::*; +use std::cell::RefCell; +use std::marker::PhantomData; +use std::rc::Rc; + + +pub trait UiComponent : Sized +{ + type Root : IsA; + type Widgets; + type Init; + type State : UiComponentState; + + + fn builder() -> UiComponentBuilder + { + UiComponentBuilder::::default() + } + + + fn build_root(init: &Self::Init) -> Self::Root; + fn build_widgets(root: &Self::Root, init: &Self::Init) -> Self::Widgets; + + fn init(root: &Self::Root, state: &Rc>); +} + + +pub trait UiComponentState +{ + fn new(init: C::Init, widgets: C::Widgets) -> Self; +} + + +pub struct UiComponentConnector +{ + pub root: C::Root, + pub state: Rc> +} + + +pub trait UiComponentConnectorWidget +{ + fn root(&self) -> gtk::Widget; +} + + +pub struct UiComponentBuilder +{ + marker: PhantomData +} + + +impl Default for UiComponentBuilder +{ + fn default() -> Self + { + Self + { + marker: PhantomData:: + } + } +} + + +impl UiComponentBuilder +{ + pub fn build(&self, init: C::Init) -> UiComponentConnector + { + let root = C::build_root(&init); + let widgets = C::build_widgets(&root, &init); + let state = Rc::new(RefCell::new(C::State::new(init, widgets))); + + C::init(&root, &state); + + + UiComponentConnector:: + { + root, + state + } + } +} + + +impl From> for gtk::Widget +{ + fn from(val: UiComponentConnector) -> Self + { + val.root.into() + } +} + + +impl UiComponentConnectorWidget for UiComponentConnector +{ + fn root(&self) -> gtk::Widget + { + self.root.clone().into() + } +} \ No newline at end of file