diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 85f1378..67ae99f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -130,14 +130,6 @@ jobs: # LLVM/libclang for bindgen echo "LIBCLANG_PATH=C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - - name: Setup icons - shell: bash - run: | - mkdir -p lightningbeam-ui/lightningbeam-editor/assets/icons - cp -f src-tauri/icons/32x32.png lightningbeam-ui/lightningbeam-editor/assets/icons/ - cp -f src-tauri/icons/128x128.png lightningbeam-ui/lightningbeam-editor/assets/icons/ - cp -f src-tauri/icons/icon.png lightningbeam-ui/lightningbeam-editor/assets/icons/256x256.png - - name: Stage factory presets shell: bash run: | @@ -327,7 +319,7 @@ jobs: mkdir -p "$APP/Contents/Resources/presets" cp lightningbeam-ui/target/release/lightningbeam-editor "$APP/Contents/MacOS/" - cp src-tauri/icons/icon.icns "$APP/Contents/Resources/lightningbeam-editor.icns" + cp lightningbeam-ui/lightningbeam-editor/assets/icons/icon.icns "$APP/Contents/Resources/lightningbeam-editor.icns" cp -r lightningbeam-ui/lightningbeam-editor/assets/presets/* "$APP/Contents/Resources/presets/" cat > "$APP/Contents/Info.plist" << EOF diff --git a/.gitignore b/.gitignore index 35df03e..ada2bc0 100644 --- a/.gitignore +++ b/.gitignore @@ -28,8 +28,6 @@ dist-ssr .gitignore # Build -src-tauri/gen -src-tauri/target lightningbeam-core/target daw-backend/target target/ diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 945104b..374de79 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -486,8 +486,7 @@ lightningbeam-2/ │ ├── synth/ # Synthesizers │ └── midi/ # MIDI handling │ -├── src-tauri/ # Legacy Tauri backend -├── src/ # Legacy JavaScript frontend +├── src/ # Legacy JavaScript frontend (browser-only) ├── CONTRIBUTING.md # Contributor guide ├── ARCHITECTURE.md # This file ├── README.md # Project overview diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bcb6d18..59a9544 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,8 +122,7 @@ lightningbeam-2/ │ │ ├── track.rs # Track management │ │ └── project.rs # Project state │ └── effects/ # Audio effects -├── src-tauri/ # Legacy Tauri backend -└── src/ # Legacy JavaScript frontend +└── src/ # Legacy JavaScript frontend (browser-only) ``` ## Making Changes diff --git a/src-tauri/icons/icon.icns b/lightningbeam-ui/lightningbeam-editor/assets/icons/icon.icns similarity index 100% rename from src-tauri/icons/icon.icns rename to lightningbeam-ui/lightningbeam-editor/assets/icons/icon.icns diff --git a/lightningbeam-ui/lightningbeam-editor/src/main.rs b/lightningbeam-ui/lightningbeam-editor/src/main.rs index cc55b97..09b04c6 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/main.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/main.rs @@ -140,7 +140,7 @@ fn main() -> eframe::Result { } // Load window icon - let icon_data = include_bytes!("../../../src-tauri/icons/icon.png"); + let icon_data = include_bytes!("../assets/icons/256x256.png"); let icon_image = match image::load_from_memory(icon_data) { Ok(img) => { let rgba = img.to_rgba8(); diff --git a/package.json b/package.json index 4bc245d..979a874 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,10 @@ "version": "0.1.0", "type": "module", "scripts": { - "tauri": "tauri", "test": "wdio run wdio.conf.js", "test:watch": "wdio run wdio.conf.js --watch" }, "devDependencies": { - "@tauri-apps/cli": "^2", "@wdio/cli": "^9.20.0", "@wdio/globals": "^9.17.0", "@wdio/local-runner": "8", @@ -19,9 +17,6 @@ }, "dependencies": { "@ffmpeg/ffmpeg": "^0.12.10", - "@tauri-apps/plugin-dialog": "~2", - "@tauri-apps/plugin-fs": "~2", - "@tauri-apps/plugin-log": "^2.2.0", "ffmpeg": "^0.0.4", "ffmpeg.js": "^4.2.9003" } diff --git a/packaging/Makefile b/packaging/Makefile index 67ba247..9b84b28 100644 --- a/packaging/Makefile +++ b/packaging/Makefile @@ -20,9 +20,7 @@ pkgbuild: setup-icons setup-icons: @echo "==> Setting up icons..." @mkdir -p $(EDITOR)/assets/icons - @cp -u $(REPO_ROOT)/src-tauri/icons/32x32.png $(EDITOR)/assets/icons/ 2>/dev/null || true - @cp -u $(REPO_ROOT)/src-tauri/icons/128x128.png $(EDITOR)/assets/icons/ 2>/dev/null || true - @cp -u $(REPO_ROOT)/src-tauri/icons/icon.png $(EDITOR)/assets/icons/256x256.png 2>/dev/null || true + @# Icons are committed under $(EDITOR)/assets/icons (32x32, 128x128, 256x256, icon.icns). @echo " Icons ready" clean: diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock deleted file mode 100644 index 11da83c..0000000 --- a/src-tauri/Cargo.lock +++ /dev/null @@ -1,6708 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" -dependencies = [ - "alsa-sys", - "bitflags 2.8.0", - "cfg-if", - "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 = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_log-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" - -[[package]] -name = "android_logger" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b07e8e73d720a1f2e4b6014766e6039fd2e96a4fa44e2a78d0e1fa2ff49826" -dependencies = [ - "android_log-sys", - "env_filter", - "log", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "ascii" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" - -[[package]] -name = "ashpd" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c39d707614dbcc6bed00015539f488d8e3fe3e66ed60961efc0c90f4b380b3" -dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.8.5", - "raw-window-handle", - "serde", - "serde_repr", - "tokio", - "url", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "zbus", -] - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "async-trait" -version = "0.1.85" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "atk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" -dependencies = [ - "atk-sys", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bindgen" -version = "0.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" -dependencies = [ - "bitflags 2.8.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.96", -] - -[[package]] -name = "bindgen" -version = "0.72.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" -dependencies = [ - "bitflags 2.8.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash 2.1.1", - "shlex", - "syn 2.0.96", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" -dependencies = [ - "serde", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - -[[package]] -name = "borsh" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb65153674e51d3a42c8f27b05b9508cea85edfaade8aa46bc8fc18cecdfef3" -dependencies = [ - "borsh-derive", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a396e17ad94059c650db3d253bb6e25927f1eb462eede7e7a153bb6e75dce0a7" -dependencies = [ - "once_cell", - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "brotli" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byte-unit" -version = "5.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174" -dependencies = [ - "rust_decimal", - "serde", - "utf8-width", -] - -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bytemuck" -version = "1.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" -dependencies = [ - "serde", -] - -[[package]] -name = "cairo-rs" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" -dependencies = [ - "bitflags 2.8.0", - "cairo-sys-rs", - "glib", - "libc", - "once_cell", - "thiserror 1.0.69", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror 2.0.11", -] - -[[package]] -name = "cargo_toml" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472" -dependencies = [ - "serde", - "toml 0.8.19", -] - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - -[[package]] -name = "cc" -version = "1.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfb" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" -dependencies = [ - "byteorder", - "fnv", - "uuid", -] - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chrono" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.6", -] - -[[package]] -name = "chunked_transfer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.6", -] - -[[package]] -name = "cocoa" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" -dependencies = [ - "bitflags 2.8.0", - "block", - "cocoa-foundation", - "core-foundation 0.10.0", - "core-graphics", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" -dependencies = [ - "bitflags 2.8.0", - "block", - "core-foundation 0.10.0", - "core-graphics-types", - "libc", - "objc", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "compact_str" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" -dependencies = [ - "castaway", - "cfg-if", - "itoa 1.0.14", - "ryu", - "static_assertions", -] - -[[package]] -name = "concurrent-queue" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "time", - "version_check", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" -dependencies = [ - "bitflags 2.8.0", - "core-foundation 0.10.0", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.8.0", - "core-foundation 0.10.0", - "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.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceec7a6067e62d6f931a2baf6f3a751f4a892595bcec1461a3c94ef9949864b6" -dependencies = [ - "bindgen 0.72.1", -] - -[[package]] -name = "coremidi" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7847ca018a67204508b77cb9e6de670125075f7464fff5f673023378fa34f5" -dependencies = [ - "core-foundation 0.9.4", - "core-foundation-sys", - "coremidi-sys", -] - -[[package]] -name = "coremidi-sys" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9504310988d938e49fff1b5f1e56e3dafe39bb1bae580c19660b58b83a191e" -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.1", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2", - "ndk 0.8.0", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.54.0", -] - -[[package]] -name = "cpufeatures" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.8.0", - "crossterm_winapi", - "libc", - "mio 0.8.11", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "cssparser" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa 0.4.8", - "matches", - "phf 0.8.0", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn 2.0.96", -] - -[[package]] -name = "ctor" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" -dependencies = [ - "quote", - "syn 2.0.96", -] - -[[package]] -name = "darling" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.96", -] - -[[package]] -name = "darling_macro" -version = "0.20.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "dasp_envelope" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec617ce7016f101a87fe85ed44180839744265fae73bb4aa43e7ece1b7668b6" -dependencies = [ - "dasp_frame", - "dasp_peak", - "dasp_ring_buffer", - "dasp_rms", - "dasp_sample", -] - -[[package]] -name = "dasp_frame" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a3937f5fe2135702897535c8d4a5553f8b116f76c1529088797f2eee7c5cd6" -dependencies = [ - "dasp_sample", -] - -[[package]] -name = "dasp_graph" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b17b071a1fa4c78054730085620c3bb22dc5fded00483312557a3fdf26d7c4" -dependencies = [ - "dasp_frame", - "dasp_ring_buffer", - "dasp_signal", - "dasp_slice", - "petgraph 0.5.1", -] - -[[package]] -name = "dasp_interpolate" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc975a6563bb7ca7ec0a6c784ead49983a21c24835b0bc96eea11ee407c7486" -dependencies = [ - "dasp_frame", - "dasp_ring_buffer", - "dasp_sample", -] - -[[package]] -name = "dasp_peak" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf88559d79c21f3d8523d91250c397f9a15b5fc72fbb3f87fdb0a37b79915bf" -dependencies = [ - "dasp_frame", - "dasp_sample", -] - -[[package]] -name = "dasp_ring_buffer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d79e19b89618a543c4adec9c5a347fe378a19041699b3278e616e387511ea1" - -[[package]] -name = "dasp_rms" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6c5dcb30b7e5014486e2822537ea2beae50b19722ffe2ed7549ab03774575aa" -dependencies = [ - "dasp_frame", - "dasp_ring_buffer", - "dasp_sample", -] - -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "dasp_signal" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa1ab7d01689c6ed4eae3d38fe1cea08cba761573fbd2d592528d55b421077e7" -dependencies = [ - "dasp_envelope", - "dasp_frame", - "dasp_interpolate", - "dasp_peak", - "dasp_ring_buffer", - "dasp_rms", - "dasp_sample", - "dasp_window", -] - -[[package]] -name = "dasp_slice" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1c7335d58e7baedafa516cb361360ff38d6f4d3f9d9d5ee2a2fc8e27178fa1" -dependencies = [ - "dasp_frame", - "dasp_sample", -] - -[[package]] -name = "dasp_window" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ded7b88821d2ce4e8b842c9f1c86ac911891ab89443cc1de750cae764c5076" -dependencies = [ - "dasp_sample", -] - -[[package]] -name = "daw-backend" -version = "0.1.0" -dependencies = [ - "base64 0.22.1", - "cpal", - "crossterm", - "dasp_envelope", - "dasp_graph", - "dasp_interpolate", - "dasp_peak", - "dasp_ring_buffer", - "dasp_rms", - "dasp_sample", - "dasp_signal", - "hound", - "midir", - "midly", - "pathdiff", - "petgraph 0.6.5", - "rand 0.8.5", - "ratatui", - "rtrb", - "serde", - "serde_json", - "symphonia", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.96", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[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 = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading 0.8.6", -] - -[[package]] -name = "dlopen2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" -dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", -] - -[[package]] -name = "dlopen2_derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dpi" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" -dependencies = [ - "serde", -] - -[[package]] -name = "dtoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "embed-resource" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379" -dependencies = [ - "cc", - "memchr", - "rustc_version", - "toml 0.8.19", - "vswhom", - "winreg", -] - -[[package]] -name = "embed_plist" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "endi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" - -[[package]] -name = "enumflags2" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "env_filter" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "erased-serde" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" -dependencies = [ - "serde", - "typeid", -] - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "event-listener" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "extended" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "fern" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" -dependencies = [ - "log", -] - -[[package]] -name = "ffmpeg-next" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da02698288e0275e442a47fc12ca26d50daf0d48b15398ba5906f20ac2e2a9f9" -dependencies = [ - "bitflags 2.8.0", - "ffmpeg-sys-next", - "libc", -] - -[[package]] -name = "ffmpeg-sys-next" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e9c75ebd4463de9d8998fb134ba26347fe5faee62fabf0a4b4d41bd500b4ad" -dependencies = [ - "bindgen 0.70.1", - "cc", - "libc", - "num_cpus", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset", - "rustc_version", -] - -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gdk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" -dependencies = [ - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" -dependencies = [ - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", - "once_cell", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gdk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkwayland-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" -dependencies = [ - "gdk-sys", - "glib-sys", - "gobject-sys", - "libc", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkx11" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" -dependencies = [ - "gdk", - "gdkx11-sys", - "gio", - "glib", - "libc", - "x11", -] - -[[package]] -name = "gdkx11-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" -dependencies = [ - "gdk-sys", - "glib-sys", - "libc", - "system-deps", - "x11", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "gio" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "gio-sys", - "glib", - "libc", - "once_cell", - "pin-project-lite", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "gio-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", -] - -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.8.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 2.0.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "gobject-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gtk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" -dependencies = [ - "atk", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", -] - -[[package]] -name = "gtk3-macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hound" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" - -[[package]] -name = "html5ever" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "http" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.14", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "http-range" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "httparse", - "itoa 1.0.14", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core 0.52.0", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ico" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" -dependencies = [ - "byteorder", - "png", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-traits", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "infer" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc150e5ce2330295b8616ce0e3f53250e53af31759a9dbedad1621ba29151847" -dependencies = [ - "cfb", -] - -[[package]] -name = "ipnet" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" - -[[package]] -name = "is-docker" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" -dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" - -[[package]] -name = "javascriptcore-rs" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" -dependencies = [ - "bitflags 1.3.2", - "glib", - "javascriptcore-rs-sys", -] - -[[package]] -name = "javascriptcore-rs-sys" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[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 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "jpeg-decoder" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07" - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "json-patch" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863726d7afb6bc2590eeff7135d923545e5e964f004c2ccf8716c25e70a86f08" -dependencies = [ - "jsonptr", - "serde", - "serde_json", - "thiserror 1.0.69", -] - -[[package]] -name = "jsonptr" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dea2b27dd239b2556ed7a25ba842fe47fd602e7fc7433c2a8d6106d4d9edd70" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "keyboard-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" -dependencies = [ - "bitflags 2.8.0", - "serde", - "unicode-segmentation", -] - -[[package]] -name = "kuchikiki" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" -dependencies = [ - "cssparser", - "html5ever", - "indexmap 1.9.3", - "matches", - "selectors", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libappindicator" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" -dependencies = [ - "glib", - "gtk", - "gtk-sys", - "libappindicator-sys", - "log", -] - -[[package]] -name = "libappindicator-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" -dependencies = [ - "gtk-sys", - "libloading 0.7.4", - "once_cell", -] - -[[package]] -name = "libc" -version = "0.2.169" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.8.0", - "libc", -] - -[[package]] -name = "lightningbeam" -version = "0.1.0" -dependencies = [ - "chrono", - "cpal", - "daw-backend", - "ffmpeg-next", - "image", - "log", - "lru", - "rtrb", - "serde", - "serde_json", - "tauri", - "tauri-build", - "tauri-plugin-dialog", - "tauri-plugin-fs", - "tauri-plugin-log", - "tauri-plugin-shell", - "tiny_http", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "litemap" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" -dependencies = [ - "value-bag", -] - -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.2", -] - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "mach2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "markup5ever" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" -dependencies = [ - "log", - "phf 0.10.1", - "phf_codegen 0.10.0", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[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 = "midly" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207d755f4cb882d20c4da58d707ca9130a0c9bc5061f657a4f299b8e36362b7a" -dependencies = [ - "rayon", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "muda" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484" -dependencies = [ - "crossbeam-channel", - "dpi", - "gtk", - "keyboard-types", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "once_cell", - "png", - "serde", - "thiserror 1.0.69", - "windows-sys 0.59.0", -] - -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.8.0", - "jni-sys", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum", - "thiserror 1.0.69", -] - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.8.0", - "jni-sys", - "log", - "ndk-sys 0.6.0+11769913", - "num_enum", - "raw-window-handle", - "thiserror 1.0.69", -] - -[[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 = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.8.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[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 = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[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.96", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" -dependencies = [ - "cc", -] - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.8.0", - "block2", - "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2", - "objc2", - "objc2-contacts", - "objc2-foundation", -] - -[[package]] -name = "objc2-encode" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.8.0", - "block2", - "dispatch", - "libc", - "objc2", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation", - "objc2-link-presentation", - "objc2-quartz-core", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2", - "objc2", - "objc2-foundation", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-core-location", - "objc2-foundation", -] - -[[package]] -name = "objc2-web-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" -dependencies = [ - "bitflags 2.8.0", - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk 0.8.0", - "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.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "open" -version = "5.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" -dependencies = [ - "dunce", - "is-wsl", - "libc", - "pathdiff", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "os_pipe" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "pango" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" -dependencies = [ - "gio", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset 0.2.0", - "indexmap 1.9.3", -] - -[[package]] -name = "petgraph" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" -dependencies = [ - "fixedbitset 0.4.2", - "indexmap 2.7.0", -] - -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_macros 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher 1.0.1", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" - -[[package]] -name = "plist" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" -dependencies = [ - "base64 0.22.1", - "indexmap 2.7.0", - "quick-xml 0.32.0", - "serde", - "time", -] - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[package]] -name = "proc-macro-crate" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" -dependencies = [ - "toml_edit 0.22.22", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "1.0.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quick-xml" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" -dependencies = [ - "memchr", -] - -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "ratatui" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" -dependencies = [ - "bitflags 2.8.0", - "cassowary", - "compact_str", - "crossterm", - "itertools 0.12.1", - "lru", - "paste", - "stability", - "strum", - "unicode-segmentation", - "unicode-truncate", - "unicode-width", -] - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" -dependencies = [ - "bitflags 2.8.0", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.15", - "libredox", - "thiserror 1.0.69", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "reqwest" -version = "0.12.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-util", - "tower", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "windows-registry", -] - -[[package]] -name = "rfd" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a24763657bff09769a8ccf12c8b8a50416fb035fe199263b4c5071e4e3f006f" -dependencies = [ - "ashpd", - "block2", - "core-foundation 0.10.0", - "core-foundation-sys", - "glib-sys", - "gobject-sys", - "gtk-sys", - "js-sys", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "raw-window-handle", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "rkyv" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rtrb" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba" - -[[package]] -name = "rust_decimal" -version = "1.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" -dependencies = [ - "arrayvec", - "borsh", - "bytes", - "num-traits", - "rand 0.8.5", - "rkyv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" -dependencies = [ - "bitflags 2.8.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustversion" -version = "1.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schemars" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" -dependencies = [ - "dyn-clone", - "indexmap 1.9.3", - "schemars_derive", - "serde", - "serde_json", - "url", - "uuid", -] - -[[package]] -name = "schemars_derive" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.96", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "selectors" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" -dependencies = [ - "bitflags 1.3.2", - "cssparser", - "derive_more", - "fxhash", - "log", - "matches", - "phf 0.8.0", - "phf_codegen 0.8.0", - "precomputed-hash", - "servo_arc", - "smallvec", - "thin-slice", -] - -[[package]] -name = "semver" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" -dependencies = [ - "serde", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde-untagged" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2676ba99bd82f75cae5cbd2c8eda6fa0b8760f18978ea840e980dd5567b5c5b6" -dependencies = [ - "erased-serde", - "serde", - "typeid", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "serde_derive_internals" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "serde_json" -version = "1.0.135" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" -dependencies = [ - "itoa 1.0.14", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa 1.0.14", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.7.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "serialize-to-javascript" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" -dependencies = [ - "serde", - "serde_json", - "serialize-to-javascript-impl", -] - -[[package]] -name = "serialize-to-javascript-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "servo_arc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shared_child" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" -dependencies = [ - "libc", - "mio 0.8.11", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "softbuffer" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" -dependencies = [ - "bytemuck", - "cfg_aliases", - "core-graphics", - "foreign-types", - "js-sys", - "log", - "objc2", - "objc2-foundation", - "objc2-quartz-core", - "raw-window-handle", - "redox_syscall", - "wasm-bindgen", - "web-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "soup3" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" -dependencies = [ - "futures-channel", - "gio", - "glib", - "libc", - "soup3-sys", -] - -[[package]] -name = "soup3-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "stability" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" -dependencies = [ - "quote", - "syn 2.0.96", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro2", - "quote", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.96", -] - -[[package]] -name = "swift-rs" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4057c98e2e852d51fdcfca832aac7b571f6b351ad159f9eda5db1655f8d0c4d7" -dependencies = [ - "base64 0.21.7", - "serde", - "serde_json", -] - -[[package]] -name = "symphonia" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" -dependencies = [ - "lazy_static", - "symphonia-bundle-flac", - "symphonia-bundle-mp3", - "symphonia-codec-aac", - "symphonia-codec-adpcm", - "symphonia-codec-alac", - "symphonia-codec-pcm", - "symphonia-codec-vorbis", - "symphonia-core", - "symphonia-format-caf", - "symphonia-format-isomp4", - "symphonia-format-mkv", - "symphonia-format-ogg", - "symphonia-format-riff", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-bundle-flac" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" -dependencies = [ - "log", - "symphonia-core", - "symphonia-metadata", - "symphonia-utils-xiph", -] - -[[package]] -name = "symphonia-bundle-mp3" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" -dependencies = [ - "lazy_static", - "log", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-codec-aac" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c263845aa86881416849c1729a54c7f55164f8b96111dba59de46849e73a790" -dependencies = [ - "lazy_static", - "log", - "symphonia-core", -] - -[[package]] -name = "symphonia-codec-adpcm" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dddc50e2bbea4cfe027441eece77c46b9f319748605ab8f3443350129ddd07f" -dependencies = [ - "log", - "symphonia-core", -] - -[[package]] -name = "symphonia-codec-alac" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8413fa754942ac16a73634c9dfd1500ed5c61430956b33728567f667fdd393ab" -dependencies = [ - "log", - "symphonia-core", -] - -[[package]] -name = "symphonia-codec-pcm" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95" -dependencies = [ - "log", - "symphonia-core", -] - -[[package]] -name = "symphonia-codec-vorbis" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73" -dependencies = [ - "log", - "symphonia-core", - "symphonia-utils-xiph", -] - -[[package]] -name = "symphonia-core" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af" -dependencies = [ - "arrayvec", - "bitflags 1.3.2", - "bytemuck", - "lazy_static", - "log", -] - -[[package]] -name = "symphonia-format-caf" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8faf379316b6b6e6bbc274d00e7a592e0d63ff1a7e182ce8ba25e24edd3d096" -dependencies = [ - "log", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-format-isomp4" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243739585d11f81daf8dac8d9f3d18cc7898f6c09a259675fc364b382c30e0a5" -dependencies = [ - "encoding_rs", - "log", - "symphonia-core", - "symphonia-metadata", - "symphonia-utils-xiph", -] - -[[package]] -name = "symphonia-format-mkv" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122d786d2c43a49beb6f397551b4a050d8229eaa54c7ddf9ee4b98899b8742d0" -dependencies = [ - "lazy_static", - "log", - "symphonia-core", - "symphonia-metadata", - "symphonia-utils-xiph", -] - -[[package]] -name = "symphonia-format-ogg" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb" -dependencies = [ - "log", - "symphonia-core", - "symphonia-metadata", - "symphonia-utils-xiph", -] - -[[package]] -name = "symphonia-format-riff" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f" -dependencies = [ - "extended", - "log", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-metadata" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16" -dependencies = [ - "encoding_rs", - "lazy_static", - "log", - "symphonia-core", -] - -[[package]] -name = "symphonia-utils-xiph" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16" -dependencies = [ - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml 0.8.19", - "version-compare", -] - -[[package]] -name = "tao" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3731d04d4ac210cd5f344087733943b9bfb1a32654387dad4d1c70de21aee2c9" -dependencies = [ - "bitflags 2.8.0", - "cocoa", - "core-foundation 0.10.0", - "core-graphics", - "crossbeam-channel", - "dispatch", - "dlopen2", - "dpi", - "gdkwayland-sys", - "gdkx11-sys", - "gtk", - "jni", - "lazy_static", - "libc", - "log", - "ndk 0.9.0", - "ndk-context", - "ndk-sys 0.6.0+11769913", - "objc", - "once_cell", - "parking_lot", - "raw-window-handle", - "scopeguard", - "tao-macros", - "unicode-segmentation", - "url", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-version", - "x11-dl", -] - -[[package]] -name = "tao-macros" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] -name = "tauri" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2979ec5ec5a9310b15d1548db3b8de98d8f75abf2b5b00fec9cd5c0553ecc09c" -dependencies = [ - "anyhow", - "bytes", - "dirs", - "dunce", - "embed_plist", - "futures-util", - "getrandom 0.2.15", - "glob", - "gtk", - "heck 0.5.0", - "http", - "http-range", - "jni", - "libc", - "log", - "mime", - "muda", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "percent-encoding", - "plist", - "raw-window-handle", - "reqwest", - "serde", - "serde_json", - "serde_repr", - "serialize-to-javascript", - "swift-rs", - "tauri-build", - "tauri-macros", - "tauri-runtime", - "tauri-runtime-wry", - "tauri-utils", - "thiserror 2.0.11", - "tokio", - "tray-icon", - "url", - "urlpattern", - "webkit2gtk", - "webview2-com", - "window-vibrancy", - "windows 0.58.0", -] - -[[package]] -name = "tauri-build" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e950124f6779c6cf98e3260c7a6c8488a74aa6350dd54c6950fdaa349bca2df" -dependencies = [ - "anyhow", - "cargo_toml", - "dirs", - "glob", - "heck 0.5.0", - "json-patch", - "schemars", - "semver", - "serde", - "serde_json", - "tauri-utils", - "tauri-winres", - "toml 0.8.19", - "walkdir", -] - -[[package]] -name = "tauri-codegen" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77894f9ddb5cb6c04fcfe8c8869ebe0aded4dabf19917118d48be4a95599ab5" -dependencies = [ - "base64 0.22.1", - "brotli", - "ico", - "json-patch", - "plist", - "png", - "proc-macro2", - "quote", - "semver", - "serde", - "serde_json", - "sha2", - "syn 2.0.96", - "tauri-utils", - "thiserror 2.0.11", - "time", - "url", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-macros" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3240a5caed760a532e8f687be6f05b2c7d11a1d791fb53ccc08cfeb3e5308736" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.96", - "tauri-codegen", - "tauri-utils", -] - -[[package]] -name = "tauri-plugin" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5841b9a0200e954ef7457f8d327091424328891e267a97b641dc246cc54d0dec" -dependencies = [ - "anyhow", - "glob", - "plist", - "schemars", - "serde", - "serde_json", - "tauri-utils", - "toml 0.8.19", - "walkdir", -] - -[[package]] -name = "tauri-plugin-dialog" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b59fd750551b1066744ab956a1cd6b1ea3e1b3763b0b9153ac27a044d596426" -dependencies = [ - "log", - "raw-window-handle", - "rfd", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "tauri-plugin-fs", - "thiserror 2.0.11", - "url", -] - -[[package]] -name = "tauri-plugin-fs" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1edf18000f02903a7c2e5997fb89aca455ecbc0acc15c6535afbb883be223" -dependencies = [ - "anyhow", - "dunce", - "glob", - "percent-encoding", - "schemars", - "serde", - "serde_json", - "serde_repr", - "tauri", - "tauri-plugin", - "tauri-utils", - "thiserror 2.0.11", - "toml 0.8.19", - "url", - "uuid", -] - -[[package]] -name = "tauri-plugin-log" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd784c138c08a43954bc3e735402e6b2b2ee8d8c254a7391f4e77c01273dd5" -dependencies = [ - "android_logger", - "byte-unit", - "cocoa", - "fern", - "log", - "objc", - "serde", - "serde_json", - "serde_repr", - "swift-rs", - "tauri", - "tauri-plugin", - "thiserror 2.0.11", - "time", -] - -[[package]] -name = "tauri-plugin-shell" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c50a63e60fb8925956cc5b7569f4b750ac197a4d39f13b8dd46ea8e2bad79" -dependencies = [ - "encoding_rs", - "log", - "open", - "os_pipe", - "regex", - "schemars", - "serde", - "serde_json", - "shared_child", - "tauri", - "tauri-plugin", - "thiserror 2.0.11", - "tokio", -] - -[[package]] -name = "tauri-runtime" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7" -dependencies = [ - "dpi", - "gtk", - "http", - "jni", - "raw-window-handle", - "serde", - "serde_json", - "tauri-utils", - "thiserror 2.0.11", - "url", - "windows 0.58.0", -] - -[[package]] -name = "tauri-runtime-wry" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0" -dependencies = [ - "gtk", - "http", - "jni", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "percent-encoding", - "raw-window-handle", - "softbuffer", - "tao", - "tauri-runtime", - "tauri-utils", - "url", - "webkit2gtk", - "webview2-com", - "windows 0.58.0", - "wry", -] - -[[package]] -name = "tauri-utils" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fb10e7cc97456b2d5b9c03e335b5de5da982039a303a20d10006885e4523a0" -dependencies = [ - "brotli", - "cargo_metadata", - "ctor", - "dunce", - "glob", - "html5ever", - "http", - "infer", - "json-patch", - "kuchikiki", - "log", - "memchr", - "phf 0.11.3", - "proc-macro2", - "quote", - "regex", - "schemars", - "semver", - "serde", - "serde-untagged", - "serde_json", - "serde_with", - "swift-rs", - "thiserror 2.0.11", - "toml 0.8.19", - "url", - "urlpattern", - "uuid", - "walkdir", -] - -[[package]] -name = "tauri-winres" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" -dependencies = [ - "embed-resource", - "toml 0.7.8", -] - -[[package]] -name = "tempfile" -version = "3.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" -dependencies = [ - "cfg-if", - "fastrand", - "getrandom 0.2.15", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" -dependencies = [ - "thiserror-impl 2.0.11", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" -dependencies = [ - "deranged", - "itoa 1.0.14", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny_http" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" -dependencies = [ - "ascii", - "chunked_transfer", - "httpdate", - "log", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio 1.0.3", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-util" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.22", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.7.0", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap 2.7.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.24", -] - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "tray-icon" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48a05076dd272615d03033bf04f480199f7d1b66a8ac64d75c625fc4a70c06b" -dependencies = [ - "core-graphics", - "crossbeam-channel", - "dirs", - "libappindicator", - "muda", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "once_cell", - "png", - "serde", - "thiserror 1.0.69", - "windows-sys 0.59.0", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typeid" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] - -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-ucd-ident" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - -[[package]] -name = "unicode-ident" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-truncate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" -dependencies = [ - "itertools 0.13.0", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "urlpattern" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70acd30e3aa1450bc2eece896ce2ad0d178e9c079493819301573dae3c37ba6d" -dependencies = [ - "regex", - "serde", - "unic-ucd-ident", - "url", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8-width" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" -dependencies = [ - "getrandom 0.2.15", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "value-bag" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vswhom" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" -dependencies = [ - "libc", - "vswhom-sys", -] - -[[package]] -name = "vswhom-sys" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" -dependencies = [ - "cc", - "libc", -] - -[[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 = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.96", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wayland-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" -dependencies = [ - "cc", - "downcast-rs", - "rustix", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" -dependencies = [ - "bitflags 2.8.0", - "rustix", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" -dependencies = [ - "bitflags 2.8.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" -dependencies = [ - "proc-macro2", - "quick-xml 0.36.2", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" -dependencies = [ - "dlib", - "log", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webkit2gtk" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" -dependencies = [ - "bitflags 1.3.2", - "cairo-rs", - "gdk", - "gdk-sys", - "gio", - "gio-sys", - "glib", - "glib-sys", - "gobject-sys", - "gtk", - "gtk-sys", - "javascriptcore-rs", - "libc", - "once_cell", - "soup3", - "webkit2gtk-sys", -] - -[[package]] -name = "webkit2gtk-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" -dependencies = [ - "bitflags 1.3.2", - "cairo-sys-rs", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "gtk-sys", - "javascriptcore-rs-sys", - "libc", - "pkg-config", - "soup3-sys", - "system-deps", -] - -[[package]] -name = "webview2-com" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823e7ebcfaea51e78f72c87fc3b65a1e602c321f407a0b36dbb327d7bb7cd921" -dependencies = [ - "webview2-com-macros", - "webview2-com-sys", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-implement", - "windows-interface", -] - -[[package]] -name = "webview2-com-macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "webview2-com-sys" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a82bce72db6e5ee83c68b5de1e2cd6ea195b9fbff91cb37df5884cbe3222df4" -dependencies = [ - "thiserror 1.0.69", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "window-vibrancy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea403deff7b51fff19e261330f71608ff2cdef5721d72b64180bb95be7c4150" -dependencies = [ - "objc2", - "objc2-app-kit", - "objc2-foundation", - "raw-window-handle", - "windows-sys 0.59.0", - "windows-version", -] - -[[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.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" -dependencies = [ - "windows-core 0.54.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" -dependencies = [ - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result 0.2.0", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result 0.2.0", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -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.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows-version" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12476c23a74725c539b24eae8bfc0dac4029c39cdb561d9f23616accd4ae26d" -dependencies = [ - "windows-targets 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "wry" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e33c08b174442ff80d5c791020696f9f8b4e4a87b8cfc7494aad6167ec44e1" -dependencies = [ - "base64 0.22.1", - "block2", - "cookie", - "crossbeam-channel", - "dpi", - "dunce", - "gdkx11", - "gtk", - "html5ever", - "http", - "javascriptcore-rs", - "jni", - "kuchikiki", - "libc", - "ndk 0.9.0", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "objc2-ui-kit", - "objc2-web-kit", - "once_cell", - "percent-encoding", - "raw-window-handle", - "sha2", - "soup3", - "tao-macros", - "thiserror 2.0.11", - "url", - "webkit2gtk", - "webkit2gtk-sys", - "webview2-com", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-version", - "x11-dl", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "x11" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", - "synstructure", -] - -[[package]] -name = "zbus" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "192a0d989036cd60a1e91a54c9851fb9ad5bd96125d41803eed79d2e2ef74bd7" -dependencies = [ - "async-broadcast", - "async-recursion", - "async-trait", - "enumflags2", - "event-listener", - "futures-core", - "futures-util", - "hex", - "nix 0.29.0", - "ordered-stream", - "serde", - "serde_repr", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys 0.59.0", - "winnow 0.6.24", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3685b5c81fce630efc3e143a4ded235b107f1b1cdf186c3f115529e5e5ae4265" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.96", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519629a3f80976d89c575895b05677cbc45eaf9f70d62a364d819ba646409cc8" -dependencies = [ - "serde", - "static_assertions", - "winnow 0.6.24", - "zvariant", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "zerofrom" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", - "synstructure", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.96", -] - -[[package]] -name = "zvariant" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e6b9b5f1361de2d5e7d9fd1ee5f6f7fcb6060618a1f82f3472f58f2b8d4be9" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "winnow 0.6.24", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573a8dd76961957108b10f7a45bac6ab1ea3e9b7fe01aff88325dc57bb8f5c8b" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.96", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd46446ea2a1f353bfda53e35f17633afa79f4fe290a611c94645c69fe96a50" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "static_assertions", - "syn 2.0.96", - "winnow 0.6.24", -] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml deleted file mode 100644 index b914805..0000000 --- a/src-tauri/Cargo.toml +++ /dev/null @@ -1,63 +0,0 @@ -[package] -name = "lightningbeam" -version = "0.1.0" -description = "A Tauri App" -authors = ["you"] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -# The `_lib` suffix may seem redundant but it is necessary -# to make the lib name unique and wouldn't conflict with the bin name. -# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519 -name = "lightningbeam_lib" -crate-type = ["staticlib", "cdylib", "rlib"] - -[build-dependencies] -tauri-build = { version = "2", features = [] } - -[dependencies] -tauri = { version = "2", features = ["protocol-asset"] } -tauri-plugin-shell = "2" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -tauri-plugin-fs = "2" -tauri-plugin-dialog = "2" -log = "0.4" -env_logger = "0.11" - -# DAW backend integration -daw-backend = { path = "../daw-backend" } -cpal = "0.15" -rtrb = "0.3" -tokio = { version = "1", features = ["sync", "time"] } - -# Video decoding -lru = "0.12" - -# WebSocket for frame streaming (disable default features to remove tracing, but keep handshake) -tungstenite = { version = "0.20", default-features = false, features = ["handshake"] } - -# Native rendering with wgpu -wgpu = "0.19" -winit = "0.29" -pollster = "0.3" -bytemuck = { version = "1.14", features = ["derive"] } -raw-window-handle = "0.6" -image = "0.24" - -[target.'cfg(target_os = "macos")'.dependencies] -ffmpeg-next = { version = "8.0", features = ["build"] } - -[target.'cfg(not(target_os = "macos"))'.dependencies] -ffmpeg-next = "8.0" - - -[profile.dev] -opt-level = 1 # Enable basic optimizations in debug mode for audio decoding performance - -[profile.release] -opt-level = 3 -lto = true - diff --git a/src-tauri/assets/factory_presets/Basic_Sine.json b/src-tauri/assets/factory_presets/Basic_Sine.json deleted file mode 100644 index 3ad4cf3..0000000 --- a/src-tauri/assets/factory_presets/Basic_Sine.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "metadata": { - "name": "Basic Sine", - "description": "Simple sine wave synthesizer with ADSR envelope. Great for learning the basics of subtractive synthesis.", - "author": "Lightningbeam", - "version": 1, - "tags": ["basic", "lead", "mono"] - }, - "nodes": [ - { - "id": 0, - "node_type": "MidiInput", - "parameters": {}, - "position": [100.0, 200.0] - }, - { - "id": 1, - "node_type": "MidiToCV", - "parameters": {}, - "position": [300.0, 200.0] - }, - { - "id": 2, - "node_type": "Oscillator", - "parameters": { - "0": 440.0, - "1": 0.7, - "2": 0.0 - }, - "position": [500.0, 150.0] - }, - { - "id": 3, - "node_type": "ADSR", - "parameters": { - "0": 0.01, - "1": 0.1, - "2": 0.7, - "3": 0.3 - }, - "position": [500.0, 300.0] - }, - { - "id": 4, - "node_type": "Gain", - "parameters": { - "0": 1.0 - }, - "position": [700.0, 200.0] - }, - { - "id": 5, - "node_type": "AudioOutput", - "parameters": {}, - "position": [900.0, 200.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 3, - "to_port": 0 - }, - { - "from_node": 2, - "from_port": 0, - "to_node": 4, - "to_port": 0 - }, - { - "from_node": 3, - "from_port": 0, - "to_node": 4, - "to_port": 1 - }, - { - "from_node": 4, - "from_port": 0, - "to_node": 5, - "to_port": 0 - } - ], - "midi_targets": [0], - "output_node": 5 -} diff --git a/src-tauri/assets/factory_presets/Pluck.json b/src-tauri/assets/factory_presets/Pluck.json deleted file mode 100644 index 792bfe7..0000000 --- a/src-tauri/assets/factory_presets/Pluck.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "metadata": { - "name": "Pluck", - "description": "Percussive pluck sound with fast attack and decay. Great for arpeggios, melodies, and rhythmic patterns.", - "author": "Lightningbeam", - "version": 1, - "tags": ["pluck", "lead", "percussive", "arpeggio"] - }, - "nodes": [ - { - "id": 0, - "node_type": "MidiInput", - "parameters": {}, - "position": [100.0, 250.0] - }, - { - "id": 1, - "node_type": "MidiToCV", - "parameters": {}, - "position": [300.0, 250.0] - }, - { - "id": 2, - "node_type": "Oscillator", - "parameters": { - "0": 440.0, - "1": 0.6, - "2": 2.0 - }, - "position": [500.0, 150.0] - }, - { - "id": 3, - "node_type": "Filter", - "parameters": { - "0": 2000.0, - "1": 0.8, - "2": 0.0 - }, - "position": [700.0, 150.0] - }, - { - "id": 4, - "node_type": "ADSR", - "parameters": { - "0": 0.001, - "1": 0.3, - "2": 0.0, - "3": 0.05 - }, - "position": [500.0, 350.0] - }, - { - "id": 5, - "node_type": "ADSR", - "parameters": { - "0": 0.001, - "1": 0.4, - "2": 0.0, - "3": 0.1 - }, - "position": [700.0, 350.0] - }, - { - "id": 6, - "node_type": "Gain", - "parameters": { - "0": 1.0 - }, - "position": [900.0, 200.0] - }, - { - "id": 7, - "node_type": "AudioOutput", - "parameters": {}, - "position": [1100.0, 200.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 4, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 5, - "to_port": 0 - }, - { - "from_node": 2, - "from_port": 0, - "to_node": 3, - "to_port": 0 - }, - { - "from_node": 4, - "from_port": 0, - "to_node": 3, - "to_port": 1 - }, - { - "from_node": 3, - "from_port": 0, - "to_node": 6, - "to_port": 0 - }, - { - "from_node": 5, - "from_port": 0, - "to_node": 6, - "to_port": 1 - }, - { - "from_node": 6, - "from_port": 0, - "to_node": 7, - "to_port": 0 - } - ], - "midi_targets": [0], - "output_node": 7 -} diff --git a/src-tauri/assets/factory_presets/Poly_Synth.json b/src-tauri/assets/factory_presets/Poly_Synth.json deleted file mode 100644 index 7999982..0000000 --- a/src-tauri/assets/factory_presets/Poly_Synth.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "metadata": { - "name": "Poly Synth", - "description": "8-voice polyphonic synthesizer with sawtooth oscillator and ADSR envelope. Perfect for chords and complex harmonies.", - "author": "Lightningbeam", - "version": 1, - "tags": ["poly", "polyphonic", "synth", "chords"] - }, - "nodes": [ - { - "id": 0, - "node_type": "MidiInput", - "parameters": {}, - "position": [100.0, 200.0] - }, - { - "id": 1, - "node_type": "VoiceAllocator", - "parameters": { - "0": 8.0 - }, - "position": [400.0, 200.0], - "template_graph": { - "metadata": { - "name": "template", - "description": "", - "author": "", - "version": 1, - "tags": [] - }, - "nodes": [ - { - "id": 0, - "node_type": "TemplateInput", - "parameters": {}, - "position": [100.0, 200.0] - }, - { - "id": 1, - "node_type": "MidiToCV", - "parameters": {}, - "position": [300.0, 200.0] - }, - { - "id": 2, - "node_type": "Oscillator", - "parameters": { - "0": 440.0, - "1": 0.7, - "2": 1.0 - }, - "position": [500.0, 150.0] - }, - { - "id": 3, - "node_type": "ADSR", - "parameters": { - "0": 0.01, - "1": 0.2, - "2": 0.6, - "3": 0.3 - }, - "position": [500.0, 300.0] - }, - { - "id": 4, - "node_type": "Gain", - "parameters": { - "0": 1.0 - }, - "position": [700.0, 200.0] - }, - { - "id": 5, - "node_type": "TemplateOutput", - "parameters": {}, - "position": [900.0, 200.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 3, - "to_port": 0 - }, - { - "from_node": 2, - "from_port": 0, - "to_node": 4, - "to_port": 0 - }, - { - "from_node": 3, - "from_port": 0, - "to_node": 4, - "to_port": 1 - }, - { - "from_node": 4, - "from_port": 0, - "to_node": 5, - "to_port": 0 - } - ], - "midi_targets": [], - "output_node": 5 - } - }, - { - "id": 2, - "node_type": "AudioOutput", - "parameters": {}, - "position": [700.0, 200.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - } - ], - "midi_targets": [0], - "output_node": 2 -} diff --git a/src-tauri/assets/factory_presets/Sawtooth_Bass.json b/src-tauri/assets/factory_presets/Sawtooth_Bass.json deleted file mode 100644 index 8a7bddb..0000000 --- a/src-tauri/assets/factory_presets/Sawtooth_Bass.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "metadata": { - "name": "Sawtooth Bass", - "description": "Classic analog-style bass synth with sawtooth oscillator and resonant lowpass filter. Perfect for electronic music basslines.", - "author": "Lightningbeam", - "version": 1, - "tags": ["bass", "analog", "electronic", "mono"] - }, - "nodes": [ - { - "id": 0, - "node_type": "MidiInput", - "parameters": {}, - "position": [100.0, 250.0] - }, - { - "id": 1, - "node_type": "MidiToCV", - "parameters": {}, - "position": [300.0, 250.0] - }, - { - "id": 2, - "node_type": "Oscillator", - "parameters": { - "0": 110.0, - "1": 0.8, - "2": 1.0 - }, - "position": [500.0, 150.0] - }, - { - "id": 3, - "node_type": "Filter", - "parameters": { - "0": 800.0, - "1": 2.5, - "2": 0.0 - }, - "position": [700.0, 150.0] - }, - { - "id": 4, - "node_type": "ADSR", - "parameters": { - "0": 0.005, - "1": 0.2, - "2": 0.3, - "3": 0.1 - }, - "position": [500.0, 300.0] - }, - { - "id": 5, - "node_type": "ADSR", - "parameters": { - "0": 0.005, - "1": 0.15, - "2": 0.6, - "3": 0.2 - }, - "position": [700.0, 350.0] - }, - { - "id": 6, - "node_type": "Gain", - "parameters": { - "0": 1.2 - }, - "position": [900.0, 200.0] - }, - { - "id": 7, - "node_type": "AudioOutput", - "parameters": {}, - "position": [1100.0, 200.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 4, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 5, - "to_port": 0 - }, - { - "from_node": 2, - "from_port": 0, - "to_node": 3, - "to_port": 0 - }, - { - "from_node": 4, - "from_port": 0, - "to_node": 3, - "to_port": 1 - }, - { - "from_node": 3, - "from_port": 0, - "to_node": 6, - "to_port": 0 - }, - { - "from_node": 5, - "from_port": 0, - "to_node": 6, - "to_port": 1 - }, - { - "from_node": 6, - "from_port": 0, - "to_node": 7, - "to_port": 0 - } - ], - "midi_targets": [0], - "output_node": 7 -} diff --git a/src-tauri/assets/factory_presets/Warm_Pad.json b/src-tauri/assets/factory_presets/Warm_Pad.json deleted file mode 100644 index 9090cc6..0000000 --- a/src-tauri/assets/factory_presets/Warm_Pad.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "metadata": { - "name": "Warm Pad", - "description": "Lush pad sound combining sawtooth and triangle waves with slow filter sweep and gentle attack. Ideal for ambient and cinematic music.", - "author": "Lightningbeam", - "version": 1, - "tags": ["pad", "ambient", "warm", "cinematic"] - }, - "nodes": [ - { - "id": 0, - "node_type": "MidiInput", - "parameters": {}, - "position": [100.0, 300.0] - }, - { - "id": 1, - "node_type": "MidiToCV", - "parameters": {}, - "position": [300.0, 300.0] - }, - { - "id": 2, - "node_type": "Oscillator", - "parameters": { - "0": 440.0, - "1": 0.5, - "2": 1.0 - }, - "position": [500.0, 150.0] - }, - { - "id": 3, - "node_type": "Oscillator", - "parameters": { - "0": 440.0, - "1": 0.4, - "2": 3.0 - }, - "position": [500.0, 250.0] - }, - { - "id": 4, - "node_type": "Mixer", - "parameters": { - "0": 0.5, - "1": 0.5, - "2": 0.0, - "3": 0.0 - }, - "position": [700.0, 200.0] - }, - { - "id": 5, - "node_type": "Filter", - "parameters": { - "0": 1200.0, - "1": 1.0, - "2": 0.0 - }, - "position": [900.0, 200.0] - }, - { - "id": 6, - "node_type": "ADSR", - "parameters": { - "0": 0.8, - "1": 1.0, - "2": 0.6, - "3": 1.5 - }, - "position": [700.0, 400.0] - }, - { - "id": 7, - "node_type": "ADSR", - "parameters": { - "0": 0.5, - "1": 0.5, - "2": 0.8, - "3": 1.0 - }, - "position": [900.0, 400.0] - }, - { - "id": 8, - "node_type": "Gain", - "parameters": { - "0": 0.8 - }, - "position": [1100.0, 250.0] - }, - { - "id": 9, - "node_type": "AudioOutput", - "parameters": {}, - "position": [1300.0, 250.0] - } - ], - "connections": [ - { - "from_node": 0, - "from_port": 0, - "to_node": 1, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 2, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 0, - "to_node": 3, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 6, - "to_port": 0 - }, - { - "from_node": 1, - "from_port": 1, - "to_node": 7, - "to_port": 0 - }, - { - "from_node": 2, - "from_port": 0, - "to_node": 4, - "to_port": 0 - }, - { - "from_node": 3, - "from_port": 0, - "to_node": 4, - "to_port": 1 - }, - { - "from_node": 4, - "from_port": 0, - "to_node": 5, - "to_port": 0 - }, - { - "from_node": 6, - "from_port": 0, - "to_node": 5, - "to_port": 1 - }, - { - "from_node": 5, - "from_port": 0, - "to_node": 8, - "to_port": 0 - }, - { - "from_node": 7, - "from_port": 0, - "to_node": 8, - "to_port": 1 - }, - { - "from_node": 8, - "from_port": 0, - "to_node": 9, - "to_port": 0 - } - ], - "midi_targets": [0], - "output_node": 9 -} diff --git a/src-tauri/build.rs b/src-tauri/build.rs deleted file mode 100644 index d860e1e..0000000 --- a/src-tauri/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - tauri_build::build() -} diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json deleted file mode 100644 index 877f5af..0000000 --- a/src-tauri/capabilities/default.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Capability for the main window", - "windows": [ - "main", - "window*" - ], - "permissions": [ - "core:default", - "core:window:allow-close", - "core:window:allow-set-title", - "shell:allow-open", - "fs:default", - { - "identifier": "fs:allow-exists", - "allow": [ - { - "path": "$HOME/*" - }, - { - "path": "$DOCUMENT/*" - }, - { - "path": "$DOWNLOAD/*" - }, - { - "path": "$DESKTOP/*" - }, - { - "path": "**/*" - } - ] - }, - { - "identifier": "fs:allow-app-write-recursive", - "allow": [ - { - "path": "$HOME/*" - }, - { - "path": "$DOCUMENT/*" - }, - { - "path": "$DOWNLOAD/*" - }, - { - "path": "$DESKTOP/*" - }, - { - "path": "**/*" - } - ] - }, - { - "identifier": "fs:allow-app-read-recursive", - "allow": [ - { - "path": "$HOME/*" - }, - { - "path": "$DOCUMENT/*" - }, - { - "path": "$DOWNLOAD/*" - }, - { - "path": "$DESKTOP/*" - }, - { - "path": "**/*" - } - ] - }, - "dialog:default" - ] -} \ No newline at end of file diff --git a/src-tauri/examples/video_inspect.rs b/src-tauri/examples/video_inspect.rs deleted file mode 100644 index 9950fd3..0000000 --- a/src-tauri/examples/video_inspect.rs +++ /dev/null @@ -1,104 +0,0 @@ -extern crate ffmpeg_next as ffmpeg; - -use std::env; - -fn main() { - ffmpeg::init().unwrap(); - - let args: Vec = env::args().collect(); - if args.len() < 2 { - eprintln!("Usage: {} ", args[0]); - std::process::exit(1); - } - - let path = &args[1]; - let input = ffmpeg::format::input(path).expect("Failed to open video"); - - println!("=== VIDEO FILE INFORMATION ==="); - println!("File: {}", path); - println!("Format: {}", input.format().name()); - println!("Duration: {:.2}s", input.duration() as f64 / f64::from(ffmpeg::ffi::AV_TIME_BASE)); - println!(); - - let video_stream = input.streams() - .best(ffmpeg::media::Type::Video) - .expect("No video stream found"); - - let stream_index = video_stream.index(); - let time_base = f64::from(video_stream.time_base()); - let duration = video_stream.duration() as f64 * time_base; - let fps = f64::from(video_stream.avg_frame_rate()); - - println!("=== VIDEO STREAM ==="); - println!("Stream index: {}", stream_index); - println!("Time base: {} ({:.10})", video_stream.time_base(), time_base); - println!("Duration: {:.2}s", duration); - println!("FPS: {:.2}", fps); - println!("Frames: {}", video_stream.frames()); - - let context = ffmpeg::codec::context::Context::from_parameters(video_stream.parameters()) - .expect("Failed to create context"); - let decoder = context.decoder().video().expect("Failed to create decoder"); - - println!("Codec: {:?}", decoder.id()); - println!("Resolution: {}x{}", decoder.width(), decoder.height()); - println!("Pixel format: {:?}", decoder.format()); - println!(); - - println!("=== SCANNING FRAMES ==="); - println!("Timestamp (ts) | Time (s) | Key | Type"); - println!("---------------|----------|-----|-----"); - - let mut input = ffmpeg::format::input(path).expect("Failed to reopen video"); - let context = ffmpeg::codec::context::Context::from_parameters( - input.streams().best(ffmpeg::media::Type::Video).unwrap().parameters() - ).expect("Failed to create context"); - let mut decoder = context.decoder().video().expect("Failed to create decoder"); - - let mut frame_count = 0; - let mut keyframe_count = 0; - - for (stream, packet) in input.packets() { - if stream.index() == stream_index { - let packet_pts = packet.pts().unwrap_or(0); - let packet_time = packet_pts as f64 * time_base; - let is_key = packet.is_key(); - - if is_key { - keyframe_count += 1; - } - - // Print first 50 packets and all keyframes - if frame_count < 50 || is_key { - println!("{:14} | {:8.2} | {:3} | {:?}", - packet_pts, - packet_time, - if is_key { "KEY" } else { " " }, - if is_key { "I-frame" } else { "P/B-frame" } - ); - } - - decoder.send_packet(&packet).ok(); - let mut frame = ffmpeg::util::frame::Video::empty(); - while decoder.receive_frame(&mut frame).is_ok() { - frame_count += 1; - } - } - } - - // Flush decoder - decoder.send_eof().ok(); - let mut frame = ffmpeg::util::frame::Video::empty(); - while decoder.receive_frame(&mut frame).is_ok() { - frame_count += 1; - } - - println!(); - println!("=== SUMMARY ==="); - println!("Total frames decoded: {}", frame_count); - println!("Total keyframes: {}", keyframe_count); - if keyframe_count > 0 { - println!("Average keyframe interval: {:.2} frames", frame_count as f64 / keyframe_count as f64); - println!("Average keyframe interval: {:.2}s", duration / keyframe_count as f64); - } -} diff --git a/src-tauri/icons/128x128.png b/src-tauri/icons/128x128.png deleted file mode 100644 index e4dfa14..0000000 Binary files a/src-tauri/icons/128x128.png and /dev/null differ diff --git a/src-tauri/icons/128x128@2x.png b/src-tauri/icons/128x128@2x.png deleted file mode 100644 index 14fb6d4..0000000 Binary files a/src-tauri/icons/128x128@2x.png and /dev/null differ diff --git a/src-tauri/icons/32x32.png b/src-tauri/icons/32x32.png deleted file mode 100644 index 2270a8c..0000000 Binary files a/src-tauri/icons/32x32.png and /dev/null differ diff --git a/src-tauri/icons/Square107x107Logo.png b/src-tauri/icons/Square107x107Logo.png deleted file mode 100644 index 3aade5c..0000000 Binary files a/src-tauri/icons/Square107x107Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square142x142Logo.png b/src-tauri/icons/Square142x142Logo.png deleted file mode 100644 index b2b0b33..0000000 Binary files a/src-tauri/icons/Square142x142Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square150x150Logo.png b/src-tauri/icons/Square150x150Logo.png deleted file mode 100644 index 8301a87..0000000 Binary files a/src-tauri/icons/Square150x150Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square284x284Logo.png b/src-tauri/icons/Square284x284Logo.png deleted file mode 100644 index d31261b..0000000 Binary files a/src-tauri/icons/Square284x284Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square30x30Logo.png b/src-tauri/icons/Square30x30Logo.png deleted file mode 100644 index 6aebd01..0000000 Binary files a/src-tauri/icons/Square30x30Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square310x310Logo.png b/src-tauri/icons/Square310x310Logo.png deleted file mode 100644 index 106b274..0000000 Binary files a/src-tauri/icons/Square310x310Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square44x44Logo.png b/src-tauri/icons/Square44x44Logo.png deleted file mode 100644 index 9d9cc09..0000000 Binary files a/src-tauri/icons/Square44x44Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square71x71Logo.png b/src-tauri/icons/Square71x71Logo.png deleted file mode 100644 index d1ec49e..0000000 Binary files a/src-tauri/icons/Square71x71Logo.png and /dev/null differ diff --git a/src-tauri/icons/Square89x89Logo.png b/src-tauri/icons/Square89x89Logo.png deleted file mode 100644 index 9fd3ba8..0000000 Binary files a/src-tauri/icons/Square89x89Logo.png and /dev/null differ diff --git a/src-tauri/icons/StoreLogo.png b/src-tauri/icons/StoreLogo.png deleted file mode 100644 index b0c3af2..0000000 Binary files a/src-tauri/icons/StoreLogo.png and /dev/null differ diff --git a/src-tauri/icons/icon.ico b/src-tauri/icons/icon.ico deleted file mode 100644 index 2d3b3cd..0000000 Binary files a/src-tauri/icons/icon.ico and /dev/null differ diff --git a/src-tauri/icons/icon.png b/src-tauri/icons/icon.png deleted file mode 100644 index a347952..0000000 Binary files a/src-tauri/icons/icon.png and /dev/null differ diff --git a/src-tauri/icons/macicon.png b/src-tauri/icons/macicon.png deleted file mode 100644 index a67544e..0000000 Binary files a/src-tauri/icons/macicon.png and /dev/null differ diff --git a/src-tauri/icons/tauri_icon.icns b/src-tauri/icons/tauri_icon.icns deleted file mode 100644 index 12a5bce..0000000 Binary files a/src-tauri/icons/tauri_icon.icns and /dev/null differ diff --git a/src-tauri/src/audio.rs b/src-tauri/src/audio.rs deleted file mode 100644 index 6c6085f..0000000 --- a/src-tauri/src/audio.rs +++ /dev/null @@ -1,1713 +0,0 @@ -use daw_backend::{AudioEvent, AudioSystem, EngineController, EventEmitter, WaveformPeak}; -use daw_backend::audio::pool::AudioPoolEntry; -use ffmpeg_next::ffi::FF_LOSS_COLORQUANT; -use std::sync::{Arc, Mutex}; -use std::collections::HashMap; -use std::path::Path; -use tauri::{Emitter, Manager}; -use tokio::sync::oneshot; - -#[derive(serde::Serialize)] -pub struct AudioFileMetadata { - pub pool_index: usize, - pub duration: f64, - pub sample_rate: u32, - pub channels: u32, - pub waveform: Vec, - pub detected_bpm: Option, // Detected BPM from audio analysis -} - -#[derive(serde::Serialize)] -pub struct MidiNote { - pub note: u8, // MIDI note number (0-127) - pub start_time: f64, // Start time in seconds - pub duration: f64, // Note duration in seconds - pub velocity: u8, // Note velocity (0-127) -} - -#[derive(serde::Serialize)] -pub struct MidiFileMetadata { - pub duration: f64, - pub notes: Vec, -} - -pub struct AudioState { - pub(crate) controller: Option, - pub(crate) sample_rate: u32, - pub(crate) channels: u32, - pub(crate) buffer_size: u32, - pub(crate) next_track_id: u32, - pub(crate) next_pool_index: usize, - pub(crate) next_graph_node_id: u32, - // Track next node ID for each VoiceAllocator template (VoiceAllocator backend ID -> next template node ID) - pub(crate) template_node_counters: HashMap, - // Pending preset save notifications (preset_path -> oneshot sender) - pub(crate) preset_save_waiters: Arc>>>, -} - -impl Default for AudioState { - fn default() -> Self { - Self { - controller: None, - sample_rate: 0, - channels: 0, - buffer_size: 256, // Default buffer size - next_track_id: 0, - next_pool_index: 0, - next_graph_node_id: 0, - preset_save_waiters: Arc::new(Mutex::new(HashMap::new())), - template_node_counters: HashMap::new(), - } - } -} - -/// Implementation of EventEmitter that uses Tauri's event system -struct TauriEventEmitter { - app_handle: tauri::AppHandle, - preset_save_waiters: Arc>>>, -} - -impl EventEmitter for TauriEventEmitter { - fn emit(&self, event: AudioEvent) { - // Handle preset save notifications - if let AudioEvent::GraphPresetSaved(_, ref preset_path) = event { - if let Ok(mut waiters) = self.preset_save_waiters.lock() { - if let Some(sender) = waiters.remove(preset_path) { - let _ = sender.send(()); - } - } - } - - // Serialize the event to the format expected by the frontend - let serialized_event = match event { - AudioEvent::PlaybackPosition(time) => { - SerializedAudioEvent::PlaybackPosition { time } - } - AudioEvent::RecordingStarted(track_id, clip_id, _, _) => { - SerializedAudioEvent::RecordingStarted { track_id, clip_id } - } - AudioEvent::RecordingProgress(clip_id, duration) => { - SerializedAudioEvent::RecordingProgress { clip_id, duration } - } - AudioEvent::RecordingStopped(clip_id, pool_index, waveform) => { - SerializedAudioEvent::RecordingStopped { clip_id, pool_index, waveform } - } - AudioEvent::RecordingError(message) => { - SerializedAudioEvent::RecordingError { message } - } - AudioEvent::NoteOn(note, velocity) => { - SerializedAudioEvent::NoteOn { note, velocity } - } - AudioEvent::NoteOff(note) => { - SerializedAudioEvent::NoteOff { note } - } - AudioEvent::GraphNodeAdded(track_id, node_id, node_type) => { - SerializedAudioEvent::GraphNodeAdded { track_id, node_id, node_type } - } - AudioEvent::GraphConnectionError(track_id, message) => { - SerializedAudioEvent::GraphConnectionError { track_id, message } - } - AudioEvent::GraphStateChanged(track_id) => { - SerializedAudioEvent::GraphStateChanged { track_id } - } - AudioEvent::GraphPresetLoaded(track_id) => { - SerializedAudioEvent::GraphPresetLoaded { track_id } - } - AudioEvent::GraphPresetSaved(track_id, preset_path) => { - SerializedAudioEvent::GraphPresetSaved { track_id, preset_path } - } - AudioEvent::MidiRecordingStopped(track_id, clip_id, note_count) => { - SerializedAudioEvent::MidiRecordingStopped { track_id, clip_id, note_count } - } - AudioEvent::MidiRecordingProgress(track_id, clip_id, duration, notes) => { - SerializedAudioEvent::MidiRecordingProgress { track_id, clip_id, duration, notes } - } - _ => return, // Ignore other event types for now - }; - - // Emit the event via Tauri - if let Err(e) = self.app_handle.emit("audio-event", serialized_event) { - eprintln!("Failed to emit audio event: {}", e); - } - } -} - -#[tauri::command] -pub async fn audio_init( - state: tauri::State<'_, Arc>>, - app_handle: tauri::AppHandle, - buffer_size: Option, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - // Update buffer size if provided (from config) - if let Some(size) = buffer_size { - audio_state.buffer_size = size; - } - - // Check if already initialized - if so, reset DAW state (for hot-reload) - if let Some(controller) = &mut audio_state.controller { - controller.reset(); - audio_state.next_track_id = 0; - audio_state.next_pool_index = 0; - audio_state.next_graph_node_id = 0; - return Ok(format!( - "Audio already initialized (DAW state reset): {} Hz, {} ch", - audio_state.sample_rate, audio_state.channels - )); - } - - // Create TauriEventEmitter - let emitter = Arc::new(TauriEventEmitter { - app_handle, - preset_save_waiters: audio_state.preset_save_waiters.clone(), - }); - - // Get buffer size from audio_state (default is 256) - let buffer_size = audio_state.buffer_size; - - // AudioSystem handles all cpal initialization internally - let system = AudioSystem::new(Some(emitter), buffer_size)?; - - let info = format!( - "Audio initialized: {} Hz, {} ch, {} frame buffer", - system.sample_rate, system.channels, buffer_size - ); - - // Leak the stream to keep it alive for the lifetime of the app - // This is intentional - we want the audio stream to run until app closes - Box::leak(Box::new(system.stream)); - - audio_state.controller = Some(system.controller); - audio_state.sample_rate = system.sample_rate; - audio_state.channels = system.channels; - audio_state.buffer_size = buffer_size; - audio_state.next_track_id = 0; - audio_state.next_pool_index = 0; - audio_state.next_graph_node_id = 0; - - Ok(info) -} - -#[tauri::command] -pub async fn audio_reset(state: tauri::State<'_, Arc>>) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.reset(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_play(state: tauri::State<'_, Arc>>) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.play(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_stop(state: tauri::State<'_, Arc>>) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.stop(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn set_metronome_enabled( - state: tauri::State<'_, Arc>>, - enabled: bool -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.set_metronome_enabled(enabled); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_test_beep(state: tauri::State<'_, Arc>>) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - // Create MIDI track - controller.create_midi_track("Test".to_string()); - - // Note: Track ID will be 0 (first track created) - // Create MIDI clip and add notes for a C major chord arpeggio - controller.create_midi_clip(0, 0.0, 2.0); - controller.add_midi_note(0, 0, 0.0, 60, 100, 0.5); // C - controller.add_midi_note(0, 0, 0.5, 64, 100, 0.5); // E - controller.add_midi_note(0, 0, 1.0, 67, 100, 0.5); // G - - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_seek( - state: tauri::State<'_, Arc>>, - seconds: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.seek(seconds); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_set_track_parameter( - state: tauri::State<'_, Arc>>, - track_id: u32, - parameter: String, - value: f32, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - match parameter.as_str() { - "volume" => controller.set_track_volume(track_id, value), - "mute" => controller.set_track_mute(track_id, value > 0.5), - "solo" => controller.set_track_solo(track_id, value > 0.5), - _ => return Err(format!("Unknown parameter: {}", parameter)), - } - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_create_track( - state: tauri::State<'_, Arc>>, - name: String, - track_type: String, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - match track_type.as_str() { - "audio" => controller.create_audio_track_sync(name), - "midi" => controller.create_midi_track_sync(name), - _ => return Err(format!("Unknown track type: {}", track_type)), - } - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_load_file( - state: tauri::State<'_, Arc>>, - path: String, -) -> Result { - // Load the audio file from disk - let audio_file = daw_backend::io::AudioFile::load(&path)?; - - // Calculate duration - let duration = audio_file.duration(); - - // Generate adaptive waveform peaks based on duration - // Aim for ~300 peaks per second, with min 1000 and max 20000 - let target_peaks = ((duration * 300.0) as usize).clamp(1000, 20000); - let waveform = audio_file.generate_waveform_overview(target_peaks); - let sample_rate = audio_file.sample_rate; - let channels = audio_file.channels; - - // Detect BPM from audio (mix to mono if stereo) - let mono_audio: Vec = if channels == 2 { - // Mix stereo to mono - audio_file.data.chunks(2) - .map(|chunk| (chunk[0] + chunk.get(1).unwrap_or(&0.0)) * 0.5) - .collect() - } else { - audio_file.data.clone() - }; - - let detected_bpm = daw_backend::audio::bpm_detector::detect_bpm_offline(&mono_audio, sample_rate); - - // Get a lock on the audio state and send the loaded data to the audio thread - let mut audio_state = state.lock().unwrap(); - - // Get pool index and increment counter before borrowing controller - let pool_index = audio_state.next_pool_index; - audio_state.next_pool_index += 1; - - if let Some(controller) = &mut audio_state.controller { - controller.add_audio_file( - path, - audio_file.data, - audio_file.channels, - audio_file.sample_rate, - ); - - Ok(AudioFileMetadata { - pool_index, - duration, - sample_rate, - channels, - waveform, - detected_bpm, - }) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_add_clip( - state: tauri::State<'_, Arc>>, - track_id: u32, - pool_index: usize, - start_time: f64, - duration: f64, - offset: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.add_audio_clip(track_id, pool_index, start_time, duration, offset); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_move_clip( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - new_start_time: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.move_clip(track_id, clip_id, new_start_time); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_trim_clip( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - internal_start: f64, - internal_end: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.trim_clip(track_id, clip_id, internal_start, internal_end); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_extend_clip( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - new_external_duration: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.extend_clip(track_id, clip_id, new_external_duration); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_start_recording( - state: tauri::State<'_, Arc>>, - track_id: u32, - start_time: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.start_recording(track_id, start_time); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_stop_recording( - state: tauri::State<'_, Arc>>, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.stop_recording(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_pause_recording( - state: tauri::State<'_, Arc>>, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.pause_recording(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_resume_recording( - state: tauri::State<'_, Arc>>, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.resume_recording(); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_start_midi_recording( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - start_time: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.start_midi_recording(track_id, clip_id, start_time); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_stop_midi_recording( - state: tauri::State<'_, Arc>>, -) -> Result<(), String> { - eprintln!("[TAURI] audio_stop_midi_recording called"); - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - eprintln!("[TAURI] Calling controller.stop_midi_recording()"); - controller.stop_midi_recording(); - eprintln!("[TAURI] controller.stop_midi_recording() returned"); - Ok(()) - } else { - eprintln!("[TAURI] Audio not initialized!"); - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_create_midi_clip( - state: tauri::State<'_, Arc>>, - track_id: u32, - start_time: f64, - duration: f64, -) -> Result { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - let clip_id = controller.create_midi_clip(track_id, start_time, duration); - Ok(clip_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_add_midi_note( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - time_offset: f64, - note: u8, - velocity: u8, - duration: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.add_midi_note(track_id, clip_id, time_offset, note, velocity, duration); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_send_midi_note_on( - state: tauri::State<'_, Arc>>, - track_id: u32, - note: u8, - velocity: u8, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - // For now, send to the first MIDI track (track_id 0) - // TODO: Make this configurable to select which track to send to - controller.send_midi_note_on(track_id, note, velocity); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_send_midi_note_off( - state: tauri::State<'_, Arc>>, - track_id: u32, - note: u8, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.send_midi_note_off(track_id, note); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_set_active_midi_track( - state: tauri::State<'_, Arc>>, - track_id: Option, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.set_active_midi_track(track_id); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_load_midi_file( - state: tauri::State<'_, Arc>>, - track_id: u32, - path: String, - start_time: f64, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - // Extract sample_rate before the mutable borrow - let sample_rate = audio_state.sample_rate; - - if let Some(controller) = &mut audio_state.controller { - // Load and parse the MIDI file (clip content only, no positioning) - let clip = daw_backend::load_midi_file(&path, 0, sample_rate)?; - let duration = clip.duration; - - // Extract note data from MIDI events - let mut notes = Vec::new(); - let mut active_notes: std::collections::HashMap = std::collections::HashMap::new(); - - for event in &clip.events { - let time_seconds = event.timestamp as f64 / sample_rate as f64; - - if event.is_note_on() { - // Store note on event (time and velocity) - active_notes.insert(event.data1, (time_seconds, event.data2)); - } else if event.is_note_off() { - // Find matching note on and create a MidiNote - if let Some((start, velocity)) = active_notes.remove(&event.data1) { - notes.push(MidiNote { - note: event.data1, - start_time: start, - duration: time_seconds - start, - velocity, - }); - } - } - } - - // Add the loaded MIDI clip to the track at the specified start_time - controller.add_loaded_midi_clip(track_id, clip, start_time); - - Ok(MidiFileMetadata { - duration, - notes, - }) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_get_midi_clip_data( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - // Query the MIDI clip data from the backend - let clip_data = controller.query_midi_clip(track_id, clip_id)?; - - // Convert MIDI events to MidiNote format - let mut notes = Vec::new(); - let mut active_notes: std::collections::HashMap = std::collections::HashMap::new(); - - for event in &clip_data.events { - // event.timestamp is already in seconds (sample-rate independent) - let time_seconds = event.timestamp; - - if event.is_note_on() { - // Store note on event (time and velocity) - active_notes.insert(event.data1, (time_seconds, event.data2)); - } else if event.is_note_off() { - // Find matching note on and create a MidiNote - if let Some((start, velocity)) = active_notes.remove(&event.data1) { - notes.push(MidiNote { - note: event.data1, - start_time: start, - duration: time_seconds - start, - velocity, - }); - } - } - } - - Ok(MidiFileMetadata { - duration: clip_data.duration, - notes, - }) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_update_midi_clip_notes( - state: tauri::State<'_, Arc>>, - track_id: u32, - clip_id: u32, - notes: Vec<(f64, u8, u8, f64)>, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.update_midi_clip_notes(track_id, clip_id, notes); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_get_pool_file_info( - state: tauri::State<'_, Arc>>, - pool_index: usize, -) -> Result<(f64, u32, u32), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.get_pool_file_info(pool_index) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_get_pool_waveform( - state: tauri::State<'_, Arc>>, - pool_index: usize, - target_peaks: usize, -) -> Result, String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.get_pool_waveform(pool_index, target_peaks) - } else { - Err("Audio not initialized".to_string()) - } -} - -// Node graph commands - -#[tauri::command] -pub async fn graph_add_node( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_type: String, - x: f32, - y: f32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - // Get the next node ID before adding (nodes are added sequentially) - let node_id = audio_state.next_graph_node_id; - audio_state.next_graph_node_id += 1; - - if let Some(controller) = &mut audio_state.controller { - controller.graph_add_node(track_id, node_type, x, y); - Ok(node_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_add_node_to_template( - state: tauri::State<'_, Arc>>, - track_id: u32, - voice_allocator_id: u32, - node_type: String, - x: f32, - y: f32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - // Get template-local node ID for this VoiceAllocator - let node_id = audio_state.template_node_counters - .entry(voice_allocator_id) - .or_insert(0); - let template_node_id = *node_id; - *node_id += 1; - - if let Some(controller) = &mut audio_state.controller { - controller.graph_add_node_to_template(track_id, voice_allocator_id, node_type, x, y); - Ok(template_node_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_remove_node( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_remove_node(track_id, node_id); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_connect( - state: tauri::State<'_, Arc>>, - track_id: u32, - from_node: u32, - from_port: usize, - to_node: u32, - to_port: usize, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_connect(track_id, from_node, from_port, to_node, to_port); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_connect_in_template( - state: tauri::State<'_, Arc>>, - track_id: u32, - voice_allocator_id: u32, - from_node: u32, - from_port: usize, - to_node: u32, - to_port: usize, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_connect_in_template(track_id, voice_allocator_id, from_node, from_port, to_node, to_port); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_disconnect( - state: tauri::State<'_, Arc>>, - track_id: u32, - from_node: u32, - from_port: usize, - to_node: u32, - to_port: usize, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_disconnect(track_id, from_node, from_port, to_node, to_port); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_set_parameter( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - param_id: u32, - value: f32, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_set_parameter(track_id, node_id, param_id, value); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_set_output_node( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - controller.graph_set_output_node(track_id, node_id); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -// Preset management commands - -#[tauri::command] -pub async fn graph_save_preset( - app_handle: tauri::AppHandle, - state: tauri::State<'_, Arc>>, - track_id: u32, - preset_name: String, - description: String, - tags: Vec, -) -> Result { - use std::fs; - - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - // Get user presets directory - let app_data_dir = app_handle.path().app_data_dir() - .map_err(|e| format!("Failed to get app data directory: {}", e))?; - let presets_dir = app_data_dir.join("presets"); - - // Create presets directory if it doesn't exist - fs::create_dir_all(&presets_dir) - .map_err(|e| format!("Failed to create presets directory: {}", e))?; - - // Create preset path - let filename = format!("{}.json", preset_name.replace(" ", "_")); - let preset_path = presets_dir.join(&filename); - let preset_path_str = preset_path.to_string_lossy().to_string(); - - // Send command to save preset - controller.graph_save_preset( - track_id, - preset_path_str.clone(), - preset_name, - description, - tags - ); - - Ok(preset_path_str) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_load_preset( - state: tauri::State<'_, Arc>>, - track_id: u32, - preset_path: String, -) -> Result<(), String> { - use daw_backend::GraphPreset; - - let mut audio_state = state.lock().unwrap(); - - // Load the preset JSON to count nodes - let json = std::fs::read_to_string(&preset_path) - .map_err(|e| format!("Failed to read preset file: {}", e))?; - let preset = GraphPreset::from_json(&json) - .map_err(|e| format!("Failed to parse preset: {}", e))?; - - // Update the node ID counter to account for nodes in the preset - let node_count = preset.nodes.len() as u32; - audio_state.next_graph_node_id = node_count; - - if let Some(controller) = &mut audio_state.controller { - // Send command to load preset - controller.graph_load_preset(track_id, preset_path); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_load_preset_from_json( - state: tauri::State<'_, Arc>>, - track_id: u32, - preset_json: String, -) -> Result<(), String> { - use daw_backend::GraphPreset; - use std::io::Write; - - let mut audio_state = state.lock().unwrap(); - - // Parse the preset JSON to count nodes - let preset = GraphPreset::from_json(&preset_json) - .map_err(|e| format!("Failed to parse preset: {}", e))?; - - // Update the node ID counter to account for nodes in the preset - let node_count = preset.nodes.len() as u32; - audio_state.next_graph_node_id = node_count; - - if let Some(controller) = &mut audio_state.controller { - // Write JSON to a temporary file - let temp_path = std::env::temp_dir().join(format!("lb_temp_preset_{}.json", track_id)); - let mut file = std::fs::File::create(&temp_path) - .map_err(|e| format!("Failed to create temp file: {}", e))?; - file.write_all(preset_json.as_bytes()) - .map_err(|e| format!("Failed to write temp file: {}", e))?; - drop(file); - - // Load from the temp file - controller.graph_load_preset(track_id, temp_path.to_string_lossy().to_string()); - - // Clean up temp file (after a delay to allow loading) - std::thread::spawn(move || { - std::thread::sleep(std::time::Duration::from_millis(500)); - let _ = std::fs::remove_file(temp_path); - }); - - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[derive(serde::Serialize)] -pub struct PresetInfo { - pub name: String, - pub path: String, - pub description: String, - pub author: String, - pub tags: Vec, - pub is_factory: bool, -} - -#[tauri::command] -pub async fn graph_list_presets( - app_handle: tauri::AppHandle, -) -> Result, String> { - use daw_backend::GraphPreset; - use std::fs; - - let mut presets = Vec::new(); - - // Recursively scan for JSON files in instruments directory - fn scan_presets_recursive(dir: &std::path::Path, presets: &mut Vec) { - eprintln!("Scanning directory: {:?}", dir); - if let Ok(entries) = std::fs::read_dir(dir) { - for entry in entries.flatten() { - let path = entry.path(); - if path.is_dir() { - // Recurse into subdirectories - scan_presets_recursive(&path, presets); - } else if path.extension().and_then(|s| s.to_str()) == Some("json") { - eprintln!("Found JSON file: {:?}", path); - // Load JSON preset files - match std::fs::read_to_string(&path) { - Ok(json) => { - match daw_backend::GraphPreset::from_json(&json) { - Ok(preset) => { - eprintln!(" ✓ Loaded preset: {}", preset.metadata.name); - presets.push(PresetInfo { - name: preset.metadata.name, - path: path.to_string_lossy().to_string(), - description: preset.metadata.description, - author: preset.metadata.author, - tags: preset.metadata.tags, - is_factory: true, - }); - } - Err(e) => eprintln!(" ✗ Failed to parse preset: {}", e), - } - } - Err(e) => eprintln!(" ✗ Failed to read file: {}", e), - } - } - } - } - } - - // Try multiple locations for instruments - let mut instruments_found = false; - - // 1. Try bundled resources (production) - if let Ok(resource_dir) = app_handle.path().resource_dir() { - let instruments_dir = resource_dir.join("assets/instruments"); - eprintln!("Trying bundled path: {:?} (exists: {})", instruments_dir, instruments_dir.exists()); - if instruments_dir.exists() { - scan_presets_recursive(&instruments_dir, &mut presets); - instruments_found = true; - } - } - - // 2. Fallback to dev location (development mode) - if !instruments_found { - // Try relative to current working directory (dev mode) - if let Ok(cwd) = std::env::current_dir() { - let dev_instruments = cwd.join("../src/assets/instruments"); - eprintln!("Trying dev path: {:?} (exists: {})", dev_instruments, dev_instruments.exists()); - if dev_instruments.exists() { - scan_presets_recursive(&dev_instruments, &mut presets); - } - } - } - - eprintln!("Found {} factory presets", presets.len()); - - // Load user presets - if let Ok(app_data_dir) = app_handle.path().app_data_dir() { - let user_presets_dir = app_data_dir.join("presets"); - if user_presets_dir.exists() { - if let Ok(entries) = fs::read_dir(user_presets_dir) { - for entry in entries.flatten() { - if let Ok(path) = entry.path().canonicalize() { - if path.extension().and_then(|s| s.to_str()) == Some("json") { - if let Ok(json) = fs::read_to_string(&path) { - if let Ok(preset) = GraphPreset::from_json(&json) { - presets.push(PresetInfo { - name: preset.metadata.name, - path: path.to_string_lossy().to_string(), - description: preset.metadata.description, - author: preset.metadata.author, - tags: preset.metadata.tags, - is_factory: false, - }); - } - } - } - } - } - } - } - } - - Ok(presets) -} - -#[tauri::command] -pub async fn graph_delete_preset( - app_handle: tauri::AppHandle, - preset_path: String, -) -> Result<(), String> { - use std::fs; - use std::path::Path; - - let preset_path = Path::new(&preset_path); - - // Check if preset is in the app's resource directory (factory content - cannot delete) - if let Ok(resource_dir) = app_handle.path().resource_dir() { - if let Ok(canonical_preset) = preset_path.canonicalize() { - if let Ok(canonical_resource) = resource_dir.canonicalize() { - if canonical_preset.starts_with(canonical_resource) { - return Err("Cannot delete factory presets or bundled instruments".to_string()); - } - } - } - } - - // If we get here, it's a user preset - safe to delete - fs::remove_file(&preset_path) - .map_err(|e| format!("Failed to delete preset: {}", e))?; - - Ok(()) -} - -#[tauri::command] -pub async fn graph_get_state( - state: tauri::State<'_, Arc>>, - track_id: u32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - // Use synchronous query to get graph state - controller.query_graph_state(track_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn graph_get_template_state( - state: tauri::State<'_, Arc>>, - track_id: u32, - voice_allocator_id: u32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - if let Some(controller) = &mut audio_state.controller { - // Use synchronous query to get template graph state - controller.query_template_state(track_id, voice_allocator_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn sampler_load_sample( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - file_path: String, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.sampler_load_sample(track_id, node_id, file_path); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn multi_sampler_add_layer( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - file_path: String, - key_min: u8, - key_max: u8, - root_key: u8, - velocity_min: u8, - velocity_max: u8, - loop_start: Option, - loop_end: Option, - loop_mode: Option, -) -> Result<(), String> { - use daw_backend::audio::node_graph::nodes::LoopMode; - - let mut audio_state = state.lock().unwrap(); - - // Parse loop mode string to enum - let loop_mode_enum = match loop_mode.as_deref() { - Some("continuous") => LoopMode::Continuous, - Some("oneshot") | Some("one-shot") => LoopMode::OneShot, - _ => LoopMode::OneShot, // Default - }; - - if let Some(controller) = &mut audio_state.controller { - controller.multi_sampler_add_layer( - track_id, - node_id, - file_path, - key_min, - key_max, - root_key, - velocity_min, - velocity_max, - loop_start, - loop_end, - loop_mode_enum, - ); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[derive(serde::Serialize)] -pub struct LayerInfo { - pub file_path: String, - pub key_min: u8, - pub key_max: u8, - pub root_key: u8, - pub velocity_min: u8, - pub velocity_max: u8, - pub loop_start: Option, - pub loop_end: Option, - pub loop_mode: String, -} - -#[tauri::command] -pub async fn multi_sampler_get_layers( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, -) -> Result, String> { - eprintln!("[multi_sampler_get_layers] FUNCTION CALLED with track_id: {}, node_id: {}", track_id, node_id); - use daw_backend::GraphPreset; - - // Set up oneshot channel to wait for preset save completion - let (tx, rx) = oneshot::channel(); - - let (temp_path_str, preset_save_waiters) = { - let mut audio_state = state.lock().unwrap(); - - // Clone preset_save_waiters first before any mutable borrows - let preset_save_waiters = audio_state.preset_save_waiters.clone(); - - if let Some(controller) = &mut audio_state.controller { - // Use preset serialization to get node data including layers - // Use timestamp to ensure unique temp file for each query to avoid conflicts - let timestamp = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap() - .as_nanos(); - let temp_path = std::env::temp_dir().join(format!("temp_layers_query_{}_{}_{}.json", track_id, node_id, timestamp)); - let temp_path_str = temp_path.to_string_lossy().to_string(); - eprintln!("[multi_sampler_get_layers] Temp path: {}", temp_path_str); - - // Register waiter for this preset path - { - let mut waiters = preset_save_waiters.lock().unwrap(); - waiters.insert(temp_path_str.clone(), tx); - } - - controller.graph_save_preset( - track_id, - temp_path_str.clone(), - "temp".to_string(), - "".to_string(), - vec![] - ); - - (temp_path_str, preset_save_waiters) - } else { - eprintln!("[multi_sampler_get_layers] Audio not initialized"); - return Err("Audio not initialized".to_string()); - } - }; - - // Wait for preset save event with timeout - eprintln!("[multi_sampler_get_layers] Waiting for preset save completion..."); - match tokio::time::timeout(std::time::Duration::from_secs(5), rx).await { - Ok(Ok(())) => { - eprintln!("[multi_sampler_get_layers] Preset save complete, reading file..."); - } - Ok(Err(_)) => { - eprintln!("[multi_sampler_get_layers] Preset save channel closed"); - return Ok(Vec::new()); - } - Err(_) => { - eprintln!("[multi_sampler_get_layers] Timeout waiting for preset save"); - // Clean up waiter - let mut waiters = preset_save_waiters.lock().unwrap(); - waiters.remove(&temp_path_str); - return Ok(Vec::new()); - } - } - - let temp_path = std::path::PathBuf::from(&temp_path_str); - // Read the temp file and parse it - eprintln!("[multi_sampler_get_layers] Reading temp file..."); - match std::fs::read_to_string(&temp_path) { - Ok(json) => { - // Clean up temp file - let _ = std::fs::remove_file(&temp_path); - - // Parse the preset JSON - let preset: GraphPreset = match serde_json::from_str(&json) { - Ok(p) => p, - Err(e) => return Err(format!("Failed to parse preset: {}", e)), - }; - - // Find the node with the matching ID - eprintln!("[multi_sampler_get_layers] Looking for node_id: {}", node_id); - eprintln!("[multi_sampler_get_layers] Available nodes: {:?}", preset.nodes.iter().map(|n| (n.id, &n.node_type)).collect::>()); - - if let Some(node) = preset.nodes.iter().find(|n| n.id == node_id) { - eprintln!("[multi_sampler_get_layers] Found node: {} type: {}", node.id, node.node_type); - if let Some(ref sample_data) = node.sample_data { - eprintln!("[multi_sampler_get_layers] Node has sample_data"); - // Check if it's a MultiSampler - if let daw_backend::audio::node_graph::preset::SampleData::MultiSampler { layers } = sample_data { - eprintln!("[multi_sampler_get_layers] Returning {} layers", layers.len()); - return Ok(layers.iter().map(|layer| { - let loop_mode_str = match layer.loop_mode { - daw_backend::audio::node_graph::nodes::LoopMode::Continuous => "continuous", - daw_backend::audio::node_graph::nodes::LoopMode::OneShot => "oneshot", - }; - LayerInfo { - file_path: layer.file_path.clone().unwrap_or_default(), - key_min: layer.key_min, - key_max: layer.key_max, - root_key: layer.root_key, - velocity_min: layer.velocity_min, - velocity_max: layer.velocity_max, - loop_start: layer.loop_start, - loop_end: layer.loop_end, - loop_mode: loop_mode_str.to_string(), - } - }).collect()); - } else { - eprintln!("[multi_sampler_get_layers] sample_data is not MultiSampler type"); - } - } else { - eprintln!("[multi_sampler_get_layers] Node has no sample_data"); - } - } else { - eprintln!("[multi_sampler_get_layers] Node not found"); - } - - Ok(Vec::new()) - } - Err(e) => { - eprintln!("[multi_sampler_get_layers] Failed to read temp file: {}", e); - Ok(Vec::new()) // Return empty list if file doesn't exist - } - } -} - -#[tauri::command] -pub async fn multi_sampler_update_layer( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - layer_index: usize, - key_min: u8, - key_max: u8, - root_key: u8, - velocity_min: u8, - velocity_max: u8, - loop_start: Option, - loop_end: Option, - loop_mode: Option, -) -> Result<(), String> { - use daw_backend::audio::node_graph::nodes::LoopMode; - - let mut audio_state = state.lock().unwrap(); - - // Parse loop mode string to enum - let loop_mode_enum = match loop_mode.as_deref() { - Some("continuous") => LoopMode::Continuous, - Some("oneshot") | Some("one-shot") => LoopMode::OneShot, - _ => LoopMode::OneShot, // Default - }; - - if let Some(controller) = &mut audio_state.controller { - controller.multi_sampler_update_layer( - track_id, - node_id, - layer_index, - key_min, - key_max, - root_key, - velocity_min, - velocity_max, - loop_start, - loop_end, - loop_mode_enum, - ); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn multi_sampler_remove_layer( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - layer_index: usize, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.multi_sampler_remove_layer(track_id, node_id, layer_index); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn get_oscilloscope_data( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - sample_count: usize, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.query_oscilloscope_data(track_id, node_id, sample_count) - } else { - Err("Audio not initialized".to_string()) - } -} - -// ===== Automation Input Node Commands ===== - -#[tauri::command] -pub async fn automation_add_keyframe( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - keyframe: daw_backend::AutomationKeyframeData, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.send_command(daw_backend::Command::AutomationAddKeyframe( - track_id, - node_id, - keyframe.time, - keyframe.value, - keyframe.interpolation, - keyframe.ease_out, - keyframe.ease_in, - )); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn automation_remove_keyframe( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - time: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.send_command(daw_backend::Command::AutomationRemoveKeyframe( - track_id, - node_id, - time, - )); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn automation_get_keyframes( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, -) -> Result, String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.query_automation_keyframes(track_id, node_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn automation_set_name( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, - name: String, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.send_command(daw_backend::Command::AutomationSetName( - track_id, - node_id, - name, - )); - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn automation_get_name( - state: tauri::State<'_, Arc>>, - track_id: u32, - node_id: u32, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.query_automation_name(track_id, node_id) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[derive(serde::Serialize, Clone)] -#[serde(tag = "type")] -pub enum SerializedAudioEvent { - PlaybackPosition { time: f64 }, - RecordingStarted { track_id: u32, clip_id: u32 }, - RecordingProgress { clip_id: u32, duration: f64 }, - RecordingStopped { clip_id: u32, pool_index: usize, waveform: Vec }, - RecordingError { message: String }, - MidiRecordingStopped { track_id: u32, clip_id: u32, note_count: usize }, - MidiRecordingProgress { track_id: u32, clip_id: u32, duration: f64, notes: Vec<(f64, u8, u8, f64)> }, - NoteOn { note: u8, velocity: u8 }, - NoteOff { note: u8 }, - GraphNodeAdded { track_id: u32, node_id: u32, node_type: String }, - GraphConnectionError { track_id: u32, message: String }, - GraphStateChanged { track_id: u32 }, - GraphPresetLoaded { track_id: u32 }, - GraphPresetSaved { track_id: u32, preset_path: String }, -} - -// audio_get_events command removed - events are now pushed via Tauri event system - -/// Serialize the audio pool for project saving -#[tauri::command] -pub async fn audio_serialize_pool( - state: tauri::State<'_, Arc>>, - project_path: String, -) -> Result, String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.serialize_audio_pool(Path::new(&project_path)) - } else { - Err("Audio not initialized".to_string()) - } -} - -/// Load audio pool from serialized entries -/// Returns a list of pool indices that failed to load (missing files) -#[tauri::command] -pub async fn audio_load_pool( - state: tauri::State<'_, Arc>>, - entries: Vec, - project_path: String, -) -> Result, String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.load_audio_pool(entries, Path::new(&project_path)) - } else { - Err("Audio not initialized".to_string()) - } -} - -/// Resolve a missing audio file by loading from a new path -#[tauri::command] -pub async fn audio_resolve_missing_file( - state: tauri::State<'_, Arc>>, - pool_index: usize, - new_path: String, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.resolve_missing_audio_file(pool_index, Path::new(&new_path)) - } else { - Err("Audio not initialized".to_string()) - } -} - -/// Serialize a track's effects/instrument graph to JSON -#[tauri::command] -pub async fn audio_serialize_track_graph( - state: tauri::State<'_, Arc>>, - track_id: u32, - project_path: String, -) -> Result { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.serialize_track_graph(track_id, Path::new(&project_path)) - } else { - Err("Audio not initialized".to_string()) - } -} - -/// Load a track's effects/instrument graph from JSON -#[tauri::command] -pub async fn audio_load_track_graph( - state: tauri::State<'_, Arc>>, - track_id: u32, - preset_json: String, - project_path: String, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - controller.load_track_graph(track_id, &preset_json, Path::new(&project_path)) - } else { - Err("Audio not initialized".to_string()) - } -} - -#[tauri::command] -pub async fn audio_export( - state: tauri::State<'_, Arc>>, - output_path: String, - format: String, - sample_rate: u32, - channels: u32, - bit_depth: u16, - mp3_bitrate: u32, - start_time: f64, - end_time: f64, -) -> Result<(), String> { - let mut audio_state = state.lock().unwrap(); - - if let Some(controller) = &mut audio_state.controller { - // Parse format - let export_format = match format.as_str() { - "wav" => daw_backend::audio::ExportFormat::Wav, - "flac" => daw_backend::audio::ExportFormat::Flac, - _ => return Err(format!("Unsupported format: {}", format)), - }; - - // Create export settings - let settings = daw_backend::audio::ExportSettings { - format: export_format, - sample_rate, - channels, - bit_depth, - mp3_bitrate, - start_time, - end_time, - }; - - // Call export through controller - controller.export_audio(&settings, &output_path)?; - - Ok(()) - } else { - Err("Audio not initialized".to_string()) - } -} diff --git a/src-tauri/src/frame_streamer.rs b/src-tauri/src/frame_streamer.rs deleted file mode 100644 index 4105f95..0000000 --- a/src-tauri/src/frame_streamer.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::net::TcpListener; -use std::sync::{Arc, Mutex}; -use std::thread; -use tungstenite::{accept, Message}; - -pub struct FrameStreamer { - port: u16, - clients: Arc>>>, -} - -impl FrameStreamer { - pub fn new() -> Result { - // Bind to localhost on a random available port - let listener = TcpListener::bind("127.0.0.1:0") - .map_err(|e| format!("Failed to create WebSocket listener: {}", e))?; - - let port = listener.local_addr() - .map_err(|e| format!("Failed to get listener address: {}", e))? - .port(); - - // eprintln!("[Frame Streamer] WebSocket server started on port {}", port); - - let clients = Arc::new(Mutex::new(Vec::new())); - let clients_clone = clients.clone(); - - // Spawn acceptor thread - thread::spawn(move || { - for stream in listener.incoming() { - match stream { - Ok(stream) => { - // eprintln!("[Frame Streamer] New WebSocket connection from {:?}", stream.peer_addr()); - match accept(stream) { - Ok(websocket) => { - let mut clients = clients_clone.lock().unwrap(); - clients.push(websocket); - // eprintln!("[Frame Streamer] Client connected, total clients: {}", clients.len()); - } - Err(_e) => { - // eprintln!("[Frame Streamer] Failed to accept WebSocket: {}", e); - } - } - } - Err(_e) => { - // eprintln!("[Frame Streamer] Failed to accept connection: {}", e); - } - } - } - }); - - Ok(Self { - port, - clients, - }) - } - - pub fn port(&self) -> u16 { - self.port - } - - /// Send a decoded frame to all connected clients - /// Frame format: [pool_index: u32][timestamp_ms: u32][width: u32][height: u32][rgba_data...] - pub fn send_frame(&self, pool_index: usize, timestamp: f64, width: u32, height: u32, rgba_data: &[u8]) { - let mut clients = self.clients.lock().unwrap(); - - // Build frame message (rgba_data is already in RGBA format from decoder) - let mut frame_msg = Vec::with_capacity(16 + rgba_data.len()); - frame_msg.extend_from_slice(&(pool_index as u32).to_le_bytes()); - frame_msg.extend_from_slice(&((timestamp * 1000.0) as u32).to_le_bytes()); - frame_msg.extend_from_slice(&width.to_le_bytes()); - frame_msg.extend_from_slice(&height.to_le_bytes()); - frame_msg.extend_from_slice(rgba_data); - - // Send to all clients, remove disconnected ones - clients.retain_mut(|client| { - match client.write_message(Message::Binary(frame_msg.clone())) { - Ok(_) => true, - Err(_e) => { - // eprintln!("[Frame Streamer] Client disconnected: {}", e); - false - } - } - }); - } -} diff --git a/src-tauri/src/frame_ws_async.rs b/src-tauri/src/frame_ws_async.rs deleted file mode 100644 index 577528a..0000000 --- a/src-tauri/src/frame_ws_async.rs +++ /dev/null @@ -1,230 +0,0 @@ -use axum::{ - extract::{ - ws::{Message, WebSocket, WebSocketUpgrade}, - State, - }, - response::IntoResponse, - routing::get, - Router, -}; -use flume::{Sender, unbounded}; -use std::collections::HashMap; -use std::sync::Arc; -use tokio::sync::RwLock; -use std::time::Duration; - -/// Playback state for a video pool -#[derive(Clone, Debug)] -pub struct PlaybackState { - pub is_playing: bool, - pub target_fps: f64, - pub current_time: f64, -} - -/// Shared server state -pub struct ServerState { - /// Connected clients - clients: RwLock>>>, - /// Playback state per pool index - playback_state: RwLock>, -} - -impl ServerState { - pub fn new() -> Self { - Self { - clients: RwLock::new(Vec::new()), - playback_state: RwLock::new(HashMap::new()), - } - } - - /// Register a new client - pub async fn add_client(&self, sender: Sender>) { - let mut clients = self.clients.write().await; - clients.push(sender); - eprintln!("[Async Frame Streamer] Client registered, total: {}", clients.len()); - } - - /// Broadcast a frame to all connected clients - pub async fn broadcast_frame(&self, frame_data: Vec) { - let clients = self.clients.read().await; - - // Send to all clients - for client in clients.iter() { - // Non-blocking send, drop frame if client is slow - let _ = client.try_send(frame_data.clone()); - } - } - - /// Remove disconnected clients - pub async fn cleanup_clients(&self) { - let mut clients = self.clients.write().await; - clients.retain(|client| !client.is_disconnected()); - eprintln!("[Async Frame Streamer] Cleaned up clients, remaining: {}", clients.len()); - } - - /// Update playback state for a pool - pub async fn set_playback_state(&self, pool_index: usize, state: PlaybackState) { - let mut states = self.playback_state.write().await; - states.insert(pool_index, state); - } - - /// Get playback state for a pool - pub async fn get_playback_state(&self, pool_index: usize) -> Option { - let states = self.playback_state.read().await; - states.get(&pool_index).cloned() - } -} - -pub struct AsyncFrameStreamer { - port: u16, - state: Arc, - shutdown_tx: Option>, -} - -impl AsyncFrameStreamer { - pub async fn new() -> Result { - let state = Arc::new(ServerState::new()); - - // Create router with WebSocket upgrade handler - let app_state = state.clone(); - let app = Router::new() - .route("/ws", get(ws_handler)) - .with_state(app_state); - - // Bind to localhost on a random port - let listener = tokio::net::TcpListener::bind("127.0.0.1:0") - .await - .map_err(|e| format!("Failed to bind: {}", e))?; - - let port = listener - .local_addr() - .map_err(|e| format!("Failed to get address: {}", e))? - .port(); - - eprintln!("[Async Frame Streamer] WebSocket server starting on port {}", port); - - // Spawn server task - let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel(); - - tokio::spawn(async move { - axum::serve(listener, app) - .with_graceful_shutdown(async { - shutdown_rx.await.ok(); - }) - .await - .expect("Server error"); - }); - - eprintln!("[Async Frame Streamer] Server started"); - - Ok(Self { - port, - state, - shutdown_tx: Some(shutdown_tx), - }) - } - - pub fn port(&self) -> u16 { - self.port - } - - /// Send a frame to all connected clients for a specific pool - /// Frame format: [pool_index: u32][timestamp_ms: u32][width: u32][height: u32][rgba_data...] - pub async fn send_frame(&self, pool_index: usize, timestamp: f64, width: u32, height: u32, rgba_data: &[u8]) { - // Build frame message - let mut frame_msg = Vec::with_capacity(16 + rgba_data.len()); - frame_msg.extend_from_slice(&(pool_index as u32).to_le_bytes()); - frame_msg.extend_from_slice(&((timestamp * 1000.0) as u32).to_le_bytes()); - frame_msg.extend_from_slice(&width.to_le_bytes()); - frame_msg.extend_from_slice(&height.to_le_bytes()); - frame_msg.extend_from_slice(rgba_data); - - // Broadcast to all connected clients - self.state.broadcast_frame(frame_msg).await; - } - - /// Start streaming frames for a pool at a target FPS - pub async fn start_stream(&self, pool_index: usize, fps: f64) { - let state = PlaybackState { - is_playing: true, - target_fps: fps, - current_time: 0.0, - }; - self.state.set_playback_state(pool_index, state).await; - eprintln!("[Async Frame Streamer] Started streaming pool {} at {} FPS", pool_index, fps); - } - - /// Stop streaming frames for a pool - pub async fn stop_stream(&self, pool_index: usize) { - if let Some(mut state) = self.state.get_playback_state(pool_index).await { - state.is_playing = false; - self.state.set_playback_state(pool_index, state).await; - eprintln!("[Async Frame Streamer] Stopped streaming pool {}", pool_index); - } - } - - /// Seek to a specific time in a pool - pub async fn seek(&self, pool_index: usize, timestamp: f64) { - if let Some(mut state) = self.state.get_playback_state(pool_index).await { - state.current_time = timestamp; - self.state.set_playback_state(pool_index, state).await; - } - } -} - -impl Drop for AsyncFrameStreamer { - fn drop(&mut self) { - if let Some(tx) = self.shutdown_tx.take() { - let _ = tx.send(()); - } - } -} - -/// WebSocket handler -async fn ws_handler( - ws: WebSocketUpgrade, - State(state): State>, -) -> impl IntoResponse { - ws.on_upgrade(move |socket| handle_socket(socket, state)) -} - -/// Handle individual WebSocket connection -async fn handle_socket(mut socket: WebSocket, state: Arc) { - eprintln!("[Async Frame Streamer] New WebSocket connection"); - - // Create a channel for this client - let (tx, rx) = unbounded::>(); - - // Register this client - state.add_client(tx).await; - - // Spawn task to send frames to this client - let mut rx = rx; - let mut send_task = tokio::spawn(async move { - while let Ok(frame) = rx.recv_async().await { - if socket.send(Message::Binary(frame)).await.is_err() { - eprintln!("[Async Frame Streamer] Failed to send frame to client"); - break; - } - } - eprintln!("[Async Frame Streamer] Send task ended"); - }); - - // Keep connection alive with ping/pong - let mut interval = tokio::time::interval(Duration::from_secs(30)); - - loop { - tokio::select! { - _ = interval.tick() => { - // Connection alive, no need to ping in this simple implementation - } - _ = &mut send_task => { - eprintln!("[Async Frame Streamer] Send task completed, closing connection"); - break; - } - } - } - - // Cleanup - state.cleanup_clients().await; -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs deleted file mode 100644 index f08cf88..0000000 --- a/src-tauri/src/lib.rs +++ /dev/null @@ -1,346 +0,0 @@ -use std::{path::PathBuf, sync::{Arc, Mutex}}; - -use tauri_plugin_log::{Target, TargetKind}; -use log::{trace, info, debug, warn, error}; -use tracing_subscriber::EnvFilter; -use chrono::Local; -use tauri::{AppHandle, Manager, Url, WebviewUrl, WebviewWindowBuilder}; - -mod audio; -mod video; -mod video_server; - - -#[derive(Default)] -struct AppState { - counter: u32, -} - -// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ -#[tauri::command] -fn greet(name: &str) -> String { - format!("Hello, {}! You've been greeted from Rust!", name) -} - -#[tauri::command] -fn trace(msg: String) { - trace!("{}",msg); -} -#[tauri::command] -fn info(msg: String) { - info!("{}",msg); -} -#[tauri::command] -fn debug(msg: String) { - debug!("{}",msg); -} -#[tauri::command] -fn warn(msg: String) { - warn!("{}",msg); -} -#[tauri::command] -fn error(msg: String) { - error!("{}",msg); -} - -#[tauri::command] -async fn open_folder_dialog(app: AppHandle, title: String) -> Result, String> { - use tauri_plugin_dialog::DialogExt; - - let folder = app.dialog() - .file() - .set_title(&title) - .blocking_pick_folder(); - - Ok(folder.map(|path| path.to_string())) -} - -#[tauri::command] -async fn read_folder_files(path: String) -> Result, String> { - use std::fs; - - let entries = fs::read_dir(&path) - .map_err(|e| format!("Failed to read directory: {}", e))?; - - let audio_extensions = vec!["wav", "aif", "aiff", "flac", "mp3", "ogg"]; - - let mut files = Vec::new(); - for entry in entries { - let entry = entry.map_err(|e| format!("Failed to read entry: {}", e))?; - let path = entry.path(); - - if path.is_file() { - if let Some(ext) = path.extension() { - let ext_str = ext.to_string_lossy().to_lowercase(); - if audio_extensions.contains(&ext_str.as_str()) { - if let Some(filename) = path.file_name() { - files.push(filename.to_string_lossy().to_string()); - } - } - } - } - } - - Ok(files) -} - -use tauri::PhysicalSize; - -#[tauri::command] -async fn create_window(app: tauri::AppHandle, path: Option) { - let state = app.state::>(); - - // Lock the mutex to get mutable access: - let mut state = state.lock().unwrap(); - - // Increment the counter and generate a unique window label - let window_label = format!("window{}", state.counter); - state.counter += 1; - - // Build the new window with the unique label - let webview_window = WebviewWindowBuilder::new(&app, &window_label, WebviewUrl::App("index.html".into())) - .title("Lightningbeam") - .build() - .unwrap(); - - // Get the current monitor's screen size from the new window - if let Ok(Some(monitor)) = webview_window.current_monitor() { - let screen_size = monitor.size(); // Get the size of the monitor - let width = 4096; - let height = 4096; - - // Set the window size to be the smaller of the specified size or the screen size - let new_width = width.min(screen_size.width as u32); - let new_height = height.min(screen_size.height as u32 - 100); - - // Set the size using PhysicalSize - webview_window.set_size(tauri::Size::Physical(PhysicalSize::new(new_width, new_height))) - .expect("Failed to set window size"); - } else { - eprintln!("Could not detect the current monitor."); - } - - // Set the opened file if provided - if let Some(val) = path { - // Pass path data to the window via JavaScript - webview_window.eval(&format!("window.openedFiles = [\"{val}\"]")).unwrap(); - - // Set the window title if provided - webview_window.set_title(&val).expect("Failed to set window title"); - } -} - - -fn handle_file_associations(app: AppHandle, files: Vec) { - // -- Scope handling start -- - - // You can remove this block if you only want to know about the paths, but not actually "use" them in the frontend. - - // This requires the `fs` tauri plugin and is required to make the plugin's frontend work: - use tauri_plugin_fs::FsExt; - let fs_scope = app.fs_scope(); - - // This is for the `asset:` protocol to work: - let asset_protocol_scope = app.asset_protocol_scope(); - - for file in &files { - // This requires the `fs` plugin: - let _ = fs_scope.allow_file(file); - - // This is for the `asset:` protocol: - let _ = asset_protocol_scope.allow_file(file); - } - - // -- Scope handling end -- - - let files = files - .into_iter() - .map(|f| { - let file = f.to_string_lossy().replace('\\', "\\\\"); // escape backslash - format!("\"{file}\"",) // wrap in quotes for JS array - }) - .collect::>() - .join(","); - warn!("{}",files); - - let window = app.get_webview_window("main").unwrap(); - window.eval(&format!("window.openedFiles = [{files}]")).unwrap(); -} - -#[cfg_attr(mobile, tauri::mobile_entry_point)] -pub fn run() { - let pkg_name = env!("CARGO_PKG_NAME").to_string(); - // Initialize video HTTP server - let video_server = video_server::VideoServer::new() - .expect("Failed to start video server"); - eprintln!("[App] Video server started on port {}", video_server.port()); - - tauri::Builder::default() - .manage(Mutex::new(AppState::default())) - .manage(Arc::new(Mutex::new(audio::AudioState::default()))) - .manage(Arc::new(Mutex::new(video::VideoState::default()))) - .manage(Arc::new(Mutex::new(video_server))) - .setup(|app| { - #[cfg(any(windows, target_os = "linux"))] // Windows/Linux needs different handling from macOS - { - let mut files = Vec::new(); - - // NOTICE: `args` may include URL protocol (`your-app-protocol://`) - // or arguments (`--`) if your app supports them. - // files may also be passed as `file://path/to/file` - for maybe_file in std::env::args().skip(1) { - // skip flags like -f or --flag - if maybe_file.starts_with('-') { - continue; - } - - // handle `file://` path urls and skip other urls - if let Ok(url) = Url::parse(&maybe_file) { - // if let Ok(url) = url::Url::parse(&maybe_file) { - if let Ok(path) = url.to_file_path() { - files.push(path); - } - } else { - files.push(PathBuf::from(maybe_file)) - } - } - - handle_file_associations(app.handle().clone(), files); - } - #[cfg(debug_assertions)] // only include this code on debug builds - { - let window = app.get_webview_window("main").unwrap(); - window.open_devtools(); - window.close_devtools(); - } - Ok(()) - }) - .plugin( - tauri_plugin_log::Builder::new() - .timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal) - .format(|out, message, record| { - let date = Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); - out.finish(format_args!( - "{}[{}] {}", - date, - record.level(), - message - )) - }) - .targets([ - Target::new(TargetKind::Stdout), - // LogDir locations: - // Linux: /home/user/.local/share/org.lightningbeam.core/logs - // macOS: /Users/user/Library/Logs/org.lightningbeam.core/logs - // Windows: C:\Users\user\AppData\Local\org.lightningbeam.core\logs - Target::new(TargetKind::LogDir { file_name: Some("logs".to_string()) }), - Target::new(TargetKind::Webview), - ]) - .build() - ) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_fs::init()) - .plugin(tauri_plugin_shell::init()) - .invoke_handler(tauri::generate_handler![ - greet, trace, debug, info, warn, error, create_window, - audio::audio_init, - audio::audio_reset, - audio::audio_play, - audio::audio_stop, - audio::set_metronome_enabled, - audio::audio_seek, - audio::audio_test_beep, - audio::audio_set_track_parameter, - audio::audio_create_track, - audio::audio_load_file, - audio::audio_add_clip, - audio::audio_move_clip, - audio::audio_trim_clip, - audio::audio_extend_clip, - audio::audio_start_recording, - audio::audio_stop_recording, - audio::audio_pause_recording, - audio::audio_resume_recording, - audio::audio_start_midi_recording, - audio::audio_stop_midi_recording, - audio::audio_create_midi_clip, - audio::audio_add_midi_note, - audio::audio_load_midi_file, - audio::audio_get_midi_clip_data, - audio::audio_update_midi_clip_notes, - audio::audio_send_midi_note_on, - audio::audio_send_midi_note_off, - audio::audio_set_active_midi_track, - audio::audio_get_pool_file_info, - audio::audio_get_pool_waveform, - audio::graph_add_node, - audio::graph_add_node_to_template, - audio::graph_remove_node, - audio::graph_connect, - audio::graph_connect_in_template, - audio::graph_disconnect, - audio::graph_set_parameter, - audio::graph_set_output_node, - audio::graph_save_preset, - audio::graph_load_preset, - audio::graph_load_preset_from_json, - audio::graph_list_presets, - audio::graph_delete_preset, - audio::graph_get_state, - audio::graph_get_template_state, - audio::sampler_load_sample, - audio::multi_sampler_add_layer, - audio::multi_sampler_get_layers, - audio::multi_sampler_update_layer, - audio::multi_sampler_remove_layer, - audio::get_oscilloscope_data, - audio::automation_add_keyframe, - audio::automation_remove_keyframe, - audio::automation_get_keyframes, - audio::automation_set_name, - audio::automation_get_name, - audio::audio_serialize_pool, - audio::audio_load_pool, - audio::audio_resolve_missing_file, - audio::audio_serialize_track_graph, - audio::audio_load_track_graph, - audio::audio_export, - video::video_load_file, - video::video_get_frame, - video::video_get_frames_batch, - video::video_set_cache_size, - open_folder_dialog, - read_folder_files, - video::video_get_pool_info, - video::video_ipc_benchmark, - video::video_get_transcode_status, - video::video_allow_asset, - ]) - // .manage(window_counter) - .build(tauri::generate_context!()) - .expect("error while running tauri application") - .run( - #[allow(unused_variables)] - |app, event| { - #[cfg(any(target_os = "macos", target_os = "ios"))] - if let tauri::RunEvent::Opened { urls } = event { - let app = app.clone(); - let files = urls - .into_iter() - .filter_map(|url| url.to_file_path().ok()) - .map(|f| { - let file = f.to_string_lossy().replace('\\', "\\\\"); // escape backslash - format!("\"{file}\"",) // wrap in quotes for JS array - }) - .collect::>(); - - tauri::async_runtime::spawn(async move { - for path in files { - create_window(app.clone(), Some(path)).await; - } - }); - } - }, - ); - tracing_subscriber::fmt().with_env_filter(EnvFilter::new(format!("{}=trace", pkg_name))).init(); -} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs deleted file mode 100644 index 56a15a0..0000000 --- a/src-tauri/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -// Prevents additional console window on Windows in release, DO NOT REMOVE!! -#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] - -fn main() { - lightningbeam_lib::run(); -} diff --git a/src-tauri/src/render_window.rs b/src-tauri/src/render_window.rs deleted file mode 100644 index 0d5ddb5..0000000 --- a/src-tauri/src/render_window.rs +++ /dev/null @@ -1,161 +0,0 @@ -use std::sync::Arc; -use std::thread; -use winit::{ - event::{Event, WindowEvent}, - event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy}, - window::WindowBuilder, -}; - -#[cfg(target_os = "linux")] -use winit::platform::x11::EventLoopBuilderExtX11; - -use crate::renderer::Renderer; - -/// Events that can be sent to the render window thread -#[derive(Debug, Clone)] -pub enum RenderEvent { - UpdateGradient { top: [f32; 4], bottom: [f32; 4] }, - SetPosition { x: i32, y: i32 }, - SetSize { width: u32, height: u32 }, - RequestRedraw, - Close, -} - -/// Handle to control the render window from other threads -pub struct RenderWindowHandle { - proxy: EventLoopProxy, -} - -impl RenderWindowHandle { - /// Update the gradient colors - pub fn update_gradient(&self, top: [f32; 4], bottom: [f32; 4]) { - let _ = self.proxy.send_event(RenderEvent::UpdateGradient { top, bottom }); - } - - /// Set window position - pub fn set_position(&self, x: i32, y: i32) { - let _ = self.proxy.send_event(RenderEvent::SetPosition { x, y }); - } - - /// Set window size - pub fn set_size(&self, width: u32, height: u32) { - let _ = self.proxy.send_event(RenderEvent::SetSize { width, height }); - } - - /// Request a redraw - pub fn request_redraw(&self) { - let _ = self.proxy.send_event(RenderEvent::RequestRedraw); - } - - /// Close the render window - pub fn close(&self) { - let _ = self.proxy.send_event(RenderEvent::Close); - } -} - -/// Spawn the render window in a separate thread -pub fn spawn_render_window( - x: i32, - y: i32, - width: u32, - height: u32, -) -> Result { - let (tx, rx) = std::sync::mpsc::channel(); - - thread::spawn(move || { - let mut event_loop_builder = EventLoopBuilder::with_user_event(); - - // On Linux, allow event loop on any thread (not just main thread) - #[cfg(target_os = "linux")] - { - event_loop_builder.with_any_thread(true); - } - - let event_loop: EventLoop = event_loop_builder.build().unwrap(); - let proxy = event_loop.create_proxy(); - - // Send the proxy back to the main thread - tx.send(proxy.clone()).unwrap(); - - let window = WindowBuilder::new() - .with_title("Lightningbeam Renderer") - .with_inner_size(winit::dpi::PhysicalSize::new(width, height)) - .with_position(winit::dpi::PhysicalPosition::new(x, y)) - .with_decorations(false) // No title bar - .with_transparent(false) // Opaque background - .with_resizable(false) - .build(&event_loop) - .unwrap(); - - let window = Arc::new(window); - - // Initialize renderer (async operation) - let mut renderer = pollster::block_on(Renderer::new(window.clone())); - - event_loop.run(move |event, elwt| { - elwt.set_control_flow(ControlFlow::Wait); - - match event { - Event::UserEvent(render_event) => match render_event { - RenderEvent::UpdateGradient { top, bottom } => { - eprintln!("[RenderWindow] Updating gradient: {:?} -> {:?}", top, bottom); - renderer.update_gradient(top, bottom); - window.request_redraw(); - } - RenderEvent::SetPosition { x, y } => { - eprintln!("[RenderWindow] Setting position: ({}, {})", x, y); - let _ = window.set_outer_position(winit::dpi::PhysicalPosition::new(x, y)); - } - RenderEvent::SetSize { width, height } => { - eprintln!("[RenderWindow] Setting size: {}x{}", width, height); - let _ = window.request_inner_size(winit::dpi::PhysicalSize::new(width, height)); - } - RenderEvent::RequestRedraw => { - window.request_redraw(); - } - RenderEvent::Close => { - eprintln!("[RenderWindow] Closing render window"); - elwt.exit(); - } - }, - - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - elwt.exit(); - } - - Event::WindowEvent { - event: WindowEvent::Resized(physical_size), - .. - } => { - renderer.resize(physical_size); - window.request_redraw(); - } - - Event::WindowEvent { - event: WindowEvent::RedrawRequested, - .. - } => { - match renderer.render() { - Ok(_) => {} - Err(wgpu::SurfaceError::Lost) => renderer.resize(window.inner_size()), - Err(wgpu::SurfaceError::OutOfMemory) => { - eprintln!("Out of memory!"); - elwt.exit(); - } - Err(e) => eprintln!("Render error: {:?}", e), - } - } - - _ => {} - } - }).expect("Event loop error"); - }); - - // Wait for the proxy to be sent back - let proxy = rx.recv().map_err(|e| format!("Failed to receive proxy: {}", e))?; - - Ok(RenderWindowHandle { proxy }) -} diff --git a/src-tauri/src/renderer.rs b/src-tauri/src/renderer.rs deleted file mode 100644 index 2ae70fe..0000000 --- a/src-tauri/src/renderer.rs +++ /dev/null @@ -1,293 +0,0 @@ -use std::sync::Arc; -use wgpu::util::DeviceExt; - -/// Vertex data for rendering -#[repr(C)] -#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] -struct Vertex { - position: [f32; 2], - color: [f32; 4], -} - -impl Vertex { - fn desc() -> wgpu::VertexBufferLayout<'static> { - wgpu::VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &[ - // Position - wgpu::VertexAttribute { - offset: 0, - shader_location: 0, - format: wgpu::VertexFormat::Float32x2, - }, - // Color - wgpu::VertexAttribute { - offset: std::mem::size_of::<[f32; 2]>() as wgpu::BufferAddress, - shader_location: 1, - format: wgpu::VertexFormat::Float32x4, - }, - ], - } - } -} - -/// Main renderer state that manages the wgpu rendering pipeline -pub struct Renderer { - surface: wgpu::Surface<'static>, - device: wgpu::Device, - queue: wgpu::Queue, - config: wgpu::SurfaceConfiguration, - size: winit::dpi::PhysicalSize, - render_pipeline: wgpu::RenderPipeline, - vertex_buffer: wgpu::Buffer, - num_vertices: u32, -} - -impl Renderer { - /// Create a new renderer for the given window - pub async fn new(window: Arc) -> Self { - let size = window.inner_size(); - - // Create wgpu instance - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::PRIMARY, - ..Default::default() - }); - - // Create surface from window - let surface = instance.create_surface(window.clone()).unwrap(); - - // Request adapter - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::HighPerformance, - compatible_surface: Some(&surface), - force_fallback_adapter: false, - }) - .await - .unwrap(); - - // Request device and queue - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: Some("Lightningbeam Render Device"), - required_features: wgpu::Features::empty(), - required_limits: wgpu::Limits::default(), - }, - None, - ) - .await - .unwrap(); - - // Configure surface - let surface_caps = surface.get_capabilities(&adapter); - let surface_format = surface_caps - .formats - .iter() - .find(|f| f.is_srgb()) - .copied() - .unwrap_or(surface_caps.formats[0]); - - let config = wgpu::SurfaceConfiguration { - usage: wgpu::TextureUsages::RENDER_ATTACHMENT, - format: surface_format, - width: size.width, - height: size.height, - present_mode: wgpu::PresentMode::Fifo, // VSync - alpha_mode: surface_caps.alpha_modes[0], - view_formats: vec![], - desired_maximum_frame_latency: 2, - }; - surface.configure(&device, &config); - - // Create shader module - let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { - label: Some("Gradient Shader"), - source: wgpu::ShaderSource::Wgsl(include_str!("shaders/gradient.wgsl").into()), - }); - - // Create render pipeline - let render_pipeline_layout = - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: Some("Render Pipeline Layout"), - bind_group_layouts: &[], - push_constant_ranges: &[], - }); - - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("Render Pipeline"), - layout: Some(&render_pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[Vertex::desc()], - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - targets: &[Some(wgpu::ColorTargetState { - format: config.format, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - polygon_mode: wgpu::PolygonMode::Fill, - unclipped_depth: false, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - count: 1, - mask: !0, - alpha_to_coverage_enabled: false, - }, - multiview: None, - }); - - // Create initial gradient vertices (two triangles forming a quad) - let vertices = Self::create_gradient_vertices(); - let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: bytemuck::cast_slice(&vertices), - usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, - }); - - Self { - surface, - device, - queue, - config, - size, - render_pipeline, - vertex_buffer, - num_vertices: vertices.len() as u32, - } - } - - /// Create vertices for a gradient quad covering the entire viewport - fn create_gradient_vertices() -> Vec { - vec![ - // First triangle - Vertex { - position: [-1.0, 1.0], - color: [0.2, 0.3, 0.8, 1.0], // Blue at top - }, - Vertex { - position: [-1.0, -1.0], - color: [0.6, 0.2, 0.8, 1.0], // Purple at bottom - }, - Vertex { - position: [1.0, -1.0], - color: [0.6, 0.2, 0.8, 1.0], // Purple at bottom - }, - // Second triangle - Vertex { - position: [-1.0, 1.0], - color: [0.2, 0.3, 0.8, 1.0], // Blue at top - }, - Vertex { - position: [1.0, -1.0], - color: [0.6, 0.2, 0.8, 1.0], // Purple at bottom - }, - Vertex { - position: [1.0, 1.0], - color: [0.2, 0.3, 0.8, 1.0], // Blue at top - }, - ] - } - - /// Resize the renderer (call when window is resized) - pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize) { - if new_size.width > 0 && new_size.height > 0 { - self.size = new_size; - self.config.width = new_size.width; - self.config.height = new_size.height; - self.surface.configure(&self.device, &self.config); - } - } - - /// Render a frame - pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> { - let output = self.surface.get_current_texture()?; - let view = output - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - - let mut encoder = self - .device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Render Encoder"), - }); - - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("Render Pass"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 0.1, - g: 0.1, - b: 0.1, - a: 1.0, - }), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - occlusion_query_set: None, - timestamp_writes: None, - }); - - render_pass.set_pipeline(&self.render_pipeline); - render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); - render_pass.draw(0..self.num_vertices, 0..1); - } - - self.queue.submit(std::iter::once(encoder.finish())); - output.present(); - - Ok(()) - } - - /// Update gradient colors (for future customization) - pub fn update_gradient(&mut self, color_top: [f32; 4], color_bottom: [f32; 4]) { - let vertices = vec![ - Vertex { - position: [-1.0, 1.0], - color: color_top, - }, - Vertex { - position: [-1.0, -1.0], - color: color_bottom, - }, - Vertex { - position: [1.0, -1.0], - color: color_bottom, - }, - Vertex { - position: [-1.0, 1.0], - color: color_top, - }, - Vertex { - position: [1.0, -1.0], - color: color_bottom, - }, - Vertex { - position: [1.0, 1.0], - color: color_top, - }, - ]; - - self.queue - .write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertices)); - } -} diff --git a/src-tauri/src/shaders/gradient.wgsl b/src-tauri/src/shaders/gradient.wgsl deleted file mode 100644 index 216e3ef..0000000 --- a/src-tauri/src/shaders/gradient.wgsl +++ /dev/null @@ -1,26 +0,0 @@ -// Vertex shader - -struct VertexInput { - @location(0) position: vec2, - @location(1) color: vec4, -} - -struct VertexOutput { - @builtin(position) clip_position: vec4, - @location(0) color: vec4, -} - -@vertex -fn vs_main(input: VertexInput) -> VertexOutput { - var output: VertexOutput; - output.clip_position = vec4(input.position, 0.0, 1.0); - output.color = input.color; - return output; -} - -// Fragment shader - -@fragment -fn fs_main(input: VertexOutput) -> @location(0) vec4 { - return input.color; -} diff --git a/src-tauri/src/video.rs b/src-tauri/src/video.rs deleted file mode 100644 index e183de8..0000000 --- a/src-tauri/src/video.rs +++ /dev/null @@ -1,528 +0,0 @@ -use std::sync::{Arc, Mutex}; -use std::num::NonZeroUsize; -use ffmpeg_next as ffmpeg; -use lru::LruCache; -use daw_backend::WaveformPeak; -use image::RgbaImage; -use tauri::Manager; - -#[derive(serde::Serialize, Clone)] -pub struct VideoFileMetadata { - pub pool_index: usize, - pub width: u32, - pub height: u32, - pub fps: f64, - pub duration: f64, - pub has_audio: bool, - pub audio_pool_index: Option, - pub audio_duration: Option, - pub audio_sample_rate: Option, - pub audio_channels: Option, - pub audio_waveform: Option>, -} - -struct VideoDecoder { - path: String, - width: u32, // Original video width - height: u32, // Original video height - output_width: u32, // Scaled output width - output_height: u32, // Scaled output height - fps: f64, - duration: f64, - time_base: f64, - stream_index: usize, - frame_cache: LruCache>, // timestamp -> RGBA data - input: Option, - decoder: Option, - last_decoded_ts: i64, // Track the last decoded frame timestamp -} - -impl VideoDecoder { - fn new(path: String, cache_size: usize, max_width: Option, max_height: Option) -> Result { - ffmpeg::init().map_err(|e| e.to_string())?; - - let input = ffmpeg::format::input(&path) - .map_err(|e| format!("Failed to open video: {}", e))?; - - let video_stream = input.streams() - .best(ffmpeg::media::Type::Video) - .ok_or("No video stream found")?; - - let stream_index = video_stream.index(); - - let context_decoder = ffmpeg::codec::context::Context::from_parameters( - video_stream.parameters() - ).map_err(|e| e.to_string())?; - - let decoder = context_decoder.decoder().video() - .map_err(|e| e.to_string())?; - - let width = decoder.width(); - let height = decoder.height(); - let time_base = f64::from(video_stream.time_base()); - - // Calculate output dimensions (scale down if larger than max) - let (output_width, output_height) = if let (Some(max_w), Some(max_h)) = (max_width, max_height) { - // Calculate scale to fit within max dimensions while preserving aspect ratio - let scale = (max_w as f32 / width as f32).min(max_h as f32 / height as f32).min(1.0); - ((width as f32 * scale) as u32, (height as f32 * scale) as u32) - } else { - (width, height) - }; - - // Try to get duration from stream, fallback to container - let duration = if video_stream.duration() > 0 { - video_stream.duration() as f64 * time_base - } else if input.duration() > 0 { - input.duration() as f64 / f64::from(ffmpeg::ffi::AV_TIME_BASE) - } else { - // If no duration available, estimate from frame count and fps - let fps = f64::from(video_stream.avg_frame_rate()); - if video_stream.frames() > 0 && fps > 0.0 { - video_stream.frames() as f64 / fps - } else { - 0.0 // Unknown duration - } - }; - - let fps = f64::from(video_stream.avg_frame_rate()); - - Ok(Self { - path, - width, - height, - output_width, - output_height, - fps, - duration, - time_base, - stream_index, - frame_cache: LruCache::new( - NonZeroUsize::new(cache_size).unwrap() - ), - input: None, - decoder: None, - last_decoded_ts: -1, - }) - } - - fn get_frame(&mut self, timestamp: f64) -> Result, String> { - use std::time::Instant; - let t_start = Instant::now(); - - // Convert timestamp to frame timestamp - let frame_ts = (timestamp / self.time_base) as i64; - - // Check cache - if let Some(cached_frame) = self.frame_cache.get(&frame_ts) { - eprintln!("[Video Timing] Cache hit for ts={:.3}s ({}ms)", timestamp, t_start.elapsed().as_millis()); - return Ok(cached_frame.clone()); - } - - let _t_after_cache = Instant::now(); - - // Determine if we need to seek - // Seek if: no decoder open, going backwards, or jumping forward more than 2 seconds - let need_seek = self.decoder.is_none() - || frame_ts < self.last_decoded_ts - || frame_ts > self.last_decoded_ts + (2.0 / self.time_base) as i64; - - if need_seek { - let t_seek_start = Instant::now(); - - // Reopen input - let mut input = ffmpeg::format::input(&self.path) - .map_err(|e| format!("Failed to reopen video: {}", e))?; - - // Seek to timestamp - input.seek(frame_ts, ..frame_ts) - .map_err(|e| format!("Seek failed: {}", e))?; - - let context_decoder = ffmpeg::codec::context::Context::from_parameters( - input.streams().best(ffmpeg::media::Type::Video).unwrap().parameters() - ).map_err(|e| e.to_string())?; - - let decoder = context_decoder.decoder().video() - .map_err(|e| e.to_string())?; - - self.input = Some(input); - self.decoder = Some(decoder); - self.last_decoded_ts = -1; // Reset since we seeked - - eprintln!("[Video Timing] Seek took {}ms", t_seek_start.elapsed().as_millis()); - } - - let input = self.input.as_mut().unwrap(); - let decoder = self.decoder.as_mut().unwrap(); - - // Decode frames until we find the one closest to our target timestamp - let mut best_frame_data: Option> = None; - let mut best_frame_ts: Option = None; - let t_decode_start = Instant::now(); - let mut decode_count = 0; - let mut scale_time_ms = 0u128; - - for (stream, packet) in input.packets() { - if stream.index() == self.stream_index { - decoder.send_packet(&packet) - .map_err(|e| e.to_string())?; - - let mut frame = ffmpeg::util::frame::Video::empty(); - while decoder.receive_frame(&mut frame).is_ok() { - decode_count += 1; - let current_frame_ts = frame.timestamp().unwrap_or(0); - self.last_decoded_ts = current_frame_ts; // Update last decoded position - - // Check if this frame is closer to our target than the previous best - let is_better = match best_frame_ts { - None => true, - Some(best_ts) => { - (current_frame_ts - frame_ts).abs() < (best_ts - frame_ts).abs() - } - }; - - if is_better { - let t_scale_start = Instant::now(); - - // Convert to RGBA and scale to output size - let mut scaler = ffmpeg::software::scaling::context::Context::get( - frame.format(), - frame.width(), - frame.height(), - ffmpeg::format::Pixel::RGBA, - self.output_width, - self.output_height, - ffmpeg::software::scaling::flag::Flags::BILINEAR, - ).map_err(|e| e.to_string())?; - - let mut rgb_frame = ffmpeg::util::frame::Video::empty(); - scaler.run(&frame, &mut rgb_frame) - .map_err(|e| e.to_string())?; - - // Remove stride padding to create tightly packed RGBA data - let width = self.output_width as usize; - let height = self.output_height as usize; - let stride = rgb_frame.stride(0); - let row_size = width * 4; // RGBA = 4 bytes per pixel - let source_data = rgb_frame.data(0); - - let mut packed_data = Vec::with_capacity(row_size * height); - for y in 0..height { - let row_start = y * stride; - let row_end = row_start + row_size; - packed_data.extend_from_slice(&source_data[row_start..row_end]); - } - - scale_time_ms += t_scale_start.elapsed().as_millis(); - best_frame_data = Some(packed_data); - best_frame_ts = Some(current_frame_ts); - } - - // If we've reached or passed the target timestamp, we can stop - if current_frame_ts >= frame_ts { - // Found our frame, cache and return it - if let Some(data) = best_frame_data { - let total_time = t_start.elapsed().as_millis(); - let decode_time = t_decode_start.elapsed().as_millis(); - eprintln!("[Video Timing] ts={:.3}s | Decoded {} frames in {}ms | Scale: {}ms | Total: {}ms", - timestamp, decode_count, decode_time, scale_time_ms, total_time); - self.frame_cache.put(frame_ts, data.clone()); - return Ok(data); - } - break; - } - } - } - } - - eprintln!("[Video Decoder] ERROR: Failed to decode frame for timestamp {}", timestamp); - Err("Failed to decode frame".to_string()) - } -} - -pub struct VideoState { - pool: Vec>>, - next_pool_index: usize, - cache_size: usize, -} - -impl Default for VideoState { - fn default() -> Self { - Self { - pool: Vec::new(), - next_pool_index: 0, - cache_size: 20, // Default cache size - } - } -} - -#[tauri::command] -pub async fn video_load_file( - video_state: tauri::State<'_, Arc>>, - audio_state: tauri::State<'_, Arc>>, - path: String, -) -> Result { - eprintln!("[Video] Loading file: {}", path); - - ffmpeg::init().map_err(|e| e.to_string())?; - - // Open input to check for audio stream - let mut input = ffmpeg::format::input(&path) - .map_err(|e| format!("Failed to open video: {}", e))?; - - let audio_stream_opt = input.streams() - .best(ffmpeg::media::Type::Audio); - - let has_audio = audio_stream_opt.is_some(); - - // Extract audio if present - let (audio_pool_index, audio_duration, audio_sample_rate, audio_channels, audio_waveform) = if has_audio { - let audio_stream = audio_stream_opt.unwrap(); - let audio_index = audio_stream.index(); - - // Get audio properties - let context_decoder = ffmpeg::codec::context::Context::from_parameters( - audio_stream.parameters() - ).map_err(|e| e.to_string())?; - - let mut audio_decoder = context_decoder.decoder().audio() - .map_err(|e| e.to_string())?; - - let sample_rate = audio_decoder.rate(); - let channels = audio_decoder.channels() as u32; - - // Decode all audio frames - let mut audio_samples: Vec = Vec::new(); - - for (stream, packet) in input.packets() { - if stream.index() == audio_index { - audio_decoder.send_packet(&packet) - .map_err(|e| e.to_string())?; - - let mut audio_frame = ffmpeg::util::frame::Audio::empty(); - while audio_decoder.receive_frame(&mut audio_frame).is_ok() { - // Convert audio to f32 planar format - let format = audio_frame.format(); - let frame_channels = audio_frame.channels() as usize; - - // Create resampler to convert to f32 planar - let mut resampler = ffmpeg::software::resampling::context::Context::get( - format, - audio_frame.channel_layout(), - sample_rate, - ffmpeg::format::Sample::F32(ffmpeg::format::sample::Type::Packed), - audio_frame.channel_layout(), - sample_rate, - ).map_err(|e| e.to_string())?; - - let mut resampled_frame = ffmpeg::util::frame::Audio::empty(); - resampler.run(&audio_frame, &mut resampled_frame) - .map_err(|e| e.to_string())?; - - // Extract f32 samples (interleaved format) - let data_ptr = resampled_frame.data(0).as_ptr() as *const f32; - let total_samples = resampled_frame.samples() * frame_channels; - let samples_slice = unsafe { - std::slice::from_raw_parts(data_ptr, total_samples) - }; - - audio_samples.extend_from_slice(samples_slice); - } - } - } - - // Flush audio decoder - audio_decoder.send_eof().map_err(|e| e.to_string())?; - let mut audio_frame = ffmpeg::util::frame::Audio::empty(); - while audio_decoder.receive_frame(&mut audio_frame).is_ok() { - let format = audio_frame.format(); - let frame_channels = audio_frame.channels() as usize; - - let mut resampler = ffmpeg::software::resampling::context::Context::get( - format, - audio_frame.channel_layout(), - sample_rate, - ffmpeg::format::Sample::F32(ffmpeg::format::sample::Type::Packed), - audio_frame.channel_layout(), - sample_rate, - ).map_err(|e| e.to_string())?; - - let mut resampled_frame = ffmpeg::util::frame::Audio::empty(); - resampler.run(&audio_frame, &mut resampled_frame) - .map_err(|e| e.to_string())?; - - let data_ptr = resampled_frame.data(0).as_ptr() as *const f32; - let total_samples = resampled_frame.samples() * frame_channels; - let samples_slice = unsafe { - std::slice::from_raw_parts(data_ptr, total_samples) - }; - - audio_samples.extend_from_slice(samples_slice); - } - - // Calculate audio duration - let total_samples_per_channel = audio_samples.len() / channels as usize; - let audio_duration = total_samples_per_channel as f64 / sample_rate as f64; - - // Generate waveform - let target_peaks = ((audio_duration * 300.0) as usize).clamp(1000, 20000); - let waveform = generate_waveform(&audio_samples, channels, target_peaks); - - // Send audio to DAW backend - let mut audio_state_guard = audio_state.lock().unwrap(); - let audio_pool_index = audio_state_guard.next_pool_index; - audio_state_guard.next_pool_index += 1; - - if let Some(controller) = &mut audio_state_guard.controller { - controller.add_audio_file( - path.clone(), - audio_samples, - channels, - sample_rate, - ); - } - drop(audio_state_guard); - - (Some(audio_pool_index), Some(audio_duration), Some(sample_rate), Some(channels), Some(waveform)) - } else { - (None, None, None, None, None) - }; - - // Create video decoder with max dimensions for playback (1920x1080) - // This scales videos to reduce data transfer over WebSocket - let mut video_state_guard = video_state.lock().unwrap(); - let pool_index = video_state_guard.next_pool_index; - video_state_guard.next_pool_index += 1; - - let decoder = VideoDecoder::new(path.clone(), video_state_guard.cache_size, Some(1920), Some(1080))?; - - let metadata = VideoFileMetadata { - pool_index, - width: decoder.output_width, // Return scaled dimensions to JS - height: decoder.output_height, - fps: decoder.fps, - duration: decoder.duration, - has_audio, - audio_pool_index, - audio_duration, - audio_sample_rate, - audio_channels, - audio_waveform, - }; - - video_state_guard.pool.push(Arc::new(Mutex::new(decoder))); - - Ok(metadata) -} - -fn generate_waveform(audio_data: &[f32], channels: u32, target_peaks: usize) -> Vec { - let total_samples = audio_data.len(); - let samples_per_channel = total_samples / channels as usize; - let samples_per_peak = (samples_per_channel / target_peaks).max(1); - - let mut waveform = Vec::new(); - - for peak_idx in 0..target_peaks { - let start_sample = peak_idx * samples_per_peak; - let end_sample = ((peak_idx + 1) * samples_per_peak).min(samples_per_channel); - - if start_sample >= samples_per_channel { - break; - } - - let mut min_val = 0.0f32; - let mut max_val = 0.0f32; - - for sample_idx in start_sample..end_sample { - // Average across channels - let mut channel_sum = 0.0f32; - for ch in 0..channels as usize { - let idx = sample_idx * channels as usize + ch; - if idx < total_samples { - channel_sum += audio_data[idx]; - } - } - let avg_sample = channel_sum / channels as f32; - - min_val = min_val.min(avg_sample); - max_val = max_val.max(avg_sample); - } - - waveform.push(WaveformPeak { - min: min_val, - max: max_val, - }); - } - - waveform -} - -#[tauri::command] -pub async fn video_set_cache_size( - state: tauri::State<'_, Arc>>, - cache_size: usize, -) -> Result<(), String> { - let mut video_state = state.lock().unwrap(); - video_state.cache_size = cache_size; - Ok(()) -} - -#[tauri::command] -pub async fn video_get_pool_info( - state: tauri::State<'_, Arc>>, - pool_index: usize, -) -> Result<(u32, u32, f64), String> { - let video_state = state.lock().unwrap(); - let decoder = video_state.pool.get(pool_index) - .ok_or("Invalid pool index")? - .lock().unwrap(); - - Ok(( - decoder.output_width, // Return scaled dimensions - decoder.output_height, - decoder.fps - )) -} - -/// Stream a decoded video frame over WebSocket (zero-copy performance testing) -#[tauri::command] -pub async fn video_stream_frame( - video_state: tauri::State<'_, Arc>>, - frame_streamer: tauri::State<'_, Arc>>, - pool_index: usize, - timestamp: f64, -) -> Result<(), String> { - use std::time::Instant; - let t_start = Instant::now(); - - // Get decoder - let state = video_state.lock().unwrap(); - let decoder = state.pool.get(pool_index) - .ok_or("Invalid pool index")? - .clone(); - drop(state); - - // Decode frame - let mut decoder = decoder.lock().unwrap(); - let width = decoder.output_width; - let height = decoder.output_height; - - let t_decode_start = Instant::now(); - let rgba_data = decoder.get_frame(timestamp)?; // Note: get_frame returns RGBA, not RGB - let t_decode = t_decode_start.elapsed().as_micros(); - drop(decoder); - - // Stream over WebSocket - let t_stream_start = Instant::now(); - let streamer = frame_streamer.lock().unwrap(); - streamer.send_frame(pool_index, timestamp, width, height, &rgba_data); - let t_stream = t_stream_start.elapsed().as_micros(); - drop(streamer); - - // Commented out per-frame logging - // let t_total = t_start.elapsed().as_micros(); - // eprintln!("[Video Stream] Frame {}x{} @ {:.2}s | Decode: {}μs | Stream: {}μs | Total: {}μs", - // width, height, timestamp, t_decode, t_stream, t_total); - - Ok(()) -} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json deleted file mode 100644 index 153d276..0000000 --- a/src-tauri/tauri.conf.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "$schema": "https://schema.tauri.app/config/2", - "productName": "Lightningbeam", - "version": "1.0.4-alpha", - "identifier": "org.lightningbeam.core", - "build": { - "frontendDist": "../src" - }, - "app": { - "withGlobalTauri": true, - "windows": [ - { - "title": "Lightningbeam", - "width": 1500, - "height": 1024, - "dragDropEnabled": false, - "zoomHotkeysEnabled": false - } - ], - "security": { - "csp": null, - "assetProtocol": { - "enable": true - } - } - }, - "bundle": { - "active": true, - "targets": "all", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "resources": [ - "../src/assets/instruments/**/*" - ], - "linux": { - "appimage": { - "bundleMediaFramework": true, - "files": {} - }, - "deb": { - "files": {} - }, - "rpm": { - "epoch": 0, - "files": {}, - "release": "1" - } - }, - "fileAssociations": [ - { - "ext": [ - "beam" - ], - "mimeType": "application/lightningbeam" - } - ] - } -} diff --git a/src-tauri/tauri.windows.conf.json b/src-tauri/tauri.windows.conf.json deleted file mode 100644 index 73dde0f..0000000 --- a/src-tauri/tauri.windows.conf.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "0.6.4-0" -} \ No newline at end of file