- 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
- clip-level loop mode (off/loop/clamp), undoable
- per-channel audio levels as one-frame RMS at a timestamp
- waveform min/max buckets over a footage range, rendered on demand
- two real fixes uncovered by this family: conform completion signals
were starved by msleep-only waits (audio renders always came back
empty), and incomplete tickets from conform-pending renders are now
retried until the conform is ready
- relink through Footage::set_filename with the engine's natural
clear+reprobe cascade; find_offline_footage recovers offline media
by exact filename match under a search directory
- synchronous proxy generate (event-loop driven like the export
family), state query, enable/disable, path, and delete, mirroring
the app's proxy dialog assembly
- documented as non-undoable, matching the app's existing semantics
- undoable track removal (content restored on undo) and true-move
track reordering assembled from the edge commands (the engine has
no move-track API)
- track height/mute/lock getters and setters, documented as
non-undoable to match the engine's current semantics
- undoable marker add/remove/rename; duplicate timestamps are
rejected with E_STATE instead of hitting the engine's debug assert
- keyframed state, count, read (time in sequence timebase + mapped
values), add/remove, easing read/write (linear/bezier/hold with
control points), and clear - all undoable with full undo/redo
assertions
- easing set commands are minimal capi-local UndoCommands matching
the app-layer semantics (engine has none of its own); same-time
duplicates are rejected with E_STATE instead of hitting the engine's
debug assert
- project node enumeration, type/name/label metadata, input
introspection (id, mapped value type, connection state)
- typed parameter read/write for the eight common NodeValue kinds
(int/float/bool/rational/color/vec2-4/combo/string), undoable via
NodeParamSetSplitStandardValueCommand - the split-track value path,
chosen after proving the standard-value command stores whole
variants into a single component track
- graph operations (add/remove/connect/disconnect) reusing the
engine's undo commands, all covered by undo/redo assertions
All four are undoable and reuse the timeline/ command classes verbatim
(BlockSplitCommand, TrackRippleRemoveAreaCommand, BlockTrimCommand,
ReplaceBlockWithGap+PlaceBlock), with undo/redo assertions covering
split halves, media-in alignment on trim, ripple shift amounts, and
full restoration on undo
- oakengine_export_render drives ExportTask synchronously (offline
render + encode) with a progress callback, codec probing, and a
thread-local error channel; exporter.h keeps clear of the visibility
macro header
- oak-cli transcode now defaults to mp4 (H.264/AAC) with --format ppm
keeping the raw output path
- two real concurrency bugs found by the facade's own test: ExportTask
deadlocks when start()ed synchronously (queued conform handshake
needs an event loop), and the progress callback must be captured by
value because it fires on the task thread
- oakengine_sequence_add_track and add_footage_clip are the facade's
first editing primitives: undoable track creation and clip placement
with full range validation, clip enumeration, and gap filtering
- oak-cli transcode closes the loop: media file -> import -> clip ->
render, producing scaled PPM frames and a WAV from just the C ABI
- engine fix uncovered by transcode: the render worker used an invalid
empty AudioParams for IPC render frames, crashing any sequence that
contains audio; it now derives them from the rendered node itself
- sequence_new hardens its defaults against missing audio config keys
- oakengine_footage_probe inspects media without a project (decoder
probe): stream counts, per-stream video info (dimensions, rate,
duration, color tags, interlacing), audio info, duration, decoder
name, source start time; thread_local last_error for the NULL-handle
failure paths
- oakengine_project_import_footage adds probed footage to a project
through the same undoable command path as the app
- oak-cli probe prints decoder/duration/per-stream details and runs as
a ctest everywhere (no GL)
- dual ownership documented: probe handles are owned, imported footage
is borrowed from its project
- oakengine_sequence_get_video_params (width/height/pixel aspect) with
assertions for the default 1920x1080 square-pixel sequence and the
invalid-handle path
- oak-cli now renders at the sequence's real dimensions instead of the
hardcoded 1920x1080
- oakengine_renderer_create/set_mode/last_error, render_frame (sync,
60s timeout, CPU frames via the existing worker pool),
render_audio (planar float), cancel; frames and audio buffers are
owned handles with borrowed data pointers
- output colorspace names map to OCIO display transforms, with
graceful fallback to reference-space output
- oakengine_renderer_test: parameter validation and error paths need
no GL and always run; render assertions gate on
DynamicRenderer backend availability and SKIP cleanly otherwise
- fix a facade bug found by its own test: wait_for_ticket leaked a
connected lambda capturing a stack reference, which a subsequent
cancelled ticket could fire into reused stack memory
- oakengine/export.h establishes the OAKENGINE_API visibility macros;
include/oakengine/ipc.h is the first pure-C surface (41 functions:
shm, frame slot pool, and the worker IPC messages as POD<->JSON
build/parse), implemented in engine/src/capi/
- the IPC implementations move to engine/src/oliveimpl (namespace
olive::engine::internal::ipc); engine/render/ipc/*.h are rebuilt as
same-name/same-API wrapper classes forwarding across the C boundary
- FrameSlotMeta is shared with the C header verbatim so the app/worker
wire format (v1) is bit-identical; static_asserts pin sizeof and
field offsets
- spscringbuffer.h moves to include/oakengine/ as an inline-only
header (no symbols, not ABI)
- new pure-C test oakengine_ipc_test (make_oakengine_test, no GL)
covers shm, frame pool, message round-trips and the layout asserts;
full gtest suite stays green (1986 tests)