Commit Graph
7081 Commits
Author SHA1 Message Date
Mike-Solar 013a175707 refactor: workspace layout — crates/, app at root, legacy C++ removed
Single mechanical restructure commit:
- root Cargo.toml = oakapp bin + workspace; one cargo build produces
  oakapp, oak-cli, oak-worker, liboakengine.dylib
- app/rust/src -> src/ (app at repo root, no rust/ nesting)
- src/<mod>/rust -> crates/oak<mod>; src/oakcore-rs -> crates/oakcore;
  src/bindings/oakotio -> crates/oakotio; src/engine/rust ->
  crates/oakengine (keeps cdylib+staticlib+rlib)
- public C headers include/<mod>/ -> crates/oakengine/include/<mod>/
- OFX SDK headers vendored into crates/oakplugin/ofx/ (HostSupport gone)
- legacy deleted: old src/ C++ modules, engine/, core/, ffmpeg_bridge/,
  app/ (Qt), cli/worker C++, root CMakeLists, third_party/KDDockWidgets
  submodule, otio-install, all build-* output (~40GB)
- oakstorage kept but excluded from the workspace (skeleton w/ todos);
  gpui excluded (own workspace)
- verified: cargo build green, cargo test --workspace 1845/0
  (with the documented OCIO_RS_* env override for the homebrew OCIO)
