- vcpkg bootstrapped in every job (the Warp runners carry none):
clone + bootstrap into .cache/vcpkg, VCPKG_ROOT exported.
- vcpkg.json: ffmpeg pinned at 9.0.1#1 via overrides with
builtin-baseline 771b0a2e pinning the port tree; feature fixes
(gnutls -> openssl, ffnvcodec -> platform-qualified nvcodec,
vaapi on Linux, librsvg windows-only).
- Linux and macOS CI/CD jobs also take FFmpeg from the manifest
(static triplets x64-linux / arm64-osx keep the packaging story);
the build-ffmpeg.sh steps, FFmpeg caches and the codec dev
packages leave the workflows — system package managers keep only
the X11/audio/GL/Vulkan/tooling deps, now documented in
docs/build.md.
- New openKylin container job (openkylin/openkylin:latest) on x64
(warp-ubuntu-latest-x64-8x) and ARM64
(warp-ubuntu-latest-arm64-16x, arm64-linux triplet): openKylin
package names surveyed against the live image's apt index
(nasm/zip come from the kylinsoft anything3.0 PPA), clang for
bindgen, xvfb + lavapipe headless tests with the watchdog and
retry policy.
Known follow-ups (declared in the commit chain): vcpkg has not run
end-to-end yet, the pkg-config vs pkgconf executable name on
Windows, TLS semantics moving gnutls -> openssl.
The MinGW path kept fighting the environment (the GitHub image's
MSVC INCLUDE/LIB poison the GNU compiles; ocio-sys' fork then
dragged the MSVC-only headers into g++ and died on vcruntime.h).
The Windows jobs on both workflows now:
- run on warp-windows-2025-vs2026-x64-16x (preinstalled VS 2026)
with the stable MSVC Rust toolchain;
- install dependencies through vcpkg MANIFEST mode: vcpkg.json at
the repo root carries FFmpeg with every free codec + hwaccel
(mirroring build-ffmpeg.sh's configure), pkgconf and librsvg;
the vcpkg_installed tree plus the binary-cache archives are
cached on the manifest hash with save-always;
- build OCIO bundled (ocio-sys' vendored sources are what MSVC
wants — the MSYS2 package was the workaround, not the
preference), so OCIO_RS_NO_MSVC_INCLUDES is gone;
- ship the vcpkg runtime DLLs next to the binaries in the NSIS
installer with a static-CRT release build (no vcruntime DLLs),
replacing the ntldd-based MSYS2 bundling.
FFmpeg version pinning via builtin-baseline is a documented
follow-up: the Configure step logs vcpkg list so the first green
run reports the resolved versions. docs/build.md keeps the MSYS2
flow as the local alternative and points at the CI path.
Per docs/zh/plans/render-pipeline-threads.md §3.8:
- oak-node/nodes/graphendpoints.rs: the GraphInput/GraphOutput
virtual node pair — factory-registered but hidden from every create
menu, duplicate refused, real value() semantics (the input forwards
its feed_in row, the output publishes its tex_in as the frame).
The input endpoint also declares a connectable feed_in port
(documented deviation: footage/generator sources have no connectable
inputs, so the walk needs a feeder anchor).
- graph.rs: ensure_endpoints/endpoints/is_endpoint — idempotent,
identified by type id, default input->output edge only while the
output's tex_in is free; remove_node refuses endpoints.
- project.rs + serializer.rs: every project graph carries the pair;
a legacy file without endpoints migrates on load (roundtrip and
legacy-migration tests, re-save is idempotent).
- traverser.rs: eval_graph_bfs — the endpoint-to-endpoint Kahn
sweep. Live set = (input's forward cone U its feeder cone) INTERSECT
(output's backward cone); multi-input nodes dequeue at zero
in-degree over the live subgraph; deterministic ascending-id ready
order (Graph::edges is a BTreeSet, so insertion order is
unrecoverable — documented); time-shifted upstreams pull through
the shared DFS memo (walk_dfs, factored out of evaluate);
un-orderable remainder reports a named cycle; missing endpoints /
unreachable output are errors. Eight BFS tests cover the plan's
acceptance bullets.
- oak-render: bfs_endpoint_sweep_renders_footage_through_position —
real clip through a real Position node via the sweep, shifted
pixels asserted against a reference decode.
- Endpoint names localized in all eight i18n packs; storage/structure
tests updated for the two extra nodes.
Two user-mandated amendments:
- Decode must be GPU wherever possible and share the render GPU's
memory: hardware surfaces (NV12/P010) are imported as GPU textures
via the platform interop paths (DMA-BUF / DXGI / IOSurface /
CUDA-Vulkan), av_hwframe_transfer_data is never executed on the hw
path, and CPU decode + staging upload demotes to fallback only.
FFmpeg hwaccel first (the hwdecode.rs device model already builds
the device contexts; upstream Olive has no hw decode at all, so the
reference for this part is FFmpeg + the existing crate), hand-written
GPU decode strictly second. YUV->RGB becomes a built-in GPU pass
replacing CPU swscale. Milestone M5 becomes the GPU-decode
zero-copy track with HW_TRANSFERS zero as its acceptance counter.
- The Job graph becomes a real adjacency structure (no linear table,
no 2D array, possibly not fully connected) with a fixed pair of
virtual GraphInput/GraphOutput nodes per graph: connected by
default, undeletable, un-duplicable, shown in the node editor.
resolve is a Kahn-style BFS from the input node — multi-input joins
wait for every input, multi-output fans out, the order is
deterministic and graph-explicit, cycles error out, unreachable
nodes never run — until every branch converges at the output node.
M0 splits into M0a (Job enum + single-loop match) and M0b (virtual
endpoints + BFS + node-editor display).
Task book for the render-pipeline rearchitecture: one decode thread
and one render thread feeding queue-linked stages with the main
process presenting (the GPU's single queue makes the multi-process
backend dead weight), one dedicated OpenFX host process with
bounded respawn, GPU-resident frames end-to-end except at the CPU
OFX/export/cache boundaries, a per-backend interop table, and the
resolve rewrite to a single-loop match over a completed Job enum
(CacheJob included) following upstream Olive's
NodeTraverser::ResolveJobs. Milestones M0-M5 with the thread backend
kept behind an OAK_PIPELINE fallback switch.
Adjustment layers (docs/zh/plans/adjustment-layers-and-transitions.md):
a new timeline block type whose effect chain grades the composite of
every video track below it, over its own range (spanning clips or a
slice of one). The graph path flushes the lower tracks at the block's
track boundary and sweeps the composite through the chain via a
transient texture-source node; the montage path mirrors it with
AdjustmentSpan tickets (wire-compatible), so worker previews and
exports agree. An empty-area context menu creates one; the block
trims/moves/deletes like a clip, with undo everywhere.
Transitions: seam blocks come alive - cross dissolve/fade/wipe/slide
evaluate both neighbors through the graph path with progress from the
transition's own range (never the whole clip). Ctrl+Shift+D or the clip
menu inserts a default transition; the gpui wedges render and drag to
resize offsets undoably, and TransitionRemoveCommand now restores
offsets and edges on undo. The transitionfx node form runs the same
shaders on an adjustment layer with progress_in auto-filled from the
layer's span (explicit value wins).
Also: every built-in effect name and parameter name is now
translatable (360 node.* keys per locale, zh-CN fully translated, two
coverage tests guard future gaps); the new nodes register in
nodes/mod.rs with the factory smoke table updated; textfootage and
adjustment-layer i18n keys included.
Text is no longer a hand-written HTML effect (docs in
docs/zh/plans/text-footage-redesign.md):
- textv3 gains structured inputs - plain text, font family/size, font
color, outline (enable/color/width), glow (enable/color/radius); the
legacy text_in HTML is hidden and auto-migrated to plain text on load.
- Outline and glow render as GPU post-process chains (dilate/blur +
colorize under the text); the font color tints the raster
premultiplied. Plain text now rasterizes even with both passes off
(previously a null deferred job), fixing a use-after-free where the
handle was lifted out of an owning Option<NodeValue> before addref.
- A cosmic-text backend (the lockfile's 0.19) installs at engine
startup through the textbackend hooks and feeds the font-family combo.
- The project panel gains 添加文本素材 next to 新建序列: a text entry
in the bin that drops onto the timeline as a clip (one undo row), its
parameters shown as structured fields in the inspector (multiline
text area, no HTML anywhere). text3 is hidden from the effect add
menus; legacy text3 chains keep evaluating.
21 built-in effects reimplemented as native GPU nodes from the
OpenFX-Misc algorithm references (cleanroom, docs in
docs/zh/plans/ofx-misc-gpu-cleanroom.md):
- Color: Color Correct, Gamma, Saturation, Invert, Clamp, Grade
- Matrix/morphology: Color Matrix, Edge Detect, Dilate, Erode
- Blur: Directional Blur, Sharpen (unsharp mask)
- Merge: Dissolve, Key Mix, Premultiply, Unpremultiply
- Geometry/generators: Position, Mirror, Checkerboard, Color Bars, Ramp
Every node carries unit tests plus GPU pixel tests (28 cases over five
ofxmisc_* suites). The effect library groups built-ins by category
(color/filter/distort/keying/generator/math/general) with collapsible
group headers persisted to the config; the inspector's add menu groups
the same way. Registration wiring and the factory smoke table land with
the adjustment/transition wave sharing the same files.
oak-common is gone; its modules (configstore, xmlutils, ocioutils,
oiioutils, colormath, colortransform, videoparams, ffmpegutils, ...)
now live in oak-core alongside the value types. The render value/GPU
types moved too: backend (wgpu context + DisplayRenderer), color
(ColorProcessor over ocio-rs), texture, frame, and the commonutil
config helpers.
Fix-ups to make the merged tree build and pass tests:
- oak-core Cargo.toml: wgpu back to 25 (the moved backend code is
written against that API generation); add the toml/quick-xml/image
deps oak-common carried.
- lib.rs: drop the duplicate 'pub mod error;'.
- error.rs: unified OAKCORE_* codes; restore Error::new() and
From<OcioError> from oak-common's error type.
- backend.rs/color.rs: oak_core::/oak_render:: self-references
rewritten to crate::; the shaderfx-dependent GPU effect test moved
to oak-render's shaderfx tests (shaderfx depends on oak-node and
cannot live in oak-core).
- oak-render's error module re-exports oak_core::error::{Error,
Result}; the OAKRENDER_* codes stay as the public-code contract.
- oak-node jobs.rs: ColorProcessor imported from oak_core::color.
- Integration tests repointed at oak_core::{texture, frame, backend,
color, colormath}.
- the display-ICC regression test treats an empty OAK_DISPLAY_ICC as
unset, matching displayicc::env_override_icc.
Preview now follows the project output colorspace end to end: the
display chain derives its content space from the project's OutputColorSpec
instead of a hardcoded sRGB name, self-managed ICC transforms go through
an XYZ D65 interchange stage (OCIO cie_xyz_d65_interchange) for non-sRGB
targets, and the platform layer declares the content colorspace (gpui
submodule bump). macOS defaults to OS-managed (fixes wide-gamut UI
oversaturation); Windows ACM warns once on non-sRGB targets.
Multi-monitor: the display ICC is looked up per the window's current
screen (macOS display id, Windows per-monitor DC, X11 RandR output
profile) with a throttled poll that invalidates frame caches on moves.
Pipeline precision: 10-bit+ sources fall back to YUV444P16LE + a Rust
matrix conversion when swscale lacks F32 output (no more 8-bit
truncation); BT.709/2020 SDR decodes with BT.1886 gamma 2.4 instead of
the sRGB EOTF; working-space compositing no longer clamps RGB to [0,1]
(alpha still clamped); the output node clamps to the target gamut;
frames without colorimetry metadata convert with BT.709 defaults
(warned once) instead of passing through; scopes read the
output-colorspace signal on both F32 paths.
Also: only emit rerun-if-changed for .env when it exists (a missing file
made every build fully dirty).
- docs/zh/plans: finished plans move to completed/ (the RIIR series, the
event-bridge and dependency plans, the v04 manual test plan).
- New design docs: the external (functional) plugin system
(process-isolated, JSON-RPC/shm) and its protocol.
- ai-agent-design refreshed; README pointers follow the moves.
All crates take the oak-* kebab-case naming (oak-audio, oak-codec,
oak-common, oak-core, oak-ffmpeg-link, oak-node, oak-otio, oak-plugin,
oak-render, oak-storage, oak-task, oak-timeline, oak-undo), with the
lib identifiers rewritten (oakrender:: -> oak_render::, oakcore_rs:: ->
oak_core::, ...) across all 226 referencing files.
The GUI application moves from the workspace root into
crates/oak-app/: src/, build.rs (paths fixed for the new location) and
tests/ travel with it, the root Cargo.toml becomes workspace-only
([workspace] + workspace.package + profiles), and the app package
inherits the workspace version. The screenshots example becomes a
standalone crate examples/simple_player/ with its own Cargo.toml.
Every crate now inherits the single workspace version
(version.workspace = true), and the workflows' crate paths and the
build docs follow the renames.
Validated with a clean cargo check --workspace.
docs/build.md + docs/zh/build.md rewritten for the Rust workspace:
project-built FFmpeg 8.1 (.cargo/config.toml presets FFMPEG_DIR),
vendored static OCIO on Linux/macOS vs MSYS2 dynamic OCIO on Windows
(with the OCIO_INSTALL_DIR/OCIO_RS_LINK env), the Windows GNU toolchain
requirements (MSYS2 Rust, RUSTFLAGS=-C link-args=-lmsvcrt for the
mingw-w64 _assert forwarding, unset INCLUDE/LIB), Linux audio dev
packages and xvfb headless testing, container packaging, and a
troubleshooting section. The macOS-only guides gain a deprecation
pointer. Also correct two stale comments in tooling/install-deps.sh
(FFmpeg is built by tooling/ffmpeg/build-ffmpeg.sh, not by cargo).
- preview_footage_media decodes the original from the footage's actual
first stream of the kind instead of hardcoded 0/1, fixing audio-first
and other atypical stream layouts (with a unit test).
- spawn_modal now probes for a nested window update and defers the
build instead of silently dropping the dialog — the phase-7
Preferences/Action Search fix applied centrally to every modal
(export, proxy settings, project manager, progress dialogs).
- The gpui_wgpu atlas no longer double-copies identity-format uploads,
leaving a single CPU staging copy (gpui RenderImage ownership) plus
the GPU upload on the onscreen path; the residual copy and the
IOSurface route to true zero-copy are documented in the M15 design.
- Audio tickets join the process backend: render_audio_batch wire
message, workers mix straight into shm slots (SLOT_FORMAT_AUDIO_F32),
ShmAudio payload with release semantics, crash isolation covers audio
renders; playback audio uses an async 4-chunk prefetch drained on the
UI tick (also fixes the sub-60fps chunk truncation bug); oversized
ranges and dispatcher outages fall back to in-process inline.
- Per-ticket slot formats: force_format is honored (exports request
F32 slots, dropping the BGRA8 round-trip and its 8-bit quantization);
segments grow on demand via worker-idle rebuild with generation
handoff; the scheduler filters over-capacity tickets.
- Adaptive defaults: 128-256MB/worker segment budgets drive slots per
worker, batch size follows workers/slots; bench_process example
measures throughput and adjacent-frame completion deltas
(e.g. 4 workers: 841 fps, 4.6ms mean delta).
- WorkerPool thread pool deleted; RenderManager defaults to the
Processes backend (oak-worker children), Threads kept as a test-only
inline dispatcher; audio tickets stay in-process until S3.
- Onscreen path reads worker shm slots directly: BGRA8 slot format,
RenderedFrame::Shm wrapped into the display buffer (single disclosed
GPU-staging memcpy), scopes analyze BGRA8; the long-lived full-res /
thumbnail paths take the counted slot_to_vec copy and release.
- Playback pre-render window: forward 120 frames (configurable) fed to
the PreviewScheduler at Playback priority, interleaved across
workers, cached in shm slots until the playhead consumes them;
generation-based invalidation cancels and releases on edits.
- oaktask export and oak-cli run on private ProcessDispatchers (fixed
a pump-while-locked self-deadlock in the export loop); facade
get_frame handles ShmFrame payloads.
- Acceptance: preview path main_heap_frame_copies == 0 with spawned
workers, CLI transcode/render verified end to end.
The static FFmpeg's external codec libs pull in -lz, which on this
toolchain resolves to a copy whose install name is @rpath/libz.1.dylib
(zlib-ng-compat); without an LC_RPATH entry all three binaries died in
dyld at startup. The app/cli/worker build scripts now emit
-Wl,-rpath,/usr/lib.
Also: FFMPEG_DIR moves into the committed .cargo/config.toml as a
workspace-relative [env] entry — ffmpeg-sys-next's build script cannot
read .env files, and without it the crate silently linked the shared
Homebrew FFmpeg while oakffmpeg-link emitted the static transitive
flags (mixed linkage). docs/build.md updated.
- track headers: name + visible/mute/lock toggles, undoable through
graphops, honored by the montage (muted tracks are skipped) and by
the edit guards (locked tracks reject trims/moves/deletes)
- project explorer gains a panel title row; the tree/icons toggle is
now small icon buttons with tooltips
- new effect library dock panel (every addable effect; double-click
appends to the selected clip's chain)
- screenshots refreshed (zh/en, window/manager/preferences)
- oakengine is now cdylib-only (no rlib/staticlib consumers anywhere;
cargo tree verified) — the plugin/external C ABI layer; README and
docs updated
- cd.yml drops the dylib embedding/re-sign steps (the app no longer
links it)
- test race root-caused and fixed for good: the global undo stack lock
is now a re-entrant mutex (parking_lot) shared by every test that
drives the stack, including the previously unlocked node/render
families; the render-manager serial-ordering bug (an earlier repro
test initialized the global manager before the not-initialized test)
is fixed with a shared SERIAL guard and a manager shutdown
- 5 consecutive parallel runs clean; serial 209/209
- viewers show the 480px proxy immediately and a background thread
fills the sequence-resolution frame (per-monitor in-flight job,
generation-based staleness, playback skips full-res)
- preferences dialog complete: cache dir (now consumed by
default_disk_cache_path), proxy policy/divider, snapshot interval
(write-through era autosave), default transition length, audio
in/out devices (new facade device-enumeration exports; audio init
from config — playback was never creating the audio instance),
language/theme/renderer backend, all persisted via config
- shortcut map (src/shortcuts.rs): space/J/K/L, I/O, S split, A/^A,
⌘Z/⌘⇧Z, ⌘N/⌘O/⌘S/⌘E/⌘Q, frame step, Home, track zoom; dispatch
shares the menu action path and stays silent over modals
- screenshots: preferences dialog zh/en captured and reviewed
D3: oakdb+pg:// fully wired (shared sea-orm entities, BIGSERIAL DDL,
connect-probe instead of pool retry on dead servers); Storage/Backend=pg
+ Storage/PgUrl config; 13 OAK_TEST_PG_URL-gated PG tests (verified
against a Docker postgres:16), always-on clean-error tests otherwise.
D4: DaVinci-style project manager — list with derived stats, create/
rename/duplicate/delete (confirm)/import/export (native dialogs,
ove/otio/fcpxml), shown at startup and from the file menu; facade
oakengine_library_* exports (list/create/delete/rename/duplicate/
import/export + project_load_library that binds write-through);
save/save-as menu becomes 'export project file', open splits into
from-library/from-file; status bar shows library write state; storage
activates on app start and flushes on exit; spawn_modal reentrancy
fixed (window-callback path) with a doc note.
Also: the P1 audio test's environment probe was lost in the ffi purge;
restored on cpal (the output device is cpal now).
- facade storage session manager: project handles bind to the default
SQLite library on project_new/load; every undo push/group_end/jump
write-throughs via DatabaseBackend::save (diff journal); project_free
flushes and unbinds
- background snapshot thread (Storage/SnapshotIntervalSec, latest-wins,
newest 3 kept) with exit flush (oakengine_storage_flush)
- config-gated: storage only activates with an explicit
Storage/Backend=sqlite, so headless consumers and tests never touch
the real library; new exports: storage_flush/is_bound/last_error
- it_storage: kill -9 recovery, cross-session undo, snapshot pruning,
multi-project isolation, graceful degradation
- also fixes a real config test polluting the user config.ini and the
undo-stack test races
oakstorage (new workspace member): URI dispatch, pluggable backends
(ove-xml built in, otio/fcpxml via oakotio, C-vtable foreign
registration), the M10 C API surface, version info codes, last-error
and alive accounting; round-trip tests per backend.
oaknode serializer: persists the full timeline — sequence track lists,
track block lists, block ranges/media_in/speed/flags, clip footage
references, footage filename+streams, folder children — through
<custom> behavior hooks with two-phase reference resolution; loads the
C++ <olive><project><layout> containers (golden: tests/
project_with_footage.ove); round-trip is field-by-field and
byte-idempotent.
- screenshot example inits i18n and captures both zh-CN and en-US
(docs/screenshot-window{,-en}.png)
- dock tabs size to content (no more 64px truncation); viewer/panel
titles follow the design (素材查看器·name etc.)
- mock project carries V1/V2 video + A1/A2 audio clips rendered as
rounded green bars; timeline clip geometry/rounded corners match the
design; status bar visible with full content; audio meter strip
docked at the program viewer's right edge; project explorer rows
have icons
- tests/waveform_e2e.rs: waveform cache extracts real peaks and hits
cache on re-query (P4 acceptance)
- oakengine_sequence_move_clip implemented for real (oaktimeline
TrackMoveBlockCommand; fixes the graph-ownership/gap-anchor/ripple
trim bugs the stub was hiding); same-track via the frozen C ABI,
cross-track supported by the module command
- oaknode clip blocks now declare a tex_in texture input and set
effect_input to it, so timeline clips can host effect chains; facade
test covers effect insert/remove on a real clip
- oakffmpeg-link: FFMPEG_DIR is now mandatory with a clear panic (a
Homebrew upgrade left the system ffmpeg .pc pointing at a deleted
dav1d Cellar path, breaking links); reads a git-ignored workspace
.env for IDEs that cannot inject env vars (RustRover); links the C++
stdlib for C++ codec libs (svt-av1)
- oakengine re-exports oaknode so tests share one crate instance;
it_node uses the direct instance's value type where it calls the
module FFI (the --workspace dev-dependency feature split builds
oaknode twice)
- tooling/ffmpeg/build-ffmpeg.sh builds release/8.0 static+PIC into
.cache/ffmpeg: GPL/version3, every free-license external codec lib
probed via pkg-config (enabled when present), per-OS hardware
acceleration (VideoToolbox/AudioToolbox, VAAPI/VDPAU/libdrm,
D3D11VA/DXVA2/MediaFoundation, nvenc when ffnvcodec exists)
- tooling/install-deps.sh installs those libraries on Homebrew / MSYS2
UCRT64 / Debian-Ubuntu / Fedora / Arch; nothing in the build sudo's
- ffmpeg-next's own build feature is unusable (every crate-version to
FFmpeg-release pairing is broken upstream: 9.0.0->FF9 AVCodec fields,
8.1.0->FF8.1 new enum variants, 8.0.0->FF8 FF_PROFILE rename), so
ffmpeg-next 9 + FFmpeg 8.x headers via FFMPEG_DIR it is
- new links-crate oakffmpeg-link emits the static FFmpeg's transitive
link flags from its .pc files (cargo only propagates them from links
crates, and rustc prunes the flags unless the rlib is referenced —
hence the force_link statics)
- docs/build.md updated for the Rust workspace flow
- App no longer depends on the oakengine rlib: build.rs links the
built liboakengine.dylib (+rpath, -export_dynamic, IOSurface) and
src/oakui/ffi.rs declares the pure-C surface; RealEngine calls only
the frozen oakengine_* C ABI
- host_syms.rs provides the oakcore_*/fb_* host symbols the dylib
imports via dynamic lookup
- Fix Preferences dialog crash (spawn_modal reentrancy) with a
regression test
- Timeline toolbar and viewer transport render C++-era icons (16px
grid, dark/light themes) with localized tooltips
- i18n: complete en-US table, add untranslated-key detection test
- New dialogs module (preferences, export, progress)
- oakcore-rs: Rational/TimeRange/TimeRangeList/PixelFormat/SampleFormat
mirroring oakcore C++ semantics (91.6% coverage)
- oakundo: UndoCommand/UndoStack with vtable commands (99.6%)
- oakcommon: config/XML/VideoParams/logging etc. (89.8%, 516 tests);
XML via quick-xml, logging via the log facade
- oaktimeline: markers/workarea/edit commands (95.4%)
- oakaudio: processor/manager/sync/waveform/levelmeter (88.4%)
- unified -MMCCCC error codes across all C ABI headers (registry in
include/common/error.h; pass-through rule)
- olive::Variant moved node -> common (cross-module value type)
- oakcommon_videoparams_set_is_3d added to the C ABI
- M11 (oakplugin Rust rewrite) plan + notes.md freeze line for the
inter-module C ABI wiring
- oakrender cache C API: add create_for_node (four cache kinds),
get_uuid, request, load/save_state, set_saving_enabled,
set_passthrough, get_passthroughs, get_valid_cache_filename,
get_timebase, lock/unlock, invalidate_range (rational variant),
get_native (C++ only, for the in-module PreviewAutoCacher)
- Node's four caches become owned OakRenderCache value handles; all
cache access in node.cpp/clip/viewer/traverser/serializers goes
through the C ABI
- oaknode_node_get_video_frame_cache returns an addref'd
OakRenderCache; drop OakNodeFrameCache; oaktask precache/export and
oakrender_video_ticket_params take the value handle
- color: OCIOBaseNode/OCIOLutNode hold OakColorProcessor handles
(dtors added); oakrender gains color_processor_create_transform/
create_lut/create_grading_primary/get_native and LUT library
queries, keeping all OCIO transform construction inside oakrender;
oaknode gains colormanager_wrap_borrowed/get_native
- RenderManager::instance() check -> oakrender_manager_available();
cancel_video_tasks and disk cache path go through manager C API
- remaining node->render C++ symbol: only olive::Texture::~Texture
via Variant's shared_ptr payload (recorded exception, same class as
the UndoCommand inheritance)
Tests: new cache/color/manager/colormanager cases; all standalone
trees green (common 196, codec 22, audio 40, task 112, render 63,
timeline 125, node 98, plugin 102).
- ViewerOutput owns timeline markers/work area via refcounted
OakTimeline* value handles (oaktimeline_*_create) instead of C++
objects
- oaktimeline C API: add marker_list_create/marker_add/
workarea_create/workarea_set_enabled; handle boxes gain an optional
deleter for owning handles
- oaknode_node_get_markers/get_work_area return addref'd OakTimeline*
handles via out params (named-struct forward declarations avoid the
public header cycle); drop OakNodeMarkerList/OakNodeWorkArea
- serializers 210528-230220 load/save markers and work areas through
the oaktimeline C API; SerializedMarker POD replaces
std::vector<TimelineMarker*> in the serializer interface
- Sequence::add_default_nodes uses oaktimeline_add_track_command
- clip.cpp display-mode enums come from the new neutral
include/timeline/displaymode.h; delete src/node/transition/timeline
- oakcommon xml: add oakcommon_xml_reader/writer_wrap_native borrowed
wrappers (C++ adapter use)
- liboaknode now has zero C++ symbol references into liboaktimeline
Tests: new owning-handle and wrap_native cases; all standalone trees
green (common 196, codec 22, audio 40, task 110, render 49,
timeline 123, node 96, plugin 100).
- de-Qt src/plugin/src (olivehost/oliveplugininstance/oliveclip/
paraminstance/image/pluginprogressreporter); QMessageBox/
QApplication replaced by facade callbacks
- new C ABI in include/plugin/{error,host,instance}.h with
refcounted OakPluginInstance value handle
- paraminstance bridges via oaknode C ABI (OakNodeNode value handle,
oaknode_node_identity registry); undo via oakundo C ABI
- oliveclip textures are OakRenderTexture value handles; oakrender
gains texture/copier/ticket C API additions
- oaknode gains get_input_at_time/set_input_at_time_undoable/
node_identity/sequence_from_node/sequence_set_default_parameters/
find_input_footage
- move avframeptr.h to src/common/src (shared by codec and render)
- node transition pluginSupport stubs bridge the real oakplugin
headers; all oaknode-building standalone trees add src/plugin and
link oakplugin into their test binaries
- plugin tests self-sufficient (ipc shim, OfxHost force_load,
PRE_TEST discovery, OCIO env); timeline standalone gains
render/c_api
- restore ffmpegdecoder.cpp in src/codec/src/ffmpeg/CMakeLists.txt
(dropped in 3d004c081, caused jump-to-0 in decoder/encoder tests)
All six standalone trees green: codec 22, audio 40, task 110,
render 49, timeline 121, plugin 100.
- de-Qt all 11 sources: markers/workarea lose QObject/signals (list
re-sort via direct resort() call, drawing moves to the app layer),
explicit unique_ptr ownership for marker lists and viewer's
workarea/markers
- timeline undo command families (split/pointer/ripple/general/track)
now hold oaknode C handles and do all graph work through the oaknode
C ABI (no adapter layer); gaps are attached to the project graph
before insertion, orphan handles tracked and freed
- fix the de-Qt severed Block->Track length-changed chain with a
direct block_length_changed() call (positions were stale after
split/trim)
- expand oaknode C API by ~20 functions needed by timeline
(copy_in_graph, block kind/casts, connect_element, input arrays,
tracklist family, marker/workarea borrowed outlets)
- pure C ABI in include/timeline (marker/workarea/edit, command
factories returning OakUndoCommand), oakcommon XML get_native
accessors
- oaknode<->oaktimeline resolve each other at runtime; standalone
drivers link both into test binaries
- tests: oaktimeline 117, regressions oakcommon 193 / oaknode 96 /
oakrender 42 / oakcodec 18 / oakaudio 36 all green
- copy engine/render to src/render/src (sunk param types excluded),
de-Qt in five parallel groups: core machinery (tickets/worker pool/
jobs), caches, color/texture, preview/IPC, GPU backends
- replace Qt GL/Vulkan wrappers with native context abstractions
(CGL/EGL/WGL, raw vulkan.h), QProcess with POSIX WorkerProcess,
QJsonObject with a minimal NDJSON-compatible workerjson (wire
protocol unchanged), QDataStream disk state with a byte-compatible
BinaryStream
- signals become single std::function callbacks or facade-triggered
calls per the documented signal/slot strategy
- pure C ABI in include/render + src/render/c_api (renderer/cache/
color/manager families, OAKRENDER_E_* codes), 37 gtest cases
- bridge src/node/transition/render/* stubs to the real oakrender
headers, closing the node<->render cycle: liboaknode links
liboakrender, zero dangling symbols
- docs: M7 implementation status + oakrender semantic-change notes
- strip QAbstractItemModel/QAction/signals-slots from UndoStack (UI
concerns belong to the app layer), index_changed becomes a
std::function callback
- decouple UndoCommand from Project via an optional modified-flag
callback pair
- add pure C ABI in include/undo + src/undo/c_api (oakundo_ prefix,
vtable-based command wrapper, OAKUNDO_E_* error codes)
- fix three engine-side defects: jump(0) infinite loop,
MultiUndoCommand child leak, push_pre_executed not undoable
- add gtest suites (22 cases) and a standalone build driver
- de-Qt all classes under src/common (std::string/vector/mutex,
std::filesystem, expat-based XmlStreamReader/Writer)
- add pure C ABI in include/common + src/common/c_api: opaque handles,
init returns NULL on failure, free(NULL) is a no-op, out-params with
negative OAKCOMMON_E_* error codes (include/common/error.h)
- remove single-consumer classes from oakcommon (html, jobtime,
otioutils, playbackaudioclock, tohex, util, avframeptr,
crashpadinterface/crashpadutils, autoscroll, digit, range); their
destinations are recorded in docs/zh/plans/riir/notes.md
- add gtest suites under src/common/tests (127 cases), standalone
build driver in src/common/standalone