From 26a9efaa861a3e8befb9f7ec0db0090413c3577a Mon Sep 17 00:00:00 2001 From: unspeaker Date: Mon, 9 Dec 2024 21:38:42 +0100 Subject: [PATCH] WorldClock/PlayClock --- Cargo.lock | 1903 +----------------------- crates/tek/Cargo.toml | 6 +- crates/tek/README.md | 3 + crates/tek/src/api/clock.rs | 2 + crates/tek/src/tui.rs | 128 +- crates/tek/src/tui/app_arranger.rs | 672 ++++++++- crates/tek/src/tui/app_sequencer.rs | 184 ++- crates/tek/src/tui/app_transport.rs | 270 +++- crates/tek/src/tui/ctrl_sequencer.rs | 1 + crates/tek/src/tui/ctrl_transport.rs | 127 -- crates/tek/src/tui/engine_style.rs | 29 +- crates/tek/src/tui/jack_arranger.rs | 53 - crates/tek/src/tui/jack_sequencer.rs | 45 - crates/tek/src/tui/jack_transport.rs | 13 - crates/tek/src/tui/model_clock.rs | 1 - crates/tek/src/tui/view_arranger.rs | 561 ------- crates/tek/src/tui/view_phrase_list.rs | 2 +- crates/tek/src/tui/view_sequencer.rs | 100 -- crates/tek/src/tui/view_transport.rs | 155 -- 19 files changed, 1216 insertions(+), 3039 deletions(-) delete mode 100644 crates/tek/src/tui/jack_arranger.rs delete mode 100644 crates/tek/src/tui/jack_sequencer.rs delete mode 100644 crates/tek/src/tui/jack_transport.rs delete mode 100644 crates/tek/src/tui/model_clock.rs delete mode 100644 crates/tek/src/tui/view_arranger.rs delete mode 100644 crates/tek/src/tui/view_sequencer.rs delete mode 100644 crates/tek/src/tui/view_transport.rs diff --git a/Cargo.lock b/Cargo.lock index 739b4bc0..bfd59c5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,22 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ab_glyph" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3672c180e71eeaaac3a541fbbc5f5ad4def8b747c595ad30d674e43049f7b0" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - [[package]] name = "addr2line" version = "0.24.2" @@ -33,61 +17,12 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android-activity" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" -dependencies = [ - "android-properties", - "bitflags 2.6.0", - "cc", - "cesu8", - "jni", - "jni-sys", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum 0.7.3", - "thiserror", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - [[package]] name = "anstream" version = "0.6.18" @@ -146,53 +81,12 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "as-raw-xcb-connection" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" - -[[package]] -name = "atk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" -dependencies = [ - "atk-sys", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - [[package]] name = "atomic_float" version = "1.1.0" @@ -230,29 +124,6 @@ dependencies = [ "console", ] -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.90", - "which", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -265,15 +136,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -298,63 +160,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bytes" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" - -[[package]] -name = "cairo-rs" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" -dependencies = [ - "bitflags 2.6.0", - "cairo-sys-rs", - "glib", - "libc", - "once_cell", - "thiserror", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "calloop" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.6.0", - "log", - "polling", - "rustix", - "slab", - "thiserror", -] - -[[package]] -name = "calloop-wayland-source" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" -dependencies = [ - "calloop", - "rustix", - "wayland-backend", - "wayland-client", -] - [[package]] name = "cassowary" version = "0.3.0" @@ -370,65 +175,12 @@ dependencies = [ "rustversion", ] -[[package]] -name = "cc" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.6", -] - [[package]] name = "clap" version = "4.5.23" @@ -457,10 +209,10 @@ version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.90", + "syn", ] [[package]] @@ -484,16 +236,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "compact_str" version = "0.7.1" @@ -507,15 +249,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "console" version = "0.15.8" @@ -528,46 +261,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -618,39 +311,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cursor-icon" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading 0.8.6", -] - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dpi" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" - [[package]] name = "either" version = "1.13.0" @@ -678,16 +338,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "extended" version = "0.1.0" @@ -700,180 +350,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset", - "rustc_version", -] - [[package]] name = "foldhash" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-macro", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "gdk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" -dependencies = [ - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" -dependencies = [ - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", - "once_cell", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gdk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -891,154 +373,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" -[[package]] -name = "gio" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "gio-sys", - "glib", - "libc", - "once_cell", - "pin-project-lite", - "smallvec", - "thiserror", -] - -[[package]] -name = "gio-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", -] - -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.6.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 2.0.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "gobject-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gtk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" -dependencies = [ - "atk", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", -] - -[[package]] -name = "gtk3-macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.90", -] - [[package]] name = "hashbrown" version = "0.15.2" @@ -1050,33 +384,12 @@ dependencies = [ "foldhash", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "indexmap" version = "2.7.0" @@ -1148,42 +461,11 @@ dependencies = [ "bitflags 1.3.2", "lazy_static", "libc", - "libloading 0.7.4", + "libloading", "log", "pkg-config", ] -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - [[package]] name = "js-sys" version = "0.3.76" @@ -1200,12 +482,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.168" @@ -1222,27 +498,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.5.7", -] - [[package]] name = "lilv" version = "0.2.4" @@ -1264,12 +519,6 @@ dependencies = [ "lv2_raw", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "livi" version = "0.7.5" @@ -1329,24 +578,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memmap2" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "midly" version = "0.5.3" @@ -1356,12 +587,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -1383,46 +608,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.6.0", - "jni-sys", - "log", - "ndk-sys", - "num_enum 0.7.3", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1432,251 +617,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive 0.7.3", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.6.0", - "block2", - "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2", - "objc2", - "objc2-contacts", - "objc2-foundation", -] - -[[package]] -name = "objc2-encode" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.6.0", - "block2", - "dispatch", - "libc", - "objc2", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation", - "objc2-link-presentation", - "objc2-quartz-core", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.6.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - [[package]] name = "object" version = "0.36.5" @@ -1692,15 +632,6 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" -[[package]] -name = "orbclient" -version = "0.3.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" -dependencies = [ - "libredox", -] - [[package]] name = "ordered-float" version = "4.5.0" @@ -1710,15 +641,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "owned_ttf_parser" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4" -dependencies = [ - "ttf-parser", -] - [[package]] name = "palette" version = "0.7.6" @@ -1741,32 +663,7 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.90", -] - -[[package]] -name = "pango" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" -dependencies = [ - "gio", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", + "syn", ] [[package]] @@ -1823,12 +720,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - [[package]] name = "phf" version = "0.11.2" @@ -1859,7 +750,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.90", + "syn", ] [[package]] @@ -1871,59 +762,12 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.90", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" -[[package]] -name = "polling" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1933,68 +777,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" -dependencies = [ - "proc-macro2", - "syn 2.0.90", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[package]] -name = "proc-macro-crate" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" -dependencies = [ - "toml_edit 0.22.22", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.92" @@ -2019,15 +801,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - [[package]] name = "quote" version = "1.0.37" @@ -2096,12 +869,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - [[package]] name = "rayon" version = "1.10.0" @@ -2131,15 +898,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.7" @@ -2149,35 +907,6 @@ dependencies = [ "bitflags 2.6.0", ] -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - [[package]] name = "ringbuf" version = "0.3.3" @@ -2193,34 +922,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - [[package]] name = "rustversion" version = "1.0.18" @@ -2233,46 +934,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - [[package]] name = "serde" version = "1.0.215" @@ -2290,7 +957,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn", ] [[package]] @@ -2302,12 +969,6 @@ dependencies = [ "serde", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "signal-hook" version = "0.3.17" @@ -2344,55 +1005,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "smithay-client-toolkit" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" -dependencies = [ - "bitflags 2.6.0", - "calloop", - "calloop-wayland-source", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix", - "thiserror", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - [[package]] name = "stability" version = "0.2.1" @@ -2400,7 +1018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.90", + "syn", ] [[package]] @@ -2409,12 +1027,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - [[package]] name = "strsim" version = "0.11.1" @@ -2436,21 +1048,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", "rustversion", - "syn 2.0.90", -] - -[[package]] -name = "suil-rs" -version = "0.1.0" -dependencies = [ - "bindgen", - "gtk", - "livi", - "winit", + "syn", ] [[package]] @@ -2648,17 +1250,6 @@ dependencies = [ "symphonia-metadata", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.90" @@ -2670,25 +1261,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "tek" version = "0.2.0" @@ -2707,13 +1279,10 @@ dependencies = [ "quanta", "rand", "ratatui", - "suil-rs", "symphonia", "toml", "uuid", - "vst", "wavers", - "winit", ] [[package]] @@ -2733,32 +1302,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", -] - -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", + "syn", ] [[package]] @@ -2770,7 +1314,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -2782,28 +1326,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" @@ -2814,31 +1336,9 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.20", + "winnow", ] -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" - -[[package]] -name = "ttf-parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" - [[package]] name = "unicode-ident" version = "1.0.14" @@ -2883,42 +1383,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vst" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf1ddbb85e53de6c1534f97340b065ca127678dcc31f88a33b93e54a5ac38dc" -dependencies = [ - "bitflags 1.3.2", - "libc", - "libloading 0.7.4", - "log", - "num-traits", - "num_enum 0.5.11", -] - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2946,23 +1410,10 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.90", + "syn", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.99" @@ -2981,7 +1432,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3004,115 +1455,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "wayland-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" -dependencies = [ - "cc", - "downcast-rs", - "rustix", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" -dependencies = [ - "bitflags 2.6.0", - "rustix", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-csd-frame" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" -dependencies = [ - "bitflags 2.6.0", - "cursor-icon", - "wayland-backend", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" -dependencies = [ - "rustix", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-plasma" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" -dependencies = [ - "proc-macro2", - "quick-xml", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - [[package]] name = "web-sys" version = "0.3.76" @@ -3123,28 +1465,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - [[package]] name = "winapi" version = "0.3.9" @@ -3161,30 +1481,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - [[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 = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -3212,21 +1514,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -3258,12 +1545,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -3276,12 +1557,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -3294,12 +1569,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -3318,12 +1587,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -3336,12 +1599,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -3354,12 +1611,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -3372,12 +1623,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -3390,67 +1635,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winit" -version = "0.30.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" -dependencies = [ - "ahash", - "android-activity", - "atomic-waker", - "bitflags 2.6.0", - "block2", - "bytemuck", - "calloop", - "cfg_aliases", - "concurrent-queue", - "core-foundation", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "memmap2", - "ndk", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "orbclient", - "percent-encoding", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix", - "sctk-adwaita", - "smithay-client-toolkit", - "smol_str", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-plasma", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "x11-dl", - "x11rb", - "xkbcommon-dl", -] - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.20" @@ -3460,63 +1644,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading 0.8.6", - "once_cell", - "rustix", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" - -[[package]] -name = "xcursor" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" - -[[package]] -name = "xkbcommon-dl" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" -dependencies = [ - "bitflags 2.6.0", - "dlib", - "log", - "once_cell", - "xkeysym", -] - -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - [[package]] name = "zerocopy" version = "0.7.35" @@ -3535,5 +1662,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn", ] diff --git a/crates/tek/Cargo.toml b/crates/tek/Cargo.toml index 545627e6..2a39075e 100644 --- a/crates/tek/Cargo.toml +++ b/crates/tek/Cargo.toml @@ -20,13 +20,13 @@ palette = { version = "0.7.6", features = [ "random" ] } quanta = "0.12.3" rand = "0.8.5" ratatui = { version = "0.26.3", features = [ "unstable-widget-ref", "underline-color" ] } -suil-rs = { path = "../suil" } +#suil-rs = { path = "../suil" } symphonia = { version = "0.5.4", features = [ "all" ] } toml = "0.8.12" uuid = { version = "1.10.0", features = [ "v4" ] } -vst = "0.4.0" +#vst = "0.4.0" wavers = "1.4.3" -winit = { version = "0.30.4", features = [ "x11" ] } +#winit = { version = "0.30.4", features = [ "x11" ] } [dev-dependencies] #tek_app = { version = "0.1.0", path = "../tek_app" } diff --git a/crates/tek/README.md b/crates/tek/README.md index b00cb3f8..0d8195be 100644 --- a/crates/tek/README.md +++ b/crates/tek/README.md @@ -1,4 +1,5 @@ + # `tek_sequencer` This crate implements a MIDI sequencer and arranger with clip launching. @@ -44,3 +45,5 @@ in response to MIDI notes. --- # `tek_plugin` + + diff --git a/crates/tek/src/api/clock.rs b/crates/tek/src/api/clock.rs index f7792912..5d1e03b2 100644 --- a/crates/tek/src/api/clock.rs +++ b/crates/tek/src/api/clock.rs @@ -160,6 +160,8 @@ impl ClockModel { pub fn update_from_scope (&self, scope: &ProcessScope) -> Usually<()> { self.set_chunk(scope.n_frames() as usize); let CycleTimes { current_frames, current_usecs, .. } = scope.cycle_times()?; + self.global.sample.set(current_frames as f64); + self.global.usec.set(current_usecs as f64); let mut started = self.started.write().unwrap(); match self.transport.query_state()? { TransportState::Rolling => { diff --git a/crates/tek/src/tui.rs b/crates/tek/src/tui.rs index 145eb790..8b80407d 100644 --- a/crates/tek/src/tui.rs +++ b/crates/tek/src/tui.rs @@ -1,32 +1,21 @@ use crate::*; -mod jack_arranger; pub(crate) use app_arranger::*; -mod jack_sequencer; pub(crate) use app_sequencer::*; -mod jack_transport; pub(crate) use app_transport::*; +mod engine_focus; pub(crate) use engine_focus::*; +mod engine_input; pub(crate) use engine_input::*; +mod engine_style; pub(crate) use engine_style::*; +mod engine_output; pub(crate) use engine_output::*; -mod engine_focus; pub(crate) use engine_focus::*; -mod engine_input; pub(crate) use engine_input::*; -mod engine_style; pub(crate) use engine_style::*; -mod engine_output; pub(crate) use engine_output::*; +mod app_transport; pub(crate) use app_transport::*; -mod app_arranger; pub(crate) use app_arranger::*; -mod app_sequencer; pub(crate) use app_sequencer::*; -mod app_transport; pub(crate) use app_transport::*; +mod app_sequencer; pub(crate) use app_sequencer::*; +mod ctrl_sequencer; pub(crate) use ctrl_sequencer::*; -mod view_arranger; pub(crate) use view_arranger::*; -mod view_sequencer; pub(crate) use view_sequencer::*; -mod view_transport; pub(crate) use view_transport::*; - -mod ctrl_arranger; pub(crate) use ctrl_arranger::*; -mod ctrl_sequencer; pub(crate) use ctrl_sequencer::*; -mod ctrl_transport; pub(crate) use ctrl_transport::*; - -mod model_arranger; pub(crate) use model_arranger::*; +mod app_arranger; pub(crate) use app_arranger::*; +mod ctrl_arranger; pub(crate) use ctrl_arranger::*; +mod model_arranger; pub(crate) use model_arranger::*; //////////////////////////////////////////////////////// -mod model_clock; pub(crate) use model_clock::*; - mod view_status_bar; pub(crate) use view_status_bar::*; mod model_file_browser; pub(crate) use model_file_browser::*; @@ -191,3 +180,100 @@ impl Tui { buffer } } + +struct Field(&'static str, String); + +render!(|self: Field|{ + Tui::to_east("│", Tui::to_east( + Tui::bold(true, self.0), + Tui::bg(Color::Rgb(0, 0, 0), self.1.as_str()), + )) +}); + +//pub struct TransportView { + //pub(crate) state: Option, + //pub(crate) selected: Option, + //pub(crate) focused: bool, + //pub(crate) bpm: f64, + //pub(crate) sync: f64, + //pub(crate) quant: f64, + //pub(crate) beat: String, + //pub(crate) msu: String, +//} + ////)?; + ////match *state { + ////Some(TransportState::Rolling) => { + ////add(&row!( + ////"│", + ////TuiStyle::fg("▶ PLAYING", Color::Rgb(0, 255, 0)), + ////format!("│0 (0)"), + ////format!("│00m00s000u"), + ////format!("│00B 0b 00/00") + ////))?; + ////add(&row!("│Now ", row!( + ////format!("│0 (0)"), //sample(chunk) + ////format!("│00m00s000u"), //msu + ////format!("│00B 0b 00/00"), //bbt + ////)))?; + ////}, + ////_ => { + ////add(&row!("│", TuiStyle::fg("⏹ STOPPED", Color::Rgb(255, 128, 0))))?; + ////add(&"")?; + ////} + ////} + ////Ok(()) + ////}).fill_x().bg(Color::Rgb(40, 50, 30)) +////}); + +//impl<'a, T: HasClock> From<&'a T> for TransportView where Option: From<&'a T> { + //fn from (state: &'a T) -> Self { + //let selected = state.into(); + //Self { + //selected, + //focused: selected.is_some(), + //state: Some(state.clock().transport.query_state().unwrap()), + //bpm: state.clock().bpm().get(), + //sync: state.clock().sync.get(), + //quant: state.clock().quant.get(), + //beat: state.clock().playhead.format_beat(), + //msu: state.clock().playhead.usec.format_msu(), + //} + //} +//} + + //row!( + ////selected.wrap(TransportFocus::PlayPause, &play_pause.fixed_xy(10, 3)), + //row!( + //col!( + //Field("SR ", format!("192000")), + //Field("BUF ", format!("1024")), + //Field("LEN ", format!("21300")), + //Field("CPU ", format!("00.0%")) + //), + //col!( + //Field("PUL ", format!("000000000")), + //Field("PPQ ", format!("96")), + //Field("BBT ", format!("00B0b00p")) + //), + //col!( + //Field("SEC ", format!("000000.000")), + //Field("BPM ", format!("000.000")), + //Field("MSU ", format!("00m00s00u")) + //), + //), + //selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, { + //row! { + //"BPM ", + //format!("{}.{:03}", *bpm as usize, (bpm * 1000.0) % 1000.0) + //} + //})), + //selected.wrap(TransportFocus::Sync, &Outset::X(1u16, row! { + //"SYNC ", pulses_to_name(*sync as usize) + //})), + //selected.wrap(TransportFocus::Quant, &Outset::X(1u16, row! { + //"QUANT ", pulses_to_name(*quant as usize) + //})), + //selected.wrap(TransportFocus::Clock, &{ + //row!("B" , beat.as_str(), " T", msu.as_str()).outset_x(1) + //}).align_e().fill_x(), + //).fill_x().bg(Color::Rgb(40, 50, 30)) diff --git a/crates/tek/src/tui/app_arranger.rs b/crates/tek/src/tui/app_arranger.rs index f9b50393..2e0c7abc 100644 --- a/crates/tek/src/tui/app_arranger.rs +++ b/crates/tek/src/tui/app_arranger.rs @@ -1,30 +1,5 @@ use crate::*; -/// Root view for standalone `tek_arranger` -pub struct ArrangerTui { - pub jack: Arc>, - pub clock: ClockModel, - pub phrases: PhraseListModel, - pub tracks: Vec, - pub scenes: Vec, - pub name: Arc>, - pub splits: [u16;2], - pub selected: ArrangerSelection, - pub mode: ArrangerMode, - pub color: ItemColor, - pub entered: bool, - pub size: Measure, - pub cursor: (usize, usize), - pub menu_bar: Option>, - pub status_bar: Option, - pub history: Vec, - pub note_buf: Vec, - pub midi_buf: Vec>>, - pub editor: PhraseEditorModel, - pub focus: FocusState, - pub perf: PerfModel, -} - impl TryFrom<&Arc>> for ArrangerTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { @@ -54,6 +29,120 @@ impl TryFrom<&Arc>> for ArrangerTui { } } +/// Root view for standalone `tek_arranger` +pub struct ArrangerTui { + pub jack: Arc>, + pub clock: ClockModel, + pub phrases: PhraseListModel, + pub tracks: Vec, + pub scenes: Vec, + pub name: Arc>, + pub splits: [u16;2], + pub selected: ArrangerSelection, + pub mode: ArrangerMode, + pub color: ItemColor, + pub entered: bool, + pub size: Measure, + pub cursor: (usize, usize), + pub menu_bar: Option>, + pub status_bar: Option, + pub history: Vec, + pub note_buf: Vec, + pub midi_buf: Vec>>, + pub editor: PhraseEditorModel, + pub focus: FocusState, + pub perf: PerfModel, +} + +impl JackApi for ArrangerTui { + fn jack (&self) -> &Arc> { + &self.jack + } +} + +impl Audio for ArrangerTui { + #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { + // Start profiling cycle + let t0 = self.perf.get_t0(); + + // Update transport clock + if ClockAudio(self).process(client, scope) == Control::Quit { + return Control::Quit + } + + // Update MIDI sequencers + if TracksAudio( + &mut self.tracks, + &mut self.note_buf, + &mut self.midi_buf, + Default::default(), + ).process(client, scope) == Control::Quit { + return Control::Quit + } + + // FIXME: one of these per playing track + //self.now.set(0.); + //if let ArrangerSelection::Clip(t, s) = self.selected { + //let phrase = self.scenes().get(s).map(|scene|scene.clips.get(t)); + //if let Some(Some(Some(phrase))) = phrase { + //if let Some(track) = self.tracks().get(t) { + //if let Some((ref started_at, Some(ref playing))) = track.player.play_phrase { + //let phrase = phrase.read().unwrap(); + //if *playing.read().unwrap() == *phrase { + //let pulse = self.current().pulse.get(); + //let start = started_at.pulse.get(); + //let now = (pulse - start) % phrase.length as f64; + //self.now.set(now); + //} + //} + //} + //} + //} + + // End profiling cycle + self.perf.update(t0, scope); + + return Control::Continue + } +} + +// Layout for standalone arranger app. +render!(|self: ArrangerTui|{ + let arranger_focused = self.arranger_focused(); + let border = Lozenge(Style::default().bg(TuiTheme::border_bg()).fg(TuiTheme::border_fg(arranger_focused))); + col_up!([ + WorldClock::from(self), + PlayClock::from(self), + col!([ + Tui::fixed_y(self.splits[0], lay!([ + border.wrap(Tui::grow_y(1, Layers::new(move |add|{ + match self.mode { + ArrangerMode::Horizontal => + add(&arranger_content_horizontal(self))?, + ArrangerMode::Vertical(factor) => + add(&arranger_content_vertical(self, factor))? + }; + add(&self.size) + }))), + self.size, + Tui::push_x(1, Tui::fg( + TuiTheme::title_fg(arranger_focused), + format!("[{}] Arranger", if self.entered { + "■" + } else { + " " + }) + )) + ])), + Split::right( + self.splits[1], + PhraseListView::from(self), + PhraseView::from(self), + ) + ]) + ]) +}); + impl HasClock for ArrangerTui { fn clock (&self) -> &ClockModel { &self.clock @@ -86,6 +175,15 @@ pub enum ArrangerFocus { PhraseEditor, } +impl From<&ArrangerTui> for Option { + fn from (state: &ArrangerTui) -> Self { + match state.focus.inner() { + ArrangerFocus::Transport(focus) => Some(focus), + _ => None + } + } +} + impl_focus!(ArrangerTui ArrangerFocus [ //&[ //Menu, @@ -237,3 +335,527 @@ render!(|self: ArrangerStatus|{ Tui::bg(status_bar_bg, Tui::fill_x(Tui::to_east(mode, commands))) }); + +/// Display mode of arranger +#[derive(Clone, PartialEq)] +pub enum ArrangerMode { + /// Tracks are rows + Horizontal, + /// Tracks are columns + Vertical(usize), +} + +/// Arranger display mode can be cycled +impl ArrangerMode { + /// Cycle arranger display mode + pub fn to_next (&mut self) { + *self = match self { + Self::Horizontal => Self::Vertical(1), + Self::Vertical(1) => Self::Vertical(2), + Self::Vertical(2) => Self::Vertical(2), + Self::Vertical(0) => Self::Horizontal, + Self::Vertical(_) => Self::Vertical(0), + } + } +} + +pub trait ArrangerViewState { + fn arranger_focused (&self) -> bool; +} +impl ArrangerViewState for ArrangerTui { + fn arranger_focused (&self) -> bool { + self.focused() == ArrangerFocus::Arranger + } +} + +fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> { + let mut widths = vec![]; + let mut total = 0; + for track in tracks.iter() { + let width = track.width; + widths.push((width, total)); + total += width; + } + widths.push((0, total)); + widths +} + +fn any_size (_: E::Size) -> Perhaps{ + Ok(Some([0.into(),0.into()].into())) +} + +fn custom_render Usually<()>+Send+Sync> (render: F) -> impl Render { + Widget::new(|_|Ok(Some([0u16,0u16].into())), render) +} + +pub fn arranger_content_vertical ( + view: &ArrangerTui, + factor: usize +) -> impl Render + use<'_> { + lay!([ + Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(TuiTheme::title_fg(view.arranger_focused()), + format!("{}x{}", view.size.w(), view.size.h())) + ))), + Tui::bg(view.color.rgb, lay!(![ + ArrangerVerticalColumnSeparator::from(view), + ArrangerVerticalRowSeparator::from((view, factor)), + col!(![ + ArrangerVerticalHeader::from(view), + ArrangerVerticalContent::from((view, factor)), + ]), + ArrangerVerticalCursor::from((view, factor)), + ])), + ]) +} + +struct ArrangerVerticalColumnSeparator { + cols: Vec<(usize, usize)>, + scenes_w: u16, + sep_fg: Color, +} +impl From<&ArrangerTui> for ArrangerVerticalColumnSeparator { + fn from (state: &ArrangerTui) -> Self { + Self { + cols: track_widths(state.tracks()), + scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, + sep_fg: TuiTheme::separator_fg(false), + } + } +} +render!(|self: ArrangerVerticalColumnSeparator|custom_render(move|to: &mut TuiOutput|{ + let style = Some(Style::default().fg(self.sep_fg)); + Ok(for x in self.cols.iter().map(|col|col.1) { + let x = self.scenes_w + to.area().x() + x as u16; + for y in to.area().y()..to.area().y2() { + to.blit(&"▎", x, y, style); + } + }) +})); + +struct ArrangerVerticalRowSeparator { + rows: Vec<(usize, usize)>, + sep_fg: Color, +} +impl From<(&ArrangerTui, usize)> for ArrangerVerticalRowSeparator { + fn from ((state, factor): (&ArrangerTui, usize)) -> Self { + Self { + rows: ArrangerScene::ppqs(state.scenes(), factor), + sep_fg: TuiTheme::separator_fg(false), + } + } +} + +render!(|self: ArrangerVerticalRowSeparator|custom_render(move|to: &mut TuiOutput|{ + Ok(for y in self.rows.iter().map(|row|row.1) { + let y = to.area().y() + (y / PPQ) as u16 + 1; + if y >= to.buffer.area.height { break } + for x in to.area().x()..to.area().x2().saturating_sub(2) { + if x < to.buffer.area.x && y < to.buffer.area.y { + let cell = to.buffer.get_mut(x, y); + cell.modifier = Modifier::UNDERLINED; + cell.underline_color = self.sep_fg; + } + } + }) +})); + +struct ArrangerVerticalCursor { + cols: Vec<(usize, usize)>, + rows: Vec<(usize, usize)>, + focused: bool, + selected: ArrangerSelection, + scenes_w: u16, + header_h: u16, +} +impl From<(&ArrangerTui, usize)> for ArrangerVerticalCursor { + fn from ((state, factor): (&ArrangerTui, usize)) -> Self { + Self { + cols: track_widths(state.tracks()), + rows: ArrangerScene::ppqs(state.scenes(), factor), + focused: state.arranger_focused(), + selected: state.selected, + scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, + header_h: 3, + } + } +} +render!(|self: ArrangerVerticalCursor|custom_render(move|to: &mut TuiOutput|{ + let area = to.area(); + let focused = self.focused; + let selected = self.selected; + let get_track_area = |t: usize| [ + self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(), + self.cols[t].0 as u16, area.h(), + ]; + let get_scene_area = |s: usize| [ + area.x(), self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16, + area.w(), (self.rows[s].0 / PPQ) as u16 + ]; + let get_clip_area = |t: usize, s: usize| [ + self.scenes_w + area.x() + self.cols[t].1 as u16, + self.header_h + area.y() + (self.rows[s].1/PPQ) as u16, + self.cols[t].0 as u16, + (self.rows[s].0 / PPQ) as u16 + ]; + let mut track_area: Option<[u16;4]> = None; + let mut scene_area: Option<[u16;4]> = None; + let mut clip_area: Option<[u16;4]> = None; + let area = match selected { + ArrangerSelection::Mix => area, + ArrangerSelection::Track(t) => { + track_area = Some(get_track_area(t)); + area + }, + ArrangerSelection::Scene(s) => { + scene_area = Some(get_scene_area(s)); + area + }, + ArrangerSelection::Clip(t, s) => { + track_area = Some(get_track_area(t)); + scene_area = Some(get_scene_area(s)); + clip_area = Some(get_clip_area(t, s)); + area + }, + }; + let bg = TuiTheme::border_bg(); + if let Some([x, y, width, height]) = track_area { + to.fill_fg([x, y, 1, height], bg); + to.fill_fg([x + width, y, 1, height], bg); + } + if let Some([_, y, _, height]) = scene_area { + to.fill_ul([area.x(), y - 1, area.w(), 1], bg); + to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg); + } + Ok(if focused { + to.render_in(if let Some(clip_area) = clip_area { clip_area } + else if let Some(track_area) = track_area { track_area.clip_h(self.header_h) } + else if let Some(scene_area) = scene_area { scene_area.clip_w(self.scenes_w) } + else { area.clip_w(self.scenes_w).clip_h(self.header_h) }, &CORNERS)? + }) +})); + +struct ArrangerVerticalHeader<'a> { + tracks: &'a Vec, + cols: Vec<(usize, usize)>, + focused: bool, + selected: ArrangerSelection, + scenes_w: u16, + header_h: u16, + timebase: &'a Arc, + current: &'a Arc, +} +impl<'a> From<&'a ArrangerTui> for ArrangerVerticalHeader<'a> { + fn from (state: &'a ArrangerTui) -> Self { + Self { + tracks: &state.tracks, + cols: track_widths(state.tracks()), + focused: state.arranger_focused(), + selected: state.selected, + scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, + header_h: 3, + timebase: state.clock().timebase(), + current: &state.clock().playhead, + } + } +} +render!(|self: ArrangerVerticalHeader<'a>|row!( + (track, w) in self.tracks.iter().zip(self.cols.iter().map(|col|col.0)) => { + // name and width of track + let name = track.name().read().unwrap(); + let max_w = w.saturating_sub(1).min(name.len()).max(2); + let name = format!("▎{}", &name[0..max_w]); + let name = Tui::bold(true, name); + // beats elapsed + let elapsed = if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() { + let length = phrase.read().unwrap().length; + let elapsed = track.player.pulses_since_start().unwrap(); + let elapsed = self.timebase.format_beats_1_short( + (elapsed as usize % length) as f64 + ); + format!("▎+{elapsed:>}") + } else { + String::from("▎") + }; + // beats until switchover + let until_next = track.player.next_phrase().as_ref().map(|(t, _)|{ + let target = t.pulse.get(); + let current = self.current.pulse.get(); + if target > current { + let remaining = target - current; + format!("▎-{:>}", self.timebase.format_beats_0_short(remaining)) + } else { + String::new() + } + }).unwrap_or(String::from("▎")); + let timer = col!([until_next, elapsed]); + // name of active MIDI input + let _input = format!("▎>{}", track.player.midi_ins().get(0) + .map(|port|port.short_name()) + .transpose()? + .unwrap_or("(none)".into())); + // name of active MIDI output + let _output = format!("▎<{}", track.player.midi_outs().get(0) + .map(|port|port.short_name()) + .transpose()? + .unwrap_or("(none)".into())); + Tui::push_x(self.scenes_w, + Tui::bg(track.color().rgb, + Tui::min_xy(w as u16, self.header_h, + col!([name, timer])))) + } +)); + +struct ArrangerVerticalContent<'a> { + size: &'a Measure, + scenes: &'a Vec, + tracks: &'a Vec, + rows: Vec<(usize, usize)>, + cols: Vec<(usize, usize)>, + header_h: u16, +} +impl<'a> From<(&'a ArrangerTui, usize)> for ArrangerVerticalContent<'a> { + fn from ((state, factor): (&'a ArrangerTui, usize)) -> Self { + Self { + size: &state.size, + scenes: &state.scenes, + tracks: &state.tracks, + rows: ArrangerScene::ppqs(state.scenes(), factor), + cols: track_widths(state.tracks()), + header_h: 3, + } + } +} +render!(|self: ArrangerVerticalContent<'a>|Tui::fixed_y( + (self.size.h() as u16).saturating_sub(self.header_h), + col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => { + let height = 1.max((pulses / PPQ) as u16); + let playing = scene.is_playing(self.tracks); + Tui::fixed_y( + height, + Tui::to_east( + Tui::to_east( + if playing { "▶ " } else { " " }, + Tui::bold(true, scene.name.read().unwrap().as_str()) + ), + row!((track, w) in self.cols.iter().map(|col|col.0).enumerate() => { + Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ + let mut bg = TuiTheme::border_bg(); + match (self.tracks.get(track), scene.clips.get(track)) { + (Some(track), Some(Some(phrase))) => { + let name = &(phrase as &Arc>).read().unwrap().name; + let name = format!("{}", name); + let max_w = name.len().min((w as usize).saturating_sub(2)); + let color = phrase.read().unwrap().color; + bg = color.dark.rgb; + if let Some((_, Some(ref playing))) = track.player.play_phrase() { + if *playing.read().unwrap() == *phrase.read().unwrap() { + bg = color.light.rgb + } + }; + add(&Tui::fixed_x(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?; + }, + _ => {} + }; + //add(&Background(bg)) + Ok(()) + })) + }) + ) + ) + }) +)); + +pub fn arranger_content_horizontal ( + view: &ArrangerTui, +) -> impl Render + use<'_> { + todo!() +} + //let focused = view.arranger_focused(); + //let _tracks = view.tracks(); + //lay!( + //focused.then_some(Background(TuiTheme::border_bg())), + //row!( + //// name + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks, selected) = self; + ////let yellow = Some(Style::default().yellow().bold().not_dim()); + ////let white = Some(Style::default().white().bold().not_dim()); + ////let area = to.area(); + ////let area = [area.x(), area.y(), 3 + 5.max(track_name_max_len(tracks)) as u16, area.h()]; + ////let offset = 0; // track scroll offset + ////for y in 0..area.h() { + ////if y == 0 { + ////to.blit(&"Mixer", area.x() + 1, area.y() + y, Some(DIM))?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2 + offset; + ////if let Some(track) = tracks.get(index) { + ////let selected = selected.track() == Some(index); + ////let style = if selected { yellow } else { white }; + ////to.blit(&format!(" {index:>02} "), area.x(), area.y() + y, style)?; + ////to.blit(&*track.name.read().unwrap(), area.x() + 4, area.y() + y, style)?; + ////} + ////} + ////} + ////Ok(Some(area)) + //}), + //// monitor + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks) = self; + ////let mut area = to.area(); + ////let on = Some(Style::default().not_dim().green().bold()); + ////let off = Some(DIM); + ////area.x += 1; + ////for y in 0..area.h() { + ////if y == 0 { + //////" MON ".blit(to.buffer, area.x, area.y + y, style2)?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2; + ////if let Some(track) = tracks.get(index) { + ////let style = if track.monitoring { on } else { off }; + ////to.blit(&" MON ", area.x(), area.y() + y, style)?; + ////} else { + ////area.height = y; + ////break + ////} + ////} + ////} + ////area.width = 4; + ////Ok(Some(area)) + //}), + //// record + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks) = self; + ////let mut area = to.area(); + ////let on = Some(Style::default().not_dim().red().bold()); + ////let off = Some(Style::default().dim()); + ////area.x += 1; + ////for y in 0..area.h() { + ////if y == 0 { + //////" REC ".blit(to.buffer, area.x, area.y + y, style2)?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2; + ////if let Some(track) = tracks.get(index) { + ////let style = if track.recording { on } else { off }; + ////to.blit(&" REC ", area.x(), area.y() + y, style)?; + ////} else { + ////area.height = y; + ////break + ////} + ////} + ////} + ////area.width = 4; + ////Ok(Some(area)) + //}), + //// overdub + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks) = self; + ////let mut area = to.area(); + ////let on = Some(Style::default().not_dim().yellow().bold()); + ////let off = Some(Style::default().dim()); + ////area.x = area.x + 1; + ////for y in 0..area.h() { + ////if y == 0 { + //////" OVR ".blit(to.buffer, area.x, area.y + y, style2)?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2; + ////if let Some(track) = tracks.get(index) { + ////to.blit(&" OVR ", area.x(), area.y() + y, if track.overdub { + ////on + ////} else { + ////off + ////})?; + ////} else { + ////area.height = y; + ////break + ////} + ////} + ////} + ////area.width = 4; + ////Ok(Some(area)) + //}), + //// erase + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks) = self; + ////let mut area = to.area(); + ////let off = Some(Style::default().dim()); + ////area.x = area.x + 1; + ////for y in 0..area.h() { + ////if y == 0 { + //////" DEL ".blit(to.buffer, area.x, area.y + y, style2)?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2; + ////if let Some(_) = tracks.get(index) { + ////to.blit(&" DEL ", area.x(), area.y() + y, off)?; + ////} else { + ////area.height = y; + ////break + ////} + ////} + ////} + ////area.width = 4; + ////Ok(Some(area)) + //}), + //// gain + //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ + //todo!() + ////let Self(tracks) = self; + ////let mut area = to.area(); + ////let off = Some(Style::default().dim()); + ////area.x = area.x() + 1; + ////for y in 0..area.h() { + ////if y == 0 { + //////" GAIN ".blit(to.buffer, area.x, area.y + y, style2)?; + ////} else if y % 2 == 0 { + ////let index = (y as usize - 2) / 2; + ////if let Some(_) = tracks.get(index) { + ////to.blit(&" +0.0 ", area.x(), area.y() + y, off)?; + ////} else { + ////area.height = y; + ////break + ////} + ////} + ////} + ////area.width = 7; + ////Ok(Some(area)) + //}), + //// scenes + //Widget::new(|_|{todo!()}, |to: &mut TuiOutput|{ + //let [x, y, _, height] = to.area(); + //let mut x2 = 0; + //Ok(for (scene_index, scene) in view.scenes().iter().enumerate() { + //let active_scene = view.selected.scene() == Some(scene_index); + //let sep = Some(if active_scene { + //Style::default().yellow().not_dim() + //} else { + //Style::default().dim() + //}); + //for y in y+1..y+height { + //to.blit(&"│", x + x2, y, sep); + //} + //let name = scene.name.read().unwrap(); + //let mut x3 = name.len() as u16; + //to.blit(&*name, x + x2, y, sep); + //for (i, clip) in scene.clips.iter().enumerate() { + //let active_track = view.selected.track() == Some(i); + //if let Some(clip) = clip { + //let y2 = y + 2 + i as u16 * 2; + //let label = format!("{}", clip.read().unwrap().name); + //to.blit(&label, x + x2, y2, Some(if active_track && active_scene { + //Style::default().not_dim().yellow().bold() + //} else { + //Style::default().not_dim() + //})); + //x3 = x3.max(label.len() as u16) + //} + //} + //x2 = x2 + x3 + 1; + //}) + //}), + //) + //) +//} diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index 9b14d8d8..9538aa11 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -2,23 +2,7 @@ use crate::*; use SequencerFocus::*; use super::app_transport::TransportFocus::*; -/// Root view for standalone `tek_sequencer`. -pub struct SequencerTui { - pub jack: Arc>, - pub clock: ClockModel, - pub phrases: PhraseListModel, - pub player: PhrasePlayerModel, - pub editor: PhraseEditorModel, - pub size: Measure, - pub cursor: (usize, usize), - pub split: u16, - pub entered: bool, - pub note_buf: Vec, - pub midi_buf: Vec>>, - pub focus: FocusState, - pub perf: PerfModel, -} - +/// Create app state from JACK handle. impl TryFrom<&Arc>> for SequencerTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { @@ -41,6 +25,93 @@ impl TryFrom<&Arc>> for SequencerTui { } } +/// Root view for standalone `tek_sequencer`. +pub struct SequencerTui { + pub jack: Arc>, + pub clock: ClockModel, + pub phrases: PhraseListModel, + pub player: PhrasePlayerModel, + pub editor: PhraseEditorModel, + pub size: Measure, + pub cursor: (usize, usize), + pub split: u16, + pub entered: bool, + pub note_buf: Vec, + pub midi_buf: Vec>>, + pub focus: FocusState, + pub perf: PerfModel, +} + +impl JackApi for SequencerTui { + fn jack (&self) -> &Arc> { + &self.jack + } +} + +impl Audio for SequencerTui { + fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { + // Start profiling cycle + let t0 = self.perf.get_t0(); + + // Update transport clock + if ClockAudio(self).process(client, scope) == Control::Quit { + return Control::Quit + } + + // Update MIDI sequencer + if PlayerAudio( + &mut self.player, + &mut self.note_buf, + &mut self.midi_buf, + ).process(client, scope) == Control::Quit { + return Control::Quit + } + + // Update sequencer playhead indicator + //self.now().set(0.); + //if let Some((ref started_at, Some(ref playing))) = self.player.play_phrase { + //let phrase = phrase.read().unwrap(); + //if *playing.read().unwrap() == *phrase { + //let pulse = self.current().pulse.get(); + //let start = started_at.pulse.get(); + //let now = (pulse - start) % phrase.length as f64; + //self.now().set(now); + //} + //} + + // End profiling cycle + self.perf.update(t0, scope); + + Control::Continue + } +} + +render!(|self: SequencerTui|{ + //col_up!([ + //Tui::max_y(2, SequencerStatusBar::from(self)), + col!([ + WorldClock::from(self), + PlayClock::from(self), + Tui::min_y(20, row!([ + Tui::min_x(20, col!([ + Tui::fixed_y(4, PhraseSelector::play_phrase( + &self.player, + self.focused() == SequencerFocus::PhrasePlay, + self.entered() + )), + Tui::fixed_y(4, PhraseSelector::next_phrase( + &self.player, + self.focused() == SequencerFocus::PhraseNext, + self.entered() + )), + PhraseListView::from(self) + ])), + PhraseView::from(self) + ])) + ]) + //]) +}); + impl HasClock for SequencerTui { fn clock (&self) -> &ClockModel { &self.clock @@ -70,6 +141,15 @@ pub enum SequencerFocus { PhraseNext, } +impl From<&SequencerTui> for Option { + fn from (state: &SequencerTui) -> Self { + match state.focus.inner() { + SequencerFocus::Transport(focus) => Some(focus), + _ => None + } + } +} + impl_focus!(SequencerTui SequencerFocus [ //&[ //Menu, @@ -209,3 +289,73 @@ impl From<&SequencerTui> for SequencerStatusBar { } } } + +render!(|self: SequencerStatusBar|{ + + lay!(|add|if self.width > 60 { + add(&row!(![ + SequencerMode::from(self), + SequencerStats::from(self), + ])) + } else if self.width > 0 { + add(&col!(![ + SequencerMode::from(self), + SequencerStats::from(self), + ])) + } else { + Ok(()) + }) + +}); + +struct SequencerMode { + mode: &'static str, + help: &'static [(&'static str, &'static str, &'static str)] +} +impl From<&SequencerStatusBar> for SequencerMode { + fn from (state: &SequencerStatusBar) -> Self { + Self { + mode: state.mode, + help: state.help, + } + } +} +render!(|self:SequencerMode|{ + let orange = Color::Rgb(255,128,0); + let light = Color::Rgb(100,100,100); + let yellow = Color::Rgb(255,255,0); + let black = Color::Rgb(0,0,0); + row!([ + Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))), + Tui::bg(light, row!((prefix, hotkey, suffix) in self.help.iter() => { + row!([" ", prefix, Tui::fg(yellow, *hotkey), suffix]) + })) + ]) +}); + +struct SequencerStats<'a> { + cpu: &'a Option, + size: &'a String, + res: &'a String, +} +impl<'a> From<&'a SequencerStatusBar> for SequencerStats<'a> { + fn from (state: &'a SequencerStatusBar) -> Self { + Self { + cpu: &state.cpu, + size: &state.size, + res: &state.res, + } + } +} +render!(|self:SequencerStats<'a>|{ + let orange = Color::Rgb(255,128,0); + let dark = Color::Rgb(100,100,100); + let cpu = &self.cpu; + let res = &self.res; + let size = &self.size; + Tui::bg(dark, row!([ + Tui::fg(orange, cpu), + Tui::fg(orange, res), + Tui::fg(orange, size), + ])) +}); diff --git a/crates/tek/src/tui/app_transport.rs b/crates/tek/src/tui/app_transport.rs index 0413de2c..e68083e9 100644 --- a/crates/tek/src/tui/app_transport.rs +++ b/crates/tek/src/tui/app_transport.rs @@ -1,23 +1,7 @@ use crate::*; - -/// Stores and displays time-related info. -pub struct TransportTui { - pub jack: Arc>, - pub clock: ClockModel, - pub size: Measure, - pub cursor: (usize, usize), - pub focus: FocusState, -} - -impl std::fmt::Debug for TransportTui { - fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - f.debug_struct("TransportTui") - .field("jack", &self.jack) - .field("size", &self.size) - .field("cursor", &self.cursor) - .finish() - } -} +use crate::api::ClockCommand::{SetBpm, SetQuant, SetSync}; +use TransportCommand::{Focus, Clock}; +use KeyCode::{Enter, Left, Right, Char}; /// Create app state from JACK handle. impl TryFrom<&Arc>> for TransportTui { @@ -33,6 +17,121 @@ impl TryFrom<&Arc>> for TransportTui { } } +/// Stores and displays time-related info. +pub struct TransportTui { + pub jack: Arc>, + pub clock: ClockModel, + pub size: Measure, + pub cursor: (usize, usize), + pub focus: FocusState, +} + +impl JackApi for TransportTui { + fn jack (&self) -> &Arc> { + &self.jack + } +} + +impl Audio for TransportTui { + fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { + ClockAudio(self).process(client, scope) + } +} + +pub struct WorldClock { + rate: String, + sample: String, + second: String, +} + +impl From<&T> for WorldClock { + fn from (state: &T) -> Self { + let clock = state.clock(); + let rate = format!("{}", clock.timebase.sr.get()); + if let Some(started) = clock.started.read().unwrap().as_ref() { + Self { + rate, + sample: format!("{:.0}", started.sample.get()), + second: format!("{:.0}", started.usec.get()), + } + } else { + Self { + rate, + sample: format!("{:.0}", clock.global.sample.get()), + second: format!("{:.0}", clock.global.usec.get()), + } + } + } +} + +render!(|self: WorldClock|row!([ + col!(["Rate", self.rate ]), " ", + col!(["Sample", self.sample]), " ", + col!(["Second", self.second]), " ", +])); + +pub struct PlayClock { + started: bool, + sample: String, + second: String, +} +impl From<&T> for PlayClock { + fn from (state: &T) -> Self { + let clock = state.clock(); + if let Some(started) = clock.started.read().unwrap().as_ref() { + Self { + started: true, + sample: format!("{:.0}", clock.global.sample.get() - started.sample.get()), + second: format!("{:.0}", clock.global.usec.get() - started.usec.get()), + } + } else { + Self { + started: false, + sample: "".to_string(), + second: "".to_string(), + } + } + } +} +render!(|self: PlayClock|lay!(|add|{ + if self.started { + add(&row!([ + col!(["", Tui::fg(Color::Rgb(0, 255, 0), "▶ PLAYING ")]), + " ", + col!(["Sample", self.sample]), + " ", + col!(["Second", self.second]), + " ", + col!(["Beat", "00B 0b 00/00"]), + ])) + } else { + add(&col!([Tui::fg(Color::Rgb(255, 128, 0), "⏹ STOPPED "), ""])) + } +})); + +render!(|self: TransportTui|{ + let bg = TuiTheme::border_bg(); + let border_style = Style::default().bg(bg).fg(TuiTheme::border_fg(false)); + lay!([ + Tui::fill_x(Lozenge(border_style)), + Tui::bg(bg, Tui::outset_xy(1, 1, row!([ + WorldClock::from(self), + " ", + PlayClock::from(self), + ]))) + ])//Tui::to_south(world, timer))) +}); + +impl std::fmt::Debug for TransportTui { + fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { + f.debug_struct("TransportTui") + .field("jack", &self.jack) + .field("size", &self.size) + .field("cursor", &self.cursor) + .finish() + } +} + impl HasClock for TransportTui { fn clock (&self) -> &ClockModel { &self.clock @@ -49,6 +148,12 @@ pub enum TransportFocus { Quant, } +impl From<&TransportTui> for Option { + fn from (state: &TransportTui) -> Self { + Some(state.focus.inner()) + } +} + impl FocusWrap for TransportFocus { fn wrap <'a, W: Render> (self, focus: TransportFocus, content: &'a W) -> impl Render + 'a @@ -95,6 +200,127 @@ impl StatusBar for TransportStatusBar { } } -render!(|self: TransportStatusBar|{ - "todo" -}); +render!(|self: TransportStatusBar|"todo"); + +impl Handle for TransportTui { + fn handle (&mut self, from: &TuiInput) -> Perhaps { + TransportCommand::execute_with_state(self, from) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum TransportCommand { + Focus(FocusCommand), + Clock(ClockCommand), +} + +impl Command for TransportCommand { + fn execute (self, state: &mut T) -> Perhaps { + Ok(match self { + Self::Focus(cmd) => cmd.execute(state)?.map(Self::Focus), + Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock), + }) + } +} + +pub trait TransportControl: HasClock + FocusGrid + HasEnter { + fn transport_focused (&self) -> Option; +} + +impl TransportControl for TransportTui { + fn transport_focused (&self) -> Option { + Some(self.focus.inner()) + } +} + +impl TransportControl for SequencerTui { + fn transport_focused (&self) -> Option { + match self.focus.inner() { + SequencerFocus::Transport(focus) => Some(focus), + _ => None + } + } +} + +impl TransportControl for ArrangerTui { + fn transport_focused (&self) -> Option { + match self.focus.inner() { + ArrangerFocus::Transport(focus) => Some(focus), + _ => None + } + } +} + +impl InputToCommand for TransportCommand { + fn input_to_command (state: &T, input: &TuiInput) -> Option { + to_transport_command(state, input) + .or_else(||to_focus_command(input).map(TransportCommand::Focus)) + } +} + +pub fn to_transport_command (state: &T, input: &TuiInput) -> Option +where + T: TransportControl +{ + Some(match input.event() { + key!(Left) => Focus(FocusCommand::Prev), + key!(Right) => Focus(FocusCommand::Next), + key!(Char(' ')) => Clock(if state.clock().is_stopped() { + ClockCommand::Play(None) + } else { + ClockCommand::Pause(None) + }), + key!(Shift-Char(' ')) => Clock(if state.clock().is_stopped() { + ClockCommand::Play(Some(0)) + } else { + ClockCommand::Pause(Some(0)) + }), + _ => match state.transport_focused().unwrap() { + TransportFocus::Bpm => match input.event() { + key!(Char(',')) => Clock(SetBpm(state.clock().bpm().get() - 1.0)), + key!(Char('.')) => Clock(SetBpm(state.clock().bpm().get() + 1.0)), + key!(Char('<')) => Clock(SetBpm(state.clock().bpm().get() - 0.001)), + key!(Char('>')) => Clock(SetBpm(state.clock().bpm().get() + 0.001)), + _ => return None, + }, + TransportFocus::Quant => match input.event() { + key!(Char(',')) => Clock(SetQuant(state.clock().quant.prev())), + key!(Char('.')) => Clock(SetQuant(state.clock().quant.next())), + key!(Char('<')) => Clock(SetQuant(state.clock().quant.prev())), + key!(Char('>')) => Clock(SetQuant(state.clock().quant.next())), + _ => return None, + }, + TransportFocus::Sync => match input.event() { + key!(Char(',')) => Clock(SetSync(state.clock().sync.prev())), + key!(Char('.')) => Clock(SetSync(state.clock().sync.next())), + key!(Char('<')) => Clock(SetSync(state.clock().sync.prev())), + key!(Char('>')) => Clock(SetSync(state.clock().sync.next())), + _ => return None, + }, + TransportFocus::Clock => match input.event() { + key!(Char(',')) => todo!("transport seek bar"), + key!(Char('.')) => todo!("transport seek bar"), + key!(Char('<')) => todo!("transport seek beat"), + key!(Char('>')) => todo!("transport seek beat"), + _ => return None, + }, + TransportFocus::PlayPause => match input.event() { + key!(Enter) => Clock( + if state.clock().is_stopped() { + ClockCommand::Play(None) + } else { + ClockCommand::Pause(None) + } + ), + key!(Shift-Enter) => Clock( + if state.clock().is_stopped() { + ClockCommand::Play(Some(0)) + } else { + ClockCommand::Pause(Some(0)) + } + ), + _ => return None, + }, + } + }) +} diff --git a/crates/tek/src/tui/ctrl_sequencer.rs b/crates/tek/src/tui/ctrl_sequencer.rs index 5c6c3837..b9b13259 100644 --- a/crates/tek/src/tui/ctrl_sequencer.rs +++ b/crates/tek/src/tui/ctrl_sequencer.rs @@ -2,6 +2,7 @@ use crate::{*, api::ClockCommand::{Play, Pause}}; use super::ctrl_phrase_editor::PhraseCommand::Show; use KeyCode::{Char, Enter}; use SequencerCommand::*; +use super::app_transport::TransportCommand; impl Handle for SequencerTui { fn handle (&mut self, i: &TuiInput) -> Perhaps { diff --git a/crates/tek/src/tui/ctrl_transport.rs b/crates/tek/src/tui/ctrl_transport.rs index 97eaf9a0..e69de29b 100644 --- a/crates/tek/src/tui/ctrl_transport.rs +++ b/crates/tek/src/tui/ctrl_transport.rs @@ -1,127 +0,0 @@ -use crate::*; -use crate::api::ClockCommand::{SetBpm, SetQuant, SetSync}; -use TransportCommand::{Focus, Clock}; -use KeyCode::{Enter, Left, Right, Char}; - -impl Handle for TransportTui { - fn handle (&mut self, from: &TuiInput) -> Perhaps { - TransportCommand::execute_with_state(self, from) - } -} - -#[derive(Clone, Debug, PartialEq)] -pub enum TransportCommand { - Focus(FocusCommand), - Clock(ClockCommand), -} - -impl Command for TransportCommand { - fn execute (self, state: &mut T) -> Perhaps { - Ok(match self { - Self::Focus(cmd) => cmd.execute(state)?.map(Self::Focus), - Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock), - }) - } -} - -pub trait TransportControl: HasClock + FocusGrid + HasEnter { - fn transport_focused (&self) -> Option; -} - -impl TransportControl for TransportTui { - fn transport_focused (&self) -> Option { - Some(self.focus.inner()) - } -} - -impl TransportControl for SequencerTui { - fn transport_focused (&self) -> Option { - match self.focus.inner() { - SequencerFocus::Transport(focus) => Some(focus), - _ => None - } - } -} - -impl TransportControl for ArrangerTui { - fn transport_focused (&self) -> Option { - match self.focus.inner() { - ArrangerFocus::Transport(focus) => Some(focus), - _ => None - } - } -} - -impl InputToCommand for TransportCommand { - fn input_to_command (state: &T, input: &TuiInput) -> Option { - to_transport_command(state, input) - .or_else(||to_focus_command(input).map(TransportCommand::Focus)) - } -} - -pub fn to_transport_command (state: &T, input: &TuiInput) -> Option -where - T: TransportControl -{ - Some(match input.event() { - key!(Left) => Focus(FocusCommand::Prev), - key!(Right) => Focus(FocusCommand::Next), - key!(Char(' ')) => Clock(if state.clock().is_stopped() { - ClockCommand::Play(None) - } else { - ClockCommand::Pause(None) - }), - key!(Shift-Char(' ')) => Clock(if state.clock().is_stopped() { - ClockCommand::Play(Some(0)) - } else { - ClockCommand::Pause(Some(0)) - }), - _ => match state.transport_focused().unwrap() { - TransportFocus::Bpm => match input.event() { - key!(Char(',')) => Clock(SetBpm(state.clock().bpm().get() - 1.0)), - key!(Char('.')) => Clock(SetBpm(state.clock().bpm().get() + 1.0)), - key!(Char('<')) => Clock(SetBpm(state.clock().bpm().get() - 0.001)), - key!(Char('>')) => Clock(SetBpm(state.clock().bpm().get() + 0.001)), - _ => return None, - }, - TransportFocus::Quant => match input.event() { - key!(Char(',')) => Clock(SetQuant(state.clock().quant.prev())), - key!(Char('.')) => Clock(SetQuant(state.clock().quant.next())), - key!(Char('<')) => Clock(SetQuant(state.clock().quant.prev())), - key!(Char('>')) => Clock(SetQuant(state.clock().quant.next())), - _ => return None, - }, - TransportFocus::Sync => match input.event() { - key!(Char(',')) => Clock(SetSync(state.clock().sync.prev())), - key!(Char('.')) => Clock(SetSync(state.clock().sync.next())), - key!(Char('<')) => Clock(SetSync(state.clock().sync.prev())), - key!(Char('>')) => Clock(SetSync(state.clock().sync.next())), - _ => return None, - }, - TransportFocus::Clock => match input.event() { - key!(Char(',')) => todo!("transport seek bar"), - key!(Char('.')) => todo!("transport seek bar"), - key!(Char('<')) => todo!("transport seek beat"), - key!(Char('>')) => todo!("transport seek beat"), - _ => return None, - }, - TransportFocus::PlayPause => match input.event() { - key!(Enter) => Clock( - if state.clock().is_stopped() { - ClockCommand::Play(None) - } else { - ClockCommand::Pause(None) - } - ), - key!(Shift-Enter) => Clock( - if state.clock().is_stopped() { - ClockCommand::Play(Some(0)) - } else { - ClockCommand::Pause(Some(0)) - } - ), - _ => return None, - }, - } - }) -} diff --git a/crates/tek/src/tui/engine_style.rs b/crates/tek/src/tui/engine_style.rs index bbc04e39..007509ff 100644 --- a/crates/tek/src/tui/engine_style.rs +++ b/crates/tek/src/tui/engine_style.rs @@ -18,28 +18,43 @@ impl Tui { pub struct Bold>(pub bool, W); impl> Render for Bold { - fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { Ok(Some([0,0])) } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { Ok(to.fill_bold(to.area(), self.0)) } + fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + self.1.min_size(to) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + to.fill_bold(to.area(), self.0); + self.1.render(to) + } } pub struct Foreground>(pub Color, W); impl> Render for Foreground { - fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { Ok(Some([0,0])) } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { Ok(to.fill_fg(to.area(), self.0)) } + fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + self.1.min_size(to) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + to.fill_fg(to.area(), self.0); + self.1.render(to) + } } pub struct Background>(pub Color, W); impl> Render for Background { - fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { Ok(Some([0,0])) } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { Ok(to.fill_bg(to.area(), self.0)) } + fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> { + self.1.min_size(to) + } + fn render (&self, to: &mut TuiOutput) -> Usually<()> { + to.fill_bg(to.area(), self.0); + self.1.render(to) + } } pub struct Bordered>(pub S, pub W); render!(|self: Bordered>|{ - Tui::fill_xy(Tui::under(Tui::inset_xy(1, 1, widget(&self.1)), Border(self.0))) + Tui::fill_xy(lay!([Border(self.0), Tui::inset_xy(1, 1, widget(&self.1))])) }); pub struct Border(pub S); diff --git a/crates/tek/src/tui/jack_arranger.rs b/crates/tek/src/tui/jack_arranger.rs deleted file mode 100644 index 1bc9765c..00000000 --- a/crates/tek/src/tui/jack_arranger.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::{*, tui::ArrangerTui}; - -impl JackApi for ArrangerTui { - fn jack (&self) -> &Arc> { - &self.jack - } -} - -impl Audio for ArrangerTui { - #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - // Start profiling cycle - let t0 = self.perf.get_t0(); - - // Update transport clock - if ClockAudio(self).process(client, scope) == Control::Quit { - return Control::Quit - } - - // Update MIDI sequencers - if TracksAudio( - &mut self.tracks, - &mut self.note_buf, - &mut self.midi_buf, - Default::default(), - ).process(client, scope) == Control::Quit { - return Control::Quit - } - - // FIXME: one of these per playing track - //self.now.set(0.); - //if let ArrangerSelection::Clip(t, s) = self.selected { - //let phrase = self.scenes().get(s).map(|scene|scene.clips.get(t)); - //if let Some(Some(Some(phrase))) = phrase { - //if let Some(track) = self.tracks().get(t) { - //if let Some((ref started_at, Some(ref playing))) = track.player.play_phrase { - //let phrase = phrase.read().unwrap(); - //if *playing.read().unwrap() == *phrase { - //let pulse = self.current().pulse.get(); - //let start = started_at.pulse.get(); - //let now = (pulse - start) % phrase.length as f64; - //self.now.set(now); - //} - //} - //} - //} - //} - - // End profiling cycle - self.perf.update(t0, scope); - - return Control::Continue - } -} diff --git a/crates/tek/src/tui/jack_sequencer.rs b/crates/tek/src/tui/jack_sequencer.rs deleted file mode 100644 index bfc7438f..00000000 --- a/crates/tek/src/tui/jack_sequencer.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::{*, tui::SequencerTui}; - -impl JackApi for SequencerTui { - fn jack (&self) -> &Arc> { - &self.jack - } -} - -impl Audio for SequencerTui { - fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - // Start profiling cycle - let t0 = self.perf.get_t0(); - - // Update transport clock - if ClockAudio(self).process(client, scope) == Control::Quit { - return Control::Quit - } - - // Update MIDI sequencer - if PlayerAudio( - &mut self.player, - &mut self.note_buf, - &mut self.midi_buf, - ).process(client, scope) == Control::Quit { - return Control::Quit - } - - // Update sequencer playhead indicator - //self.now().set(0.); - //if let Some((ref started_at, Some(ref playing))) = self.player.play_phrase { - //let phrase = phrase.read().unwrap(); - //if *playing.read().unwrap() == *phrase { - //let pulse = self.current().pulse.get(); - //let start = started_at.pulse.get(); - //let now = (pulse - start) % phrase.length as f64; - //self.now().set(now); - //} - //} - - // End profiling cycle - self.perf.update(t0, scope); - - Control::Continue - } -} diff --git a/crates/tek/src/tui/jack_transport.rs b/crates/tek/src/tui/jack_transport.rs deleted file mode 100644 index ec9843cd..00000000 --- a/crates/tek/src/tui/jack_transport.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::*; - -impl JackApi for TransportTui { - fn jack (&self) -> &Arc> { - &self.jack - } -} - -impl Audio for TransportTui { - fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - ClockAudio(self).process(client, scope) - } -} diff --git a/crates/tek/src/tui/model_clock.rs b/crates/tek/src/tui/model_clock.rs deleted file mode 100644 index c7b7e813..00000000 --- a/crates/tek/src/tui/model_clock.rs +++ /dev/null @@ -1 +0,0 @@ -use crate::*; diff --git a/crates/tek/src/tui/view_arranger.rs b/crates/tek/src/tui/view_arranger.rs deleted file mode 100644 index 84614847..00000000 --- a/crates/tek/src/tui/view_arranger.rs +++ /dev/null @@ -1,561 +0,0 @@ -use crate::*; - -// Layout for standalone arranger app. -render!(|self: ArrangerTui|{ - let arranger_focused = self.arranger_focused(); - let border = Lozenge(Style::default().bg(TuiTheme::border_bg()).fg(TuiTheme::border_fg(arranger_focused))); - col_up!([ - TransportView::from(self), - col!([ - Tui::fixed_y(self.splits[0], lay!([ - border.wrap(Tui::grow_y(1, Layers::new(move |add|{ - match self.mode { - ArrangerMode::Horizontal => - add(&arranger_content_horizontal(self))?, - ArrangerMode::Vertical(factor) => - add(&arranger_content_vertical(self, factor))? - }; - add(&self.size) - }))), - self.size, - Tui::push_x(1, Tui::fg( - TuiTheme::title_fg(arranger_focused), - format!("[{}] Arranger", if self.entered { - "■" - } else { - " " - }) - )) - ])), - Split::right( - self.splits[1], - PhraseListView::from(self), - PhraseView::from(self), - ) - ]) - ]) -}); - -/// Display mode of arranger -#[derive(Clone, PartialEq)] -pub enum ArrangerMode { - /// Tracks are rows - Horizontal, - /// Tracks are columns - Vertical(usize), -} - -/// Arranger display mode can be cycled -impl ArrangerMode { - /// Cycle arranger display mode - pub fn to_next (&mut self) { - *self = match self { - Self::Horizontal => Self::Vertical(1), - Self::Vertical(1) => Self::Vertical(2), - Self::Vertical(2) => Self::Vertical(2), - Self::Vertical(0) => Self::Horizontal, - Self::Vertical(_) => Self::Vertical(0), - } - } -} - -pub trait ArrangerViewState { - fn arranger_focused (&self) -> bool; -} -impl ArrangerViewState for ArrangerTui { - fn arranger_focused (&self) -> bool { - self.focused() == ArrangerFocus::Arranger - } -} - -fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> { - let mut widths = vec![]; - let mut total = 0; - for track in tracks.iter() { - let width = track.width; - widths.push((width, total)); - total += width; - } - widths.push((0, total)); - widths -} - -fn any_size (_: E::Size) -> Perhaps{ - Ok(Some([0.into(),0.into()].into())) -} - -fn custom_render Usually<()>+Send+Sync> (render: F) -> impl Render { - Widget::new(|_|Ok(Some([0u16,0u16].into())), render) -} - -pub fn arranger_content_vertical ( - view: &ArrangerTui, - factor: usize -) -> impl Render + use<'_> { - lay!([ - Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(TuiTheme::title_fg(view.arranger_focused()), - format!("{}x{}", view.size.w(), view.size.h())) - ))), - Tui::bg(view.color.rgb, lay!(![ - ArrangerVerticalColumnSeparator::from(view), - ArrangerVerticalRowSeparator::from((view, factor)), - col!(![ - ArrangerVerticalHeader::from(view), - ArrangerVerticalContent::from((view, factor)), - ]), - ArrangerVerticalCursor::from((view, factor)), - ])), - ]) -} - -struct ArrangerVerticalColumnSeparator { - cols: Vec<(usize, usize)>, - scenes_w: u16, - sep_fg: Color, -} -impl From<&ArrangerTui> for ArrangerVerticalColumnSeparator { - fn from (state: &ArrangerTui) -> Self { - Self { - cols: track_widths(state.tracks()), - scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, - sep_fg: TuiTheme::separator_fg(false), - } - } -} -render!(|self: ArrangerVerticalColumnSeparator|custom_render(move|to: &mut TuiOutput|{ - let style = Some(Style::default().fg(self.sep_fg)); - Ok(for x in self.cols.iter().map(|col|col.1) { - let x = self.scenes_w + to.area().x() + x as u16; - for y in to.area().y()..to.area().y2() { - to.blit(&"▎", x, y, style); - } - }) -})); - -struct ArrangerVerticalRowSeparator { - rows: Vec<(usize, usize)>, - sep_fg: Color, -} -impl From<(&ArrangerTui, usize)> for ArrangerVerticalRowSeparator { - fn from ((state, factor): (&ArrangerTui, usize)) -> Self { - Self { - rows: ArrangerScene::ppqs(state.scenes(), factor), - sep_fg: TuiTheme::separator_fg(false), - } - } -} - -render!(|self: ArrangerVerticalRowSeparator|custom_render(move|to: &mut TuiOutput|{ - Ok(for y in self.rows.iter().map(|row|row.1) { - let y = to.area().y() + (y / PPQ) as u16 + 1; - if y >= to.buffer.area.height { break } - for x in to.area().x()..to.area().x2().saturating_sub(2) { - if x < to.buffer.area.x && y < to.buffer.area.y { - let cell = to.buffer.get_mut(x, y); - cell.modifier = Modifier::UNDERLINED; - cell.underline_color = self.sep_fg; - } - } - }) -})); - -struct ArrangerVerticalCursor { - cols: Vec<(usize, usize)>, - rows: Vec<(usize, usize)>, - focused: bool, - selected: ArrangerSelection, - scenes_w: u16, - header_h: u16, -} -impl From<(&ArrangerTui, usize)> for ArrangerVerticalCursor { - fn from ((state, factor): (&ArrangerTui, usize)) -> Self { - Self { - cols: track_widths(state.tracks()), - rows: ArrangerScene::ppqs(state.scenes(), factor), - focused: state.arranger_focused(), - selected: state.selected, - scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, - header_h: 3, - } - } -} -render!(|self: ArrangerVerticalCursor|custom_render(move|to: &mut TuiOutput|{ - let area = to.area(); - let focused = self.focused; - let selected = self.selected; - let get_track_area = |t: usize| [ - self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(), - self.cols[t].0 as u16, area.h(), - ]; - let get_scene_area = |s: usize| [ - area.x(), self.header_h + area.y() + (self.rows[s].1 / PPQ) as u16, - area.w(), (self.rows[s].0 / PPQ) as u16 - ]; - let get_clip_area = |t: usize, s: usize| [ - self.scenes_w + area.x() + self.cols[t].1 as u16, - self.header_h + area.y() + (self.rows[s].1/PPQ) as u16, - self.cols[t].0 as u16, - (self.rows[s].0 / PPQ) as u16 - ]; - let mut track_area: Option<[u16;4]> = None; - let mut scene_area: Option<[u16;4]> = None; - let mut clip_area: Option<[u16;4]> = None; - let area = match selected { - ArrangerSelection::Mix => area, - ArrangerSelection::Track(t) => { - track_area = Some(get_track_area(t)); - area - }, - ArrangerSelection::Scene(s) => { - scene_area = Some(get_scene_area(s)); - area - }, - ArrangerSelection::Clip(t, s) => { - track_area = Some(get_track_area(t)); - scene_area = Some(get_scene_area(s)); - clip_area = Some(get_clip_area(t, s)); - area - }, - }; - let bg = TuiTheme::border_bg(); - if let Some([x, y, width, height]) = track_area { - to.fill_fg([x, y, 1, height], bg); - to.fill_fg([x + width, y, 1, height], bg); - } - if let Some([_, y, _, height]) = scene_area { - to.fill_ul([area.x(), y - 1, area.w(), 1], bg); - to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg); - } - Ok(if focused { - to.render_in(if let Some(clip_area) = clip_area { clip_area } - else if let Some(track_area) = track_area { track_area.clip_h(self.header_h) } - else if let Some(scene_area) = scene_area { scene_area.clip_w(self.scenes_w) } - else { area.clip_w(self.scenes_w).clip_h(self.header_h) }, &CORNERS)? - }) -})); - -struct ArrangerVerticalHeader<'a> { - tracks: &'a Vec, - cols: Vec<(usize, usize)>, - focused: bool, - selected: ArrangerSelection, - scenes_w: u16, - header_h: u16, - timebase: &'a Arc, - current: &'a Arc, -} -impl<'a> From<&'a ArrangerTui> for ArrangerVerticalHeader<'a> { - fn from (state: &'a ArrangerTui) -> Self { - Self { - tracks: &state.tracks, - cols: track_widths(state.tracks()), - focused: state.arranger_focused(), - selected: state.selected, - scenes_w: 3 + ArrangerScene::longest_name(state.scenes()) as u16, - header_h: 3, - timebase: state.clock().timebase(), - current: &state.clock().playhead, - } - } -} -render!(|self: ArrangerVerticalHeader<'a>|row!( - (track, w) in self.tracks.iter().zip(self.cols.iter().map(|col|col.0)) => { - // name and width of track - let name = track.name().read().unwrap(); - let max_w = w.saturating_sub(1).min(name.len()).max(2); - let name = format!("▎{}", &name[0..max_w]); - let name = Tui::bold(true, name); - // beats elapsed - let elapsed = if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() { - let length = phrase.read().unwrap().length; - let elapsed = track.player.pulses_since_start().unwrap(); - let elapsed = self.timebase.format_beats_1_short( - (elapsed as usize % length) as f64 - ); - format!("▎+{elapsed:>}") - } else { - String::from("▎") - }; - // beats until switchover - let until_next = track.player.next_phrase().as_ref().map(|(t, _)|{ - let target = t.pulse.get(); - let current = self.current.pulse.get(); - if target > current { - let remaining = target - current; - format!("▎-{:>}", self.timebase.format_beats_0_short(remaining)) - } else { - String::new() - } - }).unwrap_or(String::from("▎")); - let timer = Tui::to_south(until_next, elapsed); - // name of active MIDI input - let _input = format!("▎>{}", track.player.midi_ins().get(0) - .map(|port|port.short_name()) - .transpose()? - .unwrap_or("(none)".into())); - // name of active MIDI output - let _output = format!("▎<{}", track.player.midi_outs().get(0) - .map(|port|port.short_name()) - .transpose()? - .unwrap_or("(none)".into())); - Tui::push_x(self.scenes_w, - Tui::bg(track.color().rgb, - Tui::min_xy(w as u16, self.header_h, - Tui::to_south(name, timer)))) - } -)); - -struct ArrangerVerticalContent<'a> { - size: &'a Measure, - scenes: &'a Vec, - tracks: &'a Vec, - rows: Vec<(usize, usize)>, - cols: Vec<(usize, usize)>, - header_h: u16, -} -impl<'a> From<(&'a ArrangerTui, usize)> for ArrangerVerticalContent<'a> { - fn from ((state, factor): (&'a ArrangerTui, usize)) -> Self { - Self { - size: &state.size, - scenes: &state.scenes, - tracks: &state.tracks, - rows: ArrangerScene::ppqs(state.scenes(), factor), - cols: track_widths(state.tracks()), - header_h: 3, - } - } -} -render!(|self: ArrangerVerticalContent<'a>|Tui::fixed_y( - (self.size.h() as u16).saturating_sub(self.header_h), - col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => { - let height = 1.max((pulses / PPQ) as u16); - let playing = scene.is_playing(self.tracks); - Tui::fixed_y( - height, - Tui::to_east( - Tui::to_east( - if playing { "▶ " } else { " " }, - Tui::bold(true, scene.name.read().unwrap().as_str()) - ), - row!((track, w) in self.cols.iter().map(|col|col.0).enumerate() => { - Tui::fixed_xy(w as u16, height, Layers::new(move |add|{ - let mut bg = TuiTheme::border_bg(); - match (self.tracks.get(track), scene.clips.get(track)) { - (Some(track), Some(Some(phrase))) => { - let name = &(phrase as &Arc>).read().unwrap().name; - let name = format!("{}", name); - let max_w = name.len().min((w as usize).saturating_sub(2)); - let color = phrase.read().unwrap().color; - bg = color.dark.rgb; - if let Some((_, Some(ref playing))) = track.player.play_phrase() { - if *playing.read().unwrap() == *phrase.read().unwrap() { - bg = color.light.rgb - } - }; - add(&Tui::fixed_x(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?; - }, - _ => {} - }; - //add(&Background(bg)) - Ok(()) - })) - }) - ) - ) - }) -)); - -pub fn arranger_content_horizontal ( - view: &ArrangerTui, -) -> impl Render + use<'_> { - todo!() -} - //let focused = view.arranger_focused(); - //let _tracks = view.tracks(); - //lay!( - //focused.then_some(Background(TuiTheme::border_bg())), - //row!( - //// name - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks, selected) = self; - ////let yellow = Some(Style::default().yellow().bold().not_dim()); - ////let white = Some(Style::default().white().bold().not_dim()); - ////let area = to.area(); - ////let area = [area.x(), area.y(), 3 + 5.max(track_name_max_len(tracks)) as u16, area.h()]; - ////let offset = 0; // track scroll offset - ////for y in 0..area.h() { - ////if y == 0 { - ////to.blit(&"Mixer", area.x() + 1, area.y() + y, Some(DIM))?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2 + offset; - ////if let Some(track) = tracks.get(index) { - ////let selected = selected.track() == Some(index); - ////let style = if selected { yellow } else { white }; - ////to.blit(&format!(" {index:>02} "), area.x(), area.y() + y, style)?; - ////to.blit(&*track.name.read().unwrap(), area.x() + 4, area.y() + y, style)?; - ////} - ////} - ////} - ////Ok(Some(area)) - //}), - //// monitor - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks) = self; - ////let mut area = to.area(); - ////let on = Some(Style::default().not_dim().green().bold()); - ////let off = Some(DIM); - ////area.x += 1; - ////for y in 0..area.h() { - ////if y == 0 { - //////" MON ".blit(to.buffer, area.x, area.y + y, style2)?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2; - ////if let Some(track) = tracks.get(index) { - ////let style = if track.monitoring { on } else { off }; - ////to.blit(&" MON ", area.x(), area.y() + y, style)?; - ////} else { - ////area.height = y; - ////break - ////} - ////} - ////} - ////area.width = 4; - ////Ok(Some(area)) - //}), - //// record - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks) = self; - ////let mut area = to.area(); - ////let on = Some(Style::default().not_dim().red().bold()); - ////let off = Some(Style::default().dim()); - ////area.x += 1; - ////for y in 0..area.h() { - ////if y == 0 { - //////" REC ".blit(to.buffer, area.x, area.y + y, style2)?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2; - ////if let Some(track) = tracks.get(index) { - ////let style = if track.recording { on } else { off }; - ////to.blit(&" REC ", area.x(), area.y() + y, style)?; - ////} else { - ////area.height = y; - ////break - ////} - ////} - ////} - ////area.width = 4; - ////Ok(Some(area)) - //}), - //// overdub - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks) = self; - ////let mut area = to.area(); - ////let on = Some(Style::default().not_dim().yellow().bold()); - ////let off = Some(Style::default().dim()); - ////area.x = area.x + 1; - ////for y in 0..area.h() { - ////if y == 0 { - //////" OVR ".blit(to.buffer, area.x, area.y + y, style2)?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2; - ////if let Some(track) = tracks.get(index) { - ////to.blit(&" OVR ", area.x(), area.y() + y, if track.overdub { - ////on - ////} else { - ////off - ////})?; - ////} else { - ////area.height = y; - ////break - ////} - ////} - ////} - ////area.width = 4; - ////Ok(Some(area)) - //}), - //// erase - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks) = self; - ////let mut area = to.area(); - ////let off = Some(Style::default().dim()); - ////area.x = area.x + 1; - ////for y in 0..area.h() { - ////if y == 0 { - //////" DEL ".blit(to.buffer, area.x, area.y + y, style2)?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2; - ////if let Some(_) = tracks.get(index) { - ////to.blit(&" DEL ", area.x(), area.y() + y, off)?; - ////} else { - ////area.height = y; - ////break - ////} - ////} - ////} - ////area.width = 4; - ////Ok(Some(area)) - //}), - //// gain - //Widget::new(|_|{todo!()}, |_: &mut TuiOutput|{ - //todo!() - ////let Self(tracks) = self; - ////let mut area = to.area(); - ////let off = Some(Style::default().dim()); - ////area.x = area.x() + 1; - ////for y in 0..area.h() { - ////if y == 0 { - //////" GAIN ".blit(to.buffer, area.x, area.y + y, style2)?; - ////} else if y % 2 == 0 { - ////let index = (y as usize - 2) / 2; - ////if let Some(_) = tracks.get(index) { - ////to.blit(&" +0.0 ", area.x(), area.y() + y, off)?; - ////} else { - ////area.height = y; - ////break - ////} - ////} - ////} - ////area.width = 7; - ////Ok(Some(area)) - //}), - //// scenes - //Widget::new(|_|{todo!()}, |to: &mut TuiOutput|{ - //let [x, y, _, height] = to.area(); - //let mut x2 = 0; - //Ok(for (scene_index, scene) in view.scenes().iter().enumerate() { - //let active_scene = view.selected.scene() == Some(scene_index); - //let sep = Some(if active_scene { - //Style::default().yellow().not_dim() - //} else { - //Style::default().dim() - //}); - //for y in y+1..y+height { - //to.blit(&"│", x + x2, y, sep); - //} - //let name = scene.name.read().unwrap(); - //let mut x3 = name.len() as u16; - //to.blit(&*name, x + x2, y, sep); - //for (i, clip) in scene.clips.iter().enumerate() { - //let active_track = view.selected.track() == Some(i); - //if let Some(clip) = clip { - //let y2 = y + 2 + i as u16 * 2; - //let label = format!("{}", clip.read().unwrap().name); - //to.blit(&label, x + x2, y2, Some(if active_track && active_scene { - //Style::default().not_dim().yellow().bold() - //} else { - //Style::default().not_dim() - //})); - //x3 = x3.max(label.len() as u16) - //} - //} - //x2 = x2 + x3 + 1; - //}) - //}), - //) - //) -//} diff --git a/crates/tek/src/tui/view_phrase_list.rs b/crates/tek/src/tui/view_phrase_list.rs index a69d6ab9..02a6c9ad 100644 --- a/crates/tek/src/tui/view_phrase_list.rs +++ b/crates/tek/src/tui/view_phrase_list.rs @@ -58,7 +58,7 @@ render!(|self: PhraseListView<'a>|{ } }; let row2 = Tui::bold(true, row2); - add(&Tui::bg(color.base.rgb, Tui::fill_x(Tui::to_south(row1, row2))))?; + add(&Tui::bg(color.base.rgb, Tui::fill_x(col!([row1, row2]))))?; if *entered && i == *index { add(&CORNERS)?; } diff --git a/crates/tek/src/tui/view_sequencer.rs b/crates/tek/src/tui/view_sequencer.rs deleted file mode 100644 index 3c3488d5..00000000 --- a/crates/tek/src/tui/view_sequencer.rs +++ /dev/null @@ -1,100 +0,0 @@ - //])) -use crate::*; - -render!(|self: SequencerTui|{ - Tui::to_north( - SequencerStatusBar::from(self), - Tui::to_south( - TransportView::from(self), - Tui::min_y( - 20, - Tui::to_east( - Tui::min_x(20, col!([ - Tui::fixed_y(4, PhraseSelector::play_phrase( - &self.player, - self.focused() == SequencerFocus::PhrasePlay, - self.entered() - )), - Tui::fixed_y(4, PhraseSelector::next_phrase( - &self.player, - self.focused() == SequencerFocus::PhraseNext, - self.entered() - )), - PhraseListView::from(self) - ])), - PhraseView::from(self) - ) - ) - ) - ) -}); - -render!(|self: SequencerStatusBar|{ - - lay!(|add|if self.width > 60 { - add(&row!(![ - SequencerMode::from(self), - SequencerStats::from(self), - ])) - } else if self.width > 0 { - add(&col!(![ - SequencerMode::from(self), - SequencerStats::from(self), - ])) - } else { - Ok(()) - }) - -}); - -struct SequencerMode { - mode: &'static str, - help: &'static [(&'static str, &'static str, &'static str)] -} -impl From<&SequencerStatusBar> for SequencerMode { - fn from (state: &SequencerStatusBar) -> Self { - Self { - mode: state.mode, - help: state.help, - } - } -} -render!(|self:SequencerMode|{ - let orange = Color::Rgb(255,128,0); - let light = Color::Rgb(100,100,100); - let yellow = Color::Rgb(255,255,0); - let black = Color::Rgb(0,0,0); - Tui::to_east( - Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))), - Tui::bg(light, row!((prefix, hotkey, suffix) in self.help.iter() => { - row!([" ", prefix, Tui::fg(yellow, *hotkey), suffix]) - })) - ) -}); - -struct SequencerStats<'a> { - cpu: &'a Option, - size: &'a String, - res: &'a String, -} -impl<'a> From<&'a SequencerStatusBar> for SequencerStats<'a> { - fn from (state: &'a SequencerStatusBar) -> Self { - Self { - cpu: &state.cpu, - size: &state.size, - res: &state.res, - } - } -} -render!(|self:SequencerStats<'a>|{ - let orange = Color::Rgb(255,128,0); - let dark = Color::Rgb(100,100,100); - let cpu = &self.cpu; - let res = &self.res; - let size = &self.size; - Tui::bg(dark, row!([ - Tui::fg(orange, cpu), - Tui::fg(orange, res), - Tui::fg(orange, size), - ])) -}); diff --git a/crates/tek/src/tui/view_transport.rs b/crates/tek/src/tui/view_transport.rs deleted file mode 100644 index babdbcf0..00000000 --- a/crates/tek/src/tui/view_transport.rs +++ /dev/null @@ -1,155 +0,0 @@ -use crate::{*, tui::TransportTui}; - -impl Render for TransportTui { - fn min_size (&self, to: [u16;2]) -> Perhaps<[u16;2]> { - TransportView::from(self).min_size(to) - } - fn render (&self, to: &mut TuiOutput) -> Usually<()> { - TransportView::from(self).render(to) - } -} - -pub struct TransportView { - pub(crate) state: Option, - pub(crate) selected: Option, - pub(crate) focused: bool, - pub(crate) bpm: f64, - pub(crate) sync: f64, - pub(crate) quant: f64, - pub(crate) beat: String, - pub(crate) msu: String, -} - -render!(|self: TransportView|{ - let Self { state, .. } = self;// selected, focused, bpm, sync, quant, beat, msu, } = self; - let world = Tui::to_east("│World ", Tui::to_east(format!("│0 (0)"), //sample(chunk) - Tui::to_east(format!("│00m00s000u"), /*msu*/ format!("│00B 0b 00/00"), /*bbt*/))); - let timer = Tui::either( - *state == Some(TransportState::Rolling), - Tui::to_south( - Tui::to_east("│", - Tui::to_east(Tui::fg(Color::Rgb(0, 255, 0), "▶ PLAYING"), - Tui::to_east("│0 (0)", - Tui::to_east("│00m00s000u", "│00B 0b 00/00")))), - - Tui::to_east("│Now ", - Tui::to_east("│0 (0)", - Tui::to_east("│00m00s000u", "│00B 0b 00/00"))) - ), - Tui::to_south( - Tui::to_east("│", Tui::fg(Color::Rgb(255, 128, 0), "⏹ STOPPED")), - "" - ) - ); - Tui::bg(Color::Rgb(40, 50, 30), Tui::fill_x(Tui::to_south(world, timer))) -}); - //)?; - //match *state { - //Some(TransportState::Rolling) => { - //add(&row!( - //"│", - //TuiStyle::fg("▶ PLAYING", Color::Rgb(0, 255, 0)), - //format!("│0 (0)"), - //format!("│00m00s000u"), - //format!("│00B 0b 00/00") - //))?; - //add(&row!("│Now ", row!( - //format!("│0 (0)"), //sample(chunk) - //format!("│00m00s000u"), //msu - //format!("│00B 0b 00/00"), //bbt - //)))?; - //}, - //_ => { - //add(&row!("│", TuiStyle::fg("⏹ STOPPED", Color::Rgb(255, 128, 0))))?; - //add(&"")?; - //} - //} - //Ok(()) - //}).fill_x().bg(Color::Rgb(40, 50, 30)) -//}); - -impl<'a, T: HasClock> From<&'a T> for TransportView where Option: From<&'a T> { - fn from (state: &'a T) -> Self { - let selected = state.into(); - Self { - selected, - focused: selected.is_some(), - state: Some(state.clock().transport.query_state().unwrap()), - bpm: state.clock().bpm().get(), - sync: state.clock().sync.get(), - quant: state.clock().quant.get(), - beat: state.clock().playhead.format_beat(), - msu: state.clock().playhead.usec.format_msu(), - } - } -} - -impl From<&TransportTui> for Option { - fn from (state: &TransportTui) -> Self { - Some(state.focus.inner()) - } -} - -impl From<&SequencerTui> for Option { - fn from (state: &SequencerTui) -> Self { - match state.focus.inner() { - SequencerFocus::Transport(focus) => Some(focus), - _ => None - } - } -} - -impl From<&ArrangerTui> for Option { - fn from (state: &ArrangerTui) -> Self { - match state.focus.inner() { - ArrangerFocus::Transport(focus) => Some(focus), - _ => None - } - } -} - -struct Field(&'static str, String); - -render!(|self: Field|{ - Tui::to_east("│", Tui::to_east( - Tui::bold(true, self.0), - Tui::bg(Color::Rgb(0, 0, 0), self.1.as_str()), - )) -}); - - //row!( - ////selected.wrap(TransportFocus::PlayPause, &play_pause.fixed_xy(10, 3)), - //row!( - //col!( - //Field("SR ", format!("192000")), - //Field("BUF ", format!("1024")), - //Field("LEN ", format!("21300")), - //Field("CPU ", format!("00.0%")) - //), - //col!( - //Field("PUL ", format!("000000000")), - //Field("PPQ ", format!("96")), - //Field("BBT ", format!("00B0b00p")) - //), - //col!( - //Field("SEC ", format!("000000.000")), - //Field("BPM ", format!("000.000")), - //Field("MSU ", format!("00m00s00u")) - //), - //), - //selected.wrap(TransportFocus::Bpm, &Outset::X(1u16, { - //row! { - //"BPM ", - //format!("{}.{:03}", *bpm as usize, (bpm * 1000.0) % 1000.0) - //} - //})), - //selected.wrap(TransportFocus::Sync, &Outset::X(1u16, row! { - //"SYNC ", pulses_to_name(*sync as usize) - //})), - //selected.wrap(TransportFocus::Quant, &Outset::X(1u16, row! { - //"QUANT ", pulses_to_name(*quant as usize) - //})), - //selected.wrap(TransportFocus::Clock, &{ - //row!("B" , beat.as_str(), " T", msu.as_str()).outset_x(1) - //}).align_e().fill_x(), - //).fill_x().bg(Color::Rgb(40, 50, 30))