2026-08-10 20:24:25 +08:00
Mike-Solar f8540e3892 refactor(engine): single-lib phase 3 — plugin/timeline/task/codec bridges converted
- oakplugin bridges -> direct (dlsym 28->0; OFX suites untouched)
- oaktimeline bridges -> direct (teststubs slimmed to pure-Rust mocks)
- oaktask bridges -> direct; facade EncodingParamsPOD -> oakcodec alias
- dlsym total 102->24 (all in documented dead/host directions)
- All crates build+test green; dylib exports unchanged
2026-08-10 19:11:25 +08:00
Mike-Solar 96e57b3705 refactor(engine): single-lib phase 2 — node/render/audio bridges to direct calls
- oaknode bridge/{common,codec} -> oakcommon/oakcodec direct calls
  (drops node's test-stubs XML mocks; fixes decoder_probe signature drift)
- oakrender bridge/common -> direct; dead bridge/codec deleted;
  dead copier kept as dlsym (documented)
- oakaudio bridge/{codec,common} -> direct (CHandle alignment)
- oakcodec test-stubs split to support node test linkage
- dlsym: node 52->20, render 22->4
- single-lib.md updated (sec 11.3/11.4)
2026-08-10 18:29:18 +08:00
Mike-Solar e1423553c7 refactor(engine): single-lib phase 1 — direct Rust calls across the facade
- unify CHandle in oakcore-rs (all crates re-export it)
- facade bridge: 618/624 externs converted to direct module calls
- signature-drift fixes surfaced by direct calls (videoparams,
  seconds, sync estimate, POD unification)
- dead node<->render call sites removed; cancelatom -> oakcommon
- node bridge/undo -> oakundo direct calls
- docs/zh/plans/riir/single-lib.md: design + live status
2026-08-10 17:48:13 +08:00
Mike-Solar f0d551d4a8 docs(riir): settle stale tech-debt entries in notes.md 2026-08-10 17:00:37 +08:00
Mike-Solar 0ca9cad448 feat(engine): rename facade to oakengine, build liboakengine.dylib
- src/facade/rust -> src/engine/rust; package oakfacade -> oakengine
- crate-type += cdylib; module crates are real deps; linkage anchors
  force-link module C ABIs into the dylib
- build.rs: -undefined dynamic_lookup for host-provided oakcore_*/fb_*
- nm: 749 oakengine_* + 687 module oak*_* exports; undefined set is
  only the intended host-provided symbols
- worker/cli updated to the new path/name; undo test race fix
2026-08-10 16:55:35 +08:00
Mike-Solar e563b340ac feat: oakengine facade, oaknode/oakrender impls, worker+CLI, app skeleton
- oaknode Rust crate: full implementation (core engine, sequence/
  track/block/footage, traverser, serializer, 43 node behaviors;
  493 tests green)
- oakrender Rust crate: full implementation incl. wgpu backend
  skeleton, ticket arena, worker pool (136 tests green; fixed
  lost-wakeup and ticket ordering races)
- src/facade/rust (oakfacade): 222 oakengine_* exports over the
  module C ABIs (61 tests green); worker_main + real POSIX shm
  frame-slot transport (SpscRingBuffer/FrameSlotPool, wire-compatible
  with engine/render/ipc)
- cli/rust + worker/rust binaries (29 + 29 tests green)
- oakotio: FCPXML import/export (49 tests green)
- oaktask: OTIO/FCPXML format dispatch (90 tests green)
- app/rust: gpui app skeleton — dock panels (viewers/timeline/
  explorer/inspector/node editor), transport, olive themes,
  i18n (en/zh), 37 tests green
- gpui submodule: menu checkmarks, dock ratios, vertical meter,
  CPU-frame viewer surface, drop-frame timecode
2026-08-10 08:12:08 +08:00
Mike-Solar d11d80ea53 chore: add oak-gpui submodule (UI framework for the app rewrite) 2026-08-09 20:21:28 +08:00
Mike-Solar cac41d92c1 feat(rust): oakcodec/oaktask/oakplugin crates + oakotio + node/render/storage skeletons
- oakcodec: full crate incl. real FFmpeg decode/encode via ffmpeg-next
  (162 tests, 84.4% cov); new oakcodec_encoding_* metadata family
  (include/codec/format.h, C++ + Rust sides)
- oaktask: manager/tasks/project load-save incl. OTIO via oakotio
  (82 tests, 86.4% cov); concurrent render loop with reorder buffer
- oakplugin: M11 phase 1+2 — self-contained OFX host, GL path,
  ofxColour, pluginrenderer absorbed as render_driver (99 tests,
  81.7% cov); instance.h additions documented
- oakotio: native serde-based OTIO read/write (24 tests)
- oaknode gap fill: dragger/keyframe-helper/multicam C ABI families
  (113/113 gtest); fixes a latent NodeInputDragger segfault
- oaknode Rust skeleton: 43 built-in node type declarations
- oakrender/oakstorage: declaration skeletons (implementation pending)
- notes.md: gap analysis + tech-debt ledger
2026-08-09 05:49:15 +08:00
Mike-Solar 4b24aa9d67 feat(rust): first green Rust crates — oakcore-rs, oakundo, oakcommon, oaktimeline, oakaudio
- 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
2026-08-09 04:24:28 +08:00
Mike-Solar 5a564f30ca refactor(node,render): route oaknode->oakrender calls through the C ABI
- 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).
2026-08-08 03:56:17 +08:00
Mike-Solar 81431d180d refactor(node,timeline): route oaknode->oaktimeline calls through the C ABI
- 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).
2026-08-07 22:53:44 +08:00
Mike-Solar fd2111d560 refactor(plugin): de-Qt oakplugin and wrap it in a pure C ABI
- 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.
2026-08-07 22:18:36 +08:00
Mike-Solar 0462842f8c refactor(render,timeline,task): switch remaining handles to refcounted value structs
- oakrender: renderer/texture/frame/cache/colorprocessor/ticket/copier
  all become by-value {ctx, addref, release, abi_version} handles over a
  generic box; retain() folds into addref; new
  oakrender_cache_wrap_borrowed for native caches from oaknode
- oaktimeline: marker list/workarea borrowed handles become value
  handles (non-owning boxes) with explicit free
- oaktask: OakTaskTask becomes a value handle; ownership still moves
  to the manager on start (owns flag flips)
- consumers (timeline/task/codec sources) migrated; tests everywhere
  updated; suites green: render 45, timeline 117, task 106, node 96,
  common 193, codec 18, audio 36
2026-08-07 18:05:34 +08:00
Mike-Solar 67176281d9 refactor(node): switch oaknode to refcounted value handles, migrate consumers
- all 15 OakNode* handle types become neutral by-value structs
  {ctx, addref, release, abi_version}; shared box in
  src/node/c_api/nodehandle.h with owns flag (borrowed accessors
  return non-owning boxes; graph insertion flips owns off)
- oaktimeline/oaktask/oakrender call sites and their own public
  headers migrated to value handles; identity comparisons in
  timeline/task now compare native pointers
- regressions green: oaknode 96, oaktimeline 117, oaktask 106,
  oakrender 44, oakcommon 193, oakcodec 18, oakaudio 36
