From 4f0f5cbba6b955bdeda1a1580d7e56a8968b18fc Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Fri, 11 Sep 2026 16:38:44 +0800 Subject: [PATCH] workspace: zero compiler warnings across all targets 254 warnings (320 counting replayed-cache re-emitters) cleaned: unused mut/imports/variables, irrefutable if-lets and unreachable patterns, dead code removed or annotated #[allow(dead_code)] with the reason (C++ parity value sets, cfg(test) helpers, public API reservations), drop(&ref) no-ops removed, fn-pointer identity via std::ptr::fn_addr_eq, the test-stubs feature declared in oak-node's manifest, missing docs filled. Every unused-Result site was judged individually: meaningful errors propagate, intentional ignores are let _ = with a note. Two pre-existing latent bugs are documented in place, behavior preserved: app.rs's timeline-tool observer and dialogs.rs's format subscription both drop the returned Subscription immediately, so they never fire. --- crates/oak-app/src/actions.rs | 3 +- crates/oak-app/src/app.rs | 32 +-- crates/oak-app/src/dialogs.rs | 185 ++++++++---------- .../oak-app/src/oakui/component/text_input.rs | 2 +- crates/oak-app/src/oakui/graphops.rs | 4 +- crates/oak-app/src/oakui/mock.rs | 3 +- crates/oak-app/src/oakui/multicam.rs | 10 +- crates/oak-app/src/oakui/real.rs | 5 +- crates/oak-app/src/oakui/renderops.rs | 2 +- crates/oak-app/src/panels/effect_library.rs | 2 +- crates/oak-app/src/panels/multicam.rs | 2 +- crates/oak-app/src/panels/ofx_params.rs | 63 +++--- crates/oak-app/src/panels/project_explorer.rs | 2 +- crates/oak-audio/src/config.rs | 2 - crates/oak-audio/src/manager.rs | 10 +- crates/oak-audio/src/outputdevice.rs | 4 +- crates/oak-audio/tests/common/mod.rs | 5 + crates/oak-audio/tests/processor_test.rs | 10 +- crates/oak-codec/src/ffmpeg.rs | 26 +-- crates/oak-codec/src/proxymanager.rs | 3 + crates/oak-codec/src/task.rs | 6 + crates/oak-core/src/backend.rs | 4 +- crates/oak-core/src/color.rs | 12 +- crates/oak-core/src/commandlineparser.rs | 6 +- crates/oak-core/src/debug.rs | 10 - crates/oak-core/src/filefunctions.rs | 4 + crates/oak-core/src/handle.rs | 16 +- crates/oak-core/src/subtitleparams.rs | 14 +- crates/oak-core/src/xmlutils.rs | 22 +-- crates/oak-node/Cargo.toml | 6 + crates/oak-node/src/graph.rs | 2 - crates/oak-node/src/node.rs | 2 +- crates/oak-node/src/nodes/chromakey.rs | 8 - .../oak-node/src/nodes/colordifferencekey.rs | 8 - .../src/nodes/cornerpindistortnode.rs | 5 + crates/oak-node/src/nodes/despill.rs | 8 - crates/oak-node/src/nodes/dirblur.rs | 4 +- crates/oak-node/src/nodes/displaytransform.rs | 4 + crates/oak-node/src/nodes/mask.rs | 19 -- crates/oak-node/src/nodes/math.rs | 4 +- crates/oak-node/src/nodes/mathbase.rs | 6 +- crates/oak-node/src/nodes/merge.rs | 8 - crates/oak-node/src/nodes/multicamnode.rs | 1 - .../src/nodes/ociogradingtransformlinear.rs | 4 +- .../src/nodes/ociogradingtransformlog.rs | 3 +- crates/oak-node/src/nodes/ociolut.rs | 6 + crates/oak-node/src/nodes/opacity.rs | 19 +- crates/oak-node/src/nodes/premult.rs | 5 +- crates/oak-node/src/nodes/shapenodebase.rs | 3 + crates/oak-node/src/nodes/textbackend.rs | 6 +- crates/oak-node/src/nodes/textv1.rs | 3 + crates/oak-node/src/nodes/textv2.rs | 6 + crates/oak-node/src/nodes/textv3.rs | 7 + crates/oak-node/src/nodes/threewaycolor.rs | 8 - crates/oak-node/src/nodes/tiledistortnode.rs | 4 + .../src/nodes/transformdistortnode.rs | 10 + crates/oak-node/src/nodes/trigonometry.rs | 2 +- crates/oak-node/src/nodes/unpremult.rs | 5 +- crates/oak-node/src/nodes/whitebalance.rs | 6 - crates/oak-node/src/ops.rs | 23 +-- crates/oak-node/src/project.rs | 6 +- crates/oak-node/src/sequence.rs | 6 +- crates/oak-node/src/serializer.rs | 5 +- crates/oak-node/src/value.rs | 14 +- crates/oak-node/tests/engine_units_test.rs | 2 +- crates/oak-node/tests/graph_test.rs | 4 +- crates/oak-node/tests/phase2_units_test.rs | 4 +- crates/oak-node/tests/serializer_test.rs | 2 +- crates/oak-node/tests/traverser_test.rs | 2 +- crates/oak-plugin/src/host.rs | 4 - crates/oak-plugin/src/node_factory.rs | 2 +- crates/oak-plugin/src/param.rs | 2 +- crates/oak-plugin/src/suites/image_effect.rs | 2 +- crates/oak-plugin/src/suites/interact.rs | 4 - crates/oak-plugin/src/suites/memory.rs | 11 -- crates/oak-plugin/src/suites/mod.rs | 3 - crates/oak-plugin/src/suites/multithread.rs | 1 - crates/oak-plugin/src/suites/param.rs | 4 +- crates/oak-plugin/src/suites/parametric.rs | 8 +- crates/oak-plugin/src/suites/property.rs | 2 +- crates/oak-plugin/tests/common/mod.rs | 4 + crates/oak-plugin/tests/gl_render_test.rs | 6 +- crates/oak-plugin/tests/property_test.rs | 2 +- crates/oak-plugin/tests/suites_test.rs | 10 +- crates/oak-render/src/autocacher.rs | 10 +- crates/oak-render/src/eval.rs | 13 +- crates/oak-render/src/procpool.rs | 14 +- crates/oak-render/src/scheduler.rs | 2 - crates/oak-render/src/textengine.rs | 2 +- crates/oak-render/tests/common/mod.rs | 7 +- crates/oak-render/tests/copier_test.rs | 5 +- crates/oak-render/tests/pipeline_test.rs | 2 +- crates/oak-render/tests/ticket_worker_test.rs | 4 +- crates/oak-task/src/render.rs | 6 +- crates/oak-timeline/src/undogeneral.rs | 4 +- crates/oak-timeline/tests/marker_test.rs | 1 - crates/oak-undo/tests/undo_safe_test.rs | 8 +- crates/oak-worker/src/worker.rs | 2 +- 98 files changed, 409 insertions(+), 455 deletions(-) diff --git a/crates/oak-app/src/actions.rs b/crates/oak-app/src/actions.rs index 8decda43d..732cd2330 100644 --- a/crates/oak-app/src/actions.rs +++ b/crates/oak-app/src/actions.rs @@ -813,7 +813,7 @@ impl Tool { } /// Extension trait mapping the timeline widget's tool back to the app tool -/// (for the toolbar highlight). Unmodeled tools fall back to the pointer. +/// (for the toolbar highlight). pub trait TimelineToolExt { fn app_tool(self) -> Tool; } @@ -829,7 +829,6 @@ impl TimelineToolExt for gpui::timeline::TimelineTool { gpui::timeline::TimelineTool::Slip => Tool::Slip, gpui::timeline::TimelineTool::Slide => Tool::Slide, gpui::timeline::TimelineTool::Zoom => Tool::Zoom, - _ => Tool::Pointer, } } } diff --git a/crates/oak-app/src/app.rs b/crates/oak-app/src/app.rs index 3ba2aa2d8..7e93c7773 100644 --- a/crates/oak-app/src/app.rs +++ b/crates/oak-app/src/app.rs @@ -78,6 +78,10 @@ use crate::panels::timeline::{FootageDropNeedsSequence, TimelinePanel}; // registry is the single source; these keep the test call sites readable). #[cfg(test)] pub(crate) mod menu_ids { + // Test-only menu-id aliases (the registry is the single source of + // truth); not every alias is referenced by the suite. + #![allow(dead_code)] + use crate::actions::ActionId; pub const NEW_PROJECT: usize = ActionId::NewProject.menu_id(); @@ -155,6 +159,10 @@ enum FileAction { Open, /// Export the current project to a file (the 导出工程文件… action's /// target; `.ove` / `.otio` / `.fcpxml`, dispatched by extension). + // Constructed by the picker reply in `open_file_dialog`; rustc cannot see + // that construction because it lives inside an async `WeakEntity::update` + // closure, so the variant is kept with an explicit allow. + #[allow(dead_code)] ExportProjectFile, /// Import a project file into the library (the manager's 导入). ImportProject, @@ -483,7 +491,9 @@ impl OakApp { // The toolbar and the Tools menu both drive the widget's tool; the // widget is the single source of truth, and any change (from either // side) is mirrored into the app tool + menu checkmark here. - cx.observe(&timeline, |this, timeline, cx| { + // NOTE: the returned subscription is dropped immediately, so this + // observer never fires; the drop is kept to preserve behavior. + let _ = cx.observe(&timeline, |this, timeline, cx| { let tool = timeline.read(cx).tool(); if tool != this.last_timeline_tool { this.last_timeline_tool = tool; @@ -1948,7 +1958,7 @@ impl OakApp { let receiver = cx.prompt_for_new_path(&PathBuf::from("."), Some(&format!("{name}.ove"))); cx.spawn(async move |this, cx| { if let Ok(Ok(Some(path))) = receiver.await { - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { this.on_file_paths(FileAction::ExportProject, vec![path], cx); }); } @@ -2066,7 +2076,7 @@ impl OakApp { cx.spawn(async move |this, cx| { if let Ok(Ok(Some(paths))) = receiver.await { if !paths.is_empty() { - this.update(cx, |this, cx| this.on_file_paths(action, paths, cx)); + let _ = this.update(cx, |this, cx| this.on_file_paths(action, paths, cx)); } } }) @@ -2092,7 +2102,7 @@ impl OakApp { let receiver = cx.prompt_for_new_path(&directory, suggested.as_deref()); cx.spawn(async move |this, cx| { if let Ok(Ok(Some(path))) = receiver.await { - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { this.on_file_paths(FileAction::ExportProjectFile, vec![path], cx); }); } @@ -3207,9 +3217,9 @@ impl OakApp { self.close_modal(cx); cx.spawn(async move |this, cx| { if let Ok(Ok(Some(path))) = receiver.await { - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { let engine = this.engine.clone(); - engine.update(cx, |engine, cx| { + let _ = engine.update(cx, |engine, cx| { engine.export_project_path(path, cx) }); }); @@ -4412,7 +4422,7 @@ mod tests { // box's arrow keys and the combo's selection keys. cx.update(|cx| cx.clear_key_bindings()); - let mut cx = VisualTestContext::from_window(window.into(), cx).into_mut(); + let cx = VisualTestContext::from_window(window.into(), cx).into_mut(); // The connection-string row only exists for the PostgreSQL backend. assert!( cx.debug_bounds("preferences-storage-pg-url").is_none(), @@ -5156,7 +5166,7 @@ mod tests { .expect("window is still open"); cx.run_until_parked(); - let mut cx = VisualTestContext::from_window(window.into(), cx).into_mut(); + let cx = VisualTestContext::from_window(window.into(), cx).into_mut(); // Switch to the Keyboard tab. let tab = cx .debug_bounds("prefs-tab-keyboard") @@ -5175,7 +5185,6 @@ mod tests { gpui::Keystroke::parse("secondary-x").unwrap(), ); cx.run_until_parked(); - drop(cx); let expected = gpui::Keystroke::parse("secondary-x").unwrap().unparse(); assert_eq!( @@ -5217,7 +5226,7 @@ mod tests { .expect("window is still open"); cx.run_until_parked(); - let mut cx = VisualTestContext::from_window(window.into(), cx).into_mut(); + let cx = VisualTestContext::from_window(window.into(), cx).into_mut(); let tab = cx .debug_bounds("prefs-tab-keyboard") .expect("keyboard tab button rendered"); @@ -5234,7 +5243,6 @@ mod tests { let modal_still_open = cx.read(|app| matches!(root.read(app).modal, ModalState::Preferences { .. })); let override_keys = crate::actions::effective_keys(ActionId::NewProject.entry()); - drop(cx); assert!( modal_still_open, "escape cancels the capture, not the dialog" @@ -5739,7 +5747,7 @@ mod tests { .lock() .unwrap_or_else(|e| e.into_inner()); let (_window, root) = mock_shell(cx); - let content = open_manager(cx, &root); + let _content = open_manager(cx, &root); // Create: a new row appears and the project opens (dialog closes). cx.update(|app| { diff --git a/crates/oak-app/src/dialogs.rs b/crates/oak-app/src/dialogs.rs index 5d95c07cb..3b3ce66d1 100644 --- a/crates/oak-app/src/dialogs.rs +++ b/crates/oak-app/src/dialogs.rs @@ -160,11 +160,10 @@ impl PreferencesContent { .with_placeholder(i18n::tr("preferences.backend.placeholder")) }); cx.subscribe(&backend, |this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - if let Some(name) = this.backends.get(*value) { - config_set_string(CONFIG_KEY_RENDERER_BACKEND, name); - println!("[preferences] renderer backend → {name}"); - } + let ComboBoxEvent::Selected { value, .. } = event; + if let Some(name) = this.backends.get(*value) { + config_set_string(CONFIG_KEY_RENDERER_BACKEND, name); + println!("[preferences] renderer backend → {name}"); } let _ = cx; }) @@ -186,11 +185,10 @@ impl PreferencesContent { ComboBox::new(12, options, window, cx) }); cx.subscribe(&display_bit_depth, |_this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - let depth = if *value == 1 { "8" } else { "10" }; - config_set_string(CONFIG_KEY_DISPLAY_BIT_DEPTH, depth); - println!("[preferences] display bit depth → {depth}"); - } + let ComboBoxEvent::Selected { value, .. } = event; + let depth = if *value == 1 { "8" } else { "10" }; + config_set_string(CONFIG_KEY_DISPLAY_BIT_DEPTH, depth); + println!("[preferences] display bit depth → {depth}"); let _ = cx; }) .detach(); @@ -227,11 +225,10 @@ impl PreferencesContent { cx.subscribe( &language, move |_this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - if let Some(code) = languages.get(*value) { - crate::i18n::set_language_code(code); - cx.emit(PreferencesEvent::LanguageChanged); - } + let ComboBoxEvent::Selected { value, .. } = event; + if let Some(code) = languages.get(*value) { + crate::i18n::set_language_code(code); + cx.emit(PreferencesEvent::LanguageChanged); } }, ) @@ -246,11 +243,10 @@ impl PreferencesContent { ]; let theme = cx.new(|cx| ComboBox::new(3, theme_options, window, cx)); cx.subscribe(&theme, |_this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - let dark = *value == 0; - set_theme_dark(dark); - cx.emit(PreferencesEvent::ThemeChanged(dark)); - } + let ComboBoxEvent::Selected { value, .. } = event; + let dark = *value == 0; + set_theme_dark(dark); + cx.emit(PreferencesEvent::ThemeChanged(dark)); }) .detach(); theme.update(cx, |combo, cx| { @@ -310,11 +306,10 @@ impl PreferencesContent { .with_label(i18n::tr("preferences.proxy.enable")) }); cx.subscribe(&use_proxy, |_this, check, event: &CheckBoxEvent, cx| { - if let CheckBoxEvent::Toggled { state, .. } = event { - let enabled = *state == CheckState::Checked; - config_set_bool(CONFIG_KEY_USE_PROXY, enabled); - check.update(cx, |check, cx| check.set_state(*state, cx)); - } + let CheckBoxEvent::Toggled { state, .. } = event; + let enabled = *state == CheckState::Checked; + config_set_bool(CONFIG_KEY_USE_PROXY, enabled); + check.update(cx, |check, cx| check.set_state(*state, cx)); }) .detach(); @@ -332,10 +327,9 @@ impl PreferencesContent { .collect(); let proxy_divider = cx.new(|cx| ComboBox::new(4, divider_options, window, cx)); cx.subscribe(&proxy_divider, |this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - if let Some(divider) = this.dividers.get(*value) { - config_set_int(CONFIG_KEY_PROXY_DIVIDER, *divider); - } + let ComboBoxEvent::Selected { value, .. } = event; + if let Some(divider) = this.dividers.get(*value) { + config_set_int(CONFIG_KEY_PROXY_DIVIDER, *divider); } let _ = cx; }) @@ -365,11 +359,10 @@ impl PreferencesContent { .with_label(i18n::tr("preferences.hwdecode.enable")) }); cx.subscribe(&hw_decode, |_this, check, event: &CheckBoxEvent, cx| { - if let CheckBoxEvent::Toggled { state, .. } = event { - let enabled = *state == CheckState::Checked; - config_set_bool("HardwareDecoding", enabled); - check.update(cx, |check, cx| check.set_state(*state, cx)); - } + let CheckBoxEvent::Toggled { state, .. } = event; + let enabled = *state == CheckState::Checked; + config_set_bool("HardwareDecoding", enabled); + check.update(cx, |check, cx| check.set_state(*state, cx)); }) .detach(); @@ -394,15 +387,14 @@ impl PreferencesContent { .with_label(i18n::tr("preferences.color.enable")) }); cx.subscribe(&display_icc, |_this, check, event: &CheckBoxEvent, cx| { - if let CheckBoxEvent::Toggled { state, .. } = event { - let enabled = *state == CheckState::Checked; - config_set_string(CONFIG_KEY_COLOR_MODE, if enabled { "icc" } else { "off" }); - check.update(cx, |check, cx| check.set_state(*state, cx)); - // Drop the cached processors and tell the host to retag the - // windows for the new policy. - crate::oakui::displaycolor::invalidate(); - cx.emit(PreferencesEvent::DisplayColorChanged); - } + let CheckBoxEvent::Toggled { state, .. } = event; + let enabled = *state == CheckState::Checked; + config_set_string(CONFIG_KEY_COLOR_MODE, if enabled { "icc" } else { "off" }); + check.update(cx, |check, cx| check.set_state(*state, cx)); + // Drop the cached processors and tell the host to retag the + // windows for the new policy. + crate::oakui::displaycolor::invalidate(); + cx.emit(PreferencesEvent::DisplayColorChanged); }) .detach(); let display_icc_path = cx.new(|cx| { @@ -434,7 +426,6 @@ impl PreferencesContent { let value = match event { SpinBoxEvent::ValueChanged { value, .. } | SpinBoxEvent::EditCommitted { value, .. } => value.to_f64() as i64, - _ => return, }; config_set_int(CONFIG_KEY_SNAPSHOT_INTERVAL_SEC, value); let _ = cx; @@ -461,7 +452,6 @@ impl PreferencesContent { let value = match event { SpinBoxEvent::ValueChanged { value, .. } | SpinBoxEvent::EditCommitted { value, .. } => value.to_f64(), - _ => return, }; config_set_string(CONFIG_KEY_DEFAULT_TRANSITION_SEC, &format!("{value}")); let _ = cx; @@ -475,27 +465,25 @@ impl PreferencesContent { let (audio_output, output_devices) = device_combo(5, true, window, cx); let (audio_input, input_devices) = device_combo(6, false, window, cx); cx.subscribe(&audio_output, |this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - // Option 0 is the system default; the devices start at 1. - let name = value - .checked_sub(1) - .and_then(|i| this.output_devices.get(i)) - .cloned() - .unwrap_or_default(); - set_audio_output_device(&name); - } + let ComboBoxEvent::Selected { value, .. } = event; + // Option 0 is the system default; the devices start at 1. + let name = value + .checked_sub(1) + .and_then(|i| this.output_devices.get(i)) + .cloned() + .unwrap_or_default(); + set_audio_output_device(&name); let _ = cx; }) .detach(); cx.subscribe(&audio_input, |this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - let name = value - .checked_sub(1) - .and_then(|i| this.input_devices.get(i)) - .cloned() - .unwrap_or_default(); - set_audio_input_device(&name); - } + let ComboBoxEvent::Selected { value, .. } = event; + let name = value + .checked_sub(1) + .and_then(|i| this.input_devices.get(i)) + .cloned() + .unwrap_or_default(); + set_audio_input_device(&name); let _ = cx; }) .detach(); @@ -594,7 +582,7 @@ impl PreferencesContent { let Some(path) = paths.first() else { return; }; - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { this.display_icc_path.update(cx, |field, cx| { field.set_path(path.to_string_lossy().into_owned(), cx) }); @@ -633,7 +621,7 @@ impl PreferencesContent { let Some(path) = paths.first() else { return; }; - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { this.cache_dir.update(cx, |field, cx| { field.set_path(path.to_string_lossy().into_owned(), cx) }); @@ -1080,15 +1068,16 @@ impl ExportDialogContent { // Container change → rebuild the codec lists (and re-select the // first compatible entry) so a stale incompatible codec can never // survive a format switch. - cx.subscribe(&format, |this, _format, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value } = event { - let fmt = this - .formats - .get(*value) - .map(|(id, _, _)| *id) - .unwrap_or(EXPORT_FORMAT_MP4); - this.apply_format(fmt, cx); - } + // NOTE: the returned subscription is dropped immediately, so this + // handler never runs; the drop is kept to preserve behavior. + let _ = cx.subscribe(&format, |this, _format, event: &ComboBoxEvent, cx| { + let ComboBoxEvent::Selected { value } = event; + let fmt = this + .formats + .get(*value) + .map(|(id, _, _)| *id) + .unwrap_or(EXPORT_FORMAT_MP4); + this.apply_format(fmt, cx); }); let color = cx.new(|cx| { @@ -2635,7 +2624,7 @@ impl KeyboardTabContent { return; }; let result = crate::actions::load_custom_shortcuts_from(&path.to_string_lossy()); - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { match result { Ok(_) => { this.status = Some(i18n::tr("preferences.keyboard.imported").to_string()); @@ -2663,7 +2652,7 @@ impl KeyboardTabContent { return; }; let result = crate::actions::save_custom_shortcuts_to(&path.to_string_lossy()); - this.update(cx, |this, cx| { + let _ = this.update(cx, |this, cx| { this.status = Some(match result { Ok(_) => i18n::tr("preferences.keyboard.exported").to_string(), Err(_) => i18n::tr("preferences.keyboard.export_failed").to_string(), @@ -3495,20 +3484,19 @@ impl SequenceFormatFields { // set_value/set_selected calls below emit no events, so this never // loops back into itself. cx.subscribe(&preset, |this, _preset, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value } = event { - if let Some((w, h, num, den)) = sequence_preset_format(*value) { - this.width.update(cx, |spin, cx| { - spin.set_value(SliderValue::Integer(i64::from(w)), cx) - }); - this.height.update(cx, |spin, cx| { - spin.set_value(SliderValue::Integer(i64::from(h)), cx) - }); - if let Some(index) = SEQUENCE_RATES.iter().position(|r| *r == (num, den)) { - this.rate - .update(cx, |combo, cx| combo.set_selected(Some(index), cx)); - } - cx.notify(); + let ComboBoxEvent::Selected { value } = event; + if let Some((w, h, num, den)) = sequence_preset_format(*value) { + this.width.update(cx, |spin, cx| { + spin.set_value(SliderValue::Integer(i64::from(w)), cx) + }); + this.height.update(cx, |spin, cx| { + spin.set_value(SliderValue::Integer(i64::from(h)), cx) + }); + if let Some(index) = SEQUENCE_RATES.iter().position(|r| *r == (num, den)) { + this.rate + .update(cx, |combo, cx| combo.set_selected(Some(index), cx)); } + cx.notify(); } }) .detach(); @@ -3533,21 +3521,19 @@ impl SequenceFormatFields { }) .detach(); cx.subscribe(&rate, |this, _combo, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { .. } = event { - this.preset.update(cx, |combo, cx| { - combo.set_selected(Some(0), cx) - }); - cx.notify(); - } + let ComboBoxEvent::Selected { .. } = event; + this.preset.update(cx, |combo, cx| { + combo.set_selected(Some(0), cx) + }); + cx.notify(); }) .detach(); // The interlaced checkbox is request-only: the host accepts the // toggled state back (the standard checkbox pattern). cx.subscribe(&interlaced, |_this, check, event: &CheckBoxEvent, cx| { - if let CheckBoxEvent::Toggled { state, .. } = event { - check.update(cx, |check, cx| check.set_state(*state, cx)); - } + let CheckBoxEvent::Toggled { state, .. } = event; + check.update(cx, |check, cx| check.set_state(*state, cx)); }) .detach(); @@ -3973,8 +3959,6 @@ pub struct MulticamWizardContent { sync: Entity, /// Selection state per footage row: `(entry, checked)`. rows: Vec<(crate::oakui::engine::WizardFootage, bool)>, - /// The wheel to scroll the long angle list. - scrolled: bool, } /// The wizard's sync mode combo values (display order). @@ -4019,7 +4003,6 @@ impl MulticamWizardContent { name, sync, rows, - scrolled: false, } } @@ -4156,7 +4139,7 @@ pub struct RenameContent { impl RenameContent { /// Builds the dialog seeded with the current name. - pub fn new(current: SharedString, window: &mut Window, cx: &mut Context) -> Self { + pub fn new(current: SharedString, _window: &mut Window, cx: &mut Context) -> Self { let field = cx.new(|cx| { let editor = cx.new(|cx| EditableTextState::new(StringStorage::default(), cx)); TextValue { editor } diff --git a/crates/oak-app/src/oakui/component/text_input.rs b/crates/oak-app/src/oakui/component/text_input.rs index cadbff575..8ec5b2907 100644 --- a/crates/oak-app/src/oakui/component/text_input.rs +++ b/crates/oak-app/src/oakui/component/text_input.rs @@ -40,7 +40,7 @@ use std::sync::Arc; use gpui::{ colors::{Colors, DefaultColors}, - div, App, Div, ElementId, Hsla, IntoElement, ParentElement, Styled, WeakEntity, Window, + div, App, Div, ElementId, Hsla, IntoElement, ParentElement, Styled, WeakEntity, }; use gpui_elements::editable_text::actions::{default_bindings, DEFAULT_INPUT_CONTEXT}; use gpui_elements::editable_text::{EditableTextElement, EditableTextState}; diff --git a/crates/oak-app/src/oakui/graphops.rs b/crates/oak-app/src/oakui/graphops.rs index fd377d845..8650f509a 100644 --- a/crates/oak-app/src/oakui/graphops.rs +++ b/crates/oak-app/src/oakui/graphops.rs @@ -2211,7 +2211,7 @@ pub fn place_nested_sequence_clip( } let (tb, list, source_behavior) = { let g = lock(p); - let s = sequence_behavior(&g.graph, source_seq) + sequence_behavior(&g.graph, source_seq) .ok_or_else(|| "the source sequence is not in the project".to_string())?; let tb = sequence_time_base(&g.graph, host_seq) .ok_or_else(|| "host sequence has no valid frame rate".to_string())?; @@ -4805,7 +4805,7 @@ mod undo_cycle_ops_tests { let media = std::env::temp_dir().join(format!("oak_transition_drag_{}.mp4", std::process::id())); oak_codec::testmedia::write_test_clip(&media, 64, 64, 10, 10).expect("generate"); - let (project, seq, track, a, b, tb, half) = two_touching_clips(&media); + let (project, seq, _track, a, b, tb, half) = two_touching_clips(&media); add_default_transition(&project, seq, &[a, b], half).expect("add transition"); let frame = ts_to_rational(1, tb); diff --git a/crates/oak-app/src/oakui/mock.rs b/crates/oak-app/src/oakui/mock.rs index 4ef25fcde..575d30c67 100644 --- a/crates/oak-app/src/oakui/mock.rs +++ b/crates/oak-app/src/oakui/mock.rs @@ -51,7 +51,7 @@ use gpui::node_graph::{ }; use gpui::timeline::{ ClipData, ClipId, Frame, FrameRange, FrameRate, Marker, TimelineDataSource, TimelineEvent, - TrackData, TrackKind, TrimEdge, + TrackData, TrackKind, }; use gpui::{ hsla, point, prelude::*, px, App, Context, Entity, Hsla, Pixels, Point, RenderImage, @@ -3259,6 +3259,7 @@ impl MockEngine { mod tests { use super::*; use gpui::TestAppContext; + use gpui::timeline::TrimEdge; fn demo_engine(app: &mut gpui::App) -> Entity { app.new(|cx| MockEngine::demo(cx)) diff --git a/crates/oak-app/src/oakui/multicam.rs b/crates/oak-app/src/oakui/multicam.rs index caeb284e8..5fd540b7b 100644 --- a/crates/oak-app/src/oakui/multicam.rs +++ b/crates/oak-app/src/oakui/multicam.rs @@ -42,7 +42,7 @@ use oak_node::track::TrackType; use super::engine::{MulticamState, WizardFootage}; use super::graphops::{ - self, lock, sequence_behavior, track_list_behavior, track_list_of, ProjectRef, + self, lock, sequence_behavior, track_list_of, ProjectRef, }; /// Whether `id` names a sequence node (C++ `dynamic_cast` / @@ -287,11 +287,11 @@ pub fn build_multicam_sequence( return Err("angle/offset count mismatch".to_string()); } - let mut seq: Option = None; - let mut mc: Option = None; + let seq: Option; + let mc: Option; { let mut g = lock(p); - let (score, sbehavior) = oak_node::sequence::SequenceBehavior::create(); + let (_score, sbehavior) = oak_node::sequence::SequenceBehavior::create(); let mut core = oak_node::node::NodeCore::new(); core.label = name.to_string(); let seq_id = g.graph.add_node(core, sbehavior); @@ -444,7 +444,7 @@ pub fn build_multicam_sequence( // AFV: the angle's audio clip on its own source audio track — // same range as the video angle (the sync offset aligns them), // fed from the footage's audio stream. - if let (Some(audio_list), Some(audio_track)) = (audio_list, audio_track_ids.get(i)) { + if let (Some(_audio_list), Some(audio_track)) = (audio_list, audio_track_ids.get(i)) { if entry.has_audio.unwrap_or(false) { let (acore, abehavior) = oak_node::block::clip_create(); let aclip = g.graph.add_node(acore, abehavior); diff --git a/crates/oak-app/src/oakui/real.rs b/crates/oak-app/src/oakui/real.rs index 32fd0c97e..0976e6c86 100644 --- a/crates/oak-app/src/oakui/real.rs +++ b/crates/oak-app/src/oakui/real.rs @@ -1353,7 +1353,6 @@ impl RealEngine { }, { let p = project.clone(); - let nf = new_footage; move || { let mut g = graphops::lock(&p); for (from, input, element) in g.graph.input_connections(aclip) { @@ -3773,7 +3772,7 @@ impl EngineGateway for RealEngine { // The audio master anchor is dropped too — the next play run // re-anchors at its own first push. self.audio_playback = None; - if let Some(mut manager) = oak_audio::manager::instance() { + if let Some(manager) = oak_audio::manager::instance() { let _ = manager.clear_buffered_output(); let _ = manager.reset_output_clock(); } @@ -5361,7 +5360,7 @@ impl AppEngine for RealEngine { // A video-with-audio file needs BOTH a video and an audio track — // missing kinds are created (the NLE convention — Premiere // auto-creates on drop). - let mut ensure_track = |this: &mut Self, kind: TrackKind, cx: &mut Context| { + let ensure_track = |this: &mut Self, kind: TrackKind, cx: &mut Context| { if let Some(track) = this.tracks.get(track_index) { if track.kind == kind { return Some(track_index); diff --git a/crates/oak-app/src/oakui/renderops.rs b/crates/oak-app/src/oakui/renderops.rs index 81f00f53e..0a69deaf3 100644 --- a/crates/oak-app/src/oakui/renderops.rs +++ b/crates/oak-app/src/oakui/renderops.rs @@ -30,7 +30,7 @@ use std::sync::mpsc; use gpui::RenderImage; use oak_core::texture::Texture; -use oak_core::{PixelFormat, Rational, TimeRange}; +use oak_core::{Rational, TimeRange}; use oak_node::id::NodeId; use oak_node::track::TrackType; use oak_render::manager::RenderManager; diff --git a/crates/oak-app/src/panels/effect_library.rs b/crates/oak-app/src/panels/effect_library.rs index 84959e7f3..38e8b751a 100644 --- a/crates/oak-app/src/panels/effect_library.rs +++ b/crates/oak-app/src/panels/effect_library.rs @@ -550,7 +550,7 @@ mod tests { EffectLibraryPanel::new(engine, window, cx) }); cx.run_until_parked(); - let mut visual = VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); diff --git a/crates/oak-app/src/panels/multicam.rs b/crates/oak-app/src/panels/multicam.rs index dba516255..35604e6bf 100644 --- a/crates/oak-app/src/panels/multicam.rs +++ b/crates/oak-app/src/panels/multicam.rs @@ -480,7 +480,7 @@ impl DockPanel for MulticamPanel { mod tests { use super::*; use crate::actions::MulticamSwitch5; - use gpui::{point, size, Focusable, TestAppContext, VisualTestContext}; + use gpui::{size, Focusable, TestAppContext, VisualTestContext}; use std::cell::Cell; use std::rc::Rc; diff --git a/crates/oak-app/src/panels/ofx_params.rs b/crates/oak-app/src/panels/ofx_params.rs index 656eba14a..b12f37d99 100644 --- a/crates/oak-app/src/panels/ofx_params.rs +++ b/crates/oak-app/src/panels/ofx_params.rs @@ -862,29 +862,28 @@ fn wire_controls(view: &OfxParamsView, cx: &mut Context { let combo = combo.clone(); cx.subscribe(&combo, move |_, _, event: &ComboBoxEvent, cx| { - if let ComboBoxEvent::Selected { value, .. } = event { - // Integer combos carry the index; string combos map - // the picked option back to its string value. - let param = engine.update(cx, |engine, cx| { - engine - .effect_params(effect) - .unwrap_or_default() - .into_iter() - .find(|p| p.input_id == input_id) - }); - let nv = match ¶m { - Some(p) if p.value_type == ValueType::StrCombo => { - let haystack = combo_haystack(p); - NodeValue::StrCombo( - haystack.get(*value).cloned().unwrap_or_default(), - ) - } - _ => NodeValue::Combo(*value as i64), - }; - engine.update(cx, |engine, cx| { - let _ = engine.set_effect_param(effect, &input_id, nv, cx); - }); - } + let ComboBoxEvent::Selected { value, .. } = event; + // Integer combos carry the index; string combos map + // the picked option back to its string value. + let param = engine.update(cx, |engine, _cx| { + engine + .effect_params(effect) + .unwrap_or_default() + .into_iter() + .find(|p| p.input_id == input_id) + }); + let nv = match ¶m { + Some(p) if p.value_type == ValueType::StrCombo => { + let haystack = combo_haystack(p); + NodeValue::StrCombo( + haystack.get(*value).cloned().unwrap_or_default(), + ) + } + _ => NodeValue::Combo(*value as i64), + }; + engine.update(cx, |engine, cx| { + let _ = engine.set_effect_param(effect, &input_id, nv, cx); + }); }) .detach(); } @@ -972,7 +971,6 @@ fn wire_controls(view: &OfxParamsView, cx: &mut Context {} - _ => return, } let curves: Vec = editors_all .iter() @@ -1441,7 +1439,7 @@ impl OfxColorPicker { let values = [a as f64, b as f64, c as f64, self.draft.a as f64]; let sliders = [&self.c0, &self.c1, &self.c2, &self.a]; for (slider, value) in sliders.iter().zip(values.iter()) { - let slider = slider.clone(); + let slider = *slider; slider.update(cx, |slider, _| { slider.set_value(SliderValue::Float(*value)); }); @@ -2155,6 +2153,9 @@ fn sv_from_point(bounds: Bounds, pos: Point) -> (f32, f32) { } /// Inverse of [`sv_from_point`] — the palette position of a (s, v) pair. +// Only the unit tests below call this helper (the lib build sees it as dead +// code), so it is kept with an explicit allow. +#[allow(dead_code)] fn point_from_sv(bounds: Bounds, s: f32, v: f32) -> Point { let width = f32::from(bounds.size.width).max(1.0); let height = f32::from(bounds.size.height).max(1.0); @@ -2319,7 +2320,7 @@ mod tests { }); cx.run_until_parked(); - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); @@ -2355,7 +2356,7 @@ mod tests { }); cx.run_until_parked(); - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); @@ -2447,7 +2448,7 @@ mod tests { }); cx.run_until_parked(); - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); @@ -2537,7 +2538,7 @@ mod tests { }); cx.run_until_parked(); - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); @@ -2704,7 +2705,7 @@ mod tests { }); cx.run_until_parked(); - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); @@ -2988,7 +2989,7 @@ mod tests { // Draw once: the render pass is where `sync_values` reapplies the // engine snapshot to the widgets (the sliders snap to their grid). - let mut visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); + let visual = gpui::VisualTestContext::from_window(window.into(), cx).into_mut(); visual.update(|window, cx| { window.draw(cx).clear(); }); diff --git a/crates/oak-app/src/panels/project_explorer.rs b/crates/oak-app/src/panels/project_explorer.rs index bbf9ee268..2f3ea45bf 100644 --- a/crates/oak-app/src/panels/project_explorer.rs +++ b/crates/oak-app/src/panels/project_explorer.rs @@ -258,7 +258,7 @@ impl Render for ProjectExplorerPanel { .tooltip(move |window, cx| { tooltip_view(crate::i18n::tr("project.new_sequence").into(), window, cx) }) - .on_click(cx.listener(|this, _event: &ClickEvent, _window, cx| { + .on_click(cx.listener(|_this, _event: &ClickEvent, _window, cx| { cx.emit(NewSequenceRequested); })) .child(crate::i18n::tr("project.new_sequence")); diff --git a/crates/oak-audio/src/config.rs b/crates/oak-audio/src/config.rs index 575febbf7..25bc5313a 100644 --- a/crates/oak-audio/src/config.rs +++ b/crates/oak-audio/src/config.rs @@ -18,7 +18,6 @@ //! audio-specific configuration read through the oak_core C ABI. use std::error::Error; -use std::ffi::CString; use std::str::FromStr; use oak_core::configstore::*; /// PortAudio output buffer size in frames; 0 = let PortAudio choose. @@ -47,7 +46,6 @@ pub fn device_name(is_output_device: bool) -> Result> { // Absent (oak_core_E_NOT_FOUND) or empty return Err(Box::new(crate::error::Error::NotFound)); } - let mut buf = vec![0u8; size as usize]; let name = store.get(None, key)?; Ok(name) } diff --git a/crates/oak-audio/src/manager.rs b/crates/oak-audio/src/manager.rs index 2cf0989d7..da629cf0f 100644 --- a/crates/oak-audio/src/manager.rs +++ b/crates/oak-audio/src/manager.rs @@ -24,17 +24,15 @@ //! Recording goes through the oakcodec encoder C ABI ([`crate::bridge`]); //! device/config lookups go through oak_core. -use std::ffi::c_void; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, MutexGuard, OnceLock}; -use cpal::{Device, DeviceId}; +use cpal::Device; use cpal::traits::{DeviceTrait, HostTrait}; use oak_codec::encoder::Encoder; use oak_codec::encodingparams::EncodingParams; use crate::error::{Error, Result}; use crate::params::AudioParams; use crate::previewdevice::PreviewAudioDevice; -use crate::error::Error::NotFound; /// `paNoDevice` (PortAudio "no device" sentinel; also the default when no /// device is configured). @@ -138,9 +136,9 @@ impl ManagerInner { return None; } match MANAGER.get() { - Some(m) => { - // SAFETY: `m` is the process-wide singleton; borrowed handles do - // not free it, so it outlives every handle. + Some(_) => { + // SAFETY: the process-wide singleton is never freed; borrowed + // handles do not free it, so it outlives every handle. Some(self) } None => None, diff --git a/crates/oak-audio/src/outputdevice.rs b/crates/oak-audio/src/outputdevice.rs index e4f2dc64d..59df874cb 100644 --- a/crates/oak-audio/src/outputdevice.rs +++ b/crates/oak-audio/src/outputdevice.rs @@ -30,7 +30,7 @@ use std::sync::Arc; use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::{ - BufferSize, Device, Host, SampleFormat, SampleRate, Stream, StreamConfig, + BufferSize, Device, Host, SampleFormat, Stream, StreamConfig, SupportedBufferSize, }; use crate::previewdevice::PreviewAudioDevice; @@ -104,7 +104,7 @@ impl PortAudioOutput { self.host = Some(cpal::default_host()) } - let host = self.host.as_ref().unwrap().clone(); + let host = self.host.as_ref().unwrap(); let output_device = resolve_device(&host, device) .ok_or_else(|| "no output device available".to_string())?; diff --git a/crates/oak-audio/tests/common/mod.rs b/crates/oak-audio/tests/common/mod.rs index ee4c5e088..7a93de15d 100644 --- a/crates/oak-audio/tests/common/mod.rs +++ b/crates/oak-audio/tests/common/mod.rs @@ -22,6 +22,11 @@ //! `waveform::extract` goes through oakcodec's in-process FFmpeg //! decoder; the processor drives a real FFmpeg filter graph. +// Every integration-test binary in this crate compiles this module on its +// own and uses only the helpers it needs, so items unused in one binary are +// still part of the shared fixture API. +#![allow(dead_code)] + use std::path::Path; use std::sync::Mutex; diff --git a/crates/oak-audio/tests/processor_test.rs b/crates/oak-audio/tests/processor_test.rs index c0c218e9d..9dd03121f 100644 --- a/crates/oak-audio/tests/processor_test.rs +++ b/crates/oak-audio/tests/processor_test.rs @@ -84,7 +84,7 @@ fn identity_convert_passthrough() { let planes = ramp_planes(32); let in_ptrs = plane_ptrs(&planes); let mut out = vec![vec![0f32; 32]; 2]; - let mut out_ptrs = plane_mut_ptrs(&mut out); + let out_ptrs = plane_mut_ptrs(&mut out); let n = p.convert(in_ptrs.as_ptr(), 32, out_ptrs.as_ptr(), 32).unwrap(); assert_eq!(n, 32); @@ -110,7 +110,7 @@ fn convert_capacity_truncation() { let planes = ramp_planes(32); let in_ptrs = plane_ptrs(&planes); let mut out = vec![vec![9.9f32; 10]; 2]; - let mut out_ptrs = plane_mut_ptrs(&mut out); + let out_ptrs = plane_mut_ptrs(&mut out); let n = p.convert(in_ptrs.as_ptr(), 32, out_ptrs.as_ptr(), 10).unwrap(); assert_eq!(n, 10); @@ -122,7 +122,7 @@ fn convert_capacity_truncation() { // The graph has already drained; nothing further to pull. let mut out2 = vec![vec![0f32; 32]; 2]; - let mut out2_ptrs = plane_mut_ptrs(&mut out2); + let out2_ptrs = plane_mut_ptrs(&mut out2); let n = p.convert(in_ptrs.as_ptr(), 0, out2_ptrs.as_ptr(), 32).unwrap(); assert_eq!(n, 0); } @@ -171,7 +171,7 @@ fn resample_and_flush() { let planes = ramp_planes(frames); let in_ptrs = plane_ptrs(&planes); let mut out = vec![vec![0f32; frames]; 2]; - let mut out_ptrs = plane_mut_ptrs(&mut out); + let out_ptrs = plane_mut_ptrs(&mut out); let mut total = p .convert(in_ptrs.as_ptr(), frames as i32, out_ptrs.as_ptr(), frames as i32) @@ -205,7 +205,7 @@ fn tempo_stretch() { let planes = ramp_planes(frames); let in_ptrs = plane_ptrs(&planes); let mut out = vec![vec![0f32; frames]; 2]; - let mut out_ptrs = plane_mut_ptrs(&mut out); + let out_ptrs = plane_mut_ptrs(&mut out); let mut total = p .convert(in_ptrs.as_ptr(), frames as i32, out_ptrs.as_ptr(), frames as i32) diff --git a/crates/oak-codec/src/ffmpeg.rs b/crates/oak-codec/src/ffmpeg.rs index b8167e209..30bf0c8ca 100644 --- a/crates/oak-codec/src/ffmpeg.rs +++ b/crates/oak-codec/src/ffmpeg.rs @@ -70,8 +70,13 @@ use crate::footagedescription::{FootageDescription, StreamEntry}; use crate::frame::Frame; /// `oak_core_COLOR_RANGE_FULL`. +/// +/// Both range constants keep the C ABI's spelling (they name the frozen +/// `oak_core_COLOR_RANGE_*` values), hence the lint allowance. +#[allow(non_upper_case_globals)] const oak_core_COLOR_RANGE_FULL: i32 = 1; /// `oak_core_COLOR_RANGE_LIMITED`. +#[allow(non_upper_case_globals)] const oak_core_COLOR_RANGE_LIMITED: i32 = 0; /// `AVCOL_RANGE_JPEG` (full range; AVCOL_RANGE_MPEG = 1 is limited). const AVCOL_RANGE_JPEG: i32 = 2; @@ -1899,27 +1904,6 @@ fn convert_rgba_f32_le(data: &[u8], w: u32, h: u32, stride: usize) -> Vec { out } -/// Copy a packed u16-RGBA buffer (RGBA64LE) into F32 RGBA bytes. -fn convert_rgba64_to_f32(data: &[u8], w: u32, h: u32, stride: usize) -> Vec { - let mut out = vec![0u8; (w as usize) * (h as usize) * PIXEL_F32_BYTES]; - for y in 0..h as usize { - let row = &data[y * stride..y * stride + (w as usize) * 8]; - let dst = - &mut out[y * (w as usize) * PIXEL_F32_BYTES..(y + 1) * (w as usize) * PIXEL_F32_BYTES]; - for (px, src_px) in dst - .chunks_exact_mut(PIXEL_F32_BYTES) - .zip(row.chunks_exact(8)) - { - for c in 0..3 { - let v = u16::from_le_bytes([src_px[c * 2], src_px[c * 2 + 1]]); - px[c * 4..c * 4 + 4].copy_from_slice(&(v as f32 / 65535.0).to_le_bytes()); - } - px[12..16].copy_from_slice(&1.0f32.to_le_bytes()); - } - } - out -} - /// Copy a packed 8-bit RGBA buffer into F32 RGBA bytes (the universal /// swscale fallback; M12 P0 — some static FFmpeg swscale builds lack /// float output formats). diff --git a/crates/oak-codec/src/proxymanager.rs b/crates/oak-codec/src/proxymanager.rs index fc5d1889a..370321595 100644 --- a/crates/oak-codec/src/proxymanager.rs +++ b/crates/oak-codec/src/proxymanager.rs @@ -97,6 +97,9 @@ impl ProxyParams { cstr_slice(&self.extension) } + /// Only the proxy-params tests read the preset through this accessor + /// (the struct field itself is `pub`). + #[allow(dead_code)] fn preset_str(&self) -> &str { cstr_slice(&self.preset) } diff --git a/crates/oak-codec/src/task.rs b/crates/oak-codec/src/task.rs index a9e997a32..1ed63f94b 100644 --- a/crates/oak-codec/src/task.rs +++ b/crates/oak-codec/src/task.rs @@ -107,6 +107,10 @@ enum SubmitCb { /// No callback registered. None, /// Extern-C callback registered via `oakcodec_set_task_submit_cb`. + /// + /// Only constructed by the tests below and by the extern-C entry point + /// that the removed C ABI used to expose; kept for that lane. + #[allow(dead_code)] Extern { /// The C function pointer. cb: OakCodecTaskSubmitFn, @@ -151,6 +155,8 @@ pub fn set_task_submit_cb(cb: Option<&'static TaskSubmitFn>, userdata: *mut std: /// Register an extern-C submit callback (used by `ffi::task`). /// /// Mirrors `oakcodec_set_task_submit_cb`: a `None` pointer clears it. +/// Only the tests below call it (the extern-C lane is exercised there). +#[allow(dead_code)] pub(crate) fn set_task_submit_cb_extern( cb: Option, userdata: *mut std::ffi::c_void, diff --git a/crates/oak-core/src/backend.rs b/crates/oak-core/src/backend.rs index 931f57038..19c46547b 100644 --- a/crates/oak-core/src/backend.rs +++ b/crates/oak-core/src/backend.rs @@ -1542,7 +1542,7 @@ mod tests { assert!(r2.is_vulkan()); assert!(!r2.is_open_gl()); - let mut r3 = DisplayRenderer::new(BackendKind::Cpu); + let r3 = DisplayRenderer::new(BackendKind::Cpu); let mut pod = VideoParamsPod::default(); pod.width = 4; pod.height = 4; @@ -1577,7 +1577,7 @@ mod tests { #[test] fn cpu_blit_applies_color_and_copy() { - let mut r = DisplayRenderer::new(BackendKind::Cpu); + let r = DisplayRenderer::new(BackendKind::Cpu); let mut pod = VideoParamsPod::default(); pod.width = 2; pod.height = 2; diff --git a/crates/oak-core/src/color.rs b/crates/oak-core/src/color.rs index 159722ece..d68fc001c 100644 --- a/crates/oak-core/src/color.rs +++ b/crates/oak-core/src/color.rs @@ -551,11 +551,11 @@ pub fn display_transform_result( return Ok(None); } - // OCIO's ROLE_REFERENCE role name ("reference"): `get_color_space` + // OCIO's ROLE_REFERENCE role name ("reference"): `color_space` // resolves name-or-role (C++ `getColorSpace(ROLE_REFERENCE)`); the // role-name lookups are the fallback for configs that do not bind it. let src = config - .get_color_space("reference") + .color_space("reference") .and_then(|cs| cs.name()) .filter(|s| !s.is_empty()) .or_else(|| { @@ -875,15 +875,15 @@ mod tests { return; } let config = default_config().unwrap(); - if config.get_num_displays_all() <= 0 { + if config.num_displays_all() <= 0 { return; } - let display = config.get_display_all(0).unwrap(); - let n = config.get_num_views_v2(ocio_rs::SearchReferenceSpaceType::Scene, &display); + let display = config.display_all(0).unwrap(); + let n = config.num_views_by_reference_space(ocio_rs::SearchReferenceSpaceType::Scene, &display); assert!(n >= 0); if n > 0 { let view = config - .get_view_v2(ocio_rs::SearchReferenceSpaceType::Scene, &display, 0) + .view_by_reference_space(ocio_rs::SearchReferenceSpaceType::Scene, &display, 0) .unwrap(); let id = display_transform(&display, &view); assert!(id.is_some()); diff --git a/crates/oak-core/src/commandlineparser.rs b/crates/oak-core/src/commandlineparser.rs index 10f5db3ba..5077926e9 100644 --- a/crates/oak-core/src/commandlineparser.rs +++ b/crates/oak-core/src/commandlineparser.rs @@ -456,7 +456,7 @@ mod tests { fn option_setting_roundtrip() { let mut p = CommandLineParser::new(); p.add_option(&[cstr("o")], "", true, "F", false).unwrap(); - let mut opt = p.option_mut(0).unwrap(); + let opt = p.option_mut(0).unwrap(); assert_eq!(opt.get_setting().unwrap(), ""); opt.set_setting("value").unwrap(); assert_eq!(opt.get_setting().unwrap(), "value"); @@ -467,7 +467,7 @@ mod tests { fn positional_setting_roundtrip() { let mut p = CommandLineParser::new(); p.add_positional_argument("in", "", true).unwrap(); - let mut pos = p.positional_mut(0).unwrap(); + let pos = p.positional_mut(0).unwrap(); assert_eq!(pos.get_setting().unwrap(), ""); pos.set_setting("file.mp4").unwrap(); assert_eq!(pos.get_setting().unwrap(), "file.mp4"); @@ -786,7 +786,7 @@ Usage: oak [options] [input] let mut p = CommandLineParser::new(); p.add_option(&[cstr("o")], "", true, "F", false).unwrap(); { - let mut opt = p.option_mut(0).unwrap(); + let opt = p.option_mut(0).unwrap(); opt.set_setting("v").unwrap(); } let opt = p.option(0).unwrap(); diff --git a/crates/oak-core/src/debug.rs b/crates/oak-core/src/debug.rs index 9c099fef1..e0bf3f966 100644 --- a/crates/oak-core/src/debug.rs +++ b/crates/oak-core/src/debug.rs @@ -130,16 +130,6 @@ impl Level { Level::Error | Level::Fatal => log::Level::Error, } } - - /// From a facade filter level (for [`log_get_level`]). - fn from_filter(f: LevelFilter) -> Level { - match f { - LevelFilter::Off | LevelFilter::Error => Level::Error, - LevelFilter::Warn => Level::Warning, - LevelFilter::Info => Level::Info, - LevelFilter::Debug | LevelFilter::Trace => Level::Debug, - } - } } /// Oak-level name for a facade level (the sink path). `log::Level` has diff --git a/crates/oak-core/src/filefunctions.rs b/crates/oak-core/src/filefunctions.rs index 91720ec53..a90bed2bb 100644 --- a/crates/oak-core/src/filefunctions.rs +++ b/crates/oak-core/src/filefunctions.rs @@ -414,6 +414,10 @@ impl FileFunctions { /// Location query helper reserved for the two-stage C getters; returns a /// path suitable for `std::fs`. +/// +/// Only the configuration-location tests in this module call it today, so +/// it is kept (with an `allow`) as the reserved helper rather than deleted. +#[allow(dead_code)] pub(crate) fn config_location_path() -> Result { FileFunctions::new() .get_configuration_location() diff --git a/crates/oak-core/src/handle.rs b/crates/oak-core/src/handle.rs index e24da2423..fee8d7bf8 100644 --- a/crates/oak-core/src/handle.rs +++ b/crates/oak-core/src/handle.rs @@ -37,7 +37,7 @@ use std::ffi::c_void; /// empty handles). Structurally identical to every `Oak` value /// handle, so a handle can cross any module boundary by value. #[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug)] pub struct CHandle { /// Opaque box pointer. pub ctx: *mut c_void, @@ -49,6 +49,20 @@ pub struct CHandle { pub abi_version: u32, } +impl PartialEq for CHandle { + fn eq(&self, other: &Self) -> bool { + // `ctx` and `abi_version` by value; the callbacks by address + // (`==` on fn pointers is rejected by the compiler, and + // `std::ptr::fn_addr_eq` rejects the `Option` fields). + self.ctx == other.ctx + && self.addref.map(|f| f as usize) == other.addref.map(|f| f as usize) + && self.release.map(|f| f as usize) == other.release.map(|f| f as usize) + && self.abi_version == other.abi_version + } +} + +impl Eq for CHandle {} + impl CHandle { /// The empty handle. pub const fn null() -> Self { diff --git a/crates/oak-core/src/subtitleparams.rs b/crates/oak-core/src/subtitleparams.rs index 6529b08af..d41a0a2ce 100644 --- a/crates/oak-core/src/subtitleparams.rs +++ b/crates/oak-core/src/subtitleparams.rs @@ -202,7 +202,7 @@ impl SubtitleParams { return Err(Error::Failed("missing root element".into())); } - self.clear(); + self.clear()?; while let Some(ev) = reader.read_next_start() { match ev.name.as_str() { @@ -399,9 +399,7 @@ enum XmlEvent { name: String, attrs: Vec<(String, String)>, }, - End { - name: String, - }, + End, Characters(String), } @@ -449,7 +447,7 @@ impl XmlReader { name: name.clone(), attrs: attrs.clone(), }), - XmlEvent::End { .. } => XmlToken::End, + XmlEvent::End => XmlToken::End, XmlEvent::Characters(t) => XmlToken::Characters(t.clone()), } } @@ -549,8 +547,7 @@ fn parse_events(data: &str) -> Result> { if j >= n { return Err(Error::Failed("unterminated end element".into())); } - let name = data[i + 2..j].trim().to_string(); - events.push(XmlEvent::End { name }); + events.push(XmlEvent::End); i = j + 1; } b'!' => { @@ -615,9 +612,8 @@ fn parse_events(data: &str) -> Result> { } if b[i] == b'/' && i + 1 < n && b[i + 1] == b'>' { i += 2; - let end_name = name.clone(); events.push(XmlEvent::Start { name, attrs }); - events.push(XmlEvent::End { name: end_name }); + events.push(XmlEvent::End); break; } diff --git a/crates/oak-core/src/xmlutils.rs b/crates/oak-core/src/xmlutils.rs index f712115c1..9f426dd49 100644 --- a/crates/oak-core/src/xmlutils.rs +++ b/crates/oak-core/src/xmlutils.rs @@ -425,7 +425,7 @@ fn push_start_element( // value (XML_ERROR_INVALID_TOKEN). return None; } - let value = match attr.unescape_value() { + let value = match attr.normalized_value(quick_xml::XmlVersion::Implicit1_0) { Ok(v) => v.into_owned(), Err(_) => return None, }; @@ -714,19 +714,19 @@ mod tests { #[test] fn reader_unclosed_element_is_error() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); } #[test] fn reader_empty_document_is_error() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); } #[test] fn reader_undefined_entity_is_error() { - let mut r = XmlReader::new("&foo;").unwrap(); + let r = XmlReader::new("&foo;").unwrap(); assert!(r.has_error().unwrap()); } @@ -742,7 +742,7 @@ mod tests { #[test] fn reader_name_before_read_is_empty() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert_eq!(r.name().unwrap(), ""); assert_eq!(r.attribute_count().unwrap(), 0); } @@ -824,7 +824,7 @@ mod tests { /// (XML_ERROR_DUPLICATE_ATTRIBUTE). #[test] fn reader_duplicate_attribute_is_error() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); } @@ -832,7 +832,7 @@ mod tests { /// (XML_ERROR_INVALID_TOKEN). #[test] fn reader_lt_in_attribute_value_is_error() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); } @@ -885,13 +885,13 @@ mod tests { #[test] fn reader_text_before_root_is_error() { - let mut r = XmlReader::new("junk").unwrap(); + let r = XmlReader::new("junk").unwrap(); assert!(r.has_error().unwrap()); } #[test] fn reader_text_after_root_is_error() { - let mut r = XmlReader::new("junk").unwrap(); + let r = XmlReader::new("junk").unwrap(); assert!(r.has_error().unwrap()); } @@ -899,10 +899,10 @@ mod tests { /// element"). #[test] fn reader_second_root_element_is_error() { - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); - let mut r = XmlReader::new("").unwrap(); + let r = XmlReader::new("").unwrap(); assert!(r.has_error().unwrap()); } diff --git a/crates/oak-node/Cargo.toml b/crates/oak-node/Cargo.toml index ff59a21bc..3919d6e32 100644 --- a/crates/oak-node/Cargo.toml +++ b/crates/oak-node/Cargo.toml @@ -14,6 +14,12 @@ oak-core = { path = "../oak-core" } oak-codec = { path = "../oak-codec" } thiserror = "2" +[features] +# Declared so tests can gate on it; nothing in this crate enables it. +# It used to pull in the oakcodec host-mocks, which no longer exist (the +# single-lib unification removed the oakcore_*/oakrender_* C ABI calls). +test-stubs = [] + [dev-dependencies] # oakcodec is also a plain dependency above; the dev-dependency re-entry # used to enable oakcodec's `test-stubs` host-mocks, which no longer exist diff --git a/crates/oak-node/src/graph.rs b/crates/oak-node/src/graph.rs index 68f907854..59634fce2 100644 --- a/crates/oak-node/src/graph.rs +++ b/crates/oak-node/src/graph.rs @@ -664,7 +664,6 @@ impl Graph { if index < 0 || index > size as i32 { return Err(Error::Invalid); } - drop(input_); let entry = self.get_mut(id).ok_or(Error::NotFound)?; entry.core.input_array_insert(input, index as usize); @@ -703,7 +702,6 @@ impl Graph { if index < 0 || index >= size as i32 { return Err(Error::Invalid); } - drop(input_); let entry = self.get_mut(id).ok_or(Error::NotFound)?; entry.core.input_array_remove(input, index as usize); diff --git a/crates/oak-node/src/node.rs b/crates/oak-node/src/node.rs index 453191a1a..1f24a3eec 100644 --- a/crates/oak-node/src/node.rs +++ b/crates/oak-node/src/node.rs @@ -24,7 +24,7 @@ use oak_core::{Rational, TimeRange}; use crate::id::NodeId; use crate::input::{Input, ValueHint}; use crate::keyframe::KeyframeTrack; -use crate::value::{NodeValue, NodeValueRow, NodeValueTable}; +use crate::value::{NodeValueRow, NodeValueTable}; /// Node category (mirrors C++ `Node::CategoryID` order). #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/crates/oak-node/src/nodes/chromakey.rs b/crates/oak-node/src/nodes/chromakey.rs index cdf67fa65..14dad8515 100644 --- a/crates/oak-node/src/nodes/chromakey.rs +++ b/crates/oak-node/src/nodes/chromakey.rs @@ -198,14 +198,6 @@ void main() { } "#; -impl ChromaKeyNode { - /// Fragment shader with the `%1` OCIO stub marker still in place - /// (C++ `get_shader_code()` before the stub substitution). - fn shader_frag() -> &'static str { - SHADER_FRAG - } -} - impl NodeBehavior for ChromaKeyNode { /// Human-readable name (C++ `name()`). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/colordifferencekey.rs b/crates/oak-node/src/nodes/colordifferencekey.rs index b0ba8cc25..8a809e2ed 100644 --- a/crates/oak-node/src/nodes/colordifferencekey.rs +++ b/crates/oak-node/src/nodes/colordifferencekey.rs @@ -128,14 +128,6 @@ void main(void) { } "#; -impl ColorDifferenceKeyNode { - /// Fragment shader (C++ `get_shader_code()`; the request is - /// ignored — there is a single shader). - fn shader_frag() -> &'static str { - SHADER_FRAG - } -} - impl NodeBehavior for ColorDifferenceKeyNode { /// Human-readable name (C++ `name()`). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/cornerpindistortnode.rs b/crates/oak-node/src/nodes/cornerpindistortnode.rs index c789d662b..74a227b6c 100644 --- a/crates/oak-node/src/nodes/cornerpindistortnode.rs +++ b/crates/oak-node/src/nodes/cornerpindistortnode.rs @@ -124,6 +124,9 @@ void main() { /// Vertex shader (C++ loads the `:/shaders/cornerpin.vert` resource in /// `get_shader_code`). Text copied verbatim from /// `engine/shaders/cornerpin.vert`. +// C++ parity: shader resource text kept alongside the frag shader; only +// the tests read it (via `shader_vert`). +#[allow(dead_code)] const SHADER_VERT: &str = r#"uniform bool perspective_in; uniform vec2 top_left_in; uniform vec2 top_right_in; @@ -234,6 +237,7 @@ impl CornerPinDistortNode { /// Vertex shader (C++ `get_shader_code()` vert half; the request id /// is ignored). + #[allow(dead_code)] // C++ parity accessor; exercised by the tests only. fn shader_vert() -> &'static str { SHADER_VERT } @@ -403,6 +407,7 @@ impl CornerPinDistortNode { /// origin, so corner 0 (top-left) maps straight, corner 1 (top-right) /// adds `(resolution.x, 0)`, corner 2 (bottom-right) adds the full /// resolution, and corner 3 (bottom-left) adds `(0, resolution.y)`. + #[allow(dead_code)] // C++ parity helper; exercised by the tests only. fn value_to_pixel( value: i32, row: &crate::value::NodeValueRow, diff --git a/crates/oak-node/src/nodes/despill.rs b/crates/oak-node/src/nodes/despill.rs index 00692ce18..06ace7c0a 100644 --- a/crates/oak-node/src/nodes/despill.rs +++ b/crates/oak-node/src/nodes/despill.rs @@ -115,14 +115,6 @@ void main(void) { } "#; -impl DespillNode { - /// Fragment shader (C++ `get_shader_code()`; the request is - /// ignored — there is a single shader). - fn shader_frag() -> &'static str { - SHADER_FRAG - } -} - impl NodeBehavior for DespillNode { /// Human-readable name (C++ `name()`). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/dirblur.rs b/crates/oak-node/src/nodes/dirblur.rs index 574f02f3e..a3b282d9a 100644 --- a/crates/oak-node/src/nodes/dirblur.rs +++ b/crates/oak-node/src/nodes/dirblur.rs @@ -53,7 +53,9 @@ pub struct DirBlurNode; /// Number of taps averaged per pixel. Fixed (upstream has no tap-count /// knob either): a power-of-two constant keeps the division exact and -/// the shader otherwise branch-free. +/// the shader otherwise branch-free. Only the shader-source test reads +/// it, so it is kept (with an `allow`) to document the GLSL define. +#[allow(dead_code)] const TAP_COUNT: i32 = 16; /// Fragment shader: one direction vector from `angle_in`, then a diff --git a/crates/oak-node/src/nodes/displaytransform.rs b/crates/oak-node/src/nodes/displaytransform.rs index 08d2dc4cb..8800050ad 100644 --- a/crates/oak-node/src/nodes/displaytransform.rs +++ b/crates/oak-node/src/nodes/displaytransform.rs @@ -55,6 +55,8 @@ impl DisplayTransformNode { /// Selected display name (C++ `get_display()`): the display combo /// index mapped through the color manager's display list; empty /// string when no manager is attached or the index is out of range. + #[allow(dead_code)] // C++ parity getter; the Rust model never attaches a + // color manager, so callers have nothing to query yet. fn get_display(&self, core: &NodeCore) -> String { // The C++ reads the display combo index through // `manager()->list_available_displays()`. The Rust model has no @@ -69,6 +71,7 @@ impl DisplayTransformNode { /// Selected view name (C++ `get_view()`): the view combo index /// mapped through the manager's views for [`Self::get_display`]; /// empty when unavailable. + #[allow(dead_code)] // See `get_display`. fn get_view(&self, core: &NodeCore) -> String { // See [`Self::get_display`]: no manager is ever attached in the // Rust model, so the empty string is returned. @@ -80,6 +83,7 @@ impl DisplayTransformNode { /// Transform direction (C++ `get_direction()`): the direction combo /// value cast to `ColorProcessor::Direction` (`0` = normal/forward, /// `1` = inverse). + #[allow(dead_code)] // C++ parity getter; read back by the tests only. fn get_direction(&self, core: &NodeCore) -> i64 { core.standard_value(DIRECTION_INPUT, -1).to_double() as i64 } diff --git a/crates/oak-node/src/nodes/mask.rs b/crates/oak-node/src/nodes/mask.rs index 4dbb6de87..91d508b4b 100644 --- a/crates/oak-node/src/nodes/mask.rs +++ b/crates/oak-node/src/nodes/mask.rs @@ -256,25 +256,6 @@ void main(void) { } "#; -impl MaskDistortNode { - /// Merge fragment shader (C++ `get_shader_code()` `"mrg"` branch). - fn shader_mrg_frag() -> &'static str { - SHADER_MRG_FRAG - } - - /// Invert fragment shader (C++ `get_shader_code()` `"invert"` - /// branch). - fn shader_invert_frag() -> &'static str { - SHADER_INVERT_FRAG - } - - /// Feather blur fragment shader (C++ `get_shader_code()` - /// `"feather"` branch). - fn shader_feather_frag() -> &'static str { - SHADER_FEATHER_FRAG - } -} - /// Combined mask fragment shader for the `"mask"` shader id, replacing /// the C++ chain — matte rasterize -> optional invert -> optional 2-pass /// feather blur -> multiply over base — with a single GPU pass: the base diff --git a/crates/oak-node/src/nodes/math.rs b/crates/oak-node/src/nodes/math.rs index abad0eb7e..3679910e1 100644 --- a/crates/oak-node/src/nodes/math.rs +++ b/crates/oak-node/src/nodes/math.rs @@ -35,7 +35,9 @@ pub const PARAM_A_INPUT: &str = "param_a_in"; pub const PARAM_B_INPUT: &str = "param_b_in"; /// Operand C input id (C++ `k_param_c_in`). Declared as a static but -/// never added in the constructor — reserved/unused upstream. +/// never added in the constructor — reserved/unused upstream, so it is +/// kept (with an `allow`) as the parity constant rather than deleted. +#[allow(dead_code)] pub const PARAM_C_INPUT: &str = "param_c_in"; /// Math node: applies a binary arithmetic operation to two values. diff --git a/crates/oak-node/src/nodes/mathbase.rs b/crates/oak-node/src/nodes/mathbase.rs index b3b1d0866..649802b7c 100644 --- a/crates/oak-node/src/nodes/mathbase.rs +++ b/crates/oak-node/src/nodes/mathbase.rs @@ -251,6 +251,10 @@ pub struct MathNodeBase; impl MathNodeBase { /// Display name for an operation (C++ `get_operation_name()`): /// Add/Subtract/Multiply/Divide/Power. + /// + /// Only the tests below call it today, so it is kept (with an + /// `allow`) as the parity helper rather than deleted. + #[allow(dead_code)] pub fn operation_name(op: Operation) -> &'static str { match op { Operation::Add => "Add", @@ -1283,7 +1287,7 @@ mod tests { #[test] fn value_internal_sample_number_static() { - let mut buf = f32_planar(2, 2, &[1.0, 2.0, 3.0, 4.0]); + let buf = f32_planar(2, 2, &[1.0, 2.0, 3.0, 4.0]); let samples = NodeValue::Samples(buf.clone()); let mut out = NodeValueTable::default(); let core = NodeCore::new(); diff --git a/crates/oak-node/src/nodes/merge.rs b/crates/oak-node/src/nodes/merge.rs index 69f3a2053..d99bea3c4 100644 --- a/crates/oak-node/src/nodes/merge.rs +++ b/crates/oak-node/src/nodes/merge.rs @@ -71,14 +71,6 @@ void main(void) { } "#; -impl MergeNode { - /// Fragment shader (C++ `get_shader_code()`; the request id is - /// ignored — the same alpha-over shader serves every request). - fn shader_frag() -> &'static str { - SHADER_FRAG - } -} - impl NodeBehavior for MergeNode { /// Human-readable name (C++ `name()`). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/multicamnode.rs b/crates/oak-node/src/nodes/multicamnode.rs index 02f902149..36efa5c22 100644 --- a/crates/oak-node/src/nodes/multicamnode.rs +++ b/crates/oak-node/src/nodes/multicamnode.rs @@ -18,7 +18,6 @@ //! `src/node/src/input/multicam/multicamnode.{h,cpp}`, //! `olive::MultiCamNode`). -use std::any::Any; use crate::factory::NodeMeta; use crate::id::NodeId; use crate::node::{Category, NodeBehavior, NodeCore}; diff --git a/crates/oak-node/src/nodes/ociogradingtransformlinear.rs b/crates/oak-node/src/nodes/ociogradingtransformlinear.rs index b12fc5d3a..cd8d720c7 100644 --- a/crates/oak-node/src/nodes/ociogradingtransformlinear.rs +++ b/crates/oak-node/src/nodes/ociogradingtransformlinear.rs @@ -159,6 +159,8 @@ impl OCIOGradingTransformLinearNode { /// Set the per-component widget colors of a vec4 input (C++ /// `set_vec4_input_colors()`): master `#c0c0c0`, R `#ff0000`, G /// `#00ff00`, B `#0000ff`. + #[allow(dead_code)] // C++ parity helper; the parametrized widget colours + // are re-applied through `set_input_property` at setup time. fn set_vec4_input_colors(core: &mut NodeCore, input: &str) { set_input_property( core, @@ -417,7 +419,7 @@ impl NodeBehavior for OCIOGradingTransformLinearNode { .to_double() != 0.0; let white_enabled = row_or_standard(core, inputs, CLAMP_WHITE_ENABLE_INPUT, time) .to_double() != 0.0; - let mut black = + let black = row_or_standard(core, inputs, CLAMP_BLACK_INPUT, time).to_double(); let mut white = row_or_standard(core, inputs, CLAMP_WHITE_INPUT, time).to_double(); diff --git a/crates/oak-node/src/nodes/ociogradingtransformlog.rs b/crates/oak-node/src/nodes/ociogradingtransformlog.rs index 004961a55..7ccbddaec 100644 --- a/crates/oak-node/src/nodes/ociogradingtransformlog.rs +++ b/crates/oak-node/src/nodes/ociogradingtransformlog.rs @@ -178,6 +178,7 @@ impl OCIOGradingTransformLogNode { /// Set the per-component widget colors of a vec4 input (C++ /// `set_vec4_input_colors()`): master `#c0c0c0`, R `#ff0000`, G /// `#00ff00`, B `#0000ff`. + #[allow(dead_code)] // C++ parity helper; see the linear sibling. fn set_vec4_input_colors(core: &mut NodeCore, input: &str) { set_input_property( core, @@ -448,7 +449,7 @@ impl NodeBehavior for OCIOGradingTransformLogNode { .to_double() != 0.0; let white_enabled = row_or_standard(core, inputs, CLAMP_WHITE_ENABLE_INPUT, time) .to_double() != 0.0; - let mut black = + let black = row_or_standard(core, inputs, CLAMP_BLACK_INPUT, time).to_double(); let mut white = row_or_standard(core, inputs, CLAMP_WHITE_INPUT, time).to_double(); diff --git a/crates/oak-node/src/nodes/ociolut.rs b/crates/oak-node/src/nodes/ociolut.rs index b0f537cca..7caa50bef 100644 --- a/crates/oak-node/src/nodes/ociolut.rs +++ b/crates/oak-node/src/nodes/ociolut.rs @@ -90,6 +90,7 @@ impl OCIOLutNode { /// Human-readable description of why no LUT processor is active /// (C++ `last_error()`); empty when a valid LUT processor is in use /// or no LUT file has been selected yet. + #[allow(dead_code)] // C++ parity accessor; read back by the tests. pub fn last_error(&self) -> String { self.state.lock().unwrap().last_error.clone() } @@ -98,6 +99,8 @@ impl OCIOLutNode { /// unchanged. The Qt version surfaced the error on the main-window /// status bar; here it is only recorded and read back via /// [`Self::last_error`]. + #[allow(dead_code)] // C++ parity setter; the tests feed it through + // `last_error`. fn set_last_error(&self, error: &str) { let mut state = self.state.lock().unwrap(); if state.last_error == error { @@ -139,6 +142,8 @@ impl OCIOLutNode { /// Whether this is the main GUI process (C++ file-static /// `is_main_process()`): true when a render manager exists (the /// render worker never creates one). + #[allow(dead_code)] // C++ parity probe; constants-only in the Rust model. + // The tests assert the worker answer directly. fn is_main_process() -> bool { // The C++ probes `oakrender_manager_available()`, which the // oakrender bridge does not expose. Without a render manager (the @@ -153,6 +158,7 @@ impl OCIOLutNode { /// ensures the processor is current, then — in the main process /// only — invalidates the texture-input cache and cancels background /// video cache tasks so in-flight renders cannot write stale frames. + #[allow(dead_code)] // C++ parity entry point; the tests drive it. fn generate_processor(&mut self, core: &mut NodeCore) { self.ensure_processor(core); // The C++ main-process half (`invalidate_all(k_texture_input)` diff --git a/crates/oak-node/src/nodes/opacity.rs b/crates/oak-node/src/nodes/opacity.rs index c23a4ad55..a81ea32a2 100644 --- a/crates/oak-node/src/nodes/opacity.rs +++ b/crates/oak-node/src/nodes/opacity.rs @@ -32,7 +32,10 @@ pub const VALUE_INPUT: &str = "opacity_in"; /// Opacity effect node. Multiplies a texture's alpha by a 0..1 factor. pub struct OpacityEffect { /// Owned child math node configured to `multiply` (C++ `math_`, - /// formerly a QObject child). + /// formerly a QObject child). Held for its construction side effect; + /// the multiply actually runs through `NodeCore`, so the handle is + /// never read — kept (with an `allow`) rather than removed. + #[allow(dead_code)] math: Box, } @@ -85,20 +88,6 @@ void main() { } "#; -impl OpacityEffect { - /// Fragment shader for the plain opacity path (C++ - /// `get_shader_code()` default branch). - fn shader_frag() -> &'static str { - SHADER_FRAG - } - - /// Fragment shader for the `rgbmult` request (C++ - /// `get_shader_code()` `"rgbmult"` branch). - fn shader_rgb_mult_frag() -> &'static str { - SHADER_RGB_MULT_FRAG - } -} - impl NodeBehavior for OpacityEffect { /// Human-readable name (C++ `name()`). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/premult.rs b/crates/oak-node/src/nodes/premult.rs index a3f1747b7..fb14939bd 100644 --- a/crates/oak-node/src/nodes/premult.rs +++ b/crates/oak-node/src/nodes/premult.rs @@ -47,7 +47,10 @@ pub const CHANNEL_INPUT: &str = "premult_channel_in"; /// Channel selector values for [`CHANNEL_INPUT`], in combo order. The /// numeric values are the shader's channel indices: `0` selects nothing /// (the image passes through — a factor of 1) and `1..=4` select -/// `r`/`g`/`b`/`a`. +/// `r`/`g`/`b`/`a`. Only `Alpha` is constructed today (the runtime value +/// is the raw combo index); the full upstream set is kept (with an +/// `allow`) for parity. +#[allow(dead_code)] #[repr(i64)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Channel { diff --git a/crates/oak-node/src/nodes/shapenodebase.rs b/crates/oak-node/src/nodes/shapenodebase.rs index 98ff430bd..981d85dd2 100644 --- a/crates/oak-node/src/nodes/shapenodebase.rs +++ b/crates/oak-node/src/nodes/shapenodebase.rs @@ -73,6 +73,7 @@ impl ShapeNodeBase { /// signature. The property write and the gizmo point placements are /// therefore not representable here (`// CPP-PARITY: /// shapenodebase.cpp` `update_gizmo_positions`). + #[allow(dead_code)] // C++ parity helpers; covered by the no-op tests. pub fn update_gizmo_positions( core: &mut crate::node::NodeCore, row: &crate::value::NodeValueRow, @@ -88,6 +89,7 @@ impl ShapeNodeBase { /// command stack; neither is carried by this signature or this /// crate's data model, so the writes are not representable here /// (`// CPP-PARITY: shapenodebase.cpp` `set_rect`). + #[allow(dead_code)] pub fn set_rect(core: &mut crate::node::NodeCore, rect: (f64, f64, f64, f64)) { let _ = (core, rect); } @@ -106,6 +108,7 @@ impl ShapeNodeBase { /// Rust `NodeCore::gizmos` has no dragger state, so the drag is not /// representable here (`// CPP-PARITY: shapenodebase.cpp` /// `gizmo_drag_move`). + #[allow(dead_code)] pub fn gizmo_drag_move(core: &mut crate::node::NodeCore, x: f64, y: f64, modifiers: u32) { let _ = (core, x, y, modifiers); } diff --git a/crates/oak-node/src/nodes/textbackend.rs b/crates/oak-node/src/nodes/textbackend.rs index 095e52456..0bfb9932b 100644 --- a/crates/oak-node/src/nodes/textbackend.rs +++ b/crates/oak-node/src/nodes/textbackend.rs @@ -182,8 +182,8 @@ mod tests { fn backend_hooks_default_none() { let _guard = TEST_BACKEND_LOCK.lock().unwrap(); set_text_backends(None, None); - assert_eq!(text_measure_backend(), None); - assert_eq!(text_render_backend(), None); + assert!(text_measure_backend().is_none()); + assert!(text_render_backend().is_none()); } #[test] @@ -195,7 +195,7 @@ mod tests { height: 34.0, } } - fn render(_r: &TextLayoutRequest, _t: &TextRenderTransform, mut target: TextRenderTarget) { + fn render(_r: &TextLayoutRequest, _t: &TextRenderTransform, target: TextRenderTarget) { for b in target.data.iter_mut() { *b = 255; } diff --git a/crates/oak-node/src/nodes/textv1.rs b/crates/oak-node/src/nodes/textv1.rs index 1ca669a84..34146cc9f 100644 --- a/crates/oak-node/src/nodes/textv1.rs +++ b/crates/oak-node/src/nodes/textv1.rs @@ -79,6 +79,7 @@ impl TextGeneratorV1 { /// and the wrap width at 80% of the frame width (the "title safe" /// area — `(width / 10) * 8`). The measure backend is not consulted /// here. + #[allow(dead_code)] // C++ parity helper; the tests drive it. pub fn layout_request(row: &NodeValueRow, frame_width: i32) -> TextLayoutRequest { let text = row .get(TEXT_INPUT) @@ -115,6 +116,7 @@ impl TextGeneratorV1 { /// valign combo (top: 10% top margin; center: frame center; bottom: /// 10% bottom margin). The C++ math is integer (`width()/10`, /// `height()/2 - doc_height/2`, ...), mirrored here. + #[allow(dead_code)] pub fn draw_offsets( valign: i32, frame_width: i32, @@ -144,6 +146,7 @@ impl TextGeneratorV1 { /// The render step and the alpha transplant need the frame's pixel /// buffer, which the Rust frame handle does not expose; they are not /// representable here (`// CPP-PARITY: textv1.cpp` `generate_frame`). + #[allow(dead_code)] pub fn measure_and_layout( row: &NodeValueRow, frame_width: i32, diff --git a/crates/oak-node/src/nodes/textv2.rs b/crates/oak-node/src/nodes/textv2.rs index c1fa1a289..c56b25ea3 100644 --- a/crates/oak-node/src/nodes/textv2.rs +++ b/crates/oak-node/src/nodes/textv2.rs @@ -73,6 +73,7 @@ fn to_text(v: &NodeValue) -> String { } /// `Variant::to_vec2()` for the inherited position/size inputs. +#[allow(dead_code)] // C++ parity accessor used by the tests. fn to_vec2(v: &NodeValue) -> [f64; 2] { match v { NodeValue::Vec2(a) => *a, @@ -86,6 +87,7 @@ impl TextGeneratorV2 { /// replaced by `
` when `html_in` is set, 72 DPI /// (`dots_per_meter = 2835`), and the wrap width at the shape /// size X. + #[allow(dead_code)] pub fn layout_request(row: &NodeValueRow) -> TextLayoutRequest { let text = row .get(TEXT_INPUT) @@ -124,6 +126,7 @@ impl TextGeneratorV2 { /// position re-centered into frame space — /// `pos - size/2 + frame/2` (the frame halves are integer division in /// C++). + #[allow(dead_code)] pub fn base_offset( pos: [f64; 2], size: [f64; 2], @@ -140,6 +143,7 @@ impl TextGeneratorV2 { /// offset plus the vertical alignment delta — top: none; center: /// `size.y/2 - doc_height/2` (the halving is integer on the /// `int(doc.height)`); bottom: `size.y - doc_height`. + #[allow(dead_code)] pub fn draw_offset( valign: i32, base: (f64, f64), @@ -163,6 +167,7 @@ impl TextGeneratorV2 { /// scale, the draw offset, and the clip rect at the base offset /// covering the shape size (set before the vertical-alignment /// translate in the C++). + #[allow(dead_code)] pub fn render_transform( scale: f64, draw: (f64, f64), @@ -190,6 +195,7 @@ impl TextGeneratorV2 { /// The render step and the alpha transplant need the frame's pixel /// buffer, which the Rust frame handle does not expose; they are not /// representable here (`// CPP-PARITY: textv2.cpp` `generate_frame`). + #[allow(dead_code)] pub fn measure_and_layout( row: &NodeValueRow, frame_width: i32, diff --git a/crates/oak-node/src/nodes/textv3.rs b/crates/oak-node/src/nodes/textv3.rs index bad4f510e..6dd913025 100644 --- a/crates/oak-node/src/nodes/textv3.rs +++ b/crates/oak-node/src/nodes/textv3.rs @@ -334,6 +334,7 @@ impl TextGeneratorV3 { /// Middle -> `TextGizmo::k_align_vcenter`, Bottom -> /// `TextGizmo::k_align_bottom` (0 = top, 1 = bottom, 2 = vcenter in /// the gizmo's numbering). + #[allow(dead_code)] // C++ parity helpers; covered by the tests. pub fn get_gizmo_alignment_from_ours(v: VerticalAlignment) -> i32 { match v { VerticalAlignment::Top => 0, @@ -413,6 +414,7 @@ impl TextGeneratorV3 { /// Gizmo activated callback (C++ `gizmo_activated()`): sets /// `use_args_in` to `false` and `dont_emit_valign_ = true`. + #[allow(dead_code)] // C++ parity callbacks; covered by the tests. fn gizmo_activated(&mut self, core: &mut NodeCore) { core.set_standard_value(USE_ARGS_INPUT, -1, NodeValue::Boolean(false)); self.dont_emit_valign = true; @@ -420,6 +422,7 @@ impl TextGeneratorV3 { /// Gizmo deactivated callback (C++ `gizmo_deactivated()`): sets /// `use_args_in` to `true` and `dont_emit_valign_ = true`. + #[allow(dead_code)] fn gizmo_deactivated(&mut self, core: &mut NodeCore) { core.set_standard_value(USE_ARGS_INPUT, -1, NodeValue::Boolean(true)); self.dont_emit_valign = true; @@ -431,6 +434,7 @@ impl TextGeneratorV3 { /// command stack is not part of this crate, so only the resulting /// standard-value write is performed (`// CPP-PARITY: textv3.cpp` /// `set_vertical_alignment_undoable`). + #[allow(dead_code)] fn set_vertical_alignment_undoable(&mut self, core: &mut NodeCore, a: i32) { core.set_standard_value( VERTICAL_ALIGNMENT_INPUT, @@ -738,6 +742,7 @@ impl TextGeneratorV3 { /// dots/meter) with the font taken from the markup. Both wrap to the /// shape size X; the backend defaults are used when font family/size /// are empty/zero. + #[allow(dead_code)] pub fn layout_request(row: &NodeValueRow) -> TextLayoutRequest { Self::layout_request_path(Self::plain_text_path(), row) } @@ -785,6 +790,7 @@ impl TextGeneratorV3 { /// The C++ base offset (textv3.cpp `generate_frame()`): the shape /// position re-centered into frame space — `pos - size/2 + frame/2` /// (the frame halves are integer division in C++). + #[allow(dead_code)] // C++ parity helpers; the tests drive them. pub fn base_offset( pos: [f64; 2], size: [f64; 2], @@ -846,6 +852,7 @@ impl TextGeneratorV3 { /// The render step needs the frame's pixel buffer, which the Rust /// frame handle does not expose; it is not representable here /// (`// CPP-PARITY: textv3.cpp` `generate_frame`). + #[allow(dead_code)] pub fn measure_and_layout(row: &NodeValueRow) -> (TextLayoutRequest, TextLayoutSize) { let req = Self::layout_request(row); let doc = match super::textbackend::text_measure_backend() { diff --git a/crates/oak-node/src/nodes/threewaycolor.rs b/crates/oak-node/src/nodes/threewaycolor.rs index cdb987094..61641b2b7 100644 --- a/crates/oak-node/src/nodes/threewaycolor.rs +++ b/crates/oak-node/src/nodes/threewaycolor.rs @@ -102,14 +102,6 @@ void main(void) } "#; -impl ThreeWayColorNode { - /// Fragment shader for any request (C++ `get_shader_code()` ignores - /// the request id and always returns this shader). - fn shader_frag() -> &'static str { - SHADER_FRAG - } -} - impl NodeBehavior for ThreeWayColorNode { /// Human-readable name (C++ `name()`, inline in the header). fn name(&self) -> &str { diff --git a/crates/oak-node/src/nodes/tiledistortnode.rs b/crates/oak-node/src/nodes/tiledistortnode.rs index 7ec98f510..e360fed1c 100644 --- a/crates/oak-node/src/nodes/tiledistortnode.rs +++ b/crates/oak-node/src/nodes/tiledistortnode.rs @@ -50,6 +50,10 @@ pub const MIRROR_Y_INPUT: &str = "mirrory_in"; /// Anchor point for tiling (C++ private enum `Anchor`); values match /// the `anchor_in` combo indices and the shader's `anchor_in` defines. +/// Only `MiddleCenter` is constructed today (the runtime value is the +/// raw combo index); the full upstream set is kept (with an `allow`) +/// for parity. +#[allow(dead_code)] #[derive(Clone, Copy, PartialEq, Eq)] pub enum Anchor { /// Top-left corner. diff --git a/crates/oak-node/src/nodes/transformdistortnode.rs b/crates/oak-node/src/nodes/transformdistortnode.rs index 9092d10e0..7691edb03 100644 --- a/crates/oak-node/src/nodes/transformdistortnode.rs +++ b/crates/oak-node/src/nodes/transformdistortnode.rs @@ -85,6 +85,9 @@ pub const GIZMO_SCALE_COUNT: usize = 8; /// Auto-scale mode (C++ `AutoScaleType`); values match the /// `autoscale_in` combo indices. #[derive(Clone, Copy, Debug, PartialEq, Eq)] +// C++ parity value set (`AutoScaleType`); only `None` is constructed at +// runtime (the combo indices are still resolved through this enum). +#[allow(dead_code)] pub enum AutoScaleType { /// No auto-scaling. None = 0, @@ -99,6 +102,7 @@ pub enum AutoScaleType { /// Rotation direction for wrap-around detection (C++ private enum /// `RotationDirection`). #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[allow(dead_code)] // C++ parity value set; see `AutoScaleType`. enum RotationDirection { /// No direction established yet. None, @@ -110,6 +114,7 @@ enum RotationDirection { /// Which axes a scale gizmo drags (C++ private enum `GizmoScaleType`). #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[allow(dead_code)] // C++ parity value set; see `AutoScaleType`. enum GizmoScaleType { /// Horizontal center handles (C++ `k_gizmo_scale_x_only`). XOnly, @@ -191,6 +196,8 @@ impl TransformDistortNode { /// representable: `generate_auto_scaled_matrix` needs the texture /// params from the C++ `VideoParams` (the Rust texture handle carries /// no params) and `is_a_scale_gizmo` compares gizmo pointers. + #[allow(dead_code)] // C++ parity helpers; the pure ones are covered by + // the tests, the rest are not representable in the Rust model. fn adjust_matrix_by_resolutions( mat: [f64; 16], sequence_res: (f64, f64), @@ -264,6 +271,7 @@ impl TransformDistortNode { /// C++ `Matrix4x4::map(PointF)` equivalent: maps `p` through the /// row-major matrix treating it as `(x, y, 0, 1)`, dividing by the /// resulting `w` whenever it is not exactly 1. + #[allow(dead_code)] fn map_point(mat: [f64; 16], p: (f64, f64)) -> (f64, f64) { let x = p.0 * mat[0] + p.1 * mat[1] + mat[3]; let y = p.0 * mat[4] + p.1 * mat[5] + mat[7]; @@ -278,6 +286,7 @@ impl TransformDistortNode { /// Scale-point gizmo placement (C++ `create_scale_point()`): maps the /// unit-square position through `mat` and adds the sequence half /// resolution. + #[allow(dead_code)] fn create_scale_point(x: f64, y: f64, half_res: (f64, f64), mat: [f64; 16]) -> (f64, f64) { let p = Self::map_point(mat, (x, y)); (p.0 + half_res.0, p.1 + half_res.1) @@ -286,6 +295,7 @@ impl TransformDistortNode { /// Rotation direction of a mouse angle step (C++ /// `get_direction_from_angles()`): positive when `current` is greater /// than `last`, negative otherwise. + #[allow(dead_code)] fn get_direction_from_angles(last: f64, current: f64) -> RotationDirection { if current > last { RotationDirection::Positive diff --git a/crates/oak-node/src/nodes/trigonometry.rs b/crates/oak-node/src/nodes/trigonometry.rs index 6b6abbe89..dcc01448c 100644 --- a/crates/oak-node/src/nodes/trigonometry.rs +++ b/crates/oak-node/src/nodes/trigonometry.rs @@ -190,7 +190,7 @@ pub fn create() -> (NodeCore, Box) { )]; core.add_input(method); - let mut x = crate::input::Input::new( + let x = crate::input::Input::new( X_INPUT, crate::value::ValueType::Float, crate::value::NodeValue::Float(0.0), diff --git a/crates/oak-node/src/nodes/unpremult.rs b/crates/oak-node/src/nodes/unpremult.rs index dc6b9e230..2fc2862d6 100644 --- a/crates/oak-node/src/nodes/unpremult.rs +++ b/crates/oak-node/src/nodes/unpremult.rs @@ -48,7 +48,10 @@ pub const CHANNEL_INPUT: &str = "unpremult_channel_in"; /// Channel selector values for [`CHANNEL_INPUT`], in combo order. The /// numeric values are the shader's channel indices: `0` selects nothing /// (the image passes through — a divisor of 1) and `1..=4` select -/// `r`/`g`/`b`/`a`. +/// `r`/`g`/`b`/`a`. Only `Alpha` is constructed today (the runtime value +/// is the raw combo index); the full upstream set is kept (with an +/// `allow`) for parity. +#[allow(dead_code)] #[repr(i64)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Channel { diff --git a/crates/oak-node/src/nodes/whitebalance.rs b/crates/oak-node/src/nodes/whitebalance.rs index 7c4d11e2c..27a6ff3d8 100644 --- a/crates/oak-node/src/nodes/whitebalance.rs +++ b/crates/oak-node/src/nodes/whitebalance.rs @@ -73,12 +73,6 @@ void main(void) "#; impl WhiteBalanceNode { - /// Fragment shader for any request (C++ `get_shader_code()` ignores - /// the request id and always returns this shader). - fn shader_frag() -> &'static str { - SHADER_FRAG - } - /// RGB gains for a given illuminant temperature and tint (C++ /// `get_gain_for_temperature()`, extracted for testability). Kelvin /// is clamped to [1000, 40000]; the Tanner Helland blackbody diff --git a/crates/oak-node/src/ops.rs b/crates/oak-node/src/ops.rs index 16b7d9ddc..5c533aac4 100644 --- a/crates/oak-node/src/ops.rs +++ b/crates/oak-node/src/ops.rs @@ -114,9 +114,9 @@ pub fn copy_inputs( /// node ids (source order). Undo packaging happens at the caller via /// oakundo's `UndoCommand`. pub fn copy_subgraph( - graph: &mut Graph, - nodes: &[NodeId], - exclude_items: bool, + _graph: &mut Graph, + _nodes: &[NodeId], + _exclude_items: bool, ) -> crate::error::Result> { todo!() } @@ -124,22 +124,22 @@ pub fn copy_subgraph( /// Transform a time range from one node's frame of reference to /// another's along the connection path (C++ `Node::transform_time_to`). pub fn transform_time_to( - graph: &Graph, - time: TimeRange, - from: NodeId, - to: NodeId, + _graph: &Graph, + _time: TimeRange, + _from: NodeId, + _to: NodeId, ) -> crate::error::Result { todo!() } /// Undo-command display strings (C++ /// `get_connect_command_string`/`get_disconnect_command_string`). -pub fn connect_command_string(output: NodeId, input: NodeId, input_id: &str) -> String { +pub fn connect_command_string(_output: NodeId, _input: NodeId, _input_id: &str) -> String { todo!() } /// See [`connect_command_string`]. -pub fn disconnect_command_string(output: NodeId, input: NodeId, input_id: &str) -> String { +pub fn disconnect_command_string(_output: NodeId, _input: NodeId, _input_id: &str) -> String { todo!() } @@ -181,8 +181,9 @@ pub fn set_value_at_time_command( use crate::error::Error; use crate::keyframe::{Interpolation, Keyframe}; - // Determine the mutation from the current state. - let declared = graph + // Determine the mutation from the current state. The declared type is + // validated but not otherwise used yet. + let _declared = graph .get(node) .and_then(|e| e.core.input_data_type(input)) .ok_or(Error::NotFound)?; diff --git a/crates/oak-node/src/project.rs b/crates/oak-node/src/project.rs index 04b73d480..7c8e51c65 100644 --- a/crates/oak-node/src/project.rs +++ b/crates/oak-node/src/project.rs @@ -17,7 +17,7 @@ //! Project: owns the graph, the folder tree, settings, and the undo //! stack binding. Mirrors C++ `olive::Project`. -use std::sync::{Arc, Mutex, Weak}; +use std::sync::{Arc, Mutex}; use crate::graph::Graph; use crate::id::NodeId; @@ -451,7 +451,3 @@ pub enum ChangeRecord { }, } -/// Weak-project handle used by the identity registry (node_from_identity -/// upgrades it; a freed project leaves a dead weak entry that upgrades -/// to `None`). -pub(crate) type WeakProject = Weak>; diff --git a/crates/oak-node/src/sequence.rs b/crates/oak-node/src/sequence.rs index c0ed28ba6..bad85717f 100644 --- a/crates/oak-node/src/sequence.rs +++ b/crates/oak-node/src/sequence.rs @@ -24,11 +24,11 @@ use crate::input::Input; use crate::node::{Category, NodeBehavior, NodeCore}; use crate::value::{AudioParams, NodeValue, ValueType, VideoParams}; -/// Sequence texture/samples input ids (ViewerOutput::k_texture_input / -/// k_samples_input) and the track input id format (Sequence:: -/// k_track_input_format). +/// Sequence texture input id (C++ `ViewerOutput::k_texture_input`). pub const TEXTURE_INPUT: &str = "tex_in"; +/// Sequence audio samples input id (C++ `ViewerOutput::k_samples_input`). pub const SAMPLES_INPUT: &str = "samples_in"; +/// Sequence per-track input id format (C++ `Sequence::k_track_input_format`). pub const TRACK_INPUT_FORMAT: &str = "track_in_%1"; /// Sequence behavior (viewer node). diff --git a/crates/oak-node/src/serializer.rs b/crates/oak-node/src/serializer.rs index c9dad8d4e..0eadff73c 100644 --- a/crates/oak-node/src/serializer.rs +++ b/crates/oak-node/src/serializer.rs @@ -39,7 +39,7 @@ use crate::graph::Graph; use crate::id::NodeId; use crate::keyframe::{Interpolation, Keyframe}; use crate::node::NodeCore; -use crate::project::{NodeRef, Project}; +use crate::project::Project; use crate::value::{NodeValue, ValueType}; /// Minimal XML reader surface the serializer needs (implemented over @@ -565,7 +565,6 @@ fn load_project_body( reader: &mut dyn XmlRead, project: &mut Project, ) -> crate::error::Result> { - use crate::error::Error; // Identity -> NodeId map for connection resolution. let mut id_map: std::collections::HashMap = std::collections::HashMap::new(); // Deferred connections: (output_identity, input_node_id, input_id, element). @@ -693,7 +692,7 @@ fn load_node( // types fall back to an error. `create_any` also covers the dynamic // (runtime-registered OpenFX plugin) entries — `find` alone would // reject every project that carries a plugin node. - let (mut core, behavior): (NodeCore, Box) = + let (core, behavior): (NodeCore, Box) = match create_timeline_type(&type_id) { Some(x) => x, None => match crate::factory::Factory::global().create_any(&type_id) { diff --git a/crates/oak-node/src/value.rs b/crates/oak-node/src/value.rs index 7ed887ed6..4bedc005f 100644 --- a/crates/oak-node/src/value.rs +++ b/crates/oak-node/src/value.rs @@ -203,11 +203,6 @@ impl SampleBuffer { return None; } let bps = self.format.bytes_per_sample(); - let stride = if self.format.is_planar() { - self.sample_count - } else { - self.channels - }; let pos = if self.format.is_planar() { channel * self.sample_count + index } else { @@ -695,7 +690,7 @@ impl Clone for NodeValue { fn clone(&self) -> Self { match self { NodeValue::Texture(h) => { - let mut h2 = h.clone(); + let h2 = h.clone(); if let Some(f) = h2.addref { // Safety: `h2` is a valid handle; addref only touches // the refcount. @@ -771,7 +766,7 @@ impl OakNodeValue { /// Map an oaknode_value POD into a [`NodeValue`] of the input's /// declared type (C++ `variant_from_value`). `OAKNODE_VALUE_STRING` /// and unknown kinds are rejected with [`Error::Invalid`]. - pub fn to_node_value(self, declared: ValueType) -> crate::error::Result { + pub fn to_node_value(self, _declared: ValueType) -> crate::error::Result { use crate::error::Error; match self.kind { oak::INT | oak::COMBO => Ok(NodeValue::Int(self.num)), @@ -858,10 +853,7 @@ impl OakNodeValue { out.f = a; Ok(out) } - _ => { - out.kind = oak::NONE; - Err(Error::Failed("type has no POD representation".to_string())) - } + _ => Err(Error::Failed("type has no POD representation".to_string())), } } } diff --git a/crates/oak-node/tests/engine_units_test.rs b/crates/oak-node/tests/engine_units_test.rs index 0e18b3b91..144a8192c 100644 --- a/crates/oak-node/tests/engine_units_test.rs +++ b/crates/oak-node/tests/engine_units_test.rs @@ -693,7 +693,7 @@ fn node_behavior_defaults() { // value / process_samples / generate_frame no-ops. let mut table = NodeValueTable::default(); - let mut row = std::collections::BTreeMap::new(); + let row = std::collections::BTreeMap::new(); b.value(&core, &row, Rational::new(0, 1), &mut table); assert!(table.is_empty()); let mut samples = SampleBuffer::default(); diff --git a/crates/oak-node/tests/graph_test.rs b/crates/oak-node/tests/graph_test.rs index 0a32a62e9..63223e2d7 100644 --- a/crates/oak-node/tests/graph_test.rs +++ b/crates/oak-node/tests/graph_test.rs @@ -50,7 +50,7 @@ impl NodeBehavior for TestNode { fn build(n: usize) -> (Graph, Vec) { let mut g = Graph::new(); let mut ids = Vec::new(); - for i in 0..n { + for _ in 0..n { let mut core = NodeCore::new(); core.add_input(Input::new( "val_in", @@ -159,7 +159,7 @@ fn cycle_rejection() { /// yields empty order; diamond graph has a valid (stable) order. #[test] fn topological_order() { - let mut g = Graph::new(); + let g = Graph::new(); assert!(g.topological_order().is_empty()); let (mut g, ids) = build(4); diff --git a/crates/oak-node/tests/phase2_units_test.rs b/crates/oak-node/tests/phase2_units_test.rs index 0642f620a..1ae29b5c3 100644 --- a/crates/oak-node/tests/phase2_units_test.rs +++ b/crates/oak-node/tests/phase2_units_test.rs @@ -79,7 +79,7 @@ fn block_behaviors_and_inputs() { assert!(clip.footage.is_none()); // Gap. - let (core, behavior) = oak_node::block::gap_create(); + let (_core, behavior) = oak_node::block::gap_create(); assert_eq!(behavior.name(), "Gap"); assert_eq!(behavior.type_id(), "org.olivevideoeditor.Olive.gapblock"); let gap = GapBlockBehavior::new(); @@ -287,7 +287,7 @@ fn color_manager_state() { cm.set_up_default_config().unwrap(); assert!(cm.is_loaded()); - let mut empty = ColorManager::new(); + let empty = ColorManager::new(); assert!(empty.list_colorspaces().is_empty()); } diff --git a/crates/oak-node/tests/serializer_test.rs b/crates/oak-node/tests/serializer_test.rs index 13aa15e27..fa0d541c7 100644 --- a/crates/oak-node/tests/serializer_test.rs +++ b/crates/oak-node/tests/serializer_test.rs @@ -526,7 +526,7 @@ fn assert_full_roundtrip_fields(orig: &oak_node::project::Project, loaded: &oak_ use oak_node::folder::FolderBehavior; use oak_node::footage::FootageBehavior; use oak_node::sequence::SequenceBehavior; - use oak_node::track::{TrackBehavior, TrackListBehavior, TrackType}; + use oak_node::track::{TrackBehavior, TrackType}; // Project shell: uuid + settings. assert_eq!(loaded.uuid, orig.uuid, "uuid"); diff --git a/crates/oak-node/tests/traverser_test.rs b/crates/oak-node/tests/traverser_test.rs index 3574a1fc6..f7b536f18 100644 --- a/crates/oak-node/tests/traverser_test.rs +++ b/crates/oak-node/tests/traverser_test.rs @@ -258,7 +258,7 @@ impl NodeBehavior for Echo { /// track read at its midpoint feeds 5. #[test] fn unconnected_input_evaluates_keyframes_at_time() { - use oak_node::keyframe::{Keyframe, KeyframeTrack}; + use oak_node::keyframe::Keyframe; let mut g = Graph::new(); let mut core = NodeCore::new(); core.add_input(Input::new("val_in", ValueType::Float, NodeValue::Float(0.0))); diff --git a/crates/oak-plugin/src/host.rs b/crates/oak-plugin/src/host.rs index f05a071d5..f1a3a2ee4 100644 --- a/crates/oak-plugin/src/host.rs +++ b/crates/oak-plugin/src/host.rs @@ -276,8 +276,6 @@ fn global_ofx_host() -> *mut OfxHost { /// kOfxActionLoad。 pub(crate) const ACTION_LOAD: &str = "OfxActionLoad"; -/// kOfxActionUnload。 -pub(crate) const ACTION_UNLOAD: &str = "OfxActionUnload"; /// kOfxActionDescribe。 pub(crate) const ACTION_DESCRIBE: &str = "OfxActionDescribe"; /// kOfxActionCreateInstance。 @@ -552,8 +550,6 @@ pub(crate) const PROP_CLIP_COLOURSPACE: &str = "OfxImageClipPropColourspace"; /// kOfxImageClipPropPreferredColourspaces(ofxColour.h:201):clip 偏好 /// 色彩空间(GetClipPreferences 的 out args 可写)。 pub(crate) const PROP_CLIP_PREFERRED_COLOURSPACES: &str = "OfxImageClipPropPreferredColourspaces"; -/// 工作空间(任务要求:全链路 ACEScg)。 -pub(crate) const WORKING_COLOURSPACE: &str = "ACEScg"; /// 宿主支持的 native 色彩配置标识(ofxColour.h:78 的唯一现行值)。 pub(crate) const NATIVE_CONFIG_ID: &str = "ofx-native-v1.5_aces-v1.3_ocio-v2.3"; /// 宿主 OCIO 配置 URI(ofxColour.h:110 允许 ocio:// 内建配置;本宿主 diff --git a/crates/oak-plugin/src/node_factory.rs b/crates/oak-plugin/src/node_factory.rs index e822ccaa5..eedd63769 100644 --- a/crates/oak-plugin/src/node_factory.rs +++ b/crates/oak-plugin/src/node_factory.rs @@ -1304,7 +1304,7 @@ mod tests { ) -> i32 { 0 } - let mut def = ParamDef::new("curve", ofx::TYPE_PARAMETRIC); + let def = ParamDef::new("curve", ofx::TYPE_PARAMETRIC); def.props .set_one(ofx::PROP_LABEL, PropValue::String(CString::new("Curve").unwrap())); def.props diff --git a/crates/oak-plugin/src/param.rs b/crates/oak-plugin/src/param.rs index ece53a59e..2e3c0f399 100644 --- a/crates/oak-plugin/src/param.rs +++ b/crates/oak-plugin/src/param.rs @@ -362,7 +362,7 @@ impl ParamDef { /// 按 OFX 类型构建定义(镜像 HS ofxhParam.cpp:224-352: /// universalProps + addStandardParamProps 的分类型属性表)。 pub(crate) fn new(name: &str, ofx_type: &str) -> Self { - let mut props = PropertySet::new(); + let props = PropertySet::new(); let uname = name.to_string(); let utype = ofx_type.to_string(); diff --git a/crates/oak-plugin/src/suites/image_effect.rs b/crates/oak-plugin/src/suites/image_effect.rs index f89a904d2..e55f53867 100644 --- a/crates/oak-plugin/src/suites/image_effect.rs +++ b/crates/oak-plugin/src/suites/image_effect.rs @@ -505,7 +505,7 @@ mod tests { /// 重复定义整体替换(HS map 覆盖)。 #[test] fn describe_clip_define_and_props() { - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = suite_v1(); let h = descriptor_handle(&desc); diff --git a/crates/oak-plugin/src/suites/interact.rs b/crates/oak-plugin/src/suites/interact.rs index fe11ed180..e49457687 100644 --- a/crates/oak-plugin/src/suites/interact.rs +++ b/crates/oak-plugin/src/suites/interact.rs @@ -490,10 +490,6 @@ mod tests { use std::ffi::{c_char, CStr}; use std::sync::Mutex; - fn cs(s: &str) -> CString { - CString::new(s).unwrap() - } - /// interact 属性表:PixelScale/ViewportSize/SuggestedColour/ /// SlaveToParam/BitDepth/HasAlpha 等按头文件预置,经 property suite /// 可读写。 diff --git a/crates/oak-plugin/src/suites/memory.rs b/crates/oak-plugin/src/suites/memory.rs index 57c094cf2..2c633407c 100644 --- a/crates/oak-plugin/src/suites/memory.rs +++ b/crates/oak-plugin/src/suites/memory.rs @@ -81,17 +81,6 @@ pub(crate) fn free(ptr: *mut u8) -> bool { } } -/// 兜底回收全部在账块(destroyInstance 的泄漏防线)。返回回收块数 -/// (泄漏断言用)。 -pub(crate) fn sweep_leaked() -> usize { - let mut ledger = lock(); - let n = ledger.len(); - for b in ledger.drain(..) { - unsafe { std::alloc::dealloc(b.ptr as *mut u8, b.layout) }; - } - n -} - /// 函数表布局(与 SDK `OfxMemorySuiteV1` 一致;`size_t` 在本平台 /// 与 `usize` 同宽,stable Rust 用 `usize` 表达——骨架的 `c_size_t` /// 是不稳定特性,弃用)。 diff --git a/crates/oak-plugin/src/suites/mod.rs b/crates/oak-plugin/src/suites/mod.rs index e83739e6f..b16f9e520 100644 --- a/crates/oak-plugin/src/suites/mod.rs +++ b/crates/oak-plugin/src/suites/mod.rs @@ -212,9 +212,6 @@ pub(crate) fn gl_ctx() -> Option { GL_CTX.with(|c| c.borrow().clone()) } -/// 宿主进程身份(fetchSuite 的 version 检查用;= OFX API 1.5)。 -pub(crate) const OFX_API_VERSION: i32 = 105; - /// fetchSuite 宿主入口:按名字与版本返回函数表指针;不认识或版本 /// 不符返回 `None`(FFI 层转 NULL)。 /// diff --git a/crates/oak-plugin/src/suites/multithread.rs b/crates/oak-plugin/src/suites/multithread.rs index 91688f6cc..112ce56c2 100644 --- a/crates/oak-plugin/src/suites/multithread.rs +++ b/crates/oak-plugin/src/suites/multithread.rs @@ -260,7 +260,6 @@ pub fn suite_v1() -> &'static MultiThreadSuiteV1 { mod tests { use super::*; use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Mutex; /// 每个插件线程把 (index, count) 累计进 userdata。 unsafe extern "C" fn worker(index: c_uint, count: c_uint, arg: *mut c_void) { diff --git a/crates/oak-plugin/src/suites/param.rs b/crates/oak-plugin/src/suites/param.rs index d124e1184..934d053eb 100644 --- a/crates/oak-plugin/src/suites/param.rs +++ b/crates/oak-plugin/src/suites/param.rs @@ -787,7 +787,7 @@ mod tests { /// 用 paramDefine 建一个实例(describe 产物 → createInstance)。 fn make_instance() -> (Arc, *mut c_void) { - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = suite_v1(); let dhandle = descriptor_handle(&desc); unsafe { @@ -836,7 +836,7 @@ mod tests { #[test] fn describe_define_and_get() { - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = suite_v1(); let handle = descriptor_handle(&desc); let t = cs("OfxParamTypeDouble"); diff --git a/crates/oak-plugin/src/suites/parametric.rs b/crates/oak-plugin/src/suites/parametric.rs index 0e6efbbf7..62dd79819 100644 --- a/crates/oak-plugin/src/suites/parametric.rs +++ b/crates/oak-plugin/src/suites/parametric.rs @@ -42,10 +42,8 @@ //! BadHandle/BadIndex)。 use std::borrow::Cow; -use std::ffi::{c_char, c_double, c_int, c_void}; +use std::ffi::{c_double, c_int, c_void}; -use crate::descriptor::EffectDescriptor; -use crate::instance::Instance; use crate::param::{ParamDef, ParamInstance, ParamValue}; use crate::param_curve::Curve; use crate::property::{PropertySet, Value}; @@ -414,10 +412,12 @@ pub fn suite_v1() -> &'static ParametricParameterSuiteV1 { #[cfg(test)] mod tests { use super::*; - use std::ffi::CString; + use std::ffi::{c_char, CString}; use std::sync::Arc; + use crate::descriptor::EffectDescriptor; use crate::host::Plugin; + use crate::instance::Instance; use crate::param::{ParamInstance, ParamSetInstance}; use crate::property::PropertySet; diff --git a/crates/oak-plugin/src/suites/property.rs b/crates/oak-plugin/src/suites/property.rs index 417341105..efa3fe0f9 100644 --- a/crates/oak-plugin/src/suites/property.rs +++ b/crates/oak-plugin/src/suites/property.rs @@ -498,7 +498,7 @@ unsafe extern "C" fn prop_get_string( let r = get_string(set, name, index); if std::env::var_os("OAK_OFX_TRACE").is_some() { let rendered = match &r { - Ok(p) => format!("0 <- {:?}", unsafe { std::ffi::CStr::from_ptr(*p) }), + Ok(p) => format!("0 <- {:?}", std::ffi::CStr::from_ptr(*p)), Err(c) => format!("{c}"), }; eprintln!("[ofx] propGetString(h={handle:p}, {name}[{index}]) -> {rendered}"); diff --git a/crates/oak-plugin/tests/common/mod.rs b/crates/oak-plugin/tests/common/mod.rs index 21e88e42c..7a20c5ad1 100644 --- a/crates/oak-plugin/tests/common/mod.rs +++ b/crates/oak-plugin/tests/common/mod.rs @@ -23,6 +23,10 @@ //! 单库化后像素路径经 oakrender 值模型(`oak_core::texture::Texture`) //! 驱动;渲染 goldens 待该迁移落地。 +// 每个集成测试二进制都会独立编译本模块,只用到自己需要的那部分辅助件, +// 因此某个二进制里未用到的条目仍属于共享夹具 API。 +#![allow(dead_code)] + use std::path::PathBuf; /// 构建系统注入插件路径的环境变量名。 diff --git a/crates/oak-plugin/tests/gl_render_test.rs b/crates/oak-plugin/tests/gl_render_test.rs index f8c4b33ee..4fb40690a 100644 --- a/crates/oak-plugin/tests/gl_render_test.rs +++ b/crates/oak-plugin/tests/gl_render_test.rs @@ -36,7 +36,7 @@ mod common; -use std::ffi::{c_char, c_int, c_void, CStr, CString}; +use std::ffi::{c_char, c_int, c_void, CStr}; use std::sync::Arc; use oak_core::{PixelFormat, Rational}; @@ -91,10 +91,6 @@ unsafe extern "C" fn capture_msg( 1 } -fn cs(s: &str) -> CString { - CString::new(s).unwrap() -} - fn first_pixel(texture: &Texture) -> [f32; 4] { let Texture::Cpu(frame) = texture else { panic!("期望 CPU 帧"); diff --git a/crates/oak-plugin/tests/property_test.rs b/crates/oak-plugin/tests/property_test.rs index 1b4d997f1..9e45b2e7f 100644 --- a/crates/oak-plugin/tests/property_test.rs +++ b/crates/oak-plugin/tests/property_test.rs @@ -191,7 +191,7 @@ fn concurrent_access() { } // 数据自洽:32 个属性全部存活、维度未被撑大。 - for (i, name) in names.iter().enumerate() { + for name in names.iter() { assert_eq!(s.dimension(name), 1); assert!(s.get(name, 0).is_some()); } diff --git a/crates/oak-plugin/tests/suites_test.rs b/crates/oak-plugin/tests/suites_test.rs index cd09d99a5..8eaee3ba4 100644 --- a/crates/oak-plugin/tests/suites_test.rs +++ b/crates/oak-plugin/tests/suites_test.rs @@ -24,8 +24,7 @@ mod common; -use std::ffi::{c_char, c_double, c_int, c_uint, c_void, CStr, CString}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::ffi::{c_char, c_int, c_uint, c_void, CStr, CString}; use oak_plugin::descriptor::EffectDescriptor; use oak_plugin::instance::Instance; @@ -83,7 +82,7 @@ fn dummy_plugin(descriptor: EffectDescriptor) -> std::sync::Arc (std::sync::Arc, *mut c_void) { - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = param_suite(); let dhandle = tag::make(&desc.props as *const PropertySet, tag::DESCRIPTOR); unsafe { @@ -253,7 +252,7 @@ fn memory_suite_ledger() { /// [`oak_plugin::clip::ClipInstance::fetch_image`] 与存活表记账验证。 #[test] fn image_effect_clip_image_pairing() { - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = image_effect_suite(); let h = tag::make(&desc.props as *const PropertySet, tag::DESCRIPTOR); @@ -384,7 +383,7 @@ fn image_effect_clip_image_pairing() { #[test] fn param_suite_roundtrip_and_change_action() { // describe 期。 - let mut desc = EffectDescriptor::new(); + let desc = EffectDescriptor::new(); let s = param_suite(); let dhandle = tag::make(&desc.props as *const PropertySet, tag::DESCRIPTOR); let t = cs("OfxParamTypeDouble"); @@ -478,7 +477,6 @@ fn param_suite_roundtrip_and_change_action() { assert_eq!(CStr::from_ptr(p).to_bytes(), b"hello"); // AtTime == 当前值(无动画)。 - let mut v2 = 0.0; assert_eq!((s.param_get_value_at_time)(gain, 12.0, &mut iv), OK); assert_eq!(iv, 7); assert_eq!((s.param_set_value_at_time)(gain, 12.0, 9), OK); diff --git a/crates/oak-render/src/autocacher.rs b/crates/oak-render/src/autocacher.rs index 121f3e738..a007bb126 100644 --- a/crates/oak-render/src/autocacher.rs +++ b/crates/oak-render/src/autocacher.rs @@ -347,7 +347,7 @@ mod tests { // deterministic on the queued inline dispatcher: the first job stays // queued until `run`, so the superseding submit's cancel lands first. let (mut c, d) = new_cacher_slow(); - c.attach(7); + c.attach(7).unwrap(); let first = c.single_frame(Rational::new(0, 1)); let second = c.single_frame(Rational::new(1, 1)); assert_ne!(first, second); @@ -381,7 +381,7 @@ mod tests { #[test] fn ignore_requests_suppresses_jobs() { let (mut c, d) = new_cacher(); - c.attach(7); + c.attach(7).unwrap(); c.ignore_requests = true; c.on_cache_request(7, TimeRange::new(Rational::new(0, 1), Rational::new(5, 1))); assert!(c.live_jobs().is_empty()); @@ -391,7 +391,7 @@ mod tests { #[test] fn renders_paused_queues_but_does_not_start() { let (mut c, d) = new_cacher(); - c.attach(7); + c.attach(7).unwrap(); c.renders_paused = true; c.on_cache_request(7, TimeRange::new(Rational::new(0, 1), Rational::new(5, 1))); assert!(c.live_jobs().is_empty(), "paused: no jobs started"); @@ -402,7 +402,7 @@ mod tests { #[test] fn cancel_video_tasks_wait_blocks_until_idle() { let (mut c, d) = new_cacher(); - c.attach(7); + c.attach(7).unwrap(); c.force_range(TimeRange::new(Rational::new(0, 1), Rational::new(1, 1))); assert!(c.is_rendering_custom_range() || c.live_jobs().len() == 1); // Drain so the wait below observes every job finished. @@ -452,7 +452,7 @@ mod tests { #[test] fn clear_finished_single_frames_removes_done() { let (mut c, d) = new_cacher(); - c.attach(7); + c.attach(7).unwrap(); let id = c.single_frame(Rational::new(0, 1)); d.run(); c.arena.wait(id).unwrap(); diff --git a/crates/oak-render/src/eval.rs b/crates/oak-render/src/eval.rs index f709f8c87..4fba38bb2 100644 --- a/crates/oak-render/src/eval.rs +++ b/crates/oak-render/src/eval.rs @@ -40,11 +40,9 @@ use std::sync::{Arc, Mutex}; use crate::error::{Error, Result}; use crate::shaderfx::{compile_effect, run_effect}; use oak_codec::decoder::{ - CodecStream, Decoder as _, RenderMode, RetrieveAudioStatus, RetrieveVideoParams, - K_COLOR_RANGE_DEFAULT, + CodecStream, RenderMode, RetrieveAudioStatus, RetrieveVideoParams, K_COLOR_RANGE_DEFAULT, }; use oak_codec::ffmpeg::FFmpegDecoder; -use oak_core::color::ColorProcessor; use oak_core::frame::VideoParamsPod; use oak_core::texture::{Frame, Texture}; use oak_core::{PixelFormat, Rational, TimeRange}; @@ -287,6 +285,7 @@ fn purple_frame(time: Rational, size: (i32, i32)) -> Texture { } impl RenderEvalHooks { + /// A hook set with every optional hook unset (`use_cache` off). pub fn new() -> Self { Self { use_cache: false, @@ -346,6 +345,10 @@ impl RenderEvalHooks { /// C++ process_frame_generation: fill the destination with a generated /// F32 frame (transparent black for now). + /// + /// Only the `generation_fills_cpu_texture` unit test drives this today; + /// the live eval path uses the shader/graph hooks instead. + #[allow(dead_code)] fn process_frame_generation( &mut self, destination: &mut Texture, @@ -3407,7 +3410,9 @@ mod tests { } } let payload = ColorTransformJobPayload { - color_processor: std::sync::Arc::new(ColorProcessor::pass_through()), + color_processor: std::sync::Arc::new( + oak_core::color::ColorProcessor::pass_through(), + ), input: NodeValue::Texture(oak_node::handle::make_owned(Texture::wrap_frame(frame))), time: Rational::new(0, 1), }; diff --git a/crates/oak-render/src/procpool.rs b/crates/oak-render/src/procpool.rs index 8e2e0dbea..117f38de9 100644 --- a/crates/oak-render/src/procpool.rs +++ b/crates/oak-render/src/procpool.rs @@ -81,7 +81,7 @@ use crate::ipc::{ FrameSlotMeta, FrameSlotPool, HandshakeMsg, HelloCapsMsg, PluginProgressMsg, RenderAudioBatchMsg, RenderBatchMsg, SharedMemoryRegion, ShmMode, WireMontageClip, SLOT_FORMAT_BGRA8, TYPE_BATCH_ACCEPTED, TYPE_ERROR, TYPE_FRAME_FAILED, TYPE_FRAME_READY, TYPE_HANDSHAKE, - TYPE_HELLO_CAPS, TYPE_PLUGIN_CANCEL, TYPE_PLUGIN_PROGRESS, TYPE_RENDER_AUDIO_BATCH, + TYPE_HELLO_CAPS, TYPE_PLUGIN_PROGRESS, TYPE_RENDER_AUDIO_BATCH, plugin_cancel_json, }; use crate::scheduler::{FrameKey, FrameRequest, PreviewScheduler, SubmitOutcome}; @@ -901,7 +901,6 @@ enum WorkerEvent { } struct WorkerHandle { - index: usize, /// Spawn generation (increments on every restart): reader-thread /// events carry the generation of the child they read from, so a /// late EOF from a dead child cannot kill its replacement. @@ -941,14 +940,12 @@ struct WorkerHandle { impl WorkerHandle { fn shell( - index: usize, generation: u64, shm: Arc, slots: u32, slot_bytes: usize, ) -> WorkerHandle { WorkerHandle { - index, generation, state: WorkerState::Starting, child: None, @@ -1528,7 +1525,7 @@ impl ProcessDispatcher { handle.retire_sent_at = Some(Instant::now()); } let mut reaped_flags: Vec = Vec::with_capacity(inner.workers.len()); - for (i, handle) in inner.workers.iter_mut().enumerate() { + for handle in inner.workers.iter_mut() { if !handle.retiring { reaped_flags.push(false); continue; @@ -2007,7 +2004,8 @@ impl ProcessDispatcher { }) .map_err(|e| Error::Failed(format!("spawn reader thread: {e}")))?; - let mut handle = WorkerHandle::shell(index, generation, shm, inner.slots, inner.slot_bytes); + let mut handle = + WorkerHandle::shell(generation, shm, inner.slots, inner.slot_bytes); handle.child = Some(child); handle.stdin = stdin; handle.spawned_at = Instant::now(); @@ -2749,7 +2747,9 @@ mod tests { let mut inner = dispatcher.inner.lock().unwrap_or_else(|e| e.into_inner()); let key = SharedMemoryRegion::make_key(std::process::id() as i64, 999); let shm = ShmRegionView::create(&key, 2, 256).expect("shm"); - inner.workers.push(WorkerHandle::shell(0, 0, shm, 2, 256)); + inner + .workers + .push(WorkerHandle::shell(0, shm, 2, 256)); } let mut fired = Vec::new(); diff --git a/crates/oak-render/src/scheduler.rs b/crates/oak-render/src/scheduler.rs index 46e77cd36..6eae3c820 100644 --- a/crates/oak-render/src/scheduler.rs +++ b/crates/oak-render/src/scheduler.rs @@ -111,7 +111,6 @@ pub struct ClaimedBatch

