diff --git a/daw-backend/src/audio/recording.rs b/daw-backend/src/audio/recording.rs index 2386638..ee8e811 100644 --- a/daw-backend/src/audio/recording.rs +++ b/daw-backend/src/audio/recording.rs @@ -12,7 +12,7 @@ pub struct RecordingState { pub clip_id: ClipId, /// Path to temporary WAV file pub temp_file_path: PathBuf, - /// WAV file writer + /// WAV file writer (only used at finalization, not during recording) pub writer: WavWriter, /// Sample rate of recording pub sample_rate: u32, @@ -20,12 +20,8 @@ pub struct RecordingState { pub channels: u32, /// Timeline start position in seconds pub start_time: f64, - /// Total frames written to disk + /// Total frames recorded pub frames_written: usize, - /// Accumulation buffer for next flush - pub buffer: Vec, - /// Number of frames to accumulate before flushing - pub flush_interval_frames: usize, /// Whether recording is currently paused pub paused: bool, /// Number of samples remaining to skip (to discard stale buffer data) @@ -36,7 +32,7 @@ pub struct RecordingState { pub waveform_buffer: Vec, /// Number of frames per waveform peak pub frames_per_peak: usize, - /// All recorded audio data accumulated in memory (for fast finalization) + /// All recorded audio data accumulated in memory (written to disk at finalization) pub audio_data: Vec, } @@ -50,10 +46,8 @@ impl RecordingState { sample_rate: u32, channels: u32, start_time: f64, - flush_interval_seconds: f64, + _flush_interval_seconds: f64, // No longer used - kept for API compatibility ) -> Self { - let flush_interval_frames = (sample_rate as f64 * flush_interval_seconds) as usize; - // Calculate frames per waveform peak // Target ~300 peaks per second with minimum 1000 samples per peak let target_peaks_per_second = 300; @@ -68,8 +62,6 @@ impl RecordingState { channels, start_time, frames_written: 0, - buffer: Vec::new(), - flush_interval_frames, paused: false, samples_to_skip: 0, // Will be set by engine when it knows buffer size waveform: Vec::new(), @@ -102,22 +94,16 @@ impl RecordingState { samples }; - // Add to disk buffer - self.buffer.extend_from_slice(samples_to_process); - - // Add to audio data (accumulate in memory for fast finalization) + // Add to audio data (accumulate in memory - disk write happens at finalization only) self.audio_data.extend_from_slice(samples_to_process); // Add to waveform buffer and generate peaks incrementally self.waveform_buffer.extend_from_slice(samples_to_process); self.generate_waveform_peaks(); - // Check if we should flush to disk - let frames_in_buffer = self.buffer.len() / self.channels as usize; - if frames_in_buffer >= self.flush_interval_frames { - self.flush()?; - return Ok(true); - } + // Track frames for duration calculation (no disk I/O in audio callback!) + let frames_added = samples_to_process.len() / self.channels as usize; + self.frames_written += frames_added; Ok(false) } @@ -144,37 +130,17 @@ impl RecordingState { } } - /// Flush accumulated samples to disk - pub fn flush(&mut self) -> Result<(), std::io::Error> { - if self.buffer.is_empty() { - return Ok(()); - } - - // Write to WAV file - self.writer.write_samples(&self.buffer)?; - - // Update frames written - let frames_flushed = self.buffer.len() / self.channels as usize; - self.frames_written += frames_flushed; - - // Clear buffer - self.buffer.clear(); - - Ok(()) - } - /// Get current recording duration in seconds - /// Includes both flushed frames and buffered frames pub fn duration(&self) -> f64 { - let buffered_frames = self.buffer.len() / self.channels as usize; - let total_frames = self.frames_written + buffered_frames; - total_frames as f64 / self.sample_rate as f64 + self.frames_written as f64 / self.sample_rate as f64 } /// Finalize the recording and return the temp file path, waveform, and audio data pub fn finalize(mut self) -> Result<(PathBuf, Vec, Vec), std::io::Error> { - // Flush any remaining samples to disk - self.flush()?; + // Write all audio data to disk at once (outside audio callback - safe to do I/O) + if !self.audio_data.is_empty() { + self.writer.write_samples(&self.audio_data)?; + } // Generate final waveform peak from any remaining samples if !self.waveform_buffer.is_empty() { diff --git a/lightningbeam-ui/Cargo.lock b/lightningbeam-ui/Cargo.lock index 04cf011..07f4b45 100644 --- a/lightningbeam-ui/Cargo.lock +++ b/lightningbeam-ui/Cargo.lock @@ -20,15 +20,15 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" -version = "0.16.3" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b76d84ee70e30a4a7e39ab9018e2b17a6a09e31084176cc7c0b2dec036ba45" +checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" [[package]] name = "accesskit_atspi_common" -version = "0.9.3" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5393c75d4666f580f4cac0a968bc97c36076bb536a129f28210dac54ee127ed" +checksum = "890d241cf51fc784f0ac5ac34dfc847421f8d39da6c7c91a0fcc987db62a8267" dependencies = [ "accesskit", "accesskit_consumer", @@ -40,33 +40,33 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.24.3" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a12dc159d52233c43d9fe5415969433cbdd52c3d6e0df51bda7d447427b9986" +checksum = "db81010a6895d8707f9072e6ce98070579b43b717193d2614014abd5cb17dd43" dependencies = [ "accesskit", - "immutable-chunkmap", + "hashbrown 0.15.5", ] [[package]] name = "accesskit_macos" -version = "0.17.4" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc6c1ecd82053d127961ad80a8beaa6004fb851a3a5b96506d7a6bd462403f6" +checksum = "a0089e5c0ac0ca281e13ea374773898d9354cc28d15af9f0f7394d44a495b575" dependencies = [ "accesskit", "accesskit_consumer", + "hashbrown 0.15.5", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", - "once_cell", ] [[package]] name = "accesskit_unix" -version = "0.12.3" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be7f5cf6165be10a54b2655fa2e0e12b2509f38ed6fc43e11c31fdb7ee6230bb" +checksum = "301e55b39cfc15d9c48943ce5f572204a551646700d0e8efa424585f94fec528" dependencies = [ "accesskit", "accesskit_atspi_common", @@ -82,23 +82,23 @@ dependencies = [ [[package]] name = "accesskit_windows" -version = "0.23.2" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "974e96c347384d9133427167fb8a58c340cb0496988dacceebdc1ed27071023b" +checksum = "d2d63dd5041e49c363d83f5419a896ecb074d309c414036f616dc0b04faca971" dependencies = [ "accesskit", "accesskit_consumer", - "paste", + "hashbrown 0.15.5", "static_assertions", - "windows 0.58.0", - "windows-core 0.58.0", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] name = "accesskit_winit" -version = "0.22.4" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aea3522719f1c44564d03e9469a8e2f3a98b3a8a880bd66d0789c6b9c4a669dd" +checksum = "c8cfabe59d0eaca7412bfb1f70198dd31e3b0496fee7e15b066f9c36a1a140a0" dependencies = [ "accesskit", "accesskit_macos", @@ -114,6 +114,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -301,9 +312,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" dependencies = [ "clipboard-win", + "image", "log", "objc2 0.6.3", "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", @@ -349,6 +363,28 @@ dependencies = [ "libloading", ] +[[package]] +name = "ashpd" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.2", + "raw-window-handle", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -427,6 +463,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + [[package]] name = "async-process" version = "2.5.0" @@ -522,9 +569,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atspi" -version = "0.22.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf" +checksum = "c83247582e7508838caf5f316c00791eee0e15c0bf743e6880585b867e16815c" dependencies = [ "atspi-common", "atspi-connection", @@ -533,9 +580,9 @@ dependencies = [ [[package]] name = "atspi-common" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7" +checksum = "33dfc05e7cdf90988a197803bf24f5788f94f7c94a69efa95683e8ffe76cfdfb" dependencies = [ "enumflags2", "serde", @@ -549,9 +596,9 @@ dependencies = [ [[package]] name = "atspi-connection" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "430c5960624a4baaa511c9c0fcc2218e3b58f5dbcc47e6190cafee344b873333" +checksum = "4193d51303d8332304056ae0004714256b46b6635a5c556109b319c0d3784938" dependencies = [ "atspi-common", "atspi-proxies", @@ -561,14 +608,13 @@ dependencies = [ [[package]] name = "atspi-proxies" -version = "0.6.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496" +checksum = "d2eebcb9e7e76f26d0bcfd6f0295e1cd1e6f33bedbc5698a971db8dc43d7751c" dependencies = [ "atspi-common", "serde", "zbus", - "zvariant", ] [[package]] @@ -621,6 +667,21 @@ dependencies = [ "simd-abstraction", ] +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -630,7 +691,7 @@ dependencies = [ "bitflags 2.10.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", "regex", @@ -641,18 +702,18 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bit_field" @@ -717,6 +778,15 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.3", +] + [[package]] name = "blocking" version = "1.6.2" @@ -784,6 +854,12 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "byteorder-lite" version = "0.1.0" @@ -796,6 +872,26 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.13+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "cairo-rs" version = "0.18.5" @@ -930,12 +1026,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cfg_aliases" version = "0.2.1" @@ -951,6 +1041,29 @@ dependencies = [ "libc", ] +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -1002,6 +1115,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +[[package]] +name = "claxon" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" + [[package]] name = "clipboard-win" version = "5.4.1" @@ -1013,10 +1132,11 @@ dependencies = [ [[package]] name = "codespan-reporting" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ + "serde", "termcolor", "unicode-width", ] @@ -1039,37 +1159,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "com" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" -dependencies = [ - "com_macros", -] - -[[package]] -name = "com_macros" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" -dependencies = [ - "com_macros_support", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "com_macros_support" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "combine" version = "4.6.7" @@ -1122,6 +1211,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "convert_case" version = "0.6.0" @@ -1165,7 +1260,7 @@ checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation 0.9.4", - "core-graphics-types", + "core-graphics-types 0.1.3", "foreign-types", "libc", ] @@ -1181,6 +1276,17 @@ dependencies = [ "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.10.0", + "core-foundation 0.10.1", + "libc", +] + [[package]] name = "coreaudio-rs" version = "0.11.3" @@ -1253,6 +1359,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + [[package]] name = "crc32fast" version = "1.5.0" @@ -1375,17 +1496,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" -[[package]] -name = "d3d12" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdbd1f579714e3c809ebd822c81ef148b1ceaeb3d535352afc73fd0c4c6a0017" -dependencies = [ - "bitflags 2.10.0", - "libloading", - "winapi", -] - [[package]] name = "dashmap" version = "5.5.3" @@ -1549,18 +1659,30 @@ dependencies = [ "dasp_rms", "dasp_sample", "dasp_signal", + "ffmpeg-next", + "hound", "midir", "midly", "pathdiff", "petgraph 0.6.5", - "rand", + "rand 0.8.5", "ratatui", + "rayon", "rtrb", "serde", "serde_json", "symphonia", ] +[[package]] +name = "deranged" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +dependencies = [ + "powerfmt", +] + [[package]] name = "digest" version = "0.10.7" @@ -1569,6 +1691,28 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +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]] @@ -1584,6 +1728,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", + "libc", "objc2 0.6.3", ] @@ -1645,9 +1791,9 @@ dependencies = [ [[package]] name = "ecolor" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775cfde491852059e386c4e1deb4aef381c617dc364184c6f6afee99b87c402b" +checksum = "71ddb8ac7643d1dba1bb02110e804406dd459a838efcb14011ced10556711a8e" dependencies = [ "bytemuck", "emath", @@ -1655,9 +1801,9 @@ dependencies = [ [[package]] name = "eframe" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac2645a9bf4826eb4e91488b1f17b8eaddeef09396706b2f14066461338e24f" +checksum = "457481173e6db5ca9fa2be93a58df8f4c7be639587aeb4853b526c6cf87db4e6" dependencies = [ "ahash 0.8.12", "bytemuck", @@ -1666,7 +1812,7 @@ dependencies = [ "egui-wgpu", "egui-winit", "egui_glow", - "glow 0.14.2", + "glow", "glutin", "glutin-winit", "image", @@ -1677,7 +1823,8 @@ dependencies = [ "objc2-foundation 0.2.2", "parking_lot", "percent-encoding", - "pollster", + "pollster 0.4.0", + "profiling", "raw-window-handle", "static_assertions", "wasm-bindgen", @@ -1685,30 +1832,33 @@ dependencies = [ "web-sys", "web-time", "wgpu", - "winapi", - "windows-sys 0.52.0", + "windows-sys 0.61.2", "winit", ] [[package]] name = "egui" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53eafabcce0cb2325a59a98736efe0bf060585b437763f8c476957fb274bb974" +checksum = "6a9b567d356674e9a5121ed3fedfb0a7c31e059fe71f6972b691bcd0bfc284e3" dependencies = [ "accesskit", "ahash 0.8.12", + "bitflags 2.10.0", "emath", "epaint", "log", "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", ] [[package]] name = "egui-wgpu" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00fd5d06d8405397e64a928fa0ef3934b3c30273ea7603e3dc4627b1f7a1a82" +checksum = "5e4d209971c84b2352a06174abdba701af1e552ce56b144d96f2bd50a3c91236" dependencies = [ "ahash 0.8.12", "bytemuck", @@ -1716,7 +1866,8 @@ dependencies = [ "egui", "epaint", "log", - "thiserror 1.0.69", + "profiling", + "thiserror 2.0.17", "type-map", "web-time", "wgpu", @@ -1725,15 +1876,19 @@ dependencies = [ [[package]] name = "egui-winit" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9c430f4f816340e8e8c1b20eec274186b1be6bc4c7dfc467ed50d57abc36c6" +checksum = "ec6687e5bb551702f4ad10ac428bab12acf9d53047ebb1082d4a0ed8c6251a29" dependencies = [ "accesskit_winit", - "ahash 0.8.12", "arboard", + "bytemuck", "egui", "log", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "profiling", "raw-window-handle", "smithay-clipboard", "web-time", @@ -1742,10 +1897,19 @@ dependencies = [ ] [[package]] -name = "egui_extras" -version = "0.29.1" +name = "egui_code_editor" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf3c1f5cd8dfe2ade470a218696c66cf556fcfd701e7830fa2e9f4428292a2a1" +checksum = "39a1b847b0ff5a3bac4e8604eca605808970bbcdaba76b3101db1051e4206dc6" +dependencies = [ + "egui", +] + +[[package]] +name = "egui_extras" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01d34e845f01c62e3fded726961092e70417d66570c499b9817ab24674ca4ed" dependencies = [ "ahash 0.8.12", "egui", @@ -1753,26 +1917,39 @@ dependencies = [ "image", "log", "mime_guess2", - "resvg 0.37.0", + "profiling", + "resvg 0.45.1", + "syntect", ] [[package]] name = "egui_glow" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e39bccc683cd43adab530d8f21a13eb91e80de10bcc38c3f1c16601b6f62b26" +checksum = "6420863ea1d90e750f75075231a260030ad8a9f30a7cef82cdc966492dc4c4eb" dependencies = [ - "ahash 0.8.12", "bytemuck", "egui", - "glow 0.14.2", + "glow", "log", "memoffset", + "profiling", "wasm-bindgen", "web-sys", "winit", ] +[[package]] +name = "egui_node_graph2" +version = "0.7.0" +source = "git+https://github.com/PVDoriginal/egui_node_graph2#a25a90822d8f9c956e729f3907aad98f59fa46bc" +dependencies = [ + "egui", + "slotmap", + "smallvec", + "thiserror 1.0.69", +] + [[package]] name = "either" version = "1.15.0" @@ -1781,9 +1958,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "emath" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fe0049ce51d0fb414d029e668dd72eb30bc2b739bf34296ed97bd33df544f3" +checksum = "491bdf728bf25ddd9ad60d4cf1c48588fa82c013a2440b91aa7fc43e34a07c32" dependencies = [ "bytemuck", ] @@ -1810,7 +1987,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" dependencies = [ "enum-map-derive", - "serde", ] [[package]] @@ -1847,9 +2023,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a32af8da821bd4f43f2c137e295459ee2e1661d87ca8779dfa0eaf45d870e20f" +checksum = "009d0dd3c2163823a0abdb899451ecbc78798dec545ee91b43aff1fa790bab62" dependencies = [ "ab_glyph", "ahash 0.8.12", @@ -1860,13 +2036,14 @@ dependencies = [ "log", "nohash-hasher", "parking_lot", + "profiling", ] [[package]] name = "epaint_default_fonts" -version = "0.29.1" +version = "0.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483440db0b7993cf77a20314f08311dbe95675092405518c0677aa08c151a3ea" +checksum = "5c4fbe202b6578d3d56428fa185cdf114a05e49da05f477b3c7f0fbb221f1862" [[package]] name = "equator" @@ -1961,6 +2138,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" +[[package]] +name = "fancy-regex" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998b056554fbe42e03ae0e152895cd1a7e1002aec800fdc6635d20270260c46f" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1996,6 +2184,31 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ffmpeg-next" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d658424d233cbd993a972dd73a66ca733acd12a494c68995c9ac32ae1fe65b40" +dependencies = [ + "bitflags 2.10.0", + "ffmpeg-sys-next", + "libc", +] + +[[package]] +name = "ffmpeg-sys-next" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bca20aa4ee774fe384c2490096c122b0b23cf524a9910add0686691003d797b" +dependencies = [ + "bindgen", + "cc", + "libc", + "num_cpus", + "pkg-config", + "vcpkg", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -2024,6 +2237,24 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flacenc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb6da14d3c6605689b5c9ed5187a5218a6d3888e14b747bc18fd4e4bafd452bd" +dependencies = [ + "built", + "crc", + "crossbeam-channel", + "heapless", + "log", + "md-5", + "num-traits", + "rustversion", + "seq-macro", + "serde", +] + [[package]] name = "flate2" version = "1.1.5" @@ -2040,6 +2271,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +[[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" @@ -2047,10 +2284,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] -name = "font-types" -version = "0.7.3" +name = "foldhash" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3971f9a5ca983419cdc386941ba3b9e1feba01a0ab888adf78739feb2798492" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "font-types" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" dependencies = [ "bytemuck", ] @@ -2061,7 +2304,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" dependencies = [ - "roxmltree 0.20.0", + "roxmltree", ] [[package]] @@ -2187,12 +2430,6 @@ dependencies = [ "syn 2.0.110", ] -[[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" @@ -2208,7 +2445,6 @@ dependencies = [ "futures-core", "futures-io", "futures-macro", - "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -2291,7 +2527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.2", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2425,21 +2661,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "glow" -version = "0.13.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glow" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" dependencies = [ "js-sys", "slotmap", @@ -2454,7 +2678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" dependencies = [ "bitflags 2.10.0", - "cfg_aliases 0.2.1", + "cfg_aliases", "cgl", "dispatch2", "glutin_egl_sys", @@ -2478,7 +2702,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" dependencies = [ - "cfg_aliases 0.2.1", + "cfg_aliases", "glutin", "raw-window-handle", "winit", @@ -2545,15 +2769,14 @@ dependencies = [ [[package]] name = "gpu-allocator" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" dependencies = [ "log", "presser", "thiserror 1.0.69", - "winapi", - "windows 0.52.0", + "windows 0.58.0", ] [[package]] @@ -2646,9 +2869,19 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "num-traits", "zerocopy", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -2672,7 +2905,7 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -2680,20 +2913,19 @@ name = "hashbrown" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", +] [[package]] -name = "hassle-rs" -version = "0.11.0" +name = "heapless" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "bitflags 2.10.0", - "com", - "libc", - "libloading", - "thiserror 1.0.69", - "widestring", - "winapi", + "hash32", + "serde", + "stable_deref_trait", ] [[package]] @@ -2726,6 +2958,45 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.61.2", +] + +[[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 = "icu_collections" version = "2.1.1" @@ -2868,21 +3139,18 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" +[[package]] +name = "imagesize" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" + [[package]] name = "imgref" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" -[[package]] -name = "immutable-chunkmap" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3e98b1520e49e252237edc238a39869da9f3241f2ec19dc788c1d24694d1e4" -dependencies = [ - "arrayvec", -] - [[package]] name = "indexmap" version = "1.9.3" @@ -2905,6 +3173,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -3031,15 +3308,6 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" -[[package]] -name = "kurbo" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" -dependencies = [ - "arrayvec", -] - [[package]] name = "kurbo" version = "0.11.3" @@ -3048,7 +3316,6 @@ checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" dependencies = [ "arrayvec", "euclid", - "serde", "smallvec", ] @@ -3060,6 +3327,7 @@ checksum = "ce9729cc38c18d86123ab736fd2e7151763ba226ac2490ec092d1dd148825e32" dependencies = [ "arrayvec", "euclid", + "serde", "smallvec", ] @@ -3098,9 +3366,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link", + "windows-link 0.2.1", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "libredox" version = "0.1.10" @@ -3135,12 +3409,24 @@ dependencies = [ name = "lightningbeam-core" version = "0.1.0" dependencies = [ + "base64 0.21.7", + "bytemuck", + "chrono", + "claxon", + "daw-backend", "egui", - "kurbo 0.11.3", + "ffmpeg-next", + "flacenc", + "image", + "kurbo 0.12.0", + "lru", + "pathdiff", "serde", "serde_json", "uuid", "vello", + "wgpu", + "zip", ] [[package]] @@ -3148,21 +3434,32 @@ name = "lightningbeam-editor" version = "0.1.0" dependencies = [ "clap", + "cpal", "daw-backend", + "directories", "eframe", "egui-wgpu", + "egui_code_editor", "egui_extras", + "egui_node_graph2", + "ffmpeg-next", "image", - "kurbo 0.11.3", + "kurbo 0.12.0", "lightningbeam-core", "lightningcss", + "memory-stats", "muda", - "peniko 0.5.0", - "pollster", + "notify-rust", + "peniko", + "petgraph 0.6.5", + "pollster 0.3.0", + "rayon", "resvg 0.42.0", + "rfd", "rtrb", "serde", "serde_json", + "tiny-skia", "uuid", "vello", "wgpu", @@ -3215,6 +3512,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3272,6 +3575,18 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "mac-notification-sys" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65fd3f75411f4725061682ed91f131946e912859d0044d39c4ec0aac818d7621" +dependencies = [ + "cc", + "objc2 0.6.3", + "objc2-foundation 0.3.2", + "time", +] + [[package]] name = "mach2" version = "0.4.3" @@ -3306,6 +3621,16 @@ dependencies = [ "rayon", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.6" @@ -3331,14 +3656,24 @@ dependencies = [ ] [[package]] -name = "metal" -version = "0.29.0" +name = "memory-stats" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +checksum = "c73f5c649995a115e1a0220b35e4df0a1294500477f97a91d0660fb5abeb574a" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "metal" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ "bitflags 2.10.0", "block", - "core-graphics-types", + "core-graphics-types 0.2.0", "foreign-types", "log", "objc", @@ -3448,23 +3783,28 @@ dependencies = [ [[package]] name = "naga" -version = "22.1.0" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd5a652b6faf21496f2cfd88fc49989c8db0825d1f6746b1a71a6ede24a63ad" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ "arrayvec", "bit-set", "bitflags 2.10.0", - "cfg_aliases 0.1.1", + "cfg-if", + "cfg_aliases", "codespan-reporting", + "half", + "hashbrown 0.16.0", "hexf-parse", "indexmap 2.12.0", + "libm", "log", + "num-traits", + "once_cell", "rustc-hash 1.1.0", "spirv", - "termcolor", - "thiserror 1.0.69", - "unicode-xid", + "thiserror 2.0.17", + "unicode-ident", ] [[package]] @@ -3539,13 +3879,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.10.0", "cfg-if", - "cfg_aliases 0.2.1", + "cfg_aliases", "libc", "memoffset", ] @@ -3581,6 +3921,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" +[[package]] +name = "notify-rust" +version = "4.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6442248665a5aa2514e794af3b39661a8e73033b1cc5e59899e1276117ee4400" +dependencies = [ + "futures-lite", + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -3591,6 +3945,12 @@ dependencies = [ "num-traits", ] +[[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" @@ -3629,6 +3989,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", +] + +[[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]] @@ -3694,7 +4065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "libc", "objc2 0.5.2", "objc2-core-data", @@ -3710,6 +4081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", "objc2 0.6.3", "objc2-core-foundation", "objc2-core-graphics", @@ -3723,7 +4095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", "objc2-foundation 0.2.2", @@ -3735,7 +4107,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3747,7 +4119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3782,7 +4154,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", "objc2-metal", @@ -3794,7 +4166,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-contacts", "objc2-foundation 0.2.2", @@ -3813,7 +4185,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "dispatch", "libc", "objc2 0.5.2", @@ -3826,6 +4198,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", + "block2 0.6.2", + "libc", "objc2 0.6.3", "objc2-core-foundation", ] @@ -3847,7 +4221,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-app-kit 0.2.2", "objc2-foundation 0.2.2", @@ -3860,7 +4234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3872,7 +4246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", "objc2-metal", @@ -3895,7 +4269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-cloud-kit", "objc2-core-data", @@ -3915,7 +4289,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", ] @@ -3927,7 +4301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ "bitflags 2.10.0", - "block2", + "block2 0.5.1", "objc2 0.5.2", "objc2-core-location", "objc2-foundation 0.2.2", @@ -3968,6 +4342,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.49" @@ -3977,6 +4357,15 @@ dependencies = [ "libredox", ] +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -4083,7 +4472,18 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", ] [[package]] @@ -4105,13 +4505,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" [[package]] -name = "peniko" -version = "0.2.0" +name = "pbkdf2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a648c93f502a0bef0a9cb47fa1335994958a2744667d3f82defe513f276741a" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "kurbo 0.11.3", - "smallvec", + "digest", + "hmac", + "password-hash", + "sha2", ] [[package]] @@ -4179,7 +4581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -4202,7 +4604,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher", "unicase", ] @@ -4261,6 +4663,19 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plist" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +dependencies = [ + "base64 0.22.1", + "indexmap 2.12.0", + "quick-xml 0.38.4", + "serde", + "time", +] + [[package]] name = "png" version = "0.17.16" @@ -4307,6 +4722,27 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[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 = "potential_utf" version = "0.1.4" @@ -4316,6 +4752,12 @@ dependencies = [ "zerovec", ] +[[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.21" @@ -4464,9 +4906,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", "serde", @@ -4481,6 +4923,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.42" @@ -4509,8 +4960,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -4520,7 +4981,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -4532,6 +5003,15 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + [[package]] name = "range-alloc" version = "0.1.4" @@ -4584,8 +5064,8 @@ dependencies = [ "once_cell", "paste", "profiling", - "rand", - "rand_chacha", + "rand 0.8.5", + "rand_chacha 0.3.1", "simd_helpers", "system-deps", "thiserror 1.0.69", @@ -4634,17 +5114,11 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rctree" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" - [[package]] name = "read-fonts" -version = "0.22.7" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69aacb76b5c29acfb7f90155d39759a29496aebb49395830e928a9703d2eec2f" +checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" dependencies = [ "bytemuck", "font-types", @@ -4668,6 +5142,17 @@ dependencies = [ "bitflags 2.10.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.16", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regex" version = "1.12.2" @@ -4712,20 +5197,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" -[[package]] -name = "resvg" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadccb3d99a9efb8e5e00c16fbb732cbe400db2ec7fc004697ee7d97d86cf1f4" -dependencies = [ - "log", - "pico-args", - "rgb", - "svgtypes 0.13.0", - "tiny-skia", - "usvg 0.37.0", -] - [[package]] name = "resvg" version = "0.42.0" @@ -4737,11 +5208,49 @@ dependencies = [ "log", "pico-args", "rgb", - "svgtypes 0.15.3", + "svgtypes", "tiny-skia", "usvg 0.42.0", ] +[[package]] +name = "resvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" +dependencies = [ + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg 0.45.1", +] + +[[package]] +name = "rfd" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" +dependencies = [ + "ashpd", + "block2 0.6.2", + "dispatch2", + "js-sys", + "log", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "pollster 0.4.0", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.59.0", +] + [[package]] name = "rgb" version = "0.8.52" @@ -4780,12 +5289,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "roxmltree" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" - [[package]] name = "roxmltree" version = "0.20.0" @@ -4919,6 +5422,12 @@ version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.228" @@ -5002,6 +5511,17 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -5077,12 +5597,6 @@ dependencies = [ "log", ] -[[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" @@ -5091,9 +5605,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "skrifa" -version = "0.22.3" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe" +checksum = "8c31071dedf532758ecf3fed987cdb4bd9509f900e026ab684b4ecb81ea49841" dependencies = [ "bytemuck", "read-fonts", @@ -5263,22 +5777,18 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "svg_fmt" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" -[[package]] -name = "svgtypes" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e44e288cd960318917cbd540340968b90becc8bc81f171345d706e7a89d9d70" -dependencies = [ - "kurbo 0.9.5", - "siphasher 0.3.11", -] - [[package]] name = "svgtypes" version = "0.15.3" @@ -5286,7 +5796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" dependencies = [ "kurbo 0.11.3", - "siphasher 1.0.1", + "siphasher", ] [[package]] @@ -5517,6 +6027,27 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "syntect" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "656b45c05d95a5704399aeef6bd0ddec7b2b3531b7c9e900abbf7c4d2190c925" +dependencies = [ + "bincode", + "fancy-regex", + "flate2", + "fnv", + "once_cell", + "plist", + "regex-syntax", + "serde", + "serde_derive", + "serde_json", + "thiserror 2.0.17", + "walkdir", + "yaml-rust", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -5542,6 +6073,18 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "tauri-winrt-notification" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b1e66e07de489fe43a46678dd0b8df65e0c973909df1b60ba33874e297ba9b9" +dependencies = [ + "quick-xml 0.37.5", + "thiserror 2.0.17", + "windows 0.61.3", + "windows-version", +] + [[package]] name = "tempfile" version = "3.23.0" @@ -5618,6 +6161,37 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "time" +version = "0.3.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" + +[[package]] +name = "time-macros" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -5885,12 +6459,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "url" version = "2.5.7" @@ -5904,18 +6472,10 @@ dependencies = [ ] [[package]] -name = "usvg" -version = "0.37.0" +name = "urlencoding" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b0a51b72ab80ca511d126b77feeeb4fb1e972764653e61feac30adc161a756" -dependencies = [ - "base64 0.21.7", - "log", - "pico-args", - "usvg-parser", - "usvg-tree", - "xmlwriter", -] +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "usvg" @@ -5927,16 +6487,16 @@ dependencies = [ "data-url 0.3.2", "flate2", "fontdb", - "imagesize", + "imagesize 0.12.0", "kurbo 0.11.3", "log", "pico-args", - "roxmltree 0.20.0", + "roxmltree", "rustybuzz", "simplecss", - "siphasher 1.0.1", + "siphasher", "strict-num", - "svgtypes 0.15.3", + "svgtypes", "tiny-skia-path", "unicode-bidi", "unicode-script", @@ -5945,33 +6505,25 @@ dependencies = [ ] [[package]] -name = "usvg-parser" -version = "0.37.0" +name = "usvg" +version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd4e3c291f45d152929a31f0f6c819245e2921bfd01e7bd91201a9af39a2bdc" +checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" dependencies = [ + "base64 0.22.1", "data-url 0.3.2", "flate2", - "imagesize", - "kurbo 0.9.5", + "imagesize 0.13.0", + "kurbo 0.11.3", "log", - "roxmltree 0.19.0", + "pico-args", + "roxmltree", "simplecss", - "siphasher 0.3.11", - "svgtypes 0.13.0", - "usvg-tree", -] - -[[package]] -name = "usvg-tree" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee3d202ebdb97a6215604b8f5b4d6ef9024efd623cf2e373a6416ba976ec7d3" -dependencies = [ - "rctree", + "siphasher", "strict-num", - "svgtypes 0.13.0", + "svgtypes", "tiny-skia-path", + "xmlwriter", ] [[package]] @@ -6010,20 +6562,24 @@ dependencies = [ ] [[package]] -name = "vello" -version = "0.3.0" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc44dd4eb9af6a41551b9a82c93d068bd832693d6f78ab118ad19780d8e1202e" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vello" +version = "0.6.0" +source = "git+https://github.com/linebender/vello?branch=main#809244764436824f20426bd53f92e645e9845ab3" dependencies = [ "bytemuck", "futures-intrusive", "log", - "peniko 0.2.0", + "peniko", "png 0.17.16", - "raw-window-handle", "skrifa", "static_assertions", - "thiserror 1.0.69", + "thiserror 2.0.17", "vello_encoding", "vello_shaders", "wgpu", @@ -6031,26 +6587,25 @@ dependencies = [ [[package]] name = "vello_encoding" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8110c14702a4e17f9200f6e3c4fe05dda5a22bf031ae4feafed4a61429f66fb2" +version = "0.6.0" +source = "git+https://github.com/linebender/vello?branch=main#809244764436824f20426bd53f92e645e9845ab3" dependencies = [ "bytemuck", "guillotiere", - "peniko 0.2.0", + "peniko", "skrifa", "smallvec", ] [[package]] name = "vello_shaders" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cad02d6f29f2212a6ee382a8fec6f9977d0cceefacf07f8e361607ffe3988d" +version = "0.6.0" +source = "git+https://github.com/linebender/vello?branch=main#809244764436824f20426bd53f92e645e9845ab3" dependencies = [ "bytemuck", + "log", "naga", - "thiserror 1.0.69", + "thiserror 2.0.17", "vello_encoding", ] @@ -6334,17 +6889,21 @@ checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wgpu" -version = "22.1.0" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d1c4ba43f80542cf63a0a6ed3134629ae73e8ab51e4b765a67f3aa062eb433" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", - "cfg_aliases 0.1.1", + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", "document-features", + "hashbrown 0.16.0", "js-sys", "log", "naga", "parking_lot", + "portable-atomic", "profiling", "raw-window-handle", "smallvec", @@ -6359,34 +6918,68 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "22.1.0" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348c840d1051b8e86c3bcd31206080c5e71e5933dabd79be1ce732b0b2f089a" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" dependencies = [ "arrayvec", + "bit-set", "bit-vec", "bitflags 2.10.0", - "cfg_aliases 0.1.1", + "bytemuck", + "cfg_aliases", "document-features", + "hashbrown 0.16.0", "indexmap 2.12.0", "log", "naga", "once_cell", "parking_lot", + "portable-atomic", "profiling", "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.17", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-types", ] [[package]] -name = "wgpu-hal" -version = "22.0.0" +name = "wgpu-core-deps-apple" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6bbf4b4de8b2a83c0401d9e5ae0080a2792055f25859a02bf9be97952bbed4f" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "27.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" dependencies = [ "android_system_properties", "arrayvec", @@ -6394,15 +6987,16 @@ dependencies = [ "bit-set", "bitflags 2.10.0", "block", - "cfg_aliases 0.1.1", - "core-graphics-types", - "d3d12", - "glow 0.13.1", + "bytemuck", + "cfg-if", + "cfg_aliases", + "core-graphics-types 0.2.0", + "glow", "glutin_wgl_sys", "gpu-alloc", "gpu-allocator", "gpu-descriptor", - "hassle-rs", + "hashbrown 0.16.0", "js-sys", "khronos-egl", "libc", @@ -6410,40 +7004,40 @@ dependencies = [ "log", "metal", "naga", - "ndk-sys 0.5.0+25.2.9519653", + "ndk-sys 0.6.0+11769913", "objc", "once_cell", + "ordered-float", "parking_lot", + "portable-atomic", + "portable-atomic-util", "profiling", "range-alloc", "raw-window-handle", "renderdoc-sys", - "rustc-hash 1.1.0", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.17", "wasm-bindgen", "web-sys", "wgpu-types", - "winapi", + "windows 0.58.0", + "windows-core 0.58.0", ] [[package]] name = "wgpu-types" -version = "22.0.0" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9d91f0e2c4b51434dfa6db77846f2793149d8e73f800fa2e41f52b8eac3c5d" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ "bitflags 2.10.0", + "bytemuck", "js-sys", + "log", + "thiserror 2.0.17", "web-sys", ] -[[package]] -name = "widestring" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" - [[package]] name = "winapi" version = "0.3.9" @@ -6490,16 +7084,6 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - [[package]] name = "windows" version = "0.54.0" @@ -6521,12 +7105,25 @@ dependencies = [ ] [[package]] -name = "windows-core" -version = "0.52.0" +name = "windows" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", ] [[package]] @@ -6545,13 +7142,37 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.58.0", + "windows-interface 0.58.0", "windows-result 0.2.0", - "windows-strings", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.58.0" @@ -6563,6 +7184,17 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + [[package]] name = "windows-interface" version = "0.58.0" @@ -6574,12 +7206,39 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -6598,6 +7257,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-strings" version = "0.1.0" @@ -6608,6 +7276,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -6659,7 +7336,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -6714,7 +7391,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -6725,6 +7402,24 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -6915,10 +7610,10 @@ dependencies = [ "android-activity", "atomic-waker", "bitflags 2.10.0", - "block2", + "block2 0.5.1", "bytemuck", "calloop 0.13.0", - "cfg_aliases 0.2.1", + "cfg_aliases", "concurrent-queue", "core-foundation 0.9.4", "core-graphics", @@ -7044,16 +7739,6 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" -[[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 = "xkbcommon-dl" version = "0.4.2" @@ -7085,6 +7770,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yoke" version = "0.8.1" @@ -7110,13 +7804,12 @@ dependencies = [ [[package]] name = "zbus" -version = "4.4.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" dependencies = [ "async-broadcast", "async-executor", - "async-fs", "async-io", "async-lock", "async-process", @@ -7127,20 +7820,17 @@ dependencies = [ "enumflags2", "event-listener", "futures-core", - "futures-sink", - "futures-util", + "futures-lite", "hex", - "nix 0.29.0", + "nix 0.30.1", "ordered-stream", - "rand", "serde", "serde_repr", - "sha1", - "static_assertions", "tracing", "uds_windows", - "windows-sys 0.52.0", - "xdg-home", + "uuid", + "windows-sys 0.61.2", + "winnow 0.7.13", "zbus_macros", "zbus_names", "zvariant", @@ -7148,9 +7838,9 @@ dependencies = [ [[package]] name = "zbus-lockstep" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" dependencies = [ "zbus_xml", "zvariant", @@ -7158,9 +7848,9 @@ dependencies = [ [[package]] name = "zbus-lockstep-macros" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" dependencies = [ "proc-macro2", "quote", @@ -7172,35 +7862,38 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.4.0" +version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", "quote", "syn 2.0.110", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" dependencies = [ "serde", "static_assertions", + "winnow 0.7.13", "zvariant", ] [[package]] name = "zbus_xml" -version = "4.0.0" +version = "5.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233" +checksum = "589e9a02bfafb9754bb2340a9e3b38f389772684c63d9637e76b1870377bec29" dependencies = [ - "quick-xml 0.30.0", + "quick-xml 0.36.2", "serde", "static_assertions", "zbus_names", @@ -7281,6 +7974,55 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zune-core" version = "0.4.12" @@ -7307,22 +8049,24 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.2.0" +version = "5.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" dependencies = [ "endi", "enumflags2", "serde", - "static_assertions", + "url", + "winnow 0.7.13", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.2.0" +version = "5.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" dependencies = [ "proc-macro-crate 3.4.0", "proc-macro2", @@ -7333,11 +8077,13 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "2.1.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" dependencies = [ "proc-macro2", "quote", + "serde", "syn 2.0.110", + "winnow 0.7.13", ] diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/add_clip_instance.rs b/lightningbeam-ui/lightningbeam-core/src/actions/add_clip_instance.rs index f149662..ec7fb35 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/add_clip_instance.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/add_clip_instance.rs @@ -250,6 +250,10 @@ impl Action for AddClipInstanceAction { _ => Err("Unexpected query response".to_string()), } } + AudioClipType::Recording => { + // Recording clips are not synced to backend until finalized + Ok(()) + } } } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs b/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs index b9ff11f..a34b15c 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs @@ -250,6 +250,9 @@ impl Action for MoveClipInstancesAction { _ => return Err("Expected audio instance ID for sampled clip".to_string()), } } + AudioClipType::Recording => { + // Recording clips cannot be moved - skip + } } } } @@ -317,6 +320,9 @@ impl Action for MoveClipInstancesAction { _ => return Err("Expected audio instance ID for sampled clip".to_string()), } } + AudioClipType::Recording => { + // Recording clips cannot be moved - skip + } } } } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/split_clip_instance.rs b/lightningbeam-ui/lightningbeam-core/src/actions/split_clip_instance.rs index fc3570f..dcfba02 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/split_clip_instance.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/split_clip_instance.rs @@ -443,6 +443,10 @@ impl Action for SplitClipInstanceAction { _ => Err("Unexpected query response".to_string()), } } + AudioClipType::Recording => { + // Recording clips cannot be split + Err("Cannot split a clip that is currently recording".to_string()) + } } } @@ -492,6 +496,9 @@ impl Action for SplitClipInstanceAction { controller.trim_clip(track_id, *orig_backend_id, orig_internal_start, orig_internal_end); } } + AudioClipType::Recording => { + // Recording clips - nothing to rollback + } } } } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs b/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs index 3aee14c..0fba827 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs @@ -404,6 +404,9 @@ impl Action for TrimClipInstancesAction { _ => return Err("Expected audio instance ID for sampled clip".to_string()), } } + AudioClipType::Recording => { + // Recording clips cannot be trimmed - skip + } } } } @@ -481,6 +484,9 @@ impl Action for TrimClipInstancesAction { _ => return Err("Expected audio instance ID for sampled clip".to_string()), } } + AudioClipType::Recording => { + // Recording clips cannot be trimmed - skip + } } } } diff --git a/lightningbeam-ui/lightningbeam-core/src/clip.rs b/lightningbeam-ui/lightningbeam-core/src/clip.rs index eaf5edb..45c4c17 100644 --- a/lightningbeam-ui/lightningbeam-core/src/clip.rs +++ b/lightningbeam-ui/lightningbeam-core/src/clip.rs @@ -362,6 +362,11 @@ pub enum AudioClipType { /// This allows sharing MIDI data between multiple clip instances midi_clip_id: u32, }, + /// Recording in progress + /// + /// Placeholder for a clip that is currently being recorded. + /// The audio_pool_index will be assigned when recording stops. + Recording, } /// Audio clip @@ -426,6 +431,38 @@ impl AudioClip { } } + /// Create a new recording-in-progress clip + /// + /// This is a placeholder clip for audio currently being recorded. + /// Call `finalize_recording` when recording stops to set the pool index. + pub fn new_recording(name: impl Into) -> Self { + Self { + id: Uuid::new_v4(), + name: name.into(), + duration: 0.0, // Will be updated as recording progresses + clip_type: AudioClipType::Recording, + folder_id: None, + } + } + + /// Finalize a recording clip with the actual audio pool index and duration + /// + /// Returns true if the clip was a Recording type and was successfully finalized. + pub fn finalize_recording(&mut self, audio_pool_index: usize, duration: f64) -> bool { + if matches!(self.clip_type, AudioClipType::Recording) { + self.clip_type = AudioClipType::Sampled { audio_pool_index }; + self.duration = duration; + true + } else { + false + } + } + + /// Check if this clip is a recording in progress + pub fn is_recording(&self) -> bool { + matches!(self.clip_type, AudioClipType::Recording) + } + /// Get the audio pool index if this is a sampled audio clip pub fn audio_pool_index(&self) -> Option { match &self.clip_type { diff --git a/lightningbeam-ui/lightningbeam-editor/src/main.rs b/lightningbeam-ui/lightningbeam-editor/src/main.rs index eabb275..2b3d62f 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/main.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/main.rs @@ -310,6 +310,83 @@ impl ToolIconCache { } } +/// Icon cache for focus card icons (start screen) +struct FocusIconCache { + icons: HashMap, + assets_path: std::path::PathBuf, +} + +impl FocusIconCache { + fn new() -> Self { + let assets_path = std::path::PathBuf::from( + std::env::var("HOME").unwrap_or_else(|_| "/home/skyler".to_string()) + ).join("Dev/Lightningbeam-2/src/assets"); + + Self { + icons: HashMap::new(), + assets_path, + } + } + + fn get_or_load(&mut self, icon: FocusIcon, icon_color: egui::Color32, ctx: &egui::Context) -> Option<&egui::TextureHandle> { + if !self.icons.contains_key(&icon) { + // Determine which SVG file to load + let svg_filename = match icon { + FocusIcon::Animation => "focus-animation.svg", + FocusIcon::Music => "focus-music.svg", + FocusIcon::Video => "focus-video.svg", + }; + + let icon_path = self.assets_path.join(svg_filename); + if let Ok(svg_data) = std::fs::read_to_string(&icon_path) { + // Replace currentColor with the actual color + let color_hex = format!( + "#{:02x}{:02x}{:02x}", + icon_color.r(), icon_color.g(), icon_color.b() + ); + let svg_with_color = svg_data.replace("currentColor", &color_hex); + + // Rasterize at 2x size for crisp display + let render_size = 120; + + if let Ok(tree) = resvg::usvg::Tree::from_data(svg_with_color.as_bytes(), &resvg::usvg::Options::default()) { + let pixmap_size = tree.size().to_int_size(); + let scale_x = render_size as f32 / pixmap_size.width() as f32; + let scale_y = render_size as f32 / pixmap_size.height() as f32; + let scale = scale_x.min(scale_y); + + let final_size = resvg::usvg::Size::from_wh( + pixmap_size.width() as f32 * scale, + pixmap_size.height() as f32 * scale, + ).unwrap_or(resvg::usvg::Size::from_wh(render_size as f32, render_size as f32).unwrap()); + + if let Some(mut pixmap) = resvg::tiny_skia::Pixmap::new( + final_size.width() as u32, + final_size.height() as u32, + ) { + let transform = resvg::tiny_skia::Transform::from_scale(scale, scale); + resvg::render(&tree, transform, &mut pixmap.as_mut()); + + // Convert RGBA8 to egui ColorImage + let rgba_data = pixmap.data(); + let size = [pixmap.width() as usize, pixmap.height() as usize]; + let color_image = egui::ColorImage::from_rgba_unmultiplied(size, rgba_data); + + // Upload to GPU + let texture = ctx.load_texture( + svg_filename, + color_image, + egui::TextureOptions::LINEAR, + ); + self.icons.insert(icon, texture); + } + } + } + } + self.icons.get(&icon) + } +} + /// Command sent to file operations worker thread enum FileCommand { Save { @@ -516,6 +593,33 @@ enum AudioExtractionResult { }, } +/// Application mode - controls whether to show start screen or editor +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum AppMode { + /// Show the start screen (recent projects, new project options) + StartScreen, + /// Show the main editor interface + Editor, +} + +/// Icons for the focus cards on the start screen +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum FocusIcon { + Animation, + Music, + Video, +} + +/// Recording arm mode - determines how tracks are armed for recording +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +enum RecordingArmMode { + /// Armed state follows active track (simple single-track workflow) + #[default] + Auto, + /// User explicitly arms tracks (multi-track recording workflow) + Manual, +} + struct EditorApp { layouts: Vec, current_layout_index: usize, @@ -526,6 +630,7 @@ struct EditorApp { split_preview_mode: SplitPreviewMode, icon_cache: IconCache, tool_icon_cache: ToolIconCache, + focus_icon_cache: FocusIconCache, // Focus card icons (start screen) selected_tool: Tool, // Currently selected drawing tool fill_color: egui::Color32, // Fill color for drawing stroke_color: egui::Color32, // Stroke color for drawing @@ -559,6 +664,13 @@ struct EditorApp { // Playback state (global for all panes) playback_time: f64, // Current playback position in seconds (persistent - save with document) is_playing: bool, // Whether playback is currently active (transient - don't save) + // Recording state + recording_arm_mode: RecordingArmMode, // How tracks are armed for recording + armed_layers: HashSet, // Explicitly armed layers (used in Manual mode) + is_recording: bool, // Whether recording is currently active + recording_clips: HashMap, // layer_id -> backend clip_id during recording + recording_start_time: f64, // Playback time when recording started + recording_layer_id: Option, // Layer being recorded to (for creating clips) // Asset drag-and-drop state dragging_asset: Option, // Asset being dragged from Asset Library // Shader editor inter-pane communication @@ -623,6 +735,10 @@ struct EditorApp { gpu_info: Option, /// Surface texture format for GPU rendering (Rgba8Unorm or Bgra8Unorm depending on platform) target_format: wgpu::TextureFormat, + /// Current application mode (start screen vs editor) + app_mode: AppMode, + /// Pending auto-reopen file path (set on startup if reopen_last_session is enabled) + pending_auto_reopen: Option, } /// Import filter types for the file dialog @@ -643,6 +759,13 @@ impl EditorApp { // Load application config let config = AppConfig::load(); + // Check if we should auto-reopen last session + let pending_auto_reopen = if config.reopen_last_session { + config.get_recent_files().into_iter().next() + } else { + None + }; + // Initialize native menu system let mut menu_system = MenuSystem::new().ok(); @@ -728,6 +851,7 @@ impl EditorApp { split_preview_mode: SplitPreviewMode::default(), icon_cache: IconCache::new(), tool_icon_cache: ToolIconCache::new(), + focus_icon_cache: FocusIconCache::new(), selected_tool: Tool::Select, // Default tool fill_color: egui::Color32::from_rgb(100, 100, 255), // Default blue fill stroke_color: egui::Color32::from_rgb(0, 0, 0), // Default black stroke @@ -757,6 +881,12 @@ impl EditorApp { clip_instance_to_backend_map: HashMap::new(), playback_time: 0.0, // Start at beginning is_playing: false, // Start paused + recording_arm_mode: RecordingArmMode::default(), // Auto mode by default + armed_layers: HashSet::new(), // No layers explicitly armed + is_recording: false, // Not recording initially + recording_clips: HashMap::new(), // No active recording clips + recording_start_time: 0.0, // Will be set when recording starts + recording_layer_id: None, // Will be set when recording starts dragging_asset: None, // No asset being dragged initially effect_to_load: None, // No effect to load initially effect_thumbnails_to_invalidate: Vec::new(), // No thumbnails to invalidate initially @@ -788,9 +918,320 @@ impl EditorApp { debug_stats_collector: debug_overlay::DebugStatsCollector::new(), gpu_info, target_format, + // Start screen vs editor mode + app_mode: AppMode::StartScreen, // Always start with start screen (auto-reopen handled separately) + pending_auto_reopen, } } + /// Render the start screen with recent projects and new project options + fn render_start_screen(&mut self, ctx: &egui::Context) { + egui::CentralPanel::default().show(ctx, |ui| { + let available = ui.available_rect_before_wrap(); + + // Calculate content dimensions + let card_size: f32 = 180.0; + let card_spacing: f32 = 24.0; + let left_width: f32 = 350.0; + let right_width = (card_size * 3.0) + (card_spacing * 2.0); + let content_width = (left_width + right_width + 80.0).min(available.width() - 100.0); + let content_height: f32 = 450.0; // Approximate height of content + + // Center content both horizontally and vertically + let content_rect = egui::Rect::from_center_size( + available.center(), + egui::vec2(content_width, content_height), + ); + + ui.allocate_ui_at_rect(content_rect, |ui| { + ui.vertical_centered(|ui| { + // Title + ui.heading(egui::RichText::new("Welcome to Lightningbeam!") + .size(42.0) + .strong()); + + ui.add_space(50.0); + + // Main content area - two columns side by side + let recent_files = self.config.get_recent_files(); + + // Use columns for proper two-column layout + ui.columns(2, |columns| { + // Left column: Recent projects (stacked vertically) + columns[0].vertical(|ui| { + // Reopen last session section + ui.label(egui::RichText::new("Reopen last session") + .size(18.0) + .strong()); + ui.add_space(16.0); + + if let Some(last_file) = recent_files.first() { + let file_name = last_file.file_name() + .map(|s| s.to_string_lossy().to_string()) + .unwrap_or_else(|| "Unknown".to_string()); + if self.render_file_item(ui, &file_name, left_width) { + self.load_from_file(last_file.clone()); + self.app_mode = AppMode::Editor; + } + } else { + ui.label(egui::RichText::new("No recent session") + .color(egui::Color32::from_gray(120))); + } + + ui.add_space(32.0); + + // Recent projects section + ui.label(egui::RichText::new("Recent projects") + .size(18.0) + .strong()); + ui.add_space(16.0); + + if recent_files.len() > 1 { + for file in recent_files.iter().skip(1).take(5) { + let file_name = file.file_name() + .map(|s| s.to_string_lossy().to_string()) + .unwrap_or_else(|| "Unknown".to_string()); + if self.render_file_item(ui, &file_name, left_width) { + self.load_from_file(file.clone()); + self.app_mode = AppMode::Editor; + } + ui.add_space(8.0); + } + } else { + ui.label(egui::RichText::new("No other recent projects") + .color(egui::Color32::from_gray(120))); + } + }); + + // Right column: Create new project + columns[1].vertical_centered(|ui| { + ui.label(egui::RichText::new("Create a new project") + .size(18.0) + .strong()); + ui.add_space(24.0); + + // Focus cards in a horizontal row + ui.horizontal(|ui| { + // Animation + let (rect, response) = ui.allocate_exact_size( + egui::vec2(card_size, card_size + 40.0), + egui::Sense::click(), + ); + self.render_focus_card_with_icon(ui, rect, response.hovered(), "Animation", FocusIcon::Animation); + if response.clicked() { + self.create_new_project_with_focus(0); + } + + ui.add_space(card_spacing); + + // Music + let (rect, response) = ui.allocate_exact_size( + egui::vec2(card_size, card_size + 40.0), + egui::Sense::click(), + ); + self.render_focus_card_with_icon(ui, rect, response.hovered(), "Music", FocusIcon::Music); + if response.clicked() { + self.create_new_project_with_focus(2); + } + + ui.add_space(card_spacing); + + // Video editing + let (rect, response) = ui.allocate_exact_size( + egui::vec2(card_size, card_size + 40.0), + egui::Sense::click(), + ); + self.render_focus_card_with_icon(ui, rect, response.hovered(), "Video editing", FocusIcon::Video); + if response.clicked() { + self.create_new_project_with_focus(1); + } + }); + }); + }); + }); + }); + }); + } + + /// Render a clickable file item (for recent projects list) + fn render_file_item(&self, ui: &mut egui::Ui, name: &str, width: f32) -> bool { + let height = 36.0; + let (rect, response) = ui.allocate_exact_size(egui::vec2(width, height), egui::Sense::click()); + + let bg_color = if response.hovered() { + egui::Color32::from_rgb(70, 75, 85) + } else { + egui::Color32::from_rgb(55, 60, 70) + }; + + let painter = ui.painter(); + painter.rect_filled(rect, 4.0, bg_color); + + painter.text( + rect.left_center() + egui::vec2(12.0, 0.0), + egui::Align2::LEFT_CENTER, + name, + egui::FontId::proportional(14.0), + egui::Color32::from_gray(220), + ); + + response.clicked() + } + + /// Render a focus card with icon for project creation + fn render_focus_card_with_icon(&mut self, ui: &egui::Ui, rect: egui::Rect, hovered: bool, title: &str, icon: FocusIcon) { + let bg_color = if hovered { + egui::Color32::from_rgb(55, 60, 70) + } else { + egui::Color32::from_rgb(45, 50, 58) + }; + + let border_color = egui::Color32::from_rgb(80, 85, 95); + + let painter = ui.painter(); + + // Card background + painter.rect_filled(rect, 8.0, bg_color); + painter.rect_stroke(rect, 8.0, egui::Stroke::new(1.5, border_color), egui::StrokeKind::Inside); + + // Icon area - render SVG texture + let icon_color = egui::Color32::from_gray(200); + let icon_center = rect.center_top() + egui::vec2(0.0, 50.0); + let icon_display_size = 60.0; + + // Get or load the SVG icon texture + let ctx = ui.ctx().clone(); + if let Some(texture) = self.focus_icon_cache.get_or_load(icon, icon_color, &ctx) { + let texture_size = texture.size_vec2(); + let scale = icon_display_size / texture_size.x.max(texture_size.y); + let scaled_size = texture_size * scale; + + let icon_rect = egui::Rect::from_center_size(icon_center, scaled_size); + painter.image( + texture.id(), + icon_rect, + egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)), + egui::Color32::WHITE, + ); + } + + // Title at bottom + painter.text( + rect.center_bottom() - egui::vec2(0.0, 20.0), + egui::Align2::CENTER_CENTER, + title, + egui::FontId::proportional(14.0), + egui::Color32::WHITE, + ); + } + + /// Render a focus card for project creation (legacy, kept for compatibility) + #[allow(dead_code)] + fn render_focus_card(&self, ui: &mut egui::Ui, rect: egui::Rect, hovered: bool, title: &str, description: &str, _layout_index: usize) { + let bg_color = if hovered { + egui::Color32::from_rgb(60, 70, 90) + } else { + egui::Color32::from_rgb(45, 50, 60) + }; + + let painter = ui.painter(); + + // Background with rounded corners + painter.rect_filled(rect, 8.0, bg_color); + + // Border + if hovered { + painter.rect_stroke( + rect, + 8.0, + egui::Stroke::new(2.0, egui::Color32::from_rgb(100, 140, 200)), + egui::StrokeKind::Inside, + ); + } + + // Title + painter.text( + rect.center_top() + egui::vec2(0.0, 40.0), + egui::Align2::CENTER_CENTER, + title, + egui::FontId::proportional(18.0), + egui::Color32::WHITE, + ); + + // Description + painter.text( + rect.center_top() + egui::vec2(0.0, 70.0), + egui::Align2::CENTER_CENTER, + description, + egui::FontId::proportional(12.0), + egui::Color32::from_gray(180), + ); + } + + /// Create a new project with the specified focus/layout + fn create_new_project_with_focus(&mut self, layout_index: usize) { + use lightningbeam_core::layer::{AnyLayer, AudioLayer, VectorLayer, VideoLayer}; + + // Create a new blank document + let mut document = lightningbeam_core::document::Document::with_size( + "Untitled", + self.config.file_width as f64, + self.config.file_height as f64, + ) + .with_duration(60.0) // 1 minute default + .with_framerate(self.config.framerate as f64); + + // Add default layer based on focus type + // Layout indices: 0 = Animation, 1 = Video editing, 2 = Music + let layer_id = match layout_index { + 0 => { + // Animation focus -> VectorLayer + let layer = VectorLayer::new("Layer 1"); + document.root.add_child(AnyLayer::Vector(layer)) + } + 1 => { + // Video editing focus -> VideoLayer + let layer = VideoLayer::new("Video 1"); + document.root.add_child(AnyLayer::Video(layer)) + } + 2 => { + // Music focus -> MIDI AudioLayer + let layer = AudioLayer::new_midi("MIDI 1"); + document.root.add_child(AnyLayer::Audio(layer)) + } + _ => { + // Fallback to VectorLayer + let layer = VectorLayer::new("Layer 1"); + document.root.add_child(AnyLayer::Vector(layer)) + } + }; + + // Reset action executor with new document + self.action_executor = lightningbeam_core::action::ActionExecutor::new(document); + + // Apply the layout + if layout_index < self.layouts.len() { + self.current_layout_index = layout_index; + self.current_layout = self.layouts[layout_index].layout.clone(); + self.pane_instances.clear(); // Clear old pane instances + } + + // Clear file path (new unsaved document) + self.current_file_path = None; + + // Reset selection and set active layer to the newly created one + self.selection = lightningbeam_core::selection::Selection::new(); + self.active_layer_id = Some(layer_id); + + // For Music focus, sync the MIDI layer with daw-backend + if layout_index == 2 { + self.sync_audio_layers_to_backend(); + } + + // Switch to editor mode + self.app_mode = AppMode::Editor; + } + /// Synchronize all existing MIDI layers in the document with daw-backend tracks /// /// This function should be called: @@ -2660,6 +3101,12 @@ impl eframe::App for EditorApp { } } + // Handle pending auto-reopen (first frame only) + if let Some(path) = self.pending_auto_reopen.take() { + self.load_from_file(path); + // Will switch to editor mode when file finishes loading + } + // Fetch missing waveforms on-demand (for lazy loading after project load) // Collect pool indices that need waveforms let missing_waveforms: Vec = self.action_executor.document() @@ -2823,6 +3270,8 @@ impl eframe::App for EditorApp { // Apply loaded project data if available if let Some((loaded_project, path)) = loaded_project_data { self.apply_loaded_project(loaded_project, path); + // Switch to editor mode after loading a project + self.app_mode = AppMode::Editor; } // Update recent files menu if needed @@ -2886,6 +3335,188 @@ impl eframe::App for EditorApp { ctx.request_repaint(); } + // Recording events + AudioEvent::RecordingStarted(track_id, backend_clip_id) => { + println!("🎤 Recording started on track {:?}, backend_clip_id={}", track_id, backend_clip_id); + + // Create clip in document and add instance to layer + if let Some(layer_id) = self.recording_layer_id { + use lightningbeam_core::clip::{AudioClip, ClipInstance}; + + // Create a recording-in-progress clip (no pool index yet) + let clip = AudioClip::new_recording("Recording..."); + let doc_clip_id = self.action_executor.document_mut().add_audio_clip(clip); + + // Create clip instance on the layer + let clip_instance = ClipInstance::new(doc_clip_id) + .with_timeline_start(self.recording_start_time); + + // Add instance to layer + if let Some(layer) = self.action_executor.document_mut().root.children.iter_mut() + .find(|l| l.id() == layer_id) + { + if let lightningbeam_core::layer::AnyLayer::Audio(audio_layer) = layer { + audio_layer.clip_instances.push(clip_instance); + println!("✅ Created recording clip instance on layer {}", layer_id); + } + } + + // Store mapping for later updates + self.recording_clips.insert(layer_id, backend_clip_id); + } + ctx.request_repaint(); + } + AudioEvent::RecordingProgress(_clip_id, duration) => { + // Update clip duration as recording progresses + if let Some(layer_id) = self.recording_layer_id { + // First, find the clip_id from the layer (read-only borrow) + let clip_id = { + let document = self.action_executor.document(); + document.root.children.iter() + .find(|l| l.id() == layer_id) + .and_then(|layer| { + if let lightningbeam_core::layer::AnyLayer::Audio(audio_layer) = layer { + audio_layer.clip_instances.last().map(|i| i.clip_id) + } else { + None + } + }) + }; + + // Then update the clip duration (mutable borrow) + if let Some(clip_id) = clip_id { + if let Some(clip) = self.action_executor.document_mut().audio_clips.get_mut(&clip_id) { + if clip.is_recording() { + clip.duration = duration; + } + } + } + } + ctx.request_repaint(); + } + AudioEvent::RecordingStopped(_backend_clip_id, pool_index, waveform) => { + println!("🎤 Recording stopped: pool_index={}, {} peaks", pool_index, waveform.len()); + + // Store waveform for the recorded clip + if !waveform.is_empty() { + self.waveform_cache.insert(pool_index, waveform.clone()); + self.audio_pools_with_new_waveforms.insert(pool_index); + } + + // Invalidate waveform image cache so tiles are regenerated + self.waveform_image_cache.invalidate_audio(pool_index); + + // Get accurate duration from backend (not calculated from waveform peaks) + let duration = if let Some(ref controller_arc) = self.audio_controller { + let mut controller = controller_arc.lock().unwrap(); + match controller.get_pool_file_info(pool_index) { + Ok((dur, _, _)) => { + println!("✅ Got duration from backend: {:.2}s", dur); + self.audio_duration_cache.insert(pool_index, dur); + dur + } + Err(e) => { + eprintln!("⚠️ Failed to get pool file info: {}", e); + 0.0 + } + } + } else { + 0.0 + }; + + // Finalize the recording clip with real pool_index and duration + // and sync to backend for playback + if let Some(layer_id) = self.recording_layer_id { + // First, find the clip instance and clip id + let (clip_id, instance_id, timeline_start, trim_start) = { + let document = self.action_executor.document(); + document.root.children.iter() + .find(|l| l.id() == layer_id) + .and_then(|layer| { + if let lightningbeam_core::layer::AnyLayer::Audio(audio_layer) = layer { + audio_layer.clip_instances.last().map(|instance| { + (instance.clip_id, instance.id, instance.timeline_start, instance.trim_start) + }) + } else { + None + } + }) + .unwrap_or((uuid::Uuid::nil(), uuid::Uuid::nil(), 0.0, 0.0)) + }; + + if !clip_id.is_nil() { + // Finalize the clip (update pool_index and duration) + if let Some(clip) = self.action_executor.document_mut().audio_clips.get_mut(&clip_id) { + if clip.finalize_recording(pool_index, duration) { + clip.name = format!("Recording {}", pool_index); + println!("✅ Finalized recording clip: pool={}, duration={:.2}s", pool_index, duration); + } + } + + // Sync the clip instance to backend for playback + if let Some(backend_track_id) = self.layer_to_track_map.get(&layer_id) { + if let Some(ref controller_arc) = self.audio_controller { + let mut controller = controller_arc.lock().unwrap(); + use daw_backend::command::{Query, QueryResponse}; + + let query = Query::AddAudioClipSync( + *backend_track_id, + pool_index, + timeline_start, + duration, + trim_start + ); + + match controller.send_query(query) { + Ok(QueryResponse::AudioClipInstanceAdded(Ok(backend_instance_id))) => { + // Store the mapping + self.clip_instance_to_backend_map.insert( + instance_id, + lightningbeam_core::action::BackendClipInstanceId::Audio(backend_instance_id) + ); + println!("✅ Synced recording to backend: instance_id={}", backend_instance_id); + } + Ok(QueryResponse::AudioClipInstanceAdded(Err(e))) => { + eprintln!("❌ Failed to sync recording to backend: {}", e); + } + Ok(_) => { + eprintln!("❌ Unexpected query response when syncing recording"); + } + Err(e) => { + eprintln!("❌ Failed to send query to backend: {}", e); + } + } + } + } + } + } + + // Clear recording state + self.is_recording = false; + self.recording_clips.clear(); + self.recording_layer_id = None; + ctx.request_repaint(); + } + AudioEvent::RecordingError(message) => { + eprintln!("❌ Recording error: {}", message); + self.is_recording = false; + self.recording_clips.clear(); + self.recording_layer_id = None; + ctx.request_repaint(); + } + AudioEvent::MidiRecordingProgress(_track_id, _clip_id, duration, _notes) => { + println!("🎹 MIDI recording progress: {:.2}s", duration); + ctx.request_repaint(); + } + AudioEvent::MidiRecordingStopped(track_id, clip_id, note_count) => { + println!("🎹 MIDI recording stopped: track={:?}, clip_id={}, {} notes", + track_id, clip_id, note_count); + // Clear recording state + self.is_recording = false; + self.recording_clips.clear(); + self.recording_layer_id = None; + ctx.request_repaint(); + } _ => {} // Ignore other events for now } } @@ -3126,7 +3757,13 @@ impl eframe::App for EditorApp { } }); - // Main pane area + // Render start screen or editor based on app mode + if self.app_mode == AppMode::StartScreen { + self.render_start_screen(ctx); + return; // Skip editor rendering + } + + // Main pane area (editor mode) let mut layout_action: Option = None; egui::CentralPanel::default().show(ctx, |ui| { let available_rect = ui.available_rect_before_wrap(); @@ -3173,6 +3810,10 @@ impl eframe::App for EditorApp { video_manager: &self.video_manager, playback_time: &mut self.playback_time, is_playing: &mut self.is_playing, + is_recording: &mut self.is_recording, + recording_clips: &mut self.recording_clips, + recording_start_time: &mut self.recording_start_time, + recording_layer_id: &mut self.recording_layer_id, dragging_asset: &mut self.dragging_asset, stroke_width: &mut self.stroke_width, fill_enabled: &mut self.fill_enabled, @@ -3396,6 +4037,11 @@ struct RenderContext<'a> { video_manager: &'a std::sync::Arc>, playback_time: &'a mut f64, is_playing: &'a mut bool, + // Recording state + is_recording: &'a mut bool, + recording_clips: &'a mut HashMap, + recording_start_time: &'a mut f64, + recording_layer_id: &'a mut Option, dragging_asset: &'a mut Option, // Tool-specific options for infopanel stroke_width: &'a mut f64, @@ -3884,6 +4530,10 @@ fn render_pane( layer_to_track_map: ctx.layer_to_track_map, playback_time: ctx.playback_time, is_playing: ctx.is_playing, + is_recording: ctx.is_recording, + recording_clips: ctx.recording_clips, + recording_start_time: ctx.recording_start_time, + recording_layer_id: ctx.recording_layer_id, dragging_asset: ctx.dragging_asset, stroke_width: ctx.stroke_width, fill_enabled: ctx.fill_enabled, @@ -3948,6 +4598,10 @@ fn render_pane( layer_to_track_map: ctx.layer_to_track_map, playback_time: ctx.playback_time, is_playing: ctx.is_playing, + is_recording: ctx.is_recording, + recording_clips: ctx.recording_clips, + recording_start_time: ctx.recording_start_time, + recording_layer_id: ctx.recording_layer_id, dragging_asset: ctx.dragging_asset, stroke_width: ctx.stroke_width, fill_enabled: ctx.fill_enabled, diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs index de91e5f..d92a572 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs @@ -948,6 +948,10 @@ impl AssetLibraryPane { let (extra_info, drag_clip_type) = match &clip.clip_type { AudioClipType::Sampled { .. } => ("Sampled".to_string(), DragClipType::AudioSampled), AudioClipType::Midi { .. } => ("MIDI".to_string(), DragClipType::AudioMidi), + AudioClipType::Recording => { + // Skip recording-in-progress clips from asset library + continue; + } }; assets.push(AssetEntry { @@ -1148,6 +1152,10 @@ impl AssetLibraryPane { AudioClipType::Midi { .. } => { ("MIDI".to_string(), DragClipType::AudioMidi) } + AudioClipType::Recording => { + // Skip recording-in-progress clips + continue; + } }; items.push(LibraryItem::Asset(AssetEntry { @@ -1823,6 +1831,10 @@ impl AssetLibraryPane { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) } } + AudioClipType::Recording => { + // Recording in progress - show placeholder + Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) + } } } else { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) @@ -2384,6 +2396,9 @@ impl AssetLibraryPane { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) } } + AudioClipType::Recording => { + Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) + } } } else { None @@ -2526,6 +2541,9 @@ impl AssetLibraryPane { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) } } + AudioClipType::Recording => { + Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) + } } } else { None @@ -2893,6 +2911,9 @@ impl AssetLibraryPane { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) } } + AudioClipType::Recording => { + Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) + } } } else { Some(generate_placeholder_thumbnail(AssetCategory::Audio, 200)) diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs index 26e4fde..e7127a6 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs @@ -171,6 +171,11 @@ pub struct SharedPaneState<'a> { /// Global playback state pub playback_time: &'a mut f64, // Current playback position in seconds pub is_playing: &'a mut bool, // Whether playback is currently active + /// Recording state + pub is_recording: &'a mut bool, // Whether recording is currently active + pub recording_clips: &'a mut std::collections::HashMap, // layer_id -> clip_id + pub recording_start_time: &'a mut f64, // Playback time when recording started + pub recording_layer_id: &'a mut Option, // Layer being recorded to /// Asset being dragged from Asset Library (for cross-pane drag-and-drop) pub dragging_asset: &'a mut Option, // Tool-specific options for infopanel diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs index 2bd7c3e..d31863d 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs @@ -494,10 +494,6 @@ impl NodeGraphPane { } } - if checked_count > 0 || connection_only_count > 0 || non_float_count > 0 { - eprintln!("[DEBUG] Parameter check: {} float params checked, {} connection-only, {} non-float", - checked_count, connection_only_count, non_float_count); - } } fn draw_dot_grid_background( diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs index 7b1af58..1fc4765 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs @@ -136,6 +136,119 @@ impl TimelinePane { } } + /// Toggle recording on/off + /// In Auto mode, records to the active audio layer + fn toggle_recording(&mut self, shared: &mut SharedPaneState) { + if *shared.is_recording { + // Stop recording + self.stop_recording(shared); + } else { + // Start recording on active layer + self.start_recording(shared); + } + } + + /// Start recording on the active audio layer + fn start_recording(&mut self, shared: &mut SharedPaneState) { + let Some(active_layer_id) = *shared.active_layer_id else { + println!("⚠️ No active layer selected for recording"); + return; + }; + + // Get the active layer and check if it's an audio layer + let document = shared.action_executor.document(); + let Some(layer) = document.root.children.iter().find(|l| l.id() == active_layer_id) else { + println!("⚠️ Active layer not found in document"); + return; + }; + + let AnyLayer::Audio(audio_layer) = layer else { + println!("⚠️ Active layer is not an audio layer - cannot record"); + return; + }; + + // Get the backend track ID for this layer + let Some(&track_id) = shared.layer_to_track_map.get(&active_layer_id) else { + println!("⚠️ No backend track mapped for layer {}", active_layer_id); + return; + }; + + let start_time = *shared.playback_time; + + // Start recording based on layer type + if let Some(controller_arc) = shared.audio_controller { + let mut controller = controller_arc.lock().unwrap(); + + match audio_layer.audio_layer_type { + AudioLayerType::Midi => { + // For MIDI recording, we need to create a clip first + // The backend will emit MidiRecordingStarted with the clip_id + let clip_id = controller.create_midi_clip(track_id, start_time, 4.0); + controller.start_midi_recording(track_id, clip_id, start_time); + shared.recording_clips.insert(active_layer_id, clip_id); + println!("🎹 Started MIDI recording on track {:?} at {:.2}s, clip_id={}", + track_id, start_time, clip_id); + } + AudioLayerType::Sampled => { + // For audio recording, backend creates the clip + controller.start_recording(track_id, start_time); + println!("🎤 Started audio recording on track {:?} at {:.2}s", track_id, start_time); + } + } + + // Auto-start playback if not already playing + if !*shared.is_playing { + controller.play(); + *shared.is_playing = true; + println!("▶ Auto-started playback for recording"); + } + + // Store recording state for clip creation when RecordingStarted event arrives + *shared.is_recording = true; + *shared.recording_start_time = start_time; + *shared.recording_layer_id = Some(active_layer_id); + } else { + println!("⚠️ No audio controller available"); + } + } + + /// Stop the current recording + fn stop_recording(&mut self, shared: &mut SharedPaneState) { + // Determine if this is MIDI or audio recording by checking the layer type + let is_midi_recording = if let Some(layer_id) = *shared.recording_layer_id { + shared.action_executor.document().root.children.iter() + .find(|l| l.id() == layer_id) + .map(|layer| { + if let lightningbeam_core::layer::AnyLayer::Audio(audio_layer) = layer { + matches!(audio_layer.audio_layer_type, lightningbeam_core::layer::AudioLayerType::Midi) + } else { + false + } + }) + .unwrap_or(false) + } else { + false + }; + + if let Some(controller_arc) = shared.audio_controller { + let mut controller = controller_arc.lock().unwrap(); + + if is_midi_recording { + controller.stop_midi_recording(); + println!("🎹 Stopped MIDI recording"); + } else { + controller.stop_recording(); + println!("🎤 Stopped audio recording"); + } + } + + // Note: Don't clear recording_layer_id here! + // The RecordingStopped/MidiRecordingStopped event handler in main.rs + // needs it to finalize the clip. It will clear the state after processing. + // Only clear is_recording to update UI state immediately. + *shared.is_recording = false; + } + /// Detect which clip is under the pointer and what type of drag would occur /// /// Returns (drag_type, clip_id) if pointer is over a clip, None otherwise @@ -1434,6 +1547,10 @@ impl TimelinePane { ); } } + // Recording in progress: no visualization yet + lightningbeam_core::clip::AudioClipType::Recording => { + // Could show a pulsing "Recording..." indicator here + } } } } @@ -2061,6 +2178,12 @@ impl PaneRenderer for TimelinePane { // Play/Pause toggle let play_pause_text = if *shared.is_playing { "⏸" } else { "▶" }; if ui.add_sized(button_size, egui::Button::new(play_pause_text)).clicked() { + // If pausing while recording, stop recording first + if *shared.is_playing && *shared.is_recording { + self.stop_recording(shared); + println!("⏹ Stopped recording (playback paused)"); + } + *shared.is_playing = !*shared.is_playing; println!("🔘 Play/Pause button clicked! is_playing = {}", *shared.is_playing); @@ -2096,6 +2219,31 @@ impl PaneRenderer for TimelinePane { controller.seek(self.duration); } } + + // Small separator before record button + ui.add_space(8.0); + + // Record button - red circle, pulsing when recording + let record_color = if *shared.is_recording { + // Pulsing red when recording (vary alpha based on time) + let pulse = (ui.ctx().input(|i| i.time) * 2.0).sin() * 0.3 + 0.7; + egui::Color32::from_rgba_unmultiplied(220, 50, 50, (pulse * 255.0) as u8) + } else { + egui::Color32::from_rgb(180, 60, 60) + }; + + let record_button = egui::Button::new( + egui::RichText::new("⏺").color(record_color).size(16.0) + ); + + if ui.add_sized(button_size, record_button).clicked() { + self.toggle_recording(shared); + } + + // Request repaint while recording for pulse animation + if *shared.is_recording { + ui.ctx().request_repaint(); + } }); });