2026-08-07 17:20:42 +08:00
Mike-Solar 295ea1bfe5 refactor(undo): switch oakundo to refcounted value handles, migrate consumers
- OakUndoCommand/OakUndoStack become neutral by-value handles
  {ctx, addref, release, abi_version}; a handle is a shared_ptr
  equivalent at the ABI level, internals untouched (box owns/observes
  flag; containers adopt, boxes created by factories own)
- oaknode command factories and undoable variants return/write value
  handles; timeline command classes hold value handles; task import
  take_command returns a value handle
- tests updated everywhere; suites green: oakundo 22, oaktimeline 117,
  oaktask 106, oaknode 96, oakrender 44, oakcodec 18, oakcommon 193,
  oakaudio 36
2026-08-07 15:48:34 +08:00
Mike-Solar da2ab512c6 refactor(task): OTIO load/save tasks over oaknode/oaktimeline C ABIs
- LoadOTIOTask/SaveOTIOTask de-Qt'd: graph traversal and construction
  through oaknode C ABI (find_input_footage, sequence defaults, block
  factories, context positions), track creation through oaktimeline's
  add_track command; the OTIO import dialog becomes a facade callback
  (headless default: accept all)
- oaknode additions: find_input_footage, sequence_set_default_parameters
- USE_OTIO + otio-install libs wired into oaktask; OTIO dylibs copied
  next to liboaktask for @loader_path resolution
- OTIO round-trip test passes; build-oaktask 106/106 green
2026-08-07 14:58:56 +08:00
Mike-Solar 40a336276f refactor(task,render): RenderTask family over a new oakrender ticket C ABI
- oakrender: new ticket family (render_frame/render_audio with finished
  callback, result frame/samples access, cancel/wait), project copier
  C API, cache get_invalidated_ranges, manager set_aggressive_gc
- oaknode: node_copy_inputs, set_value_hint_track, viewer params
  setters, video frame cache borrowed outlet, project copy_settings
- oakcodec: encoder desired pixel format, export format extension,
  encoding generate_matrix, custom range in encoding params POD
- oaktask: RenderTask orchestrates oakrender tickets (no Qt threads/
  watchers), PreCacheTask and ExportTask rewritten over the oaknode/
  oakrender/oakcodec C ABIs; frames cross from oakrender to oakcodec
  handles by pixel copy (different control blocks)
- the two-step texture/download render path collapses into single-step
  (tickets always yield frames); subtitle sidecar kept
- tests: 105 in build-oaktask (export/precache factory paths,
  construction, conform end-to-end); regressions all green
2026-08-07 14:40:12 +08:00
Mike-Solar 6ded1d2d63 refactor(task): de-Qt oaktask base + project tasks, wire codec task submitter
- Task base: Qt signals become lifecycle listeners (the async-command
  callback exception), cancellation uses oakrender's OakCancelAtom C
  handle; TaskManager runs std::thread workers, no signals
- ConformTask/ProxyTask implement oakcodec's submit-callback contract
  (synchronous interim); register_codec_task_submitter() closes the
  conform/proxy loop - conform of demo.mp4 produces pcm caches in tests
- ProjectImportTask/ProjectLoadTask/ProjectSaveTask over the oaknode
  C ABI; image-sequence confirmation becomes a facade callback
  (default: not a sequence)
- C API additions needed by oaktask: oaknode serializer file-level
  save/load (auto-initializing), footage video-params/cancel-atom/
  as-node, folder add-child command factory; oakcodec decoder
  conform_audio + image-sequence helpers; oakrender cancelatom
  get_native
- fix double-ownership: submitting a task to the manager transfers
  ownership, freeing its handle only releases the wrapper
- C ABI in include/task (task/manager/project, OakTaskTask opaque
  handle + lifecycle subscribe), every function tested (103 cases in
  build-oaktask incl. regressions)
- RenderTask family and OTIO tasks follow in separate commits
2026-08-07 14:01:23 +08:00
Mike-Solar 66831a870e refactor(timeline): de-Qt oaktimeline and wrap it in a pure C ABI
- 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
2026-08-07 04:37:24 +08:00
Mike-Solar 354df2e194 refactor(config,audio): merge config into oakcommon, split oakaudio
- config moves into oakcommon as ConfigStore + oakcommon_config_* C
  API (INI storage, typed entries, error-handler injection); node and
  render call sites keep OAK_CONFIG() macro shape via a local shim
  that forwards to the C API; transition config stubs removed