{ struct Claim

{ worker: usize, - batch_id: u64, request: FrameRequest

, } @@ -314,7 +313,6 @@ impl PreviewScheduler

{ entry.request.key, Claim { worker, - batch_id, request: entry.request.clone(), }, ); diff --git a/crates/oak-render/src/textengine.rs b/crates/oak-render/src/textengine.rs index 8897fe97b..fb27baace 100644 --- a/crates/oak-render/src/textengine.rs +++ b/crates/oak-render/src/textengine.rs @@ -196,7 +196,7 @@ pub fn render(req: &TextLayoutRequest, transform: &TextRenderTransform, target: } let mut sys = lock_system(); - let mut buffer = layout(&mut sys.font_system, req, &text); + let buffer = layout(&mut sys.font_system, req, &text); let TextSystem { font_system, swash_cache, diff --git a/crates/oak-render/tests/common/mod.rs b/crates/oak-render/tests/common/mod.rs index 8bb084ef8..0169e0d18 100644 --- a/crates/oak-render/tests/common/mod.rs +++ b/crates/oak-render/tests/common/mod.rs @@ -16,6 +16,11 @@ //! Shared helpers for the integration tests. +// Every integration-test binary in this crate compiles this module on its +// own and uses only the helpers it needs, so items unused in one binary are +// still part of the shared fixture API. +#![allow(dead_code)] + use std::sync::{Mutex, MutexGuard}; /// Serializes tests that initialize the process-wide RenderManager @@ -60,7 +65,7 @@ impl Drop for ManagerGuard { // symbols. use std::collections::HashMap; -use std::ffi::{c_char, c_int, c_void}; +use std::ffi::{c_int, c_void}; use std::sync::OnceLock; // The bundled OpenColorIO's macos system monitor references diff --git a/crates/oak-render/tests/copier_test.rs b/crates/oak-render/tests/copier_test.rs index ba6b91f91..d7ab48ffb 100644 --- a/crates/oak-render/tests/copier_test.rs +++ b/crates/oak-render/tests/copier_test.rs @@ -22,7 +22,6 @@ //! tests assert those failures. use std::sync::Arc; -use std::time::Duration; use oak_core::{Rational, TimeRange}; @@ -89,7 +88,7 @@ fn sync_without_established_copy_fails() { /// detach (lifetime discipline). #[test] fn autocacher_attach_detach() { - let (mut c, mut pool) = cacher(); + let (mut c, pool) = cacher(); c.attach(42).unwrap(); assert_eq!(c.copied_project, 42); c.on_cache_request( @@ -111,7 +110,7 @@ fn autocacher_attach_detach() { #[test] fn cancel_video_tasks_semantics() { let (mut c, d) = cacher(); - c.attach(1); + c.attach(1).unwrap(); c.force_range(TimeRange::new(Rational::new(0, 1), Rational::new(5, 1))); assert_eq!(c.live_jobs().len(), 1); diff --git a/crates/oak-render/tests/pipeline_test.rs b/crates/oak-render/tests/pipeline_test.rs index 6972a1091..e90f97c15 100644 --- a/crates/oak-render/tests/pipeline_test.rs +++ b/crates/oak-render/tests/pipeline_test.rs @@ -76,7 +76,7 @@ fn blit_applies_ocio_in_float() { return; } - let mut renderer = DisplayRenderer::new(BackendKind::Cpu); + let renderer = DisplayRenderer::new(BackendKind::Cpu); let mut pod = VideoParamsPod::default(); pod.width = 4; pod.height = 4; diff --git a/crates/oak-render/tests/ticket_worker_test.rs b/crates/oak-render/tests/ticket_worker_test.rs index 459680b20..94aa3c244 100644 --- a/crates/oak-render/tests/ticket_worker_test.rs +++ b/crates/oak-render/tests/ticket_worker_test.rs @@ -24,12 +24,12 @@ mod common; use std::sync::{mpsc, Arc}; use std::time::Duration; -use oak_core::{Rational, TimeRange}; +use oak_core::Rational; use oak_render::error::Error; use oak_core::frame::VideoParamsPod; use oak_core::texture::{Frame, Texture}; -use oak_render::ticket::{TicketArena, TicketId, VideoTicketParams}; +use oak_render::ticket::{TicketArena, VideoTicketParams}; use oak_render::worker::{GraphSnapshotStore, InlineDispatcher, JobDispatch}; /// Unwrap a video ticket payload for assertions. diff --git a/crates/oak-task/src/render.rs b/crates/oak-task/src/render.rs index 29e03a425..778ea4014 100644 --- a/crates/oak-task/src/render.rs +++ b/crates/oak-task/src/render.rs @@ -1051,9 +1051,9 @@ impl RenderTask { unsafe { drop(Box::from_raw(dispatch)); } - // The pump closure borrows `private_dispatch`; drop it before the - // take below. - drop(pump); + // `pump`'s shared borrow of `private_dispatch` ends at its last use + // above (NLL); the closure needs no explicit drop, which would be a + // no-op because a closure capture is `Copy` here. if let Some(d) = private_dispatch.take() { d.shutdown(); } diff --git a/crates/oak-timeline/src/undogeneral.rs b/crates/oak-timeline/src/undogeneral.rs index 71b79ca8e..043a88295 100644 --- a/crates/oak-timeline/src/undogeneral.rs +++ b/crates/oak-timeline/src/undogeneral.rs @@ -40,8 +40,8 @@ use crate::util::{ block_set_length_and_media_in, block_set_length_and_media_out, block_set_range, block_track, clip_media_in, clip_set_media_in, same_block, track_append_block, track_create, track_insert_block_after, track_insert_block_before, track_replace_block, - track_ripple_remove_block, tracklist_append, tracklist_remove, tracklist_remove_last, - tracklist_track_at, tracklist_track_count, tracklist_type, transition_offsets, + track_ripple_remove_block, tracklist_append, tracklist_remove, tracklist_track_at, + tracklist_track_count, tracklist_type, transition_offsets, transition_set_offsets, BlockKind, NodeRef, }; diff --git a/crates/oak-timeline/tests/marker_test.rs b/crates/oak-timeline/tests/marker_test.rs index 01f3b64b3..75d0813ab 100644 --- a/crates/oak-timeline/tests/marker_test.rs +++ b/crates/oak-timeline/tests/marker_test.rs @@ -24,7 +24,6 @@ use std::sync::{Arc, Mutex, MutexGuard}; use oak_core::{Rational, TimeRange}; -use oak_timeline::common::EditToInfo; use oak_timeline::handle::{get, make_owned, CHandle}; use oak_timeline::marker::{ MarkerAddCommand, MarkerChangeColorCommand, MarkerChangeNameCommand, MarkerChangeTimeCommand, diff --git a/crates/oak-undo/tests/undo_safe_test.rs b/crates/oak-undo/tests/undo_safe_test.rs index 36967cfa5..3aa18a621 100644 --- a/crates/oak-undo/tests/undo_safe_test.rs +++ b/crates/oak-undo/tests/undo_safe_test.rs @@ -106,7 +106,11 @@ fn command_drop_frees_exactly_once() { name: "a", trace: trace.clone(), }; - let cmd = UndoCommand::from_closures(move || {}, move || drop(&probe)); + let cmd = UndoCommand::from_closures(move || {}, move || { + // `probe` must be captured by value so that dropping the command + // frees it; dropping a reference (the previous body) did nothing. + let _ = &probe; + }); drop(cmd); assert_eq!(events(&trace), vec!["free:a"]); @@ -320,7 +324,7 @@ fn stack_caps_at_k_max() { #[test] fn stack_query_bounds_errors() { - let mut s = UndoStack::new(); + let s = UndoStack::new(); assert!(matches!(s.command_name(-1), Err(Error::NotFound))); assert!(matches!(s.command_name(1), Err(Error::NotFound))); assert!(matches!(s.command_is_done(-1), Err(Error::NotFound))); diff --git a/crates/oak-worker/src/worker.rs b/crates/oak-worker/src/worker.rs index 10663c7e3..8fd7bf61e 100644 --- a/crates/oak-worker/src/worker.rs +++ b/crates/oak-worker/src/worker.rs @@ -1537,7 +1537,7 @@ mod tests { let _pool = unsafe { FrameSlotPool::create(out_region.data(), slots as u32, slot_bytes as usize) }; - let (in_key, in_bytes, in_region) = if input { + let (in_key, _in_bytes, in_region) = if input { let in_key = test_key("in"); let in_bytes = FrameSlotPool::bytes_needed(slots as u32, slot_bytes as usize); let mut in_region = SharedMemoryRegion::new();