From 8318208bd0e8f29bca36443cdcc9e79caa26be0b Mon Sep 17 00:00:00 2001 From: ardura Date: Wed, 1 May 2024 11:48:18 -0700 Subject: [PATCH 1/5] Related to #20 and #21 and possibly #13 --- Cargo.lock | 910 +++++++++++++++++++++- Cargo.toml | 6 +- README.md | 24 +- src/Scrollscope.ini | 13 + src/lib.rs | 1696 +++++++++++++++++++++++++++++++----------- src/main.rs | 8 + src/slim_checkbox.rs | 97 +++ 7 files changed, 2307 insertions(+), 447 deletions(-) create mode 100644 src/Scrollscope.ini create mode 100644 src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 93b0890..1974190 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,96 @@ dependencies = [ "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 = "alsa" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" +dependencies = [ + "alsa-sys", + "bitflags 1.3.2", + "libc", + "nix 0.24.3", +] + +[[package]] +name = "alsa" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" +dependencies = [ + "alsa-sys", + "bitflags 2.5.0", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -111,6 +201,24 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "baseview" +version = "0.1.0" +source = "git+https://github.com/RustAudio/baseview.git?rev=7001c2521fa1a439a01967cb881b411cd75d9ee0#7001c2521fa1a439a01967cb881b411cd75d9ee0" +dependencies = [ + "cocoa", + "core-foundation", + "keyboard-types", + "nix 0.22.3", + "objc", + "raw-window-handle", + "uuid", + "winapi", + "x11", + "xcb", + "xcb-util", +] + [[package]] name = "baseview" version = "0.1.0" @@ -129,12 +237,38 @@ dependencies = [ "xcb-util", ] +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.48", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + [[package]] name = "block" version = "0.1.6" @@ -167,27 +301,107 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cache-padded" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" + [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading 0.8.1", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + [[package]] name = "clap-sys" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27f4e06657d33d5d194db1155cef359c359483a4170362bf4e105146dd0109e3" +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + [[package]] name = "clipboard-win" version = "3.1.1" @@ -204,7 +418,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation", @@ -220,7 +434,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-foundation", "core-graphics-types", @@ -228,6 +442,28 @@ dependencies = [ "objc", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "configparser" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec6d3da8e550377a85339063af6e3735f4b1d9392108da4e083a1b3b9820288" + [[package]] name = "copypasta" version = "0.8.2" @@ -264,7 +500,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-graphics-types", "foreign-types", @@ -277,11 +513,74 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "libc", ] +[[package]] +name = "coreaudio-rs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" +dependencies = [ + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", +] + +[[package]] +name = "coreaudio-sys" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" +dependencies = [ + "bindgen", +] + +[[package]] +name = "coremidi" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "coremidi-sys", +] + +[[package]] +name = "coremidi-sys" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79a6deed0c97b2d40abbab77e4c97f81d71e162600423382c277dd640019116c" +dependencies = [ + "core-foundation-sys", +] + +[[package]] +name = "cpal" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa 0.9.0", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -344,6 +643,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + [[package]] name = "deranged" version = "0.3.11" @@ -353,13 +658,34 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dlib" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading", + "libloading 0.8.1", ] [[package]] @@ -401,7 +727,7 @@ name = "egui-baseview" version = "0.1.0" source = "git+https://github.com/BillyDM/egui-baseview.git?rev=46e21cc11c57c705fb83611389399ec3d2670a44#46e21cc11c57c705fb83611389399ec3d2670a44" dependencies = [ - "baseview", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=eae4033e7d2cc9c31ccaa2794d5d08eedf2f510c)", "copypasta", "egui 0.19.0", "egui_glow", @@ -481,6 +807,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -523,6 +859,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "glow" version = "0.11.2" @@ -552,6 +894,12 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -586,6 +934,64 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jack" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e5a18a3c2aefb354fb77111ade228b20267bdc779de84e7a4ccf7ea96b9a6cd" +dependencies = [ + "bitflags 1.3.2", + "jack-sys", + "lazy_static", + "libc", + "log", +] + +[[package]] +name = "jack-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6013b7619b95a22b576dfb43296faa4ecbe40abbdb97dfd22ead520775fc86ab" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "libc", + "libloading 0.7.4", + "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.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.67" @@ -601,7 +1007,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7668b7cff6a51fe61cdde64cd27c8a220786f399501b57ebe36f7d8112fd68" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -616,12 +1022,28 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libloading" version = "0.8.1" @@ -629,9 +1051,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + [[package]] name = "lock_api" version = "0.4.11" @@ -648,6 +1086,15 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -687,6 +1134,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f2dd5c7f8aaf48a76e389068ab25ed80bdbc226b887f9013844c415698c9952" +[[package]] +name = "midir" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a456444d83e7ead06ae6a5c0a215ed70282947ff3897fb45fcb052b757284731" +dependencies = [ + "alsa 0.7.1", + "bitflags 1.3.2", + "coremidi", + "js-sys", + "libc", + "wasm-bindgen", + "web-sys", + "windows 0.43.0", +] + +[[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.7.1" @@ -696,6 +1165,35 @@ dependencies = [ "adler", ] +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.5.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + [[package]] name = "nih_log" version = "0.3.1" @@ -707,7 +1205,7 @@ dependencies = [ "once_cell", "termcolor", "time", - "windows", + "windows 0.44.0", ] [[package]] @@ -721,25 +1219,31 @@ dependencies = [ "atomic_float", "atomic_refcell", "backtrace", - "bitflags", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=7001c2521fa1a439a01967cb881b411cd75d9ee0)", + "bitflags 1.3.2", "cfg-if", + "clap", "clap-sys", "core-foundation", + "cpal", "crossbeam", + "jack", "lazy_static", "libc", "log", "midi-consts", + "midir", "nih_log", "nih_plug_derive", "objc", "parking_lot", "raw-window-handle", + "rtrb", "serde", "serde_json", "vst3-sys", "widestring", - "windows", + "windows 0.44.0", ] [[package]] @@ -757,7 +1261,7 @@ name = "nih_plug_egui" version = "0.0.0" source = "git+https://github.com/ardura/nih-plug.git?rev=e59dc33aaf0c06c834dba0821f6e269e6377f362#e59dc33aaf0c06c834dba0821f6e269e6377f362" dependencies = [ - "baseview", + "baseview 0.1.0 (git+https://github.com/RustAudio/baseview.git?rev=eae4033e7d2cc9c31ccaa2794d5d08eedf2f510c)", "crossbeam", "egui 0.19.0", "egui-baseview", @@ -785,7 +1289,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if", "libc", @@ -798,7 +1302,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset", @@ -810,6 +1314,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +[[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-complex" version = "0.4.5" @@ -819,6 +1333,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -837,6 +1362,27 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "num_threads" version = "0.1.6" @@ -884,12 +1430,41 @@ dependencies = [ "memchr", ] +[[package]] +name = "oboe" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" +dependencies = [ + "jni", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", +] + +[[package]] +name = "oboe-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" +dependencies = [ + "cc", +] + [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "owned_ttf_parser" version = "0.20.0" @@ -955,6 +1530,15 @@ dependencies = [ "num-integer", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro2" version = "1.0.78" @@ -988,7 +1572,18 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", ] [[package]] @@ -1000,12 +1595,56 @@ dependencies = [ "winapi", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rtrb" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e704dd104faf2326a320140f70f0b736d607c1caa1b1748a6c568a79819109" +dependencies = [ + "cache-padded", +] + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustfft" version = "6.2.0" @@ -1021,12 +1660,34 @@ dependencies = [ "version_check", ] +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[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" @@ -1061,9 +1722,11 @@ dependencies = [ [[package]] name = "scrollscope" -version = "1.3.0" +version = "1.3.1" dependencies = [ "atomic_float", + "configparser", + "dirs", "egui 0.21.0", "itertools", "nih_plug", @@ -1111,6 +1774,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "slotmap" version = "1.0.7" @@ -1132,7 +1801,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" dependencies = [ - "bitflags", + "bitflags 1.3.2", "dlib", "lazy_static", "log", @@ -1160,6 +1829,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.109" @@ -1191,6 +1866,36 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "time" version = "0.3.31" @@ -1231,7 +1936,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -1256,6 +1961,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" @@ -1297,6 +2013,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "0.8.2" @@ -1349,6 +2071,16 @@ dependencies = [ "vst3-com", ] +[[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" @@ -1380,6 +2112,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.90" @@ -1415,7 +2159,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" dependencies = [ - "bitflags", + "bitflags 1.3.2", "downcast-rs", "libc", "nix 0.24.3", @@ -1454,7 +2198,7 @@ version = "0.29.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "wayland-client", "wayland-commons", "wayland-scanner", @@ -1538,6 +2282,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +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" version = "0.44.0" @@ -1547,6 +2306,44 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-result" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -1556,6 +2353,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -1586,6 +2392,22 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -1598,6 +2420,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -1610,6 +2438,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -1622,6 +2456,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -1634,6 +2480,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -1646,6 +2498,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -1658,6 +2516,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -1670,6 +2534,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winnow" version = "0.5.35" diff --git a/Cargo.toml b/Cargo.toml index 5332e46..0f21a75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "scrollscope" -version = "1.3.0" +version = "1.3.1" edition = "2021" authors = ["Ardura "] license = "GPL-3.0-or-later" @@ -15,10 +15,12 @@ crate-type = ["cdylib","lib"] [dependencies] atomic_float = "0.1" +configparser = "3.0.4" +dirs = "5.0.1" egui = "0.21.0" itertools = "0.12.1" # This is copied from Actuate, technically it could point to Robbert's Git too, doesn't matter -nih_plug = { git = "https://github.com/ardura/nih-plug.git", rev = "e59dc33aaf0c06c834dba0821f6e269e6377f362", features = ["assert_process_allocs"] } +nih_plug = { git = "https://github.com/ardura/nih-plug.git", rev = "e59dc33aaf0c06c834dba0821f6e269e6377f362", features = ["assert_process_allocs","standalone"] } nih_plug_egui = { git = "https://github.com/ardura/nih-plug.git", rev = "e59dc33aaf0c06c834dba0821f6e269e6377f362" } rustfft = "6.2.0" diff --git a/README.md b/README.md index f574a84..7a02e54 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,29 @@ Note this can take a sidechain input! Do the routing in FL in plugin processing VST3: Copy the vst3 file to C:\Program Files\Common Files\VST3 CLAP: Copy the CLAP file to C:\Program Files\Common Files\CLAP -I don't know the plugin install locations for linux or mac sorry +*When this plugin runs the first time it will attempt to create a config file: Scrollscope.ini under:* +- $XDG_CONFIG_HOME or $HOME/.config on Linux +- $HOME/Library/Application Support on MacOS +- FOLDERID_LocalAppData on Windows (like C:\Users\Ardura\AppData\Local\) + +You can use this config to make your own custom color themes, have fun! + +Here is the default config otherwise (Also included in source) +```ini +# These are in RGB +[ui_colors] +background = 40,40,40 +guidelines = 160,160,160 +ui_main_color = 239,123,69 +user_main = 239,123,69 +user_aux_1 = 14,177,210 +user_aux_2 = 50,255,40 +user_aux_3 = 0,153,255 +user_aux_4 = 255,0,255 +user_aux_5 = 230,80,80 +user_sum_line = 248,255,31 +inactive_bg = 60,60,60 +``` ## Features - Sidechain input graphing - simply route sidechain input from another channel (up to 5) diff --git a/src/Scrollscope.ini b/src/Scrollscope.ini new file mode 100644 index 0000000..8d7ea67 --- /dev/null +++ b/src/Scrollscope.ini @@ -0,0 +1,13 @@ +# These are in RGB +[ui_colors] +background = 40,40,40 +guidelines = 160,160,160 +ui_main_color = 239,123,69 +user_main = 239,123,69 +user_aux_1 = 14,177,210 +user_aux_2 = 50,255,40 +user_aux_3 = 0,153,255 +user_aux_4 = 255,0,255 +user_aux_5 = 230,80,80 +user_sum_line = 248,255,31 +inactive_bg = 60,60,60 \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 575b5b6..9d49870 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use atomic_float::AtomicF32; +use configparser::ini::Ini; use itertools::{izip}; -use nih_plug::prelude::*; +use nih_plug::{prelude::*}; use nih_plug_egui::{ create_egui_editor, egui::{ @@ -9,27 +10,19 @@ use nih_plug_egui::{ widgets, EguiState, }; use rustfft::{num_complex::Complex, FftDirection, FftPlanner}; -use std::sync::{atomic::{AtomicI32, Ordering}, Arc}; +use std::{env, fs::File, io::Write, path::MAIN_SEPARATOR_STR, str::FromStr, sync::{atomic::{AtomicBool, AtomicI32, AtomicU8, Ordering}, Arc}}; use std::{collections::VecDeque, ops::RangeInclusive, sync::Mutex}; mod slim_checkbox; /************************************************** - * Scrollscope v1.3.0 by Ardura + * Scrollscope v1.3.1 by Ardura + * "A simple scrolling Oscilloscope has become complex now" * * Build with: cargo xtask bundle scrollscope --profile release * Debug with: cargo xtask bundle scrollscope --profile profiling * ************************************************/ -const ORANGE: Color32 = Color32::from_rgb(239, 123, 69); -const CYAN: Color32 = Color32::from_rgb(14, 177, 210); -const YELLOW: Color32 = Color32::from_rgb(248, 255, 31); -const LIME_GREEN: Color32 = Color32::from_rgb(50, 255, 40); -const MAGENTA: Color32 = Color32::from_rgb(255, 0, 255); -const ELECTRIC_BLUE: Color32 = Color32::from_rgb(0, 153, 255); -const PURPLE: Color32 = Color32::from_rgb(230, 80, 80); -const DARK: Color32 = Color32::from_rgb(40, 40, 40); - #[derive(Enum, Clone, PartialEq)] pub enum BeatSync { Beat, @@ -41,16 +34,18 @@ pub struct Scrollscope { // Counter for scaling sample skipping skip_counter: i32, - focused_line_toggle: Arc>, + focused_line_toggle: Arc, is_clipping: Arc, - direction: Arc>, - enable_main: Arc>, - enable_aux_1: Arc>, - enable_aux_2: Arc>, - enable_aux_3: Arc>, - enable_aux_4: Arc>, - enable_aux_5: Arc>, - enable_sum: Arc>, + direction: Arc, + enable_main: Arc, + enable_aux_1: Arc, + enable_aux_2: Arc, + enable_aux_3: Arc, + enable_aux_4: Arc, + enable_aux_5: Arc, + enable_sum: Arc, + enable_guidelines: Arc, + enable_bar_mode: Arc, // Data holding values samples: Arc>>, @@ -59,16 +54,18 @@ pub struct Scrollscope { aux_samples_3: Arc>>, aux_samples_4: Arc>>, aux_samples_5: Arc>>, + scrolling_beat_lines: Arc>>, // Syncing for beats - sync_var: Arc>, - alt_sync: Arc>, - in_place_index: Arc>, - threshold_combo: Arc>, + sync_var: Arc, + alt_sync: Arc, + in_place_index: Arc, + threshold_combo: Arc, + add_beat_line: Arc, // FFT/Analyzer fft: Arc>>, - show_analyzer: Arc>, + show_analyzer: Arc, sample_rate: Arc, prev_skip: Arc, @@ -102,28 +99,32 @@ impl Default for Scrollscope { Self { params: Arc::new(ScrollscopeParams::default()), skip_counter: 0, - focused_line_toggle: Arc::new(Mutex::new(0)), - direction: Arc::new(Mutex::new(false)), + focused_line_toggle: Arc::new(AtomicU8::new(0)), + direction: Arc::new(AtomicBool::new(false)), is_clipping: Arc::new(AtomicF32::new(0.0)), - enable_main: Arc::new(Mutex::new(true)), - enable_aux_1: Arc::new(Mutex::new(false)), - enable_aux_2: Arc::new(Mutex::new(false)), - enable_aux_3: Arc::new(Mutex::new(false)), - enable_aux_4: Arc::new(Mutex::new(false)), - enable_aux_5: Arc::new(Mutex::new(false)), - enable_sum: Arc::new(Mutex::new(true)), + enable_main: Arc::new(AtomicBool::new(true)), + enable_aux_1: Arc::new(AtomicBool::new(false)), + enable_aux_2: Arc::new(AtomicBool::new(false)), + enable_aux_3: Arc::new(AtomicBool::new(false)), + enable_aux_4: Arc::new(AtomicBool::new(false)), + enable_aux_5: Arc::new(AtomicBool::new(false)), + enable_sum: Arc::new(AtomicBool::new(true)), + enable_guidelines: Arc::new(AtomicBool::new(true)), + enable_bar_mode: Arc::new(AtomicBool::new(false)), samples: Arc::new(Mutex::new(VecDeque::with_capacity(130))), aux_samples_1: Arc::new(Mutex::new(VecDeque::with_capacity(130))), aux_samples_2: Arc::new(Mutex::new(VecDeque::with_capacity(130))), aux_samples_3: Arc::new(Mutex::new(VecDeque::with_capacity(130))), aux_samples_4: Arc::new(Mutex::new(VecDeque::with_capacity(130))), aux_samples_5: Arc::new(Mutex::new(VecDeque::with_capacity(130))), - sync_var: Arc::new(Mutex::new(false)), - alt_sync: Arc::new(Mutex::new(false)), - in_place_index: Arc::new(Mutex::new(0)), - threshold_combo: Arc::new(Mutex::new(0)), + scrolling_beat_lines: Arc::new(Mutex::new(VecDeque::with_capacity(130))), + sync_var: Arc::new(AtomicBool::new(false)), + alt_sync: Arc::new(AtomicBool::new(false)), + add_beat_line: Arc::new(AtomicBool::new(false)), + in_place_index: Arc::new(AtomicI32::new(0)), + threshold_combo: Arc::new(AtomicI32::new(0)), fft: Arc::new(Mutex::new(FftPlanner::new())), - show_analyzer: Arc::new(Mutex::new(false)), + show_analyzer: Arc::new(AtomicBool::new(false)), sample_rate: Arc::new(AtomicF32::new(44100.0)), prev_skip: Arc::new(AtomicI32::new(24)), } @@ -199,7 +200,6 @@ impl Plugin for Scrollscope { self.params.clone() } - #[allow(unused_assignments)] fn editor(&self, _async_executor: AsyncExecutor) -> Option> { let params = self.params.clone(); let samples = self.samples.clone(); @@ -208,6 +208,7 @@ impl Plugin for Scrollscope { let aux_samples_3 = self.aux_samples_3.clone(); let aux_samples_4 = self.aux_samples_4.clone(); let aux_samples_5 = self.aux_samples_5.clone(); + let scrolling_beat_lines = self.scrolling_beat_lines.clone(); let ontop = self.focused_line_toggle.clone(); let is_clipping = self.is_clipping.clone(); let sync_var = self.sync_var.clone(); @@ -220,48 +221,177 @@ impl Plugin for Scrollscope { let en_aux4 = self.enable_aux_4.clone(); let en_aux5 = self.enable_aux_5.clone(); let en_sum = self.enable_sum.clone(); + let en_guidelines = self.enable_guidelines.clone(); + let en_bar_mode = self.enable_bar_mode.clone(); let fft = self.fft.clone(); let show_analyzer = self.show_analyzer.clone(); let sample_rate = self.sample_rate.clone(); let prev_skip = self.prev_skip.clone(); + let mut config = Ini::new(); + let binding = dirs::config_local_dir(); + let location; + if binding.is_some() { + location = String::from(binding.unwrap().as_os_str().to_str().unwrap()) + MAIN_SEPARATOR_STR + "Scrollscope.ini"; + let location_clone = location.clone(); + let location_clone_2 = location.clone(); + nih_log!("{}", location); + let mut _config_loaded = config.load(location); + if _config_loaded.is_ok() { + nih_log!("Loaded!"); + } else { + nih_log!("Not found!"); + let mut file = File::create(location_clone).unwrap(); + // Create our default config file if we can + let write_result = file.write_all(b"# These are in RGB +[ui_colors] +background = 40,40,40 +guidelines = 160,160,160 +ui_main_color = 239,123,69 +user_main = 239,123,69 +user_aux_1 = 14,177,210 +user_aux_2 = 50,255,40 +user_aux_3 = 0,153,255 +user_aux_4 = 255,0,255 +user_aux_5 = 230,80,80 +user_sum_line = 248,255,31 +inactive_bg = 60,60,60"); + if write_result.is_ok() { + nih_log!("Created!"); + _config_loaded = config.load(location_clone_2); + } else { + nih_log!("Coudldn't Create!"); + } + } + } + + let mut t: Vec = config.get("ui_colors", "user_main") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let primary_line_color = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "background") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let background_color = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "guidelines") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let guidelines = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "ui_main_color") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let ui_main_color = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_sum_line") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_sum_line = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_aux_1") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_aux_1 = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_aux_2") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_aux_2 = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_aux_3") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_aux_3 = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_aux_4") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_aux_4 = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "user_aux_5") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let user_aux_5 = Color32::from_rgb(t[0], t[1], t[2]); + t = config.get("ui_colors", "inactive_bg") + .unwrap() + .split(',') + .map(|elem|{ + let u: u8 = FromStr::from_str(elem).unwrap_or_default(); + u + }) + .collect(); + let inactive_bg = Color32::from_rgb(t[0], t[1], t[2]); + create_egui_editor( self.params.editor_state.clone(), (), |_, _| {}, move |egui_ctx, setter, _state| { egui::CentralPanel::default().show(egui_ctx, |ui| { - // Default colors - let mut primary_line_color = ORANGE; - let mut aux_line_color = CYAN; - let mut aux_line_color_2 = LIME_GREEN; - let mut aux_line_color_3 = ELECTRIC_BLUE; - let mut aux_line_color_4 = MAGENTA; - let mut aux_line_color_5 = PURPLE; - let sum_line_color = YELLOW; - let background_color = DARK; - // Change colors - there's probably a better way to do this - let mut style_var = ui.style_mut().clone(); - style_var.visuals.widgets.inactive.bg_fill = Color32::from_rgb(60, 60, 60); + let style_var = ui.style_mut(); + style_var.visuals.widgets.inactive.bg_fill = inactive_bg; // Assign default colors if user colors not set - style_var.visuals.widgets.inactive.fg_stroke.color = primary_line_color; + style_var.visuals.widgets.inactive.fg_stroke.color = ui_main_color; style_var.visuals.widgets.noninteractive.fg_stroke.color = primary_line_color; style_var.visuals.widgets.inactive.bg_stroke.color = primary_line_color; - style_var.visuals.widgets.active.fg_stroke.color = primary_line_color; + style_var.visuals.widgets.active.fg_stroke.color = ui_main_color; style_var.visuals.widgets.active.bg_stroke.color = primary_line_color; style_var.visuals.widgets.open.fg_stroke.color = primary_line_color; // Param fill style_var.visuals.selection.bg_fill = primary_line_color; - style_var.visuals.widgets.noninteractive.bg_stroke.color = aux_line_color; + style_var.visuals.widgets.noninteractive.bg_stroke.color = guidelines; style_var.visuals.widgets.noninteractive.bg_fill = background_color; // Trying to draw background as rect ui.painter() .rect_filled(Rect::EVERYTHING, Rounding::none(), background_color); - ui.set_style(style_var); + //ui.set_style(style_var); // Reset these to be assigned/reassigned when params change let mut sum_line: Line = Line::new(PlotPoints::default()); @@ -270,6 +400,7 @@ impl Plugin for Scrollscope { let mut aux_line_3: Line = Line::new(PlotPoints::default()); let mut aux_line_4: Line = Line::new(PlotPoints::default()); let mut aux_line_5: Line = Line::new(PlotPoints::default()); + let mut scrolling_beat_line: Line = Line::new(PlotPoints::default()); let mut line: Line = Line::new(PlotPoints::default()); let mut samples = samples.lock().unwrap(); let mut aux_samples_1 = aux_samples_1.lock().unwrap(); @@ -277,6 +408,7 @@ impl Plugin for Scrollscope { let mut aux_samples_3 = aux_samples_3.lock().unwrap(); let mut aux_samples_4 = aux_samples_4.lock().unwrap(); let mut aux_samples_5 = aux_samples_5.lock().unwrap(); + let mut scrolling_beat_lines = scrolling_beat_lines.lock().unwrap(); let sr = sample_rate.clone(); // The entire "window" container @@ -292,7 +424,7 @@ impl Plugin for Scrollscope { ui.add_space(4.0); let swap_response: Response; - if *show_analyzer.lock().unwrap() { + if show_analyzer.load(Ordering::SeqCst) { let _scroll_handle = ui.add( widgets::ParamSlider::for_param(¶ms.scrollspeed, setter) .with_width(120.0), @@ -320,12 +452,11 @@ impl Plugin for Scrollscope { .button("Toggle Focus") .on_hover_text("Change the drawing order of waveforms"); - let sync_response = ui - .checkbox(&mut sync_var.lock().unwrap(), "Sync") - .on_hover_text("Lock drawing to timing"); - let alt_sync_response = ui - .checkbox(&mut alt_sync.lock().unwrap(), "Alt Sync") - .on_hover_text("Try this if Sync doesn't work"); + let sync_box = slim_checkbox::AtomicSlimCheckbox::new(&sync_var, "Sync"); + let sync_response = ui.add(sync_box).on_hover_text("Lock drawing to timing"); + let alt_sync_box = slim_checkbox::AtomicSlimCheckbox::new(&alt_sync, "Alt Sync"); + let alt_sync_response = ui.add(alt_sync_box).on_hover_text("Try this if Sync doesn't work"); + let timing_response = ui .add( widgets::ParamSlider::for_param(¶ms.sync_timing, setter) @@ -333,9 +464,8 @@ impl Plugin for Scrollscope { ) .on_hover_text("Refresh interval when sync enabled"); - let dir_response = ui - .checkbox(&mut dir_var.lock().unwrap(), "Flip") - .on_hover_text("Flip direction of oscilloscope"); + let dir_box = slim_checkbox::AtomicSlimCheckbox::new(&dir_var, "Flip"); + let dir_response = ui.add(dir_box).on_hover_text("Flip direction of oscilloscope"); // Reset our line on change if sync_response.clicked() @@ -346,12 +476,12 @@ impl Plugin for Scrollscope { // Keep same direction when syncing (Issue #12) if sync_response.clicked() { // If flip selected already, it should be deselected on this click - if *dir_var.lock().unwrap() { - *dir_var.lock().unwrap() = false; + if dir_var.load(Ordering::SeqCst) { + dir_var.store(false, Ordering::SeqCst); } // If flip not selected, it should now be selected else { - *dir_var.lock().unwrap() = true; + dir_var.store(true, Ordering::SeqCst); } } sum_line = Line::new(PlotPoints::default()); @@ -360,6 +490,7 @@ impl Plugin for Scrollscope { aux_line_3 = Line::new(PlotPoints::default()); aux_line_4 = Line::new(PlotPoints::default()); aux_line_5 = Line::new(PlotPoints::default()); + scrolling_beat_line = Line::new(PlotPoints::default()); line = Line::new(PlotPoints::default()); samples.clear(); aux_samples_1.clear(); @@ -367,89 +498,90 @@ impl Plugin for Scrollscope { aux_samples_3.clear(); aux_samples_4.clear(); aux_samples_5.clear(); + scrolling_beat_lines.clear(); } } if swap_response.clicked() { - let mut num = ontop.lock().unwrap(); + let num = ontop.load(Ordering::SeqCst); // This skips possible "OFF" lines when toggling - match *num { + match num { 0 => { - if *en_aux1.lock().unwrap() { - *num = 1; - } else if *en_aux2.lock().unwrap() { - *num = 2; - } else if *en_aux3.lock().unwrap() { - *num = 3; - } else if *en_aux4.lock().unwrap() { - *num = 4; - } else if *en_aux5.lock().unwrap() { - *num = 5; + if en_aux1.load(Ordering::SeqCst) { + ontop.store(1, Ordering::SeqCst); + } else if en_aux2.load(Ordering::SeqCst) { + ontop.store(2, Ordering::SeqCst); + } else if en_aux3.load(Ordering::SeqCst) { + ontop.store(3, Ordering::SeqCst); + } else if en_aux4.load(Ordering::SeqCst) { + ontop.store(4, Ordering::SeqCst); + } else if en_aux5.load(Ordering::SeqCst) { + ontop.store(5, Ordering::SeqCst); } } 1 => { - if *en_aux2.lock().unwrap() { - *num = 2; - } else if *en_aux3.lock().unwrap() { - *num = 3; - } else if *en_aux4.lock().unwrap() { - *num = 4; - } else if *en_aux5.lock().unwrap() { - *num = 5; - } else if *en_main.lock().unwrap() { - *num = 0; + if en_aux2.load(Ordering::SeqCst) { + ontop.store(2, Ordering::SeqCst); + } else if en_aux3.load(Ordering::SeqCst) { + ontop.store(3, Ordering::SeqCst); + } else if en_aux4.load(Ordering::SeqCst) { + ontop.store(4, Ordering::SeqCst); + } else if en_aux5.load(Ordering::SeqCst) { + ontop.store(5, Ordering::SeqCst); + } else if en_main.load(Ordering::SeqCst) { + ontop.store(0, Ordering::SeqCst); } } 2 => { - if *en_aux3.lock().unwrap() { - *num = 3; - } else if *en_aux4.lock().unwrap() { - *num = 4; - } else if *en_aux5.lock().unwrap() { - *num = 5; - } else if *en_main.lock().unwrap() { - *num = 0; - } else if *en_aux1.lock().unwrap() { - *num = 1; + if en_aux3.load(Ordering::SeqCst) { + ontop.store(3, Ordering::SeqCst); + } else if en_aux4.load(Ordering::SeqCst) { + ontop.store(4, Ordering::SeqCst); + } else if en_aux5.load(Ordering::SeqCst) { + ontop.store(5, Ordering::SeqCst); + } else if en_main.load(Ordering::SeqCst) { + ontop.store(0, Ordering::SeqCst); + } else if en_aux1.load(Ordering::SeqCst) { + ontop.store(1, Ordering::SeqCst); } } 3 => { - if *en_aux4.lock().unwrap() { - *num = 4; - } else if *en_aux5.lock().unwrap() { - *num = 5; - } else if *en_main.lock().unwrap() { - *num = 0; - } else if *en_aux1.lock().unwrap() { - *num = 1; - } else if *en_aux2.lock().unwrap() { - *num = 2; + if en_aux4.load(Ordering::SeqCst) { + ontop.store(4, Ordering::SeqCst); + } else if en_aux5.load(Ordering::SeqCst) { + ontop.store(5, Ordering::SeqCst); + } else if en_main.load(Ordering::SeqCst) { + ontop.store(0, Ordering::SeqCst); + } else if en_aux1.load(Ordering::SeqCst) { + ontop.store(1, Ordering::SeqCst); + } else if en_aux2.load(Ordering::SeqCst) { + ontop.store(2, Ordering::SeqCst); } } 4 => { - if *en_aux5.lock().unwrap() { - *num = 5; - } else if *en_main.lock().unwrap() { - *num = 0; - } else if *en_aux1.lock().unwrap() { - *num = 1; - } else if *en_aux2.lock().unwrap() { - *num = 2; - } else if *en_aux3.lock().unwrap() { - *num = 3; + if en_aux5.load(Ordering::SeqCst) { + ontop.store(5, Ordering::SeqCst); + } else if en_main.load(Ordering::SeqCst) { + ontop.store(0, Ordering::SeqCst); + } else if en_aux1.load(Ordering::SeqCst) { + ontop.store(1, Ordering::SeqCst); + } else if en_aux2.load(Ordering::SeqCst) { + ontop.store(2, Ordering::SeqCst); + } else if en_aux3.load(Ordering::SeqCst) { + ontop.store(3, Ordering::SeqCst); } } 5 => { - if *en_main.lock().unwrap() { - *num = 0; - } else if *en_aux1.lock().unwrap() { - *num = 1; - } else if *en_aux2.lock().unwrap() { - *num = 2; - } else if *en_aux3.lock().unwrap() { - *num = 3; - } else if *en_aux4.lock().unwrap() { - *num = 4; + if en_main.load(Ordering::SeqCst) { + ontop.store(0, Ordering::SeqCst); + } else if en_aux1.load(Ordering::SeqCst) { + ontop.store(1, Ordering::SeqCst); + } else if en_aux2.load(Ordering::SeqCst) { + ontop.store(2, Ordering::SeqCst); + } else if en_aux3.load(Ordering::SeqCst) { + ontop.store(3, Ordering::SeqCst); + } else if en_aux4.load(Ordering::SeqCst) { + ontop.store(4, Ordering::SeqCst); } } _ => { @@ -458,43 +590,53 @@ impl Plugin for Scrollscope { } } - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_main.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_main, "In", )); - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_aux1.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_aux1, "2", )); - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_aux2.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_aux2, "3", )); - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_aux3.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_aux3, "4", )); - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_aux4.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_aux4, "5", )); - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_aux5.lock().unwrap(), + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_aux5, "6", )); - if !*show_analyzer.lock().unwrap() { - ui.add(slim_checkbox::SlimCheckbox::new( - &mut en_sum.lock().unwrap(), + if !show_analyzer.load(Ordering::SeqCst) { + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_sum, "Sum", )); } - let analyzer_toggle = ui.add(slim_checkbox::SlimCheckbox::new( - &mut show_analyzer.lock().unwrap(), + let analyzer_toggle = ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &show_analyzer, "Analyze", )); + if show_analyzer.load(Ordering::SeqCst) { + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_guidelines, + "Guidelines", + )); + ui.add(slim_checkbox::AtomicSlimCheckbox::new( + &en_bar_mode, + "Bar Mode", + )); + } if analyzer_toggle.clicked() { // This is a ! because we'll always be behind the param toggle in time - if !*show_analyzer.lock().unwrap() { + if !show_analyzer.load(Ordering::SeqCst) { setter.set_parameter(¶ms.h_scale, prev_skip.load(Ordering::Relaxed)); } else { prev_skip.store(params.h_scale.value(), Ordering::Relaxed); @@ -507,66 +649,80 @@ impl Plugin for Scrollscope { }); // Reverse our order for drawing if desired (I know this is "slow") - if *dir_var.lock().unwrap() { + if dir_var.load(Ordering::SeqCst) { samples.make_contiguous().reverse(); aux_samples_1.make_contiguous().reverse(); aux_samples_2.make_contiguous().reverse(); aux_samples_3.make_contiguous().reverse(); aux_samples_4.make_contiguous().reverse(); aux_samples_5.make_contiguous().reverse(); + scrolling_beat_lines.make_contiguous().reverse(); } + let mut final_primary_color: Color32 = Default::default(); + let mut final_aux_line_color: Color32 = Default::default(); + let mut final_aux_line_color_2: Color32 = Default::default(); + let mut final_aux_line_color_3: Color32 = Default::default(); + let mut final_aux_line_color_4: Color32 = Default::default(); + let mut final_aux_line_color_5: Color32 = Default::default(); + ui.allocate_ui(egui::Vec2::new(900.0, 380.0), |ui| { // Fix our colors to focus on our line let lmult: f32 = 0.25; - match *ontop.lock().unwrap() { + match ontop.load(Ordering::SeqCst) { 0 => { // Main unaffected - aux_line_color = aux_line_color.linear_multiply(lmult); - aux_line_color_2 = aux_line_color_2.linear_multiply(lmult); - aux_line_color_3 = aux_line_color_3.linear_multiply(lmult); - aux_line_color_4 = aux_line_color_4.linear_multiply(lmult); - aux_line_color_5 = aux_line_color_5.linear_multiply(lmult); + final_primary_color = primary_line_color; + final_aux_line_color = user_aux_1.linear_multiply(lmult); + final_aux_line_color_2 = user_aux_2.linear_multiply(lmult); + final_aux_line_color_3 = user_aux_3.linear_multiply(lmult); + final_aux_line_color_4 = user_aux_4.linear_multiply(lmult); + final_aux_line_color_5 = user_aux_5.linear_multiply(lmult); } 1 => { // Aux unaffected - primary_line_color = primary_line_color.linear_multiply(lmult); - aux_line_color_2 = aux_line_color_2.linear_multiply(lmult); - aux_line_color_3 = aux_line_color_3.linear_multiply(lmult); - aux_line_color_4 = aux_line_color_4.linear_multiply(lmult); - aux_line_color_5 = aux_line_color_5.linear_multiply(lmult); + final_primary_color = primary_line_color.linear_multiply(lmult); + final_aux_line_color = user_aux_1; + final_aux_line_color_2 = user_aux_2.linear_multiply(lmult); + final_aux_line_color_3 = user_aux_3.linear_multiply(lmult); + final_aux_line_color_4 = user_aux_4.linear_multiply(lmult); + final_aux_line_color_5 = user_aux_5.linear_multiply(lmult); } 2 => { // Aux 2 unaffected - primary_line_color = primary_line_color.linear_multiply(lmult); - aux_line_color = aux_line_color.linear_multiply(lmult); - aux_line_color_3 = aux_line_color_3.linear_multiply(lmult); - aux_line_color_4 = aux_line_color_4.linear_multiply(lmult); - aux_line_color_5 = aux_line_color_5.linear_multiply(lmult); + final_primary_color = primary_line_color.linear_multiply(lmult); + final_aux_line_color = user_aux_1.linear_multiply(lmult); + final_aux_line_color_2 = user_aux_2; + final_aux_line_color_3 = user_aux_3.linear_multiply(lmult); + final_aux_line_color_4 = user_aux_4.linear_multiply(lmult); + final_aux_line_color_5 = user_aux_5.linear_multiply(lmult); } 3 => { // Aux 3 unaffected - primary_line_color = primary_line_color.linear_multiply(lmult); - aux_line_color = aux_line_color.linear_multiply(lmult); - aux_line_color_2 = aux_line_color_2.linear_multiply(lmult); - aux_line_color_4 = aux_line_color_4.linear_multiply(lmult); - aux_line_color_5 = aux_line_color_5.linear_multiply(lmult); + final_primary_color = primary_line_color.linear_multiply(lmult); + final_aux_line_color = user_aux_1.linear_multiply(lmult); + final_aux_line_color_2 = user_aux_2.linear_multiply(lmult); + final_aux_line_color_3 = user_aux_3; + final_aux_line_color_4 = user_aux_4.linear_multiply(lmult); + final_aux_line_color_5 = user_aux_5.linear_multiply(lmult); } 4 => { // Aux 4 unaffected - primary_line_color = primary_line_color.linear_multiply(lmult); - aux_line_color = aux_line_color.linear_multiply(lmult); - aux_line_color_2 = aux_line_color_2.linear_multiply(lmult); - aux_line_color_3 = aux_line_color_3.linear_multiply(lmult); - aux_line_color_5 = aux_line_color_5.linear_multiply(lmult); + final_primary_color = primary_line_color.linear_multiply(lmult); + final_aux_line_color = user_aux_1.linear_multiply(lmult); + final_aux_line_color_2 = user_aux_2.linear_multiply(lmult); + final_aux_line_color_3 = user_aux_3.linear_multiply(lmult); + final_aux_line_color_4 = user_aux_4; + final_aux_line_color_5 = user_aux_5.linear_multiply(lmult); } 5 => { // Aux 5 unaffected - primary_line_color = primary_line_color.linear_multiply(lmult); - aux_line_color = aux_line_color.linear_multiply(lmult); - aux_line_color_2 = aux_line_color_2.linear_multiply(lmult); - aux_line_color_3 = aux_line_color_3.linear_multiply(lmult); - aux_line_color_4 = aux_line_color_4.linear_multiply(lmult); + final_primary_color = primary_line_color.linear_multiply(lmult); + final_aux_line_color = user_aux_1.linear_multiply(lmult); + final_aux_line_color_2 = user_aux_2.linear_multiply(lmult); + final_aux_line_color_3 = user_aux_3.linear_multiply(lmult); + final_aux_line_color_4 = user_aux_4.linear_multiply(lmult); + final_aux_line_color_5 = user_aux_5; } _ => { // We shouldn't be here @@ -574,7 +730,7 @@ impl Plugin for Scrollscope { } // Show the frequency analyzer - if *show_analyzer.lock().unwrap() { + if show_analyzer.load(Ordering::SeqCst) { let mut shapes = vec![]; // Compute our fast fourier transforms @@ -613,213 +769,886 @@ impl Plugin for Scrollscope { let frequencies: Vec = (0..buffer_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / buffer_len as f32) .collect(); - let magnitudes_ax1: Vec = ax1.iter().map(|c| c.norm() as f32).collect(); let frequencies_ax1: Vec = (0..ax1_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / ax1_len as f32) .collect(); - let magnitudes_ax2: Vec = ax2.iter().map(|c| c.norm() as f32).collect(); let frequencies_ax2: Vec = (0..ax2_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / ax2_len as f32) .collect(); - let magnitudes_ax3: Vec = ax3.iter().map(|c| c.norm() as f32).collect(); let frequencies_ax3: Vec = (0..ax3_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / ax3_len as f32) .collect(); - let magnitudes_ax4: Vec = ax4.iter().map(|c| c.norm() as f32).collect(); let frequencies_ax4: Vec = (0..ax4_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / ax4_len as f32) .collect(); - let magnitudes_ax5: Vec = ax5.iter().map(|c| c.norm() as f32).collect(); let frequencies_ax5: Vec = (0..ax5_len / 2) .map(|i| i as f32 * sr.load(Ordering::Relaxed) / ax5_len as f32) .collect(); - // Scale for visibility let db_scaler = 2.75; let freq_scaler = 285.0; let x_shift = -220.0; let y_shift = 220.0; - // 1Khz pivot and -4.5 slope is same as Fruity Parametric EQ2 // For some reason 12 lines up the same here... let pivot = 1000.0; let slope = 12.0; - - // Primary Input - let data: Vec = frequencies - .iter() - .zip(magnitudes.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + if en_bar_mode.load(Ordering::SeqCst) { + let length = frequencies.len(); + let bar_scaler = 300.0; + let bars: f32 = 32.0; + let chunk_size = length as f32 / bars; + let mut chunked_f: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m: Vec = Vec::with_capacity(bars as usize); + let mut chunked_f_ax1: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m_ax1: Vec = Vec::with_capacity(bars as usize); + let mut chunked_f_ax2: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m_ax2: Vec = Vec::with_capacity(bars as usize); + let mut chunked_f_ax3: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m_ax3: Vec = Vec::with_capacity(bars as usize); + let mut chunked_f_ax4: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m_ax4: Vec = Vec::with_capacity(bars as usize); + let mut chunked_f_ax5: Vec = Vec::with_capacity(bars as usize); + let mut chunked_m_ax5: Vec = Vec::with_capacity(bars as usize); + for i in 0..bars as i32 { + let start = (i as f32 * chunk_size) as usize; + let end = if i == bars as i32 - 1 { + length + } else { + ((i + 1) as f32 * chunk_size) as usize + }; + + let sum_f: f32 = frequencies[start..end].iter().sum(); + let average_f = sum_f / ((end - start) as f32); + let sum_m: f32 = magnitudes[start..end].iter().sum(); + let average_m = sum_m / ((end - start) as f32); + chunked_f.push(average_f); + chunked_m.push(average_m); + + let sum_f_ax1: f32 = frequencies_ax1[start..end].iter().sum(); + let average_f_ax1 = sum_f_ax1 / ((end - start) as f32); + let sum_m_ax1: f32 = magnitudes_ax1[start..end].iter().sum(); + let average_m_ax1 = sum_m_ax1 / ((end - start) as f32); + chunked_f_ax1.push(average_f_ax1); + chunked_m_ax1.push(average_m_ax1); + + let sum_f_ax2: f32 = frequencies_ax2[start..end].iter().sum(); + let average_f_ax2 = sum_f_ax2 / ((end - start) as f32); + let sum_m_ax2: f32 = magnitudes_ax2[start..end].iter().sum(); + let average_m_ax2 = sum_m_ax2 / ((end - start) as f32); + chunked_f_ax2.push(average_f_ax2); + chunked_m_ax2.push(average_m_ax2); + + let sum_f_ax3: f32 = frequencies_ax3[start..end].iter().sum(); + let average_f_ax3 = sum_f_ax3 / ((end - start) as f32); + let sum_m_ax3: f32 = magnitudes_ax3[start..end].iter().sum(); + let average_m_ax3 = sum_m_ax3 / ((end - start) as f32); + chunked_f_ax3.push(average_f_ax3); + chunked_m_ax3.push(average_m_ax3); + + let sum_f_ax4: f32 = frequencies_ax4[start..end].iter().sum(); + let average_f_ax4 = sum_f_ax4 / ((end - start) as f32); + let sum_m_ax4: f32 = magnitudes_ax4[start..end].iter().sum(); + let average_m_ax4 = sum_m_ax4 / ((end - start) as f32); + chunked_f_ax4.push(average_f_ax4); + chunked_m_ax4.push(average_m_ax4); + + let sum_f_ax5: f32 = frequencies_ax5[start..end].iter().sum(); + let average_f_ax5 = sum_f_ax5 / ((end - start) as f32); + let sum_m_ax5: f32 = magnitudes_ax5[start..end].iter().sum(); + let average_m_ax5 = sum_m_ax5 / ((end - start) as f32); + chunked_f_ax5.push(average_f_ax5); + chunked_m_ax5.push(average_m_ax5); + } - // Aux - let ax1_data: Vec = frequencies_ax1 - .iter() - .zip(magnitudes_ax1.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + // Primary Input + let data: Vec = chunked_f + .iter() + .zip(chunked_m.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - let ax2_data: Vec = frequencies_ax2 - .iter() - .zip(magnitudes_ax2.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + // Aux inputs + let data_ax1: Vec = chunked_f_ax1 + .iter() + .zip(chunked_m_ax1.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - let ax3_data: Vec = frequencies_ax3 - .iter() - .zip(magnitudes_ax3.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + let data_ax2: Vec = chunked_f_ax2 + .iter() + .zip(chunked_m_ax2.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - let ax4_data: Vec = frequencies_ax4 - .iter() - .zip(magnitudes_ax4.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + let data_ax3: Vec = chunked_f_ax3 + .iter() + .zip(chunked_m_ax3.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - let ax5_data: Vec = frequencies_ax5 - .iter() - .zip(magnitudes_ax5.iter()) - .map(|(freq, magnitude)| { - let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); - pos2( - freq.log10() * freq_scaler + x_shift, - (util::gain_to_db(y) * -1.0) * db_scaler + y_shift - ) - }) - .collect(); + let data_ax4: Vec = chunked_f_ax4 + .iter() + .zip(chunked_m_ax4.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - let freqs: [f32; 12] = [ - 0.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0, 18000.0]; - let scaled_ref_freqs: Vec = freqs.iter().map(|num|{num.log10() * freq_scaler}).collect(); - for (num,scaled_num) in freqs.iter().zip(scaled_ref_freqs.iter()) { - shapes.push( - epaint::Shape::line_segment( - [ - Pos2::new(*scaled_num + x_shift, 515.0), - Pos2::new(*scaled_num + x_shift, 30.0) - ], - Stroke::new(0.5, Color32::GRAY) - ) - ); - ui.painter().text( - Pos2::new(scaled_num + 2.0 + x_shift, 510.0), - Align2::LEFT_CENTER, - *num, - FontId::monospace(12.0), - Color32::GRAY - ); - } - let sub_freqs: [f32; 18] = [ - 30.0,40.0,60.0,70.0,80.0,90.0,300.0,400.0,600.0,700.0,800.0,900.0,3000.0,4000.0,6000.0,7000.0,8000.0,9000.0]; - let scaled_sub_freqs: Vec = sub_freqs.iter().map(|num|{num.log10() * freq_scaler}).collect(); - for scaled_num in scaled_sub_freqs.iter() { - shapes.push( - epaint::Shape::line_segment( - [ - Pos2::new(*scaled_num + x_shift, 515.0), - Pos2::new(*scaled_num + x_shift, 30.0) - ], - Stroke::new(0.5, Color32::DARK_GRAY) - ) - ); - } + let data_ax5: Vec = chunked_f_ax5 + .iter() + .zip(chunked_m_ax5.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * bar_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); - // Draw whichever order next - match *ontop.lock().unwrap() { - 0 => { - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - } - 1 => { - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - } - 2 => { - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - } - 3 => { - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - } - 4 => { - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - } - 5 => { - if *en_aux4.lock().unwrap() { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, aux_line_color_4))); } - if *en_aux3.lock().unwrap() { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, aux_line_color_3))); } - if *en_aux2.lock().unwrap() { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, aux_line_color_2))); } - if *en_aux1.lock().unwrap() { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, aux_line_color))); } - if *en_main.lock().unwrap() { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, primary_line_color))); } - if *en_aux5.lock().unwrap() { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, aux_line_color_5))); } + // Draw whichever order next + match ontop.load(Ordering::SeqCst) { + 0 => { + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + } + 1 => { + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + } + 2 => { + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + } + 3 => { + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + } + 4 => { + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + } + 5 => { + if en_aux4.load(Ordering::SeqCst) { + for elem in data_ax4.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_4 + ) + ); + } + } + if en_aux3.load(Ordering::SeqCst) { + for elem in data_ax3.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_3 + ) + ); + } + } + if en_aux2.load(Ordering::SeqCst) { + for elem in data_ax2.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_2 + ) + ); + } + } + if en_aux1.load(Ordering::SeqCst) { + for elem in data_ax1.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_1 + ) + ); + } + } + if en_main.load(Ordering::SeqCst) { + for elem in data.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + final_primary_color + ) + ); + } + } + if en_aux5.load(Ordering::SeqCst) { + for elem in data_ax5.iter() { + shapes.push( + epaint::Shape::rect_filled( + Rect { + min: Pos2::new(elem.x + x_shift, elem.y), + max: Pos2::new(elem.x + 10.0 + x_shift, 515.0) + }, + Rounding::none(), + user_aux_5 + ) + ); + } + } + } + _ => { + // We shouldn't be here + } + } + + ui.painter().extend(shapes); + } else { + // Primary Input + let data: Vec = frequencies + .iter() + .zip(magnitudes.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + // Aux + let ax1_data: Vec = frequencies_ax1 + .iter() + .zip(magnitudes_ax1.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + let ax2_data: Vec = frequencies_ax2 + .iter() + .zip(magnitudes_ax2.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + let ax3_data: Vec = frequencies_ax3 + .iter() + .zip(magnitudes_ax3.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + let ax4_data: Vec = frequencies_ax4 + .iter() + .zip(magnitudes_ax4.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + let ax5_data: Vec = frequencies_ax5 + .iter() + .zip(magnitudes_ax5.iter()) + .map(|(freq, magnitude)| { + let y = pivot_frequency_slope(*freq, *magnitude, pivot, slope); + pos2( + freq.log10() * freq_scaler + x_shift, + (util::gain_to_db(y) * -1.0) * db_scaler + y_shift + ) + }) + .collect(); + + if en_guidelines.load(Ordering::SeqCst) { + let freqs: [f32; 12] = [ + 0.0, 10.0, 20.0, 50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0, 5000.0, 10000.0, 18000.0]; + let scaled_ref_freqs: Vec = freqs.iter().map(|num|{num.log10() * freq_scaler}).collect(); + for (num,scaled_num) in freqs.iter().zip(scaled_ref_freqs.iter()) { + shapes.push( + epaint::Shape::line_segment( + [ + Pos2::new(*scaled_num + x_shift, 515.0), + Pos2::new(*scaled_num + x_shift, 30.0) + ], + Stroke::new(0.5, Color32::GRAY) + ) + ); + ui.painter().text( + Pos2::new(scaled_num + 2.0 + x_shift, 510.0), + Align2::LEFT_CENTER, + *num, + FontId::monospace(12.0), + Color32::GRAY + ); + } + let sub_freqs: [f32; 18] = [ + 30.0,40.0,60.0,70.0,80.0,90.0,300.0,400.0,600.0,700.0,800.0,900.0,3000.0,4000.0,6000.0,7000.0,8000.0,9000.0]; + let scaled_sub_freqs: Vec = sub_freqs.iter().map(|num|{num.log10() * freq_scaler}).collect(); + for scaled_num in scaled_sub_freqs.iter() { + shapes.push( + epaint::Shape::line_segment( + [ + Pos2::new(*scaled_num + x_shift, 515.0), + Pos2::new(*scaled_num + x_shift, 30.0) + ], + Stroke::new(0.5, Color32::DARK_GRAY) + ) + ); + } } - _ => { - // We shouldn't be here + + // Draw whichever order next + match ontop.load(Ordering::SeqCst) { + 0 => { + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + } + 1 => { + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + } + 2 => { + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + } + 3 => { + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + } + 4 => { + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + } + 5 => { + if en_aux4.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax4_data, Stroke::new(1.0, final_aux_line_color_4))); } + if en_aux3.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax3_data, Stroke::new(1.0, final_aux_line_color_3))); } + if en_aux2.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax2_data, Stroke::new(1.0, final_aux_line_color_2))); } + if en_aux1.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax1_data, Stroke::new(1.0, final_aux_line_color))); } + if en_main.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(data, Stroke::new(1.0, final_primary_color))); } + if en_aux5.load(Ordering::SeqCst) { shapes.push(epaint::Shape::line(ax5_data, Stroke::new(1.0, final_aux_line_color_5))); } + } + _ => { + // We shouldn't be here + } } - } - ui.painter().extend(shapes); + ui.painter().extend(shapes); + } } else { let mut sum_data = samples.clone(); + let sbl: PlotPoints = scrolling_beat_lines + .iter() + .enumerate() + .map(|(i, sample)| { + [i as f64, *sample as f64] + }) + .collect(); + let sbl_line = Line::new(sbl) + .color(guidelines) + .stroke(Stroke::new(0.25, guidelines.linear_multiply(0.5))); + // Primary Input let data: PlotPoints = samples .iter() @@ -827,7 +1656,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; } else { @@ -848,7 +1677,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; let sum_temp = sum_data.get_mut(i).unwrap(); @@ -861,8 +1690,8 @@ impl Plugin for Scrollscope { }) .collect(); aux_line = Line::new(aux_data) - .color(aux_line_color) - .stroke(Stroke::new(1.0, aux_line_color)); + .color(user_aux_1) + .stroke(Stroke::new(1.0, user_aux_1)); let aux_data_2: PlotPoints = aux_samples_2 .iter() @@ -870,7 +1699,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; let sum_temp = sum_data.get_mut(i).unwrap(); @@ -883,8 +1712,8 @@ impl Plugin for Scrollscope { }) .collect(); aux_line_2 = Line::new(aux_data_2) - .color(aux_line_color_2) - .stroke(Stroke::new(1.0, aux_line_color_2)); + .color(user_aux_2) + .stroke(Stroke::new(1.0, user_aux_2)); let aux_data_3: PlotPoints = aux_samples_3 .iter() @@ -892,7 +1721,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; let sum_temp = sum_data.get_mut(i).unwrap(); @@ -905,8 +1734,8 @@ impl Plugin for Scrollscope { }) .collect(); aux_line_3 = Line::new(aux_data_3) - .color(aux_line_color_3) - .stroke(Stroke::new(1.0, aux_line_color_3)); + .color(user_aux_3) + .stroke(Stroke::new(1.0, user_aux_3)); let aux_data_4: PlotPoints = aux_samples_4 .iter() @@ -914,7 +1743,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; let sum_temp = sum_data.get_mut(i).unwrap(); @@ -927,8 +1756,8 @@ impl Plugin for Scrollscope { }) .collect(); aux_line_4 = Line::new(aux_data_4) - .color(aux_line_color_4) - .stroke(Stroke::new(1.0, aux_line_color_4)); + .color(user_aux_4) + .stroke(Stroke::new(1.0, user_aux_4)); let aux_data_5: PlotPoints = aux_samples_5 .iter() @@ -936,7 +1765,7 @@ impl Plugin for Scrollscope { .map(|(i, sample)| { let x: f64; let y: f64; - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { x = i as f64; y = *sample as f64; let sum_temp = sum_data.get_mut(i).unwrap(); @@ -949,10 +1778,10 @@ impl Plugin for Scrollscope { }) .collect(); aux_line_5 = Line::new(aux_data_5) - .color(aux_line_color_5) - .stroke(Stroke::new(1.0, aux_line_color_5)); + .color(user_aux_5) + .stroke(Stroke::new(1.0, user_aux_5)); - if *en_sum.lock().unwrap() { + if en_sum.load(Ordering::SeqCst) { // Summed audio line let sum_plotpoints: PlotPoints = sum_data .iter() @@ -964,8 +1793,8 @@ impl Plugin for Scrollscope { }) .collect(); sum_line = Line::new(sum_plotpoints) - .color(sum_line_color.linear_multiply(0.25)) - .stroke(Stroke::new(0.9, sum_line_color)); + .color(user_sum_line.linear_multiply(0.25)) + .stroke(Stroke::new(0.9, user_sum_line)); } // Show the Oscilloscope @@ -985,7 +1814,9 @@ impl Plugin for Scrollscope { // Format hover to blank or value .label_formatter(|_, _| "".to_owned()) .show(ui, |plot_ui| { - if *en_sum.lock().unwrap() { + plot_ui.line(sbl_line); + + if en_sum.load(Ordering::SeqCst) { // Draw the sum line first so it's furthest behind plot_ui.line(sum_line); } @@ -993,124 +1824,124 @@ impl Plugin for Scrollscope { // Figure out the lines to draw // Draw whichever order next - match *ontop.lock().unwrap() { + match ontop.load(Ordering::SeqCst) { 0 => { - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } } 1 => { - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } } 2 => { - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } } 3 => { - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } } 4 => { - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } } 5 => { - if *en_aux4.lock().unwrap() { + if en_aux4.load(Ordering::SeqCst) { plot_ui.line(aux_line_4); } - if *en_aux3.lock().unwrap() { + if en_aux3.load(Ordering::SeqCst) { plot_ui.line(aux_line_3); } - if *en_aux2.lock().unwrap() { + if en_aux2.load(Ordering::SeqCst) { plot_ui.line(aux_line_2); } - if *en_aux1.lock().unwrap() { + if en_aux1.load(Ordering::SeqCst) { plot_ui.line(aux_line); } - if *en_main.lock().unwrap() { + if en_main.load(Ordering::SeqCst) { plot_ui.line(line); } - if *en_aux5.lock().unwrap() { + if en_aux5.load(Ordering::SeqCst) { plot_ui.line(aux_line_5); } } @@ -1140,7 +1971,7 @@ impl Plugin for Scrollscope { }); // Put things back after drawing so process() isn't broken - if *dir_var.lock().unwrap() { + if dir_var.load(Ordering::SeqCst) { samples.make_contiguous().reverse(); aux_samples_1.make_contiguous().reverse(); aux_samples_2.make_contiguous().reverse(); @@ -1186,15 +2017,19 @@ impl Plugin for Scrollscope { let aux_3 = aux.inputs[3].as_slice_immutable(); let aux_4 = aux.inputs[4].as_slice_immutable(); - if !*self.show_analyzer.lock().unwrap() { + if !self.show_analyzer.load(Ordering::SeqCst) { for (b0, ax0, ax1, ax2, ax3, ax4) in izip!(raw_buffer, aux_0, aux_1, aux_2, aux_3, aux_4) { + let mut current_beat: f64 = context.transport().pos_beats().unwrap(); + let temp_current_beat: f64 = (current_beat * 10000.0 as f64).round() / 10000.0 as f64; + if temp_current_beat % 1.0 == 0.0 && context.transport().playing { + self.add_beat_line.store(true, Ordering::SeqCst); + } // Beat syncing control - if *self.sync_var.lock().unwrap() { + if self.sync_var.load(Ordering::SeqCst) { // Make the current bar precision a one thousandth of a beat - I couldn't find a better way to do this - let mut current_beat: f64 = context.transport().pos_beats().unwrap(); - if *self.alt_sync.lock().unwrap() { + if self.alt_sync.load(Ordering::SeqCst) { // Jitter reduction in timeline dependent DAWs let start_pos = context.transport().bar_start_pos_beats().unwrap(); if current_beat < start_pos { @@ -1211,28 +2046,29 @@ impl Plugin for Scrollscope { // Tracks based off beat number for other daws - this is a mutex instead of atomic for locking if current_beat % 4.0 <= threshold { // If this is the first time we've been under our threshold, reset our drawing - if *self.threshold_combo.lock().unwrap() == 0 { + if self.threshold_combo.load(Ordering::SeqCst) == 0 { // I'm wondering if this reassign was part of the jitter issue instead of being an update so I changed that too - *self.in_place_index.lock().unwrap() = 0; - //self.skip_counter = 0; + //*self.in_place_index.lock().unwrap() = 0; + self.in_place_index.store(0, Ordering::SeqCst); } // Increment here so multiple threshold hits in a row don't stack - *self.threshold_combo.lock().unwrap() += 1; + self.threshold_combo.fetch_add(1, Ordering::SeqCst); + //*self.threshold_combo.lock().unwrap() += 1; } else { // We haven't met threshold, keep it 0 - *self.threshold_combo.lock().unwrap() = 0; + self.in_place_index.store(0, Ordering::SeqCst); } } BeatSync::Beat => { // Tracks based off beat number for other daws - this is a mutex instead of atomic for locking if current_beat % 1.0 <= threshold { - if *self.threshold_combo.lock().unwrap() == 0 { - *self.in_place_index.lock().unwrap() = 0; + if self.threshold_combo.load(Ordering::SeqCst) == 0 { + self.in_place_index.store(0, Ordering::SeqCst); //self.skip_counter = 0; } - *self.threshold_combo.lock().unwrap() += 1; + self.threshold_combo.fetch_add(1, Ordering::SeqCst); } else { - *self.threshold_combo.lock().unwrap() = 0; + self.threshold_combo.store(0, Ordering::SeqCst); } } } @@ -1244,7 +2080,7 @@ impl Plugin for Scrollscope { if current_beat % 4.0 == 0.0 { // Reset our index to the sample vecdeques //self.in_place_index = Arc::new(Mutex::new(0)); - *self.in_place_index.lock().unwrap() = 0; + self.in_place_index.store(0, Ordering::SeqCst); self.skip_counter = 0; } } @@ -1252,7 +2088,7 @@ impl Plugin for Scrollscope { if current_beat % 1.0 == 0.0 { // Reset our index to the sample vecdeques //self.in_place_index = Arc::new(Mutex::new(0)); - *self.in_place_index.lock().unwrap() = 0; + self.in_place_index.store(0, Ordering::SeqCst); self.skip_counter = 0; } } @@ -1325,10 +2161,11 @@ impl Plugin for Scrollscope { let mut aux_guard_3 = self.aux_samples_3.lock().unwrap(); let mut aux_guard_4 = self.aux_samples_4.lock().unwrap(); let mut aux_guard_5 = self.aux_samples_5.lock().unwrap(); + let mut sbl_guard = self.scrolling_beat_lines.lock().unwrap(); // If beat sync is on, we need to process changes in place - if *self.sync_var.lock().unwrap() { + if self.sync_var.load(Ordering::SeqCst) { // Access the in place index - let ipi_index: usize = *self.in_place_index.lock().unwrap() as usize; + let ipi_index: usize = self.in_place_index.load(Ordering::SeqCst) as usize; // Check if our indexes exists let main_element: Option<&f32> = guard.get(ipi_index); let aux_element: Option<&f32> = aux_guard.get(ipi_index); @@ -1372,10 +2209,17 @@ impl Plugin for Scrollscope { *aux_index_value_5 = visual_aux_sample_5; } // Increment our in_place_index now that we have substituted - *self.in_place_index.lock().unwrap() = ipi_index as i32 + 1; + self.in_place_index.fetch_add(1, Ordering::SeqCst); } // Beat sync is off: allow "scroll" else { + if self.add_beat_line.load(Ordering::SeqCst) { + sbl_guard.push_front(1.0); + sbl_guard.push_front(-1.0); + self.add_beat_line.store(false, Ordering::SeqCst); + } else { + sbl_guard.push_front(0.0); + } guard.push_front(visual_main_sample); aux_guard.push_front(visual_aux_sample_1); aux_guard_2.push_front(visual_aux_sample_2); @@ -1405,6 +2249,9 @@ impl Plugin for Scrollscope { if aux_guard_5.len() != scroll { aux_guard_5.resize(scroll, 0.0); } + if sbl_guard.len() != scroll { + sbl_guard.resize(scroll, 0.0); + } } self.skip_counter += 1; } @@ -1527,10 +2374,11 @@ impl Vst3Plugin for Scrollscope { nih_export_clap!(Scrollscope); nih_export_vst3!(Scrollscope); + fn pivot_frequency_slope(freq: f32, magnitude: f32, f0: f32, slope: f32) -> f32{ if freq < f0 { magnitude * (freq / f0).powf(slope / 20.0) } else { magnitude * (f0 / freq).powf(slope / 20.0) } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..361b8bf --- /dev/null +++ b/src/main.rs @@ -0,0 +1,8 @@ +// src/main.rs for standalone only + +use nih_plug::prelude::*; +use scrollscope::Scrollscope; + +fn main() { + nih_export_standalone::(); +} \ No newline at end of file diff --git a/src/slim_checkbox.rs b/src/slim_checkbox.rs index 6aa136e..610fccb 100644 --- a/src/slim_checkbox.rs +++ b/src/slim_checkbox.rs @@ -1,7 +1,10 @@ // This is a copy of egui checkbox just with slimmer padding/spacing needed in Scrollscope +// I also added a version to work with Atomic structures // ---------------------------------------------------------------------------- +use std::sync::atomic::{AtomicBool, Ordering}; + use nih_plug_egui::egui::{ epaint, pos2, vec2, NumExt, Response, Sense, Shape, TextStyle, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType, @@ -26,6 +29,100 @@ pub struct SlimCheckbox<'a> { text: WidgetText, } +#[must_use = "You should put this widget in an ui with `ui.add(widget);`"] +pub struct AtomicSlimCheckbox<'a> { + checked: &'a AtomicBool, + text: WidgetText, +} + +impl<'a> AtomicSlimCheckbox<'a> { + pub fn new(checked: &'a AtomicBool, text: impl Into) -> Self { + AtomicSlimCheckbox { + checked, + text: text.into(), + } + } +} + +impl<'a> Widget for AtomicSlimCheckbox<'a> { + fn ui(self, ui: &mut Ui) -> Response { + let AtomicSlimCheckbox { checked, text } = self; + + let spacing = &ui.spacing(); + let icon_width = spacing.icon_width; + let icon_spacing = spacing.icon_spacing; + + let (text, mut desired_size) = if text.is_empty() { + (None, vec2(icon_width, 0.0)) + } else { + let total_extra = vec2(icon_width + icon_spacing, 0.0); + + let wrap_width = ui.available_width() - total_extra.x; + let text = text.into_galley(ui, None, wrap_width, TextStyle::Button); + + let mut desired_size = total_extra + text.size(); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //This is the only piece I changed -Ardura + desired_size = + desired_size.at_least(vec2(spacing.interact_size.x * 0.45, spacing.interact_size.y)); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + (Some(text), desired_size) + }; + + desired_size = desired_size.at_least(Vec2::splat(spacing.interact_size.y)); + desired_size.y = desired_size.y.max(icon_width); + let (rect, mut response) = ui.allocate_exact_size(desired_size, Sense::click()); + + if response.clicked() { + checked.fetch_xor(true, Ordering::SeqCst); + response.mark_changed(); + } + response.widget_info(|| { + WidgetInfo::selected( + WidgetType::Checkbox, + checked.load(Ordering::SeqCst), + text.as_ref().map_or("", |x| x.text()), + ) + }); + + if ui.is_rect_visible(rect) { + // let visuals = ui.style().interact_selectable(&response, *checked); // too colorful + let visuals = ui.style().interact(&response); + let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect); + ui.painter().add(epaint::RectShape { + rect: big_icon_rect.expand(visuals.expansion), + rounding: visuals.rounding, + fill: visuals.bg_fill, + stroke: visuals.bg_stroke, + }); + + if checked.load(Ordering::SeqCst) { + // Check mark: + ui.painter().add(Shape::line( + vec![ + pos2(small_icon_rect.left(), small_icon_rect.center().y), + pos2(small_icon_rect.center().x, small_icon_rect.bottom()), + pos2(small_icon_rect.right(), small_icon_rect.top()), + ], + visuals.fg_stroke, + )); + } + if let Some(text) = text { + let text_pos = pos2( + rect.min.x + icon_width + icon_spacing, + rect.center().y - 0.5 * text.size().y, + ); + text.paint_with_visuals(ui.painter(), text_pos, visuals); + } + } + + response + } +} + + impl<'a> SlimCheckbox<'a> { pub fn new(checked: &'a mut bool, text: impl Into) -> Self { SlimCheckbox { From a67c255738f005e1fafa8b62c42c68895dcd560d Mon Sep 17 00:00:00 2001 From: ardura Date: Wed, 1 May 2024 11:56:35 -0700 Subject: [PATCH 2/5] Trying to fix Linux build failure because of ALSA --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a731341..e410d41 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -38,7 +38,7 @@ jobs: - uses: ConorMacBride/install-package@v1.1.0 with: # Packages to install with apt on Linux - apt: libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxkbcommon-x11-dev libatk1.0-dev build-essential libgtk-3-dev libxcb-dri2-0-dev libxcb-icccm4-dev libx11-xcb-dev + apt: libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxkbcommon-x11-dev libatk1.0-dev build-essential libgtk-3-dev libxcb-dri2-0-dev libxcb-icccm4-dev libx11-xcb-dev librust-alsa-sys-dev libasound2-dev - uses: actions/checkout@v3 - name: Run bundler run: cargo xtask bundle scrollscope --profile release From 7a27937ff68384ecf9c245e8d0fef7990dfbbaee Mon Sep 17 00:00:00 2001 From: ardura Date: Wed, 1 May 2024 11:59:12 -0700 Subject: [PATCH 3/5] trying to fix JACK error now on linux build --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e410d41..0fc98ad 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -38,7 +38,7 @@ jobs: - uses: ConorMacBride/install-package@v1.1.0 with: # Packages to install with apt on Linux - apt: libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxkbcommon-x11-dev libatk1.0-dev build-essential libgtk-3-dev libxcb-dri2-0-dev libxcb-icccm4-dev libx11-xcb-dev librust-alsa-sys-dev libasound2-dev + apt: libgl1-mesa-dev libglu1-mesa-dev libxcursor-dev libxkbcommon-x11-dev libatk1.0-dev build-essential libgtk-3-dev libxcb-dri2-0-dev libxcb-icccm4-dev libx11-xcb-dev librust-alsa-sys-dev libasound2-dev libjack-dev - uses: actions/checkout@v3 - name: Run bundler run: cargo xtask bundle scrollscope --profile release From 7a47ab72bddc06ea9fcc19b377441073c66572b9 Mon Sep 17 00:00:00 2001 From: ardura Date: Wed, 1 May 2024 12:14:31 -0700 Subject: [PATCH 4/5] Fix Windows build missing artifacts --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0fc98ad..3cffb72 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -56,5 +56,5 @@ jobs: - uses: actions/upload-artifact@v4 with: name: windows_build - path: target/bundled/scrollscope.vst3 + path: target/bundled/* if-no-files-found: warn From 59ed81627d641d7c8d34972ad8a417a4b28cbe66 Mon Sep 17 00:00:00 2001 From: ardura Date: Wed, 1 May 2024 12:19:48 -0700 Subject: [PATCH 5/5] Readme info added --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7a02e54..af34a39 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ inactive_bg = 60,60,60 - Reordering waveforms to display main or sidechain on top - Beat synchronization and Bar Synchronization - Support for different DAWs with different time-tracking modes (Alt Sync option) +- Standalone version. I've run it on Windows to test with options like: ./scrollscope.exe --input-device 'Stereo Mix (Realtek(R) Audio)' --sample-rate 48000 +Note that with the standalone version, I'm not sure how to setup the aux inputs sorry - I've just used the standalone generation in nih-plug. This plugin was made possible thanks to the Nih-Plug Rust Library and the egui GUI library