- oakaudio: de-Qt all six classes, C ABI in include/audio with
  refcounted handles (processor/manager/waveform/levelmeter/sync,
  48 functions); PreviewAudioDevice moved in from render; recording
  goes through oakcodec encoder; waveform extract uses probe +
  ffmpeg_bridge decode (decode_audio needs M8 task system)
- fix re_sum_samples min/max init bug (values clamped to 0 for
  same-sign ranges)
- every C API function has positive + error-path tests; suites:
  oakcommon 193, oakaudio 36, oaknode 96, oakrender 42, oakcodec 18
2026-08-06 20:53:07 +08:00
Mike-Solar 3d004c081b refactor(codec): de-Qt oakcodec and wrap it in a pure C ABI; switch common handles to refcounted value structs
- oakcodec: de-Qt all 20 sources (QThread decode loop -> std::thread,
  QObject/signals -> callbacks), pure C ABI in include/codec with
  refcounted neutral handles (OakFrame/OakDecoder/OakEncoder),
  framemanager moved in from render, frame_to_buffer/buffer_to_frame
  moved in from oakcommon oiioutils, codec->task via submit callback
  (M8 will register), all cross-module calls go through the other
  side's C API, -fvisibility=hidden + OAKCODEC_API
- oakcommon: handles become refcounted value structs
  {ctx, addref, release, abi_version} (FFmpeg-style), pass-by-value
  signatures, free() as release wrapper; init_from_native/get_native
  for copyable value objects; OakCommonXxx renamed to OakXxx
- oakcommon: add logging (log_debug/info/warning/critical with level
  filtering and sink injection) + printf-style oakcommon_log C wrapper
- oakrender: add CancelAtom C API family; complete
  oakrender_color_processor_convert_frame; fix get_processor() missing
  definition and OCIO env var lookup
- tests: oakcommon 174, oaknode 96, oakrender 42, oakcodec 18, all
  green in their standalone builds
2026-08-06 18:50:07 +08:00
Mike-Solar edbd3913af refactor(render): de-Qt oakrender and wrap it in a pure C ABI
- 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
2026-08-06 03:21:26 +08:00
Mike-Solar d77348ad9f refactor(node): de-Qt oaknode and wrap it in a pure C ABI
- copy engine/node (188 files) to src/node/src, de-Qt in waves:
  core infra (Node/Param/Value/Variant/mathtypes), project/serializer,
  block/output, color, effect leaves, generator, gizmo/plugins
- strip QObject/signals/slots: notifications move to the facade's
  oakengine_event channel, ownership becomes explicit (unique_ptr,
  add_keyframe/add_gizmo), sender() replaced by current_gizmo
- QVariant replaced by olive::Variant, Qt math types by POD mathtypes,
  QXmlStreamReader/Writer by oakcommon's expat-based classes
- sink VideoParams/SubtitleParams/LoopMode/ColorTransform to oakcommon
  (M3.5); polygon/text rasterization behind backend hooks
- pure C ABI in include/node + src/node/c_api (oaknode_ prefix,
  OAKNODE_E_* codes, undoable variants take OakUndoCommand out-params)
- fix Project::clear() root_ reset + disconnect assert, Sequence
  TrackList leak
- 96 gtest cases green in standalone build (build-oaknode)
- docs: signal/slot handling strategy + M3 implementation status
2026-08-05 23:55:54 +08:00
Mike-Solar c50017127b refactor(undo): de-Qt oakundo and wrap it in a pure C ABI
- 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
2026-08-05 18:02:24 +08:00
Mike-Solar bad52feda3 refactor(common): de-Qt oakcommon and wrap it in a pure C ABI
- 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
2026-08-05 17:20:19 +08:00
Mike-Solar bb09872a2f Merge remote-tracking branch 'upstream/main'
CI / build-test (warp-macos-15-arm64-6x) (push) Canceled after 0s
CI / build-test (warp-ubuntu-latest-x64-8x) (push) Canceled after 0s
CI / build-test (warp-windows-latest-x64-16x) (push) Canceled after 0s
2026-08-05 14:57:23 +08:00
Mike-Solar 82162580ef test(app): add gtest coverage for previously untested app modules
Add 312 test cases across 14 new files under tests/gtest, covering:

