diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fb1f00e..f6ea37c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -17,17 +17,6 @@ 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" @@ -98,23 +87,6 @@ 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" @@ -124,6 +96,56 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + [[package]] name = "anyhow" version = "1.0.95" @@ -183,7 +205,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -194,7 +216,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -268,7 +290,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -286,7 +308,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -304,18 +326,6 @@ 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" @@ -340,29 +350,6 @@ 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" @@ -390,39 +377,6 @@ 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" @@ -593,10 +547,8 @@ checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", "windows-targets 0.52.6", ] @@ -653,6 +605,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "combine" version = "4.6.7" @@ -925,7 +883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -935,7 +893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -959,7 +917,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -970,7 +928,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1087,6 +1045,12 @@ dependencies = [ "dasp_sample", ] +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + [[package]] name = "daw-backend" version = "0.1.0" @@ -1134,7 +1098,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1182,7 +1146,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1214,7 +1178,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1318,7 +1282,7 @@ checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1331,6 +1295,19 @@ dependencies = [ "regex", ] +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1399,15 +1376,6 @@ 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" @@ -1495,7 +1463,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1513,12 +1481,6 @@ 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" @@ -1569,7 +1531,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1813,7 +1775,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1892,7 +1854,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -1900,9 +1862,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash", -] [[package]] name = "hashbrown" @@ -1953,6 +1912,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.14", +] + [[package]] name = "http" version = "1.2.0" @@ -1971,7 +1941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", - "http", + "http 1.2.0", ] [[package]] @@ -1982,7 +1952,7 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", "futures-util", - "http", + "http 1.2.0", "http-body", "pin-project-lite", ] @@ -2014,7 +1984,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", + "http 1.2.0", "http-body", "httparse", "itoa 1.0.14", @@ -2033,7 +2003,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "http", + "http 1.2.0", "http-body", "hyper", "pin-project-lite", @@ -2191,7 +2161,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -2290,6 +2260,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.12.1" @@ -2343,6 +2319,30 @@ dependencies = [ "system-deps", ] +[[package]] +name = "jiff" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.109", +] + [[package]] name = "jni" version = "0.21.1" @@ -2506,9 +2506,9 @@ dependencies = [ name = "lightningbeam" version = "0.1.0" dependencies = [ - "chrono", "cpal", "daw-backend", + "env_logger", "ffmpeg-next", "image", "log", @@ -2520,11 +2520,9 @@ dependencies = [ "tauri-build", "tauri-plugin-dialog", "tauri-plugin-fs", - "tauri-plugin-log", "tauri-plugin-shell", "tiny_http", - "tracing", - "tracing-subscriber", + "tungstenite", ] [[package]] @@ -2554,9 +2552,6 @@ name = "log" version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" -dependencies = [ - "value-bag", -] [[package]] name = "lru" @@ -2605,15 +2600,6 @@ dependencies = [ "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" @@ -2824,16 +2810,6 @@ dependencies = [ "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" @@ -2848,7 +2824,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -2888,16 +2864,7 @@ 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", + "syn 2.0.109", ] [[package]] @@ -3166,6 +3133,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "open" version = "5.3.2" @@ -3204,12 +3177,6 @@ dependencies = [ "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" @@ -3406,7 +3373,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -3480,6 +3447,21 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -3568,26 +3550,6 @@ 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" @@ -3615,12 +3577,6 @@ 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" @@ -3776,17 +3732,8 @@ 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", + "regex-automata", + "regex-syntax", ] [[package]] @@ -3797,30 +3744,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] -[[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" @@ -3831,7 +3763,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "http", + "http 1.2.0", "http-body", "http-body-util", "hyper", @@ -3884,57 +3816,12 @@ dependencies = [ "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" @@ -4020,7 +3907,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4035,12 +3922,6 @@ 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" @@ -4108,7 +3989,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4119,7 +4000,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4142,7 +4023,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4193,7 +4074,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4228,6 +4109,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -4239,15 +4131,6 @@ dependencies = [ "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" @@ -4300,12 +4183,6 @@ 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" @@ -4398,7 +4275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4464,7 +4341,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4686,9 +4563,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.96" +version = "2.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f" dependencies = [ "proc-macro2", "quote", @@ -4712,7 +4589,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -4774,15 +4651,9 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] -[[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" @@ -4805,7 +4676,7 @@ dependencies = [ "glob", "gtk", "heck 0.5.0", - "http", + "http 1.2.0", "http-range", "jni", "libc", @@ -4880,7 +4751,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "syn 2.0.96", + "syn 2.0.109", "tauri-utils", "thiserror 2.0.11", "time", @@ -4898,7 +4769,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "tauri-codegen", "tauri-utils", ] @@ -4961,28 +4832,6 @@ dependencies = [ "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" @@ -5012,7 +4861,7 @@ checksum = "2274ef891ccc0a8d318deffa9d70053f947664d12d58b9c0d1ae5e89237e01f7" dependencies = [ "dpi", "gtk", - "http", + "http 1.2.0", "jni", "raw-window-handle", "serde", @@ -5030,7 +4879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3707b40711d3b9f6519150869e358ffbde7c57567fb9b5a8b51150606939b2a0" dependencies = [ "gtk", - "http", + "http 1.2.0", "jni", "log", "objc2", @@ -5061,7 +4910,7 @@ dependencies = [ "dunce", "glob", "html5ever", - "http", + "http 1.2.0", "infer", "json-patch", "kuchikiki", @@ -5153,7 +5002,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -5164,17 +5013,7 @@ 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", + "syn 2.0.109", ] [[package]] @@ -5185,9 +5024,7 @@ checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa 1.0.14", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", @@ -5232,21 +5069,6 @@ dependencies = [ "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" @@ -5393,7 +5215,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -5403,36 +5225,6 @@ 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]] @@ -5462,6 +5254,25 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "sha1", + "thiserror 1.0.69", + "url", + "utf-8", +] + [[package]] name = "typeid" version = "1.0.2" @@ -5591,18 +5402,18 @@ 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 = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.12.0" @@ -5613,18 +5424,6 @@ dependencies = [ "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" @@ -5716,7 +5515,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "wasm-bindgen-shared", ] @@ -5751,7 +5550,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5914,7 +5713,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -6048,7 +5847,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -6059,9 +5858,15 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-registry" version = "0.2.0" @@ -6137,6 +5942,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -6185,10 +5999,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -6205,7 +6020,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c12476c23a74725c539b24eae8bfc0dac4029c39cdb561d9f23616accd4ae26d" dependencies = [ - "windows-targets 0.53.0", + "windows-targets 0.53.5", ] [[package]] @@ -6443,7 +6258,7 @@ dependencies = [ "gdkx11", "gtk", "html5ever", - "http", + "http 1.2.0", "javascriptcore-rs", "jni", "kuchikiki", @@ -6471,15 +6286,6 @@ dependencies = [ "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" @@ -6531,7 +6337,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "synstructure", ] @@ -6574,7 +6380,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "zbus_names", "zvariant", "zvariant_utils", @@ -6610,7 +6416,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -6630,7 +6436,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "synstructure", ] @@ -6653,7 +6459,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", ] [[package]] @@ -6681,7 +6487,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.96", + "syn 2.0.109", "zvariant_utils", ] @@ -6695,6 +6501,6 @@ dependencies = [ "quote", "serde", "static_assertions", - "syn 2.0.96", + "syn 2.0.109", "winnow 0.6.24", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 248155a..e639876 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -24,12 +24,8 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" tauri-plugin-fs = "2" tauri-plugin-dialog = "2" -tauri-plugin-log = "2" -tracing = "0.1.41" -# enable env-filter feature -tracing-subscriber = {version = "0.3.19", features = ["env-filter"] } log = "0.4" -chrono = "0.4" +env_logger = "0.11" # DAW backend integration daw-backend = { path = "../daw-backend" } @@ -44,6 +40,9 @@ image = { version = "0.24", default-features = false, features = ["jpeg"] } # HTTP server for video streaming tiny_http = "0.12" +# WebSocket for frame streaming (disable default features to remove tracing, but keep handshake) +tungstenite = { version = "0.20", default-features = false, features = ["handshake"] } + [profile.dev] opt-level = 1 # Enable basic optimizations in debug mode for audio decoding performance diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 3bbee78..877f5af 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -72,7 +72,6 @@ } ] }, - "dialog:default", - "log:default" + "dialog:default" ] } \ No newline at end of file diff --git a/src-tauri/src/frame_streamer.rs b/src-tauri/src/frame_streamer.rs new file mode 100644 index 0000000..ef947d0 --- /dev/null +++ b/src-tauri/src/frame_streamer.rs @@ -0,0 +1,88 @@ +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(); + + // Debug: Log input dimensions and first few RGBA bytes + eprintln!("[Frame Streamer SEND] pool={}, {}x{} pixels, RGBA input len={}, first 20 RGBA bytes: {:?}", + pool_index, width, height, rgba_data.len(), &rgba_data[..20.min(rgba_data.len())]); + + // 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/lib.rs b/src-tauri/src/lib.rs index 3d91f68..8890a02 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,14 +1,12 @@ 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; +mod frame_streamer; #[derive(Default)] @@ -43,6 +41,14 @@ fn error(msg: String) { error!("{}",msg); } +#[tauri::command] +fn get_frame_streamer_port( + frame_streamer: tauri::State<'_, Arc>>, +) -> u16 { + let streamer = frame_streamer.lock().unwrap(); + streamer.port() +} + use tauri::PhysicalSize; #[tauri::command] @@ -128,17 +134,27 @@ fn handle_file_associations(app: AppHandle, files: Vec) { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - let pkg_name = env!("CARGO_PKG_NAME").to_string(); + // Initialize env_logger with Error level only + env_logger::Builder::from_default_env() + .filter_level(log::LevelFilter::Error) + .init(); + // 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()); + // Initialize WebSocket frame streamer + let frame_streamer = frame_streamer::FrameStreamer::new() + .expect("Failed to start frame streamer"); + eprintln!("[App] Frame streamer started on port {}", frame_streamer.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))) + .manage(Arc::new(Mutex::new(frame_streamer))) .setup(|app| { #[cfg(any(windows, target_os = "linux"))] // Windows/Linux needs different handling from macOS { @@ -174,34 +190,38 @@ pub fn run() { } 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_log::Builder::new() + // .filter(|metadata| { + // // ONLY allow Error-level logs, block everything else + // metadata.level() == log::Level::Error + // }) + // .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, + greet, trace, debug, info, warn, error, create_window, get_frame_streamer_port, audio::audio_init, audio::audio_reset, audio::audio_play, @@ -263,6 +283,7 @@ pub fn run() { video::video_load_file, video::video_get_frame, video::video_get_frames_batch, + video::video_stream_frame, video::video_set_cache_size, video::video_get_pool_info, video::video_ipc_benchmark, @@ -295,5 +316,4 @@ pub fn run() { } }, ); - tracing_subscriber::fmt().with_env_filter(EnvFilter::new(format!("{}=trace", pkg_name))).init(); } diff --git a/src-tauri/src/video.rs b/src-tauri/src/video.rs index 9b2490a..9ecd841 100644 --- a/src-tauri/src/video.rs +++ b/src-tauri/src/video.rs @@ -876,3 +876,46 @@ pub async fn video_get_frames_batch( Ok(()) } + +/// 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/frame-receiver.js b/src/frame-receiver.js new file mode 100644 index 0000000..187f120 --- /dev/null +++ b/src/frame-receiver.js @@ -0,0 +1,106 @@ +// WebSocket frame receiver for zero-copy video playback +// Uses ArrayBuffer views to avoid copying data + +export class FrameReceiver { + constructor() { + this.ws = null; + this.port = null; + this.connected = false; + this.frameCallbacks = new Map(); // pool_index -> callback(imageData, timestamp) + } + + async connect() { + // Get WebSocket port from Tauri + const { invoke } = window.__TAURI__.core; + this.port = await invoke('get_frame_streamer_port'); + + const wsUrl = `ws://127.0.0.1:${this.port}`; + console.log(`[FrameReceiver] Connecting to ${wsUrl}`); + + return new Promise((resolve, reject) => { + this.ws = new WebSocket(wsUrl); + this.ws.binaryType = 'arraybuffer'; // Important: receive as ArrayBuffer for zero-copy + + this.ws.onopen = () => { + console.log('[FrameReceiver] Connected'); + this.connected = true; + resolve(); + }; + + this.ws.onerror = (error) => { + console.error('[FrameReceiver] WebSocket error:', error); + reject(error); + }; + + this.ws.onclose = () => { + console.log('[FrameReceiver] Disconnected'); + this.connected = false; + }; + + this.ws.onmessage = (event) => { + this.handleFrame(event.data); + }; + }); + } + + handleFrame(arrayBuffer) { + // Frame format: [pool_index: u32][timestamp_ms: u32][width: u32][height: u32][rgba_data...] + + // Create DataView for reading header (zero-copy view into buffer) + const view = new DataView(arrayBuffer); + const poolIndex = view.getUint32(0, true); // little-endian + const timestampMs = view.getUint32(4, true); + const width = view.getUint32(8, true); + const height = view.getUint32(12, true); + + // Get callback for this pool + const callback = this.frameCallbacks.get(poolIndex); + if (!callback) { + // No subscriber for this pool + return; + } + + // Create zero-copy view of RGBA data (starts at byte 16) + // IMPORTANT: Uint8ClampedArray is required for ImageData + // Specify exact length to avoid stride issues + const dataLength = width * height * 4; + const rgbaData = new Uint8ClampedArray(arrayBuffer, 16, dataLength); + + // Debug: Log received data + console.log(`[FrameReceiver RECV] pool=${poolIndex}, ${width}x${height}, total buffer len=${arrayBuffer.byteLength}, data len=${dataLength}, first 20 RGBA bytes:`, Array.from(rgbaData.slice(0, 20))); + + // Create ImageData directly from the view (zero-copy!) + const imageData = new ImageData(rgbaData, width, height); + + // Debug: Log ImageData properties + console.log(`[FrameReceiver RECV] ImageData: ${imageData.width}x${imageData.height}, data len=${imageData.data.length}, first 20 bytes:`, Array.from(imageData.data.slice(0, 20))); + + // Call subscriber with frame data + const timestamp = timestampMs / 1000.0; + callback(imageData, timestamp); + } + + // Subscribe to frames for a specific video pool + subscribe(poolIndex, callback) { + console.log(`[FrameReceiver] Subscribing to pool ${poolIndex}`); + this.frameCallbacks.set(poolIndex, callback); + } + + // Unsubscribe from a video pool + unsubscribe(poolIndex) { + console.log(`[FrameReceiver] Unsubscribing from pool ${poolIndex}`); + this.frameCallbacks.delete(poolIndex); + } + + disconnect() { + if (this.ws) { + this.ws.close(); + this.ws = null; + } + this.connected = false; + this.frameCallbacks.clear(); + } +} + +// Global singleton instance +export const frameReceiver = new FrameReceiver(); diff --git a/src/models/layer.js b/src/models/layer.js index 33599d0..977eea9 100644 --- a/src/models/layer.js +++ b/src/models/layer.js @@ -13,6 +13,7 @@ import { getShapeAtPoint, generateWaveform } from '../utils.js'; +import { frameReceiver } from '../frame-receiver.js'; // External libraries (globals) const Tone = window.Tone; @@ -1284,6 +1285,10 @@ class VideoLayer extends Widget { this.useJpegCompression = false; // JPEG compression adds more overhead than it saves (default: false) this.prefetchCount = 3; // Number of frames to prefetch ahead of playhead + // WebSocket streaming (experimental - zero-copy RGBA frames from Rust) + this.useWebSocketStreaming = true; // Use WebSocket streaming (enabled for testing) + this.wsConnected = false; // Track WebSocket connection status + // Timeline display this.collapsed = false; this.curvesMode = 'segment'; @@ -1319,8 +1324,38 @@ class VideoLayer extends Widget { console.log(`Video clip added: ${name}, ${width}x${height}, duration: ${duration}s, browser-compatible: ${clip.isBrowserCompatible}, http_url: ${clip.httpUrl}`); - // If HTTP URL is available, create video element immediately - if (clip.httpUrl) { + // If using WebSocket streaming, connect and subscribe + if (this.useWebSocketStreaming) { + // Connect to WebSocket if not already connected + if (!this.wsConnected) { + try { + await frameReceiver.connect(); + this.wsConnected = true; + console.log(`[Video] WebSocket connected for streaming`); + } catch (error) { + console.error('[Video] Failed to connect WebSocket, falling back to browser video:', error); + this.useWebSocketStreaming = false; + } + } + + // Subscribe to frames for this pool + if (this.wsConnected) { + frameReceiver.subscribe(poolIndex, (imageData, timestamp) => { + // Store received frame + clip.wsCurrentFrame = imageData; + clip.wsLastTimestamp = timestamp; + // console.log(`[Video WS] Received frame ${width}x${height} @ ${timestamp.toFixed(3)}s`); + + // Trigger UI redraw + if (updateUI) { + updateUI(); + } + }); + console.log(`[Video] Subscribed to WebSocket frames for pool ${poolIndex}`); + } + } + // Otherwise use browser video if available + else if (clip.httpUrl) { await this._createVideoElement(clip); clip.useBrowserVideo = true; } @@ -1440,6 +1475,7 @@ class VideoLayer extends Widget { if (currentTime < clip.startTime || currentTime >= clip.startTime + clip.duration) { clip.currentFrame = null; + clip.wsCurrentFrame = null; // Pause video element if we left its time range if (clip.videoElement && clip.isPlaying) { @@ -1450,6 +1486,24 @@ class VideoLayer extends Widget { continue; } + // If using WebSocket streaming + if (this.useWebSocketStreaming && this.wsConnected) { + const videoTime = clip.offset + (currentTime - clip.startTime); + + // Request frame via WebSocket streaming (non-blocking) + // The frame will arrive via the subscription callback and trigger a redraw + try { + await invoke('video_stream_frame', { + poolIndex: clip.poolIndex, + timestamp: videoTime + }); + } catch (error) { + console.error('[Video WS] Failed to stream frame:', error); + } + + continue; // Skip other frame fetching methods + } + // If using browser video element if (clip.useBrowserVideo && clip.videoElement) { const videoTime = clip.offset + (currentTime - clip.startTime); @@ -1687,13 +1741,50 @@ class VideoLayer extends Widget { } // Debug: log what path we're taking - if (!clip._drawPathLogged) { - console.log(`[Video Draw] useBrowserVideo=${clip.useBrowserVideo}, videoElement=${!!clip.videoElement}, currentFrame=${!!clip.currentFrame}`); - clip._drawPathLogged = true; - } + // if (!clip._drawPathLogged) { + // console.log(`[Video Draw] useWebSocketStreaming=${this.useWebSocketStreaming}, wsCurrentFrame=${!!clip.wsCurrentFrame}, useBrowserVideo=${clip.useBrowserVideo}, videoElement=${!!clip.videoElement}, currentFrame=${!!clip.currentFrame}`); + // clip._drawPathLogged = true; + // } + // Prefer WebSocket streaming if available + if (this.useWebSocketStreaming && clip.wsCurrentFrame) { + try { + // Create a temporary canvas to hold the ImageData + if (!clip._wsCanvas) { + clip._wsCanvas = document.createElement('canvas'); + } + const tempCanvas = clip._wsCanvas; + + // Set temp canvas size to match ImageData dimensions + if (tempCanvas.width !== clip.wsCurrentFrame.width || tempCanvas.height !== clip.wsCurrentFrame.height) { + tempCanvas.width = clip.wsCurrentFrame.width; + tempCanvas.height = clip.wsCurrentFrame.height; + } + + // Put ImageData on temp canvas (zero-copy) + const tempCtx = tempCanvas.getContext('2d'); + tempCtx.putImageData(clip.wsCurrentFrame, 0, 0); + + // Scale to fit canvas while maintaining aspect ratio + const canvasWidth = config.fileWidth; + const canvasHeight = config.fileHeight; + const scale = Math.min( + canvasWidth / clip.width, + canvasHeight / clip.height + ); + const scaledWidth = clip.width * scale; + const scaledHeight = clip.height * scale; + const x = (canvasWidth - scaledWidth) / 2; + const y = (canvasHeight - scaledHeight) / 2; + + // Draw scaled to main canvas (GPU-accelerated) + ctx.drawImage(tempCanvas, x, y, scaledWidth, scaledHeight); + } catch (error) { + console.error('[Video WS Draw] Failed to draw WebSocket frame:', error); + } + } // Prefer browser video element if available - if (clip.useBrowserVideo && clip.videoElement) { + else if (clip.useBrowserVideo && clip.videoElement) { // Debug: log readyState issues if (clip.videoElement.readyState < 2) { if (!clip._readyStateWarned) {