- new primitives: keyframes_set_time_many (conflict-safe batch time
move), keyframes_set_value_many (captured or explicit old values),
keyframes_set_bezier_many (double precision), and
keyframe_set_bezier_point (single handle with NaN-capture fallback)
- dialog and curveview drag finalization go through the facade; the
tests exercise the same global undo stack via oakengine_project_undo
- keyframeview/keyframeviewundo.{h,cpp} removed with zero remaining
references
- new facade API: video params ex (dimensions/rate/par/interlacing/
preview format/divider), audio params, preview divider, and
undoable-flagged setters mirroring the dialog's dual undo/no-undo
modes; label setting gains node_set_label_ex
- the dialog's own SequenceParamCommand is gone; accept now issues
facade calls (per-field commands, unchanged fields skipped)
- preset system stays UI-side by design: its flat XML schema never
touches engine objects
- the auto-cache checkbox maps to the engine's existing stub (no undo
noise)
- new facade API: video stream overrides (colorspace/range/interlacing/
premultiply), pixel aspect, image-sequence params, stream enable,
source start time, and colorspace candidates - all undoable
- project explorer proxy actions now run through FacadeProxyTask and
the facade media-management functions (ProxyManager references in
projectexplorer.cpp drop from 5 call sites to a comment)
- footage properties dialog reads/writes through the facade; its two
app-side undo command classes are gone
- handle-model fix: the footage handle is a heap state object, not a
plain pointer cast - oakengine_footage_borrow() wraps app-held
Footage nodes correctly (nine UB reinterpret_casts caught by the
DialogFootageProperties tests)
- oakengine_export_render_ex covers the dialog's entire option surface
(formats, codecs, pix fmts, audio params, ranges incl. still frame,
subtitles, scaling, threads, custom OCIO color transform names,
per-codec key/value options) - zero feature reduction
- the dialog's Start now creates a FacadeExportTask that drives
oakengine_export_render_ex instead of constructing ExportTask in the
UI; progress flows through the facade callback and cancel through
oakengine_export_cancel (OAKENGINE_E_CANCELLED preserves the
keep-dialog-open semantics)
- two real fixes: audio sample format 0 no longer means an
AAC-unsupported u8_p (default is f32_p), and image-sequence exports
use the engine's real [#####] placeholder instead of a made-up -%04d
- NodeFactory's menu creation moves to UI-side widget/menu/factorymenu
(the factory only exposes its node library read-only now)
- DiskManager's cache-settings dialog is created through a registered
std::function handler (registered by Core at startup)
- OlivePluginInstance creates progress UIs through a
PluginProgressReporter interface (Null fallback headless) and queries
the active viewer through a provider callback, both registered by Core
- factory.h, diskmanager and pluginSupport no longer reference any
widget//dialog//panel//window headers or classes
- slider DisplayType enums sink to node/sliderdisplaytype.h (canonical
engine home); FloatSlider/RationalSlider alias them for compatibility
- DropWithoutSequenceBehavior enum sinks to common/dropworkflowbehavior.h
- Config errors now go through a registered ErrorHandler hook instead of
QMessageBox with a MainWindow parent; the style default no longer
depends on the UI style manager
- MainWindowLayoutInfo moves to node/project/serializer/ and its panel
dependency is reduced to a plain std::map alias (PanelLayoutInfo),
breaking the engine -> PanelWidget -> KDDockWidgets chain
- ProjectImportErrorDialog moves from task/ to dialog/projectimport/
- remove confirmed-redundant UI includes and give project.h/import.h/
project.cpp the direct includes they were borrowing transitively
- project.h includes folder/sequence headers directly (it used both
types in its own API all along)
- playback timer uses the audio output device as its master clock: the
PortAudio callback counts consumed frames (including underrun
zero-fill) so video cannot drift away from what is heard; wall clock
remains as fallback when no clocked output is running
- output clock compensates for device output latency; new Preferences >
Audio buffer size setting (0 = auto)
- SampleBuffer::speed() now uses linear interpolation instead of
nearest-neighbor sampling
- regression tests: audio-clock driven timer (fwd/rev/speed), wall
clock fallback, interpolation correctness
- FootageJob::should_use_proxy() centralizes the proxy decision; worker
pre-decode now honors the render mode so exports always decode the
original media (previously every frame was pre-decoded from proxies)
- global Tools > Use Proxy Media toggle with footage invalidation
- ffmpeg -progress parsing for real percentage feedback while generating
- divider mode (1/2, 1/4, 1/8 of source resolution) with UI, proxy
filename tags and per-footage persistence (pdivider)
- Media Offline warning slat rendered for missing footage
- regression tests: export isolation, relink invalidation, offline slat,
progress parsing, divider arguments
Enzo GD, administrator of the Olive Facebook user group, gave this
project generous promotional support in its early days. The shared body
text now carries a special-thanks line in both the About dialog and the
first-run Welcome dialog; zh_CN translation included.
- SequencePreset::Save() wrote element "interlacing_" while Load() read
"interlacing", losing the interlacing mode on preset round-trips;
Save() now writes "interlacing" and Load() accepts both for backward
compatibility with existing preset files
- ExportFormatComboBox: current_ was never initialized (UB on GetFormat
before first user selection)
- ExportSubtitlesTab::SetSidecarEnabled() called setEnabled instead of
setChecked, so restored export params could never re-enable sidecar
subtitles
- h264section.h: static const int constants were odr-use unsafe (link
error when referenced); changed to static constexpr
- Waveform sync no longer treats uncached waveform regions as silence:
the envelope extraction now reports a per-window validity mask and the
correlation skips invalid windows on either side, improving accuracy
for partially cached clips
- Add stretch/speed sync: AudioWaveformSync::EstimateStretchAndOffset
searches a playback-rate range plus offset, and a new timeline
context action 'Synchronize by Waveform (Adjust Speed)' applies the
estimated rate as a clip speed change (with undo) when plain offset
alignment is inconclusive
- Footage properties dialog gains a Source Start Time field so the
value used by source-time sync can be viewed and edited manually
instead of relying solely on auto-detected metadata; applied via an
undo command, with Footage::ClearSourceStartTime() for removal
- Regression tests for masked correlation, stretch estimation, the
envelope validity mask, and source-start-time set/clear
- Add a global LUT library: user-configurable directories (new
Preferences > LUT tab) scanned recursively for .cube/.3dl files; LUT
node file pickers offer the library dirs as sidebar shortcuts via a
'lut_library' input property handled by the param view bridge
- OCIOLutNode no longer fails silently: missing files, unsupported
extensions and OCIO load errors are recorded in last_error() and
surfaced in the status bar (input still passes through for rendering
safety)
- ColorDialog: re-enable the display -> reference conversion using
ColorProcessor::kInverse with a validity guard, and re-enable the
Display tab in ColorValuesWidget; covered by a round-trip regression
test proving the old OCIO inverse crash no longer occurs
- OCIOGradingTransformLinearNode: enforce the OCIO clampWhite >
clampBlack invariant per frame in Value() so keyframed/connected
values cannot produce invalid grading transforms, and constrain the
white clamp UI minimum whenever the black clamp is static
- Regression tests for LUT extension checks, direction switching, node
error reporting, LUT library scanning, display inverse round-trip and
clamp enforcement
- New ProxyDialog (Tools > Proxy Settings..., plus 'Proxy Settings...'
in the project panel and timeline Proxy submenus) unifying global
proxy settings, per-footage custom presets, generation and deletion
in one place instead of three scattered entry points; this also fixes
the Tools menu action opening the wrong preferences tab
- Preferences Disk tab gains an 'include audio in proxies' checkbox and
an ffmpeg executable path field (blank = auto-detect)
- Add ProxyDialog smoke tests
Replace every direct FFmpeg call in the editor and the render worker
with the pure C ffmpeg_bridge API, wrapped in thin C++ adapters that
preserve the original interfaces:
- avframeptr.h: olive::AVFrame adapter around FBFrame handles
- ffmpegutils: format conversion helpers on FB_* constants; the int
overload is renamed GetCompatibleBridgePixelFormat to avoid a silent
overload-resolution trap with the PixelFormat enum
- ffmpegdecoder/ffmpegencoder: rewritten as handle-based adapters over
FBDecoder/FBProbe/FBEncoder/FBScaler/FBResampler
- audioprocessor: FBAudioGraph push/pull adapter
- pluginrenderer/OliveClip: sws/pixdesc usage converted to FBScaler and
fb_pix_fmt_* queries
- AudioParams/channel layouts are plain uint64_t masks everywhere
Build integration: the root project no longer links FFMPEG directly;
only ffmpeg_bridge does. Binaries resolve the bridge library at runtime
via @loader_path inside the macOS app bundle (copied there post-build)
and via $ORIGIN/../ffmpeg_bridge/bin on Linux; on Windows the DLL is
installed next to the executables, so packages on all three platforms
ship the bridge library.
ffmpeg_bridge gains the extra API the adapters need:
fb_frame_make_writable, fb_decoder_get_format_duration,
fb_resampler_convert_frame, FB_PIX_FMT_YUV440P, SRT validation in
fb_probe_read_subtitle_stream, packed/planar fixes in
fb_encoder_write_audio, and a component-size fix in
fb_pix_fmt_component_size.
- Move Behavior-General options (hover focus, slider ladder, scroll zooms)
into the General preferences tab.
- Move Behavior-Audio option (audio scrubbing) into the Audio preferences tab.
- Promote remaining Behavior categories (Timeline, Playback, Project, Nodes,
Rendering) to top-level sidebar entries without the 'Behavior - ' prefix.
- Update Chinese translations for the new sidebar titles and fill unfinished
Behavior tab strings.
NodeView:
- Remove double-click jump-to-parameter-editor behavior; keep expand/collapse.
- Add right-click context menu item 'Show in Parameter Editor'.
- Add Shift+P shortcut bound to the same action.
Render:
- Fix crash in PreviewAutoCacher::ClearSingleFrameRenders when proxy playback
causes a render ticket to finish synchronously before the watcher pointer is
returned. Defer the watcher Finished signal via queued connection so the
caller can safely register the watcher before it is deleted.
Behavior preferences used a nested QTreeWidget with groups like General,
Audio, Timeline, etc. Replace it with one tab per group in the left sidebar
so users can jump directly to a category without expanding a secondary menu.
Also wire double-clicking a node in the node graph to emit a selection
signal with its context, causing the parameter panel to scroll to that
node's parameters (in addition to showing/raising the panel as before).
TaskDialog::closeEvent() was calling deleteLater() immediately when the
user closed the window. The ExportTask was a child QObject of the dialog,
so it got destroyed while its Run() method was still executing in the
worker thread, leading to a use-after-free on encoder_->Close().
Defer deletion until the QFutureWatcher reports that the task has actually
finished. A new task_finished_ flag tracks this so closeEvent only deletes
when it is safe, and TaskFinished() closes the dialog (which now deletes
instead of calling close() again while the task is still alive).
- Extend ProxyManager::ProxyParams with crf and preset, and update
ProxyTask/ProxyParamsEqual to use them.
- Add global config keys ProxyWidth, ProxyHeight, ProxyCRF, ProxyPreset.
- Add a Proxy Settings group to Preferences -> Disk with width/height/CRF/preset
controls.
- Read proxy settings from config when generating proxies from the timeline.
- Add Tools -> Proxy Settings... menu entry that opens Preferences on the Disk tab.
- Add ConfigDialogBase::SetCurrentTab() so PreferencesDialog can start on a
specific tab.
- Add PickRenderableFormat / IsColorAttachmentSupported so 3-channel
Vulkan formats fall back to 4-channel when unsupported.
- Make oakvulkan target and C ABI check conditional on Vulkan_FOUND;
skip liboakvulkan build/dependencies when Vulkan headers/libs are
absent.
- Update Preferences tooltip to reflect Vulkan is an experimental
prototype that may fall back to OpenGL.
- Revise dynamic backend plan doc: phase 3/4/5 described as prototype
frameworks with runtime validation pending, and list recent Vulkan
fixes (init idempotency, descriptor/sampler lifetime, dynamic
viewport/scissor, render pass clear, format probing).
Both OAK_ENABLE_DYNAMIC_RENDER_BACKEND=ON and OFF configurations
build and pass ctest (4/4).
i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl i hate opengl