- app/common utility headers (tooltypes, projecttypes, nodedatatypes,
  trackreferencehandle, undowrapper, configwrapper, subtitleapp, ...)
- all 8 standardcombos widgets
- slider base classes (NumericSliderBase, SliderLadder)
- timeline/track handles, marker handle/painting, drag button,
  elapsed counter
- timebased views, selection manager, time target, resizable timeline
  scrollbar
- viewer sizer, display buffer, playback timer, text editor
- timeline common helpers, TimelineAndTrackView, TrackView(-item/-splitter)
- project explorer views, navigation and undo commands
- node view items/edges/connectors/minimap/toolbar/context
- node param view sub-widgets
- about/export/sequence/footage-properties dialogs
- scope widgets (histogram/vectorscope/waveform), managed display
- main menu, main window undo commands, viewer/footage panels,
  engine event bridge
- keyframe view handle/input connection, multicam display,
  node combo box, audio monitor

Includes regression tests for the TimelineAndTrackView teardown and
TimeScaledObject inverted-limits fixes. Full suite: 2341 tests, 0 failures
(64 skips are pre-existing GL-dependent cases under the offscreen QPA).
2026-08-05 14:53:26 +08:00
Mike-Solar 7b6042168a fix(widget): harden TimelineAndTrackView teardown and TimeScaledObject limits
- TimelineAndTrackView: disconnect the scrollbar sync connections in the
  destructor. Child views reset their scene during destruction, which can
  re-emit QScrollBar::valueChanged into a half-destroyed object and trip
  Qt's assertObjectType abort.
- TimeScaledObject: keep minimum <= maximum when setting scale limits so
  set_scale()'s std::clamp is never called with inverted limits (UB).
  Setting the maximum below the minimum now pulls the minimum down, and
  vice versa, matching QAbstractSlider conventions.
2026-08-05 14:53:04 +08:00
Mike-Solar 774eda75fe docs(riir): design inter-module C ABI interfaces and split out oakstorage
- riir.md: split project file read/write into standalone oakstorage
  module (pluggable backend, DB-replaceable); add Mermaid data flow
  diagram of all modules; adjust batch table and milestones
- riir/04-interfaces.md: new provides/consumes contract matrix for
  all modules
- riir/M10-oakstorage.md: new manual with frozen C API (typed opaque
  handles, manual vtable for storage backends, URI addressing)
- riir/01: codify pure-C OO interface rules (typed handles instead of
  void*, init/free pairs, manual vtables, no C++ objects or member
  calls across shared library boundaries); upper layers issue commands
  only, no module-to-module event subscriptions (async task callbacks
  excepted)
- sync 00/02/03 and M2-M9 manuals: remove subscribe APIs, replace
  void* with typed handles, update tests accordingly
