mirror of
https://github.com/storytold/filmcraft.git
synced 2026-11-02 18:09:21 +00:00
Integration: #2438 port the lib.rs hunks to app.rs and app/frame.rs
This commit is contained in:
@@ -270,6 +270,9 @@ impl FilmcraftApp {
|
||||
ctx.request_repaint_after(std::time::Duration::from_secs(1));
|
||||
}
|
||||
self.sync_pool();
|
||||
// a frame server rebuilt by sync_pool (another project opened) gets its wake-up now: no
|
||||
// poll asks for the next frame, so its finished frames would wait for the mouse (#2438 review)
|
||||
self.frames.set_context(ctx);
|
||||
updates_ui::tick(self, ctx);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
self.tick_media_refresh(ctx, now);
|
||||
@@ -395,7 +398,10 @@ impl FilmcraftApp {
|
||||
if !self.synthetic.is_empty() || self.synthetic_pending_step.is_some() {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
if self.frames.queue_len() > 0 {
|
||||
// Only the web renders queued frames in the UI pass (`pump`): poll for them there. Native
|
||||
// workers wake the UI when a frame is done, so a backlog (thumbnails after launch, slow
|
||||
// effects) doesn't run empty passes at 60 Hz beside them (#1142, #1606).
|
||||
if cfg!(target_arch = "wasm32") && self.frames.queue_len() > 0 {
|
||||
ctx.request_repaint_after(std::time::Duration::from_millis(16));
|
||||
}
|
||||
if !ctx.will_discard() {
|
||||
|
||||
@@ -25,7 +25,9 @@ impl FilmcraftApp {
|
||||
let focused = self.native_window_focused.unwrap_or(false);
|
||||
let was_focused: bool = ctx.data(|d| d.get_temp(focus_key)).unwrap_or(focused);
|
||||
ctx.data_mut(|d| d.insert_temp(focus_key, focused));
|
||||
if !on || filmcraft_engine::media_watch::media_files(&self.session.project, &self.session.media).is_empty() {
|
||||
// Listing the media files resolves every item's path: only when a scan is due (it ran on
|
||||
// every frame, #1142); between scans a cheap look for file media decides the next wake-up.
|
||||
if !on || !has_file_media(&self.session.project) {
|
||||
return;
|
||||
}
|
||||
let last: f64 = ctx.data(|d| d.get_temp(last_key)).unwrap_or(f64::NEG_INFINITY);
|
||||
@@ -237,3 +239,56 @@ impl FilmcraftApp {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the project has online file media (what the growing-files refresh watches). It can
|
||||
/// say yes for a file `media_files` leaves out (a stored path the pool won't follow): then a scan
|
||||
/// just finds nothing to watch.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn has_file_media(p: &filmcraft_project::Project) -> bool {
|
||||
use filmcraft_project::{ItemKind, MediaRef};
|
||||
p.items.values().any(|i| matches!(&i.kind, ItemKind::Media(m) if !m.offline && matches!(m.media, MediaRef::File { .. })))
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_arch = "wasm32")))]
|
||||
mod media_watch_tests {
|
||||
use filmcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
/// The per-frame check for file media agrees with the media file list it stands in for: the
|
||||
/// demo's generated media has no files, an imported file does, a made-offline one doesn't.
|
||||
#[test]
|
||||
fn has_file_media_matches_the_media_file_list() {
|
||||
let mut s = Session::default();
|
||||
s.execute("file.openDemoProject", json!({})).unwrap();
|
||||
let agrees = |s: &Session| super::has_file_media(&s.project) == !filmcraft_engine::media_watch::media_files(&s.project, &s.media).is_empty();
|
||||
assert!(!super::has_file_media(&s.project) && agrees(&s));
|
||||
let dir = std::env::temp_dir().join(format!("fc-has-file-media-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let wav = dir.join("a.wav");
|
||||
let mut b = b"RIFF".to_vec();
|
||||
b.extend_from_slice(&(36u32 + 16).to_le_bytes());
|
||||
b.extend_from_slice(b"WAVEfmt ");
|
||||
for v in [
|
||||
16u32.to_le_bytes().to_vec(),
|
||||
1u16.to_le_bytes().to_vec(),
|
||||
1u16.to_le_bytes().to_vec(),
|
||||
8000u32.to_le_bytes().to_vec(),
|
||||
16000u32.to_le_bytes().to_vec(),
|
||||
2u16.to_le_bytes().to_vec(),
|
||||
16u16.to_le_bytes().to_vec(),
|
||||
] {
|
||||
b.extend_from_slice(&v);
|
||||
}
|
||||
b.extend_from_slice(b"data");
|
||||
b.extend_from_slice(&16u32.to_le_bytes());
|
||||
b.extend_from_slice(&[0u8; 16]);
|
||||
std::fs::write(&wav, b).unwrap();
|
||||
let r = s.execute("file.import", json!({"paths": [wav.to_string_lossy()]})).unwrap();
|
||||
assert!(super::has_file_media(&s.project) && agrees(&s), "{r}");
|
||||
let item = r["items"][0].as_u64().unwrap();
|
||||
s.execute("project.select", json!({"items": [item]})).unwrap();
|
||||
s.execute("media.makeOffline", json!({"items": [item]})).unwrap();
|
||||
assert!(!super::has_file_media(&s.project) && agrees(&s), "a made-offline file is not watched");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user