2026-08-05 14:48:08 +08:00
Mike-Solar b55d626c0c docs: dependency analysis and two-person split for issues 9-20 (#34-#45) 2026-08-05 01:16:07 +08:00
Mike-Solar 00328ee95e Merge pull request #57 from Mike-Solar/main
app: migrate playhead/undo/modified events off EventBridge (issues 5-8)
2026-08-05 01:12:31 +08:00
Mike-Solar 40eea8d97c ci: use smaller runners 2026-08-05 00:59:09 +08:00
Mike-Solar a030f2da20 app: migrate playhead/undo/modified events off EventBridge (issues 5-8)
- issue 5 (#53): ExportDialog playhead via PlaybackController
- issue 6 (#54): timebasedwidget/timelinewidget playhead via PlaybackController
- issue 7 (#55): historywidget via app-internal Core::undo_index_changed
- issue 8 (#33): PROJECT_MODIFIED_CHANGED re-broadcast as Core::project_modified_changed
2026-08-05 00:52:37 +08:00
Mike-Solar 1738dbf224 Merge pull request #56 from Mike-Solar/main
app: PlaybackController + playhead subscription migration (issues 0c,…
2026-08-05 00:13:06 +08:00
Mike-Solar b77344b506 app: PlaybackController + playhead subscription migration (issues 0c, 1-4)
New app/playback/playbackcontroller.{h,cpp}: a lazily created
process-wide singleton whose set_playhead() forwards to
oakengine_viewer_set_playhead and re-broadcasts playhead_changed as a
plain Qt signal. Every app-side oakengine_viewer_set_playhead call site
(17 across viewer, timelinewidget, timelineview, import tool,
timebasedwidget, keyframecontrol, export dialog, mainwindow) now goes
through it.

Migrate the first four playhead subscribers off the raw C event
subscription / EngineEventBridge to the controller signal:
- TimeBasedView (issue 1)
- NodeParamViewWidgetBridge (issue 2)
- NodeParamViewKeyframeControl (issue 3)
- NodeParamViewConnectedLabel (issue 4)

Each stores a QMetaObject::Connection filtered on its viewer node and
disconnects on teardown; the viewer_sub_ members are gone. Plan docs
mark issues 0c and 1-4 as done.

Closes #30, closes #31, closes #32, closes #51, closes #52.
2026-08-05 00:01:12 +08:00
Mike-Solar ac7d942ec7 Merge pull request #27 from lulumumu9999/main
fix: issue #26 Assign independent ID for AUDIO_MANAGER_OUTPUT_NOTIFY
2026-08-04 23:24:05 +08:00
Mike-Solar 5baa9e3814 Merge branch 'main' into lulumumu9999/main 2026-08-04 23:10:33 +08:00
Mike-Solar 712badbaa7 build/ci: green builds and tests on all three platforms
Compiler hygiene (all platforms):
- Silence warnings across the tree: missing override, -Wreorder ctor
  init, -Wshadow, -Wsign-compare, missing switch cases, unused
  functions/captures, Qt 6.11 deprecations (QMouseEvent/QDropEvent
  accessors, qAsConst, Q_FOREACH over non-shared containers,
  AA_UseHighDpiPixmaps) and the .bak/ backup tree removal.
- Fix regressions from the cleanup: missing clip decls in
  capi/timeline.cpp, plugin.cpp rename fallout, panel setFocus
  ambiguity, QGraphicsItem::pos vs event->position(), duplicate
  k_push_button case, boolean test variable.

Windows:
- Qt portability: CommandLineParser is_set/add_option, QTimeZone
  systemTimeZone (QTimeZone::LocalTime is 6.11-only), k_progress_* enum.
- Linking: stop adding oakengine to OLIVE_LIBRARIES (import lib plus
  oakengine-obj caused multiple definitions); add OAKENGINE_STATIC so
  internal consumers no longer reference __imp_* stubs.
- oakengine.ver: export olive::Renderer typeinfo so liboakgl.so can be
  dlopened (Linux), DynamicRenderer no longer dlcloses backend libraries
  (crash in RenderManager's dtor calling into unmapped memory).
- OTIO runtime: copy DLLs next to every binary on Windows instead of
  relying on PATH (0xc0000135 in gtest discovery).
- Headless GL: the runner only has GDI OpenGL 1.1, killing every render
  worker. Deploy Mesa llvmpipe as opengl32sw.dll (Qt's software-GL
  channel) with QT_OPENGL=software, and let QT_OPENGL override the
  AA_UseDesktopOpenGL default. ExportTask fails fast after 8 consecutive
  undelivered frames instead of segfaulting or grinding forever;
  FFmpegEncoder::write_frame tolerates null frames.
- Tests: GetTempPathA+PID temp dirs, GetLongPathNameA for 8.3 names,
  forward-slash normalization when comparing project filenames.

Linux:
- Install libshaderc-dev so oakvulkan compiles GLSL (Vulkan tests).
- Accept UNORM floor-or-round (63/64) in the blit ping-pong test.
- Skip MainWindow construction test on the offscreen QPA (cannot paint
  QOpenGLWidget).

Also: oak_cli_transcode gets a 300s ctest timeout, worker logs GL
context version and LoadGraph/render_frame stages, and
docs/plans/eliminate-event-bridge-issues.md (English translation).
2026-08-04 21:34:31 +08:00
Mike-Solar 5006382790 ci: oakvulkan keeps full sources on Windows
vulkanrenderer.cpp is NOT part of oakengine-obj (unlike
openglrenderer.cpp), so the entry-point-only treatment from the
previous change left VulkanRenderer symbols undefined. Compile the
renderer into the plugin and link oakengine-obj + olive-version-obj.
2026-08-03 14:38:38 +08:00
Mike-Solar 248b1873e8 ci: enable Vulkan tests on Linux via Mesa lavapipe
Install libvulkan-dev + mesa-vulkan-drivers (lavapipe = software Vulkan,
no GPU needed) and stop passing CMAKE_DISABLE_FIND_PACKAGE_Vulkan so the
Vulkan backend and its tests are built and exercised.
2026-08-03 14:01:03 +08:00
Mike-Solar a304cc0759 ci: install Mesa DRI drivers for llvmpipe GL in headless Linux tests
libgl1-mesa-dev only ships headers; the software rasterizer that makes
OpenGL work under Xvfb (no GPU required) lives in libgl1-mesa-dri.
2026-08-03 13:56:16 +08:00
Mike-Solar 960d6361d5 ci: make Windows render plugins entry-point-only (fix duplicate symbols)
oakengine-obj already contains openglrenderer.cpp and its moc output;
compiling them again into oakgl.dll plus embedding oakengine-obj caused
duplicate definitions and a stray k_app_version reference. On Windows
the plugins now compile only the C entry point and link oakengine-obj +
olive-version-obj.
2026-08-03 13:52:28 +08:00
Mike-Solar 1af7ab7838 ci: engine tests use dllexport-consistent macros on Windows; run Linux tests under Xvfb
- make_oakengine_gtest embeds oakengine-obj; test code must see
  OAKENGINE_API as dllexport too (OAKENGINE_BUILD), otherwise MinGW
  resolves nothing against __imp_* stubs
- the render worker intentionally drops QT_QPA_PLATFORM=offscreen and
  needs a real display for its GL context; run the Linux ctest and the
  filtered gtest steps under xvfb-run
2026-08-03 13:32:18 +08:00
Mike-Solar 631f9e5bd1 ci: link render backend plugins against oakengine-obj on Windows; switch runners
- liboakengine.dll does not export engine-internal C++ symbols
  (olive::Renderer, FileFunctions, VideoParams, Texture), so oakgl.dll
  failed to link on Windows. Embed oakengine-obj instead (same pattern
  as the engine tests); MinGW's name-based RTTI keeps cross-DLL casts
  working.
- ci.yml: move to warp runners
2026-08-03 13:13:42 +08:00
Mike-Solar 835d47244c ci: sweep remaining QLatin1String::toUtf8; embed version obj in oakengine.dll
- pointer.cpp/transition.cpp: same Qt 6.4 incompatibility as import.cpp
- Windows: DLLs cannot have undefined symbols, so the
  executable-provides-k_app_version trick does not link; embed
  olive-version-obj into oakengine on WIN32 (each module keeps its own
  copy)
2026-08-03 12:48:27 +08:00
lulumumu9999 e995aa80ec fix: issue0a 修复音频事件ID碰撞,给AUDIO_MANAGER_OUTPUT_NOTIFY分配独立ID 2026-08-02 23:54:11 +08:00
Mike-Solar 348881f558 ci: fix Qt6.4 QLatin1String::toUtf8 and stale Windows shm branch
- import.cpp: pass the const char* input ids directly; the QLatin1String
  roundtrip uses toUtf8(), unavailable in distro Qt 6.4
- sharedmemoryregion.cpp: the Windows branch still used the pre-refactor
  API (Open/Close/kCreate); rewritten to the current lowercase
  open/close/k_create interface
2026-08-02 21:29:03 +08:00
Mike-Solar 4f13e20fff ci: move OakEngineMarker opaque decl to timeline.h; guard execinfo.h for Windows
- resizabletimelinescrollbar instantiates QMetaType over OakEngineMarker
  via timeline.h includes; the declaration belongs there, not serializer.h
- execinfo.h doesn't exist on Windows; the OAK_DEBUG_INVALID_INPUT
  backtrace diagnostic is now Unix-only
2026-08-02 18:56:44 +08:00
Mike-Solar 393b650fb4 fix: opaque-pointer declarations need qmetatype include and single ownership
The scripted Q_DECLARE_OPAQUE_POINTER sweep missed the QtCore/qmetatype.h
include (cascade of stdlib errors) and declared a few types in two headers
(redefinition of IsPointerDeclaredOpaque). Include qmetatype.h everywhere
and declare each handle in exactly one header.
2026-08-02 18:25:52 +08:00