- 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
288 lines
18 KiB
Markdown
288 lines
18 KiB
Markdown
# 记录项
|
||
|
||
## common
|
||
|
||
CancelableObject只在render和task处有🚰,移入对应模块。
|
||
|
||
## 从 oakcommon(src/common)移除的类(2026-08-05)
|
||
|
||
判据:不严重依赖 common 其他类,且只有一个非 common 模块使用它
|
||
(tests/gtest 不计入使用方)。以下类已从 `src/common/` 移除,
|
||
拆分时应放到对应模块:
|
||
|
||
| 类 | 唯一使用方 | 应放到 |
|
||
|---|---|---|
|
||
| `Html`(html.h/.cpp) | engine/node | oaknode(M3)。注意它依赖 common 的 xmlutils,迁移时需连同 XML 辅助或改为调用 oakcommon C API |
|
||
| `JobTime`(jobtime.h/.cpp) | engine/render | oakrender(M7) |
|
||
| `OTIOUtils`(otioutils.h) | engine/task | oaktask(M8) |
|
||
| `PlaybackAudioClock`(playbackaudioclock.h) | engine/audio | oakaudio(M6) |
|
||
| `to_hex`(tohex.h) | engine/node | oaknode(M3) |
|
||
| `mid()`(util.h) | engine/node | oaknode(M3) |
|
||
| `AVFramePtr`(avframeptr.h) | engine/render | oakrender(M7) |
|
||
| `CrashpadInterface`(crashpadinterface.h/.cpp) | app/main.cpp | app(crashhandler 相关) |
|
||
| crashpadutils.h | app/crashhandler | app/crashhandler |
|
||
| `AutoScroll`(autoscroll.h,oakutil shim) | app/dialog、app/widget | app |
|
||
| `digit.h`(oakutil shim) | app/dialog | app |
|
||
| `range.h`(oakutil shim) | app/widget | app |
|
||
|
||
另:`power.h`、`memorypool.h`、`threadsafemap.h` 当前没有任何
|
||
common 模块外的使用方(零用户),不满足移除判据,暂保留在
|
||
oakcommon;后续若确认无用途可直接删除。
|
||
|
||
## oakcommon 去Qt化的删除与语义变更(2026-08-05)
|
||
|
||
去Qt化过程中以下函数被删除或语义变化,迁移调用方时需注意:
|
||
|
||
- `CommandLineParser::print_help()`:不再自动读取
|
||
`QCoreApplication::applicationName()/applicationVersion()`,需先调
|
||
`set_app_info()`(C API:`oakcommon_commandlineparser_set_app_info`),
|
||
否则打印默认 `"oak"` + 空版本。
|
||
- `FileFunctions::get_unique_file_identifier`:哈希由 SHA-1 改为
|
||
FNV-1a 64-bit,旧缓存 key 全部失效(需一次重建)。
|
||
`get_configuration_location`/`get_application_path`/
|
||
`get_temp_file_path`/`get_auto_recovery_root` 的标准路径改为手写
|
||
平台实现,路径与原 Qt 版不同。`read_file_as_string(":/...")` 的
|
||
qrc 资源路径不再可用,shader 等资源调用方需改为磁盘路径或内嵌。
|
||
- xmlutils:`xml_read_next_start_element(reader, CancelAtom*)`
|
||
重载与 cancel_atom 参数删除(依赖 render/cancelatom.h),取消语义
|
||
由调用方在循环外自行检查;`XMLAttributeLoop` 宏删除,由
|
||
`XmlStreamReader::attributes()` + range-for 替代;
|
||
`QXmlStreamReader/Writer` 由基于 expat 的
|
||
`olive::XmlStreamReader/Writer` 替代(不支持 XML 命名空间)。
|
||
- `OIIOUtils::frame_to_buffer/buffer_to_frame`:未进 C API,C++ 侧签名
|
||
拍平为 `(const void *data, int64_t linesize_bytes, OIIO::ImageBuf *)`,
|
||
engine/codec/frame.cpp 迁移时传成员即可。`OakCommonPixelFormat` 枚举
|
||
目前定义在 include/common/ocioutils.h,oiioutils 复用,后续可抽成
|
||
独立的 include/common/pixelformat.h。
|
||
- `MemoryPool`:删除 QTimer 每 5 秒自动回收空 arena,改为公有
|
||
`clear_empty_arenas()` 由调用方周期调用;不再继承 QObject。
|
||
memorypool/threadsafemap 零使用方且为模板/多态基类,未包 C API。
|
||
- `debug_handler`:丢失 `QMessageLogContext`(文件/行号)参数(原实现
|
||
本就未用);`qInstallMessageHandler` 无对应物。
|
||
- `Current::set_current_video_params/audio_params`:由按值拷贝改为持有
|
||
`std::shared_ptr<void>`(类型擦除),调用方需自行管理生命周期并用
|
||
`static_pointer_cast` 还原(调用点:olivehost.cpp、
|
||
timebasedwidget.cpp、plugin.cpp 等 6 处)。
|
||
- qtutils:engine 未使用的纯 UI 函数(`q_font_metrics_width`、
|
||
`create_horizontal/vertical_line`、`set_combo_box_data`、
|
||
`word_wrap_string`、`flip_control_and_shift_modifiers`、
|
||
`get_formatted_date_time`、`to_q_color`、`core::qHash`、
|
||
`Q_DECLARE_METATYPE` 宏组)未迁入 oakcommon,app 层继续用 Qt 版。
|
||
`ptr_to_value/value_to_ptr` 载体由 QVariant 改为 `uintptr_t`,
|
||
迁移时调用点需同步改(renderprocessor.cpp、rendermanager.cpp、
|
||
previewautocacher.cpp、src/capi/worker.cpp)。`get_parent_of_type`
|
||
依赖 C++ 模板+RTTI,未进 C API。
|
||
- define.h:删除 `MACRO_NAME_AS_STR`/`MACRO_VAL_AS_STR`/
|
||
`OLIVE_NS_CONST_ARG`/`OLIVE_NS_ARG`/`OLIVE_NS_RETURN_ARG`
|
||
(依赖 Qt QArgument,全仓无使用)。
|
||
- decibel.h:删除 `ALLOW_RETURNING_INFINITY` 编译开关分支(代码库
|
||
未定义该宏,行为不变)。
|
||
- `FFmpegUtils`:新增类内常量 `k_rgb_channel_count/k_rgba_channel_count`
|
||
(3/4)取代对 `VideoParams` 同名常量的引用,消除 common→render
|
||
反向依赖。
|
||
|
||
## oakundo 去Qt化的删除与语义变更(2026-08-05)
|
||
|
||
`src/undo/`(olive::UndoCommand / MultiUndoCommand / UndoStack)去Qt化
|
||
过程中以下删除与语义变化,迁移调用方时需注意:
|
||
|
||
- `UndoStack` 不再继承 `QAbstractItemModel`(删除 `Q_OBJECT`、
|
||
`columnCount/data/index/parent/rowCount/headerData/hasChildren` 全部
|
||
model overrides 及 `begin/end*Rows` 通知)。历史面板(QTreeView 等)
|
||
属 app UI 层,迁移时应以 facade 的行式查询
|
||
(command_count/done_count/command_name/command_is_done)自行实现
|
||
model。
|
||
- `UndoStack::GetUndoAction/GetRedoAction/update_actions`(QAction 成员
|
||
及其文本/使能维护)删除——QAction 属 app 菜单层,app 应自行创建
|
||
action 并连接 undo/redo;`index_changed(int)` signal 改为 C++ 侧
|
||
`std::function<void(int)>`(`set_index_changed_callback`),C ABI
|
||
不暴露事件,调用方在变更命令后读 `oakundo_undostack_index`。
|
||
- `UndoCommand` 与 `olive::Project` 解耦:删除纯虚
|
||
`get_relevant_project()`(含 MultiUndoCommand/EmptyCommand 的
|
||
override)与 `project_` 成员;`redo_and_set_modified/
|
||
undo_and_set_modified` 的修改标记语义改为可选回调对
|
||
`set_modified_callbacks(is_modified, set_modified)`:redo 时记录当前
|
||
修改标记并置 true,undo 时恢复记录值;不挂回调则退化为纯
|
||
redo/undo。读写顺序与 Qt 版一致(redo_now() 之后读取并置位),
|
||
行为对齐。Project 侧迁移时在适配层把 `Project::is_modified/
|
||
set_modified` 绑到这对回调即可。
|
||
- `UndoStack` 析构不再调用 `clear()`(Qt 版在析构里 clear 会再 push
|
||
一个 EmptyCommand 造成泄漏),改为直接删除所有持有命令。
|
||
- 顺带修复三处 engine 原版就存在的缺陷(迁移调用方无需适配,但
|
||
行为与旧版不同,特此记录):
|
||
- `jump(0)` 死循环:底部 EmptyCommand 不可 undo,`jump` 现以
|
||
`can_undo()/can_redo()` 为守卫,跳到 0 时停在 index 1;
|
||
- `MultiUndoCommand` 原来不拥有子命令(析构泄漏),现析构删除
|
||
全部 children;
|
||
- `push_pre_executed` 原来不置 `done_` 标记,导致入栈后 undo
|
||
为空操作(facade undo-group 的组撤销实际不生效),现入栈前
|
||
`set_done(true)`(UndoCommand 新增 `set_done()`)。
|
||
- `clear()` 推入的占位命令名固定为字面量 "New/Open Project"(原
|
||
`tr()` 翻译移除,翻译由 app 层负责)。
|
||
- `push/push_pre_executed` 的命令名由 `QString` 改为 `std::string`;
|
||
C ABI 中 NULL name 视同空串。
|
||
- C ABI 句柄语义:`oakundo_command_init/init_multi` 返回的句柄拥有
|
||
底层命令;push 或 `oakundo_command_multi_add_child` 成功后所有权
|
||
转移、wrapper 被消费(不可再用/再 free);
|
||
`oakundo_command_multi_child` 返回 borrowed wrapper(free 只释放
|
||
wrapper)。
|
||
|
||
## oaknode 去Qt化的删除与语义变更(2026-08-05)
|
||
|
||
`src/node/`(Node 族、Project 族、Sequence/Track/Block 族、serializer、
|
||
ColorManager)去Qt化过程中的删除与语义变化,迁移调用方时需注意
|
||
(详细约定见 `src/node/DEQT.md` §4/§7):
|
||
|
||
- 信号槽整组删除:Node 的 28 个信号(label_changed、input_connected、
|
||
keyframe_added、added_to_graph 等)、NodeKeyframe 的 5 个、
|
||
Project/Folder/Sequence/Footage 的全部信号(name_changed、
|
||
modified_changed、track_added、begin/end_insert_item 等),变更通知
|
||
统一由 facade 经 `oakengine_event` 发出,oaknode 不持有上层回调。
|
||
- QObject 父子生命周期改显式所有权:Project 持有全部节点
|
||
(`add_node`/`remove_node`,`clear()`/析构删除);nodeundo 用
|
||
`std::unique_ptr<Node>` 替代 `memory_manager_`;keyframe 经
|
||
`Node::add_keyframe()/remove_keyframe()` 显式注册(自动 set_parent),
|
||
gizmo 经 `Node::add_gizmo()/remove_gizmo()` 显式注册(构造不再自
|
||
注册);`NodeInputImmediate::delete_all_keyframes(reclaimed)` 替代
|
||
"reparent 续命"。
|
||
- polygon/text 的 `generate_frame()` 光栅化(QPainter/QTextDocument)
|
||
改后端钩子:`PathFillBackend`(geometry.h)、`TextMeasureBackend`/
|
||
`TextRenderBackend`(textbackend.h),facade 未安装前输出空白
|
||
(被迫行为差异)。
|
||
- gizmo 绘制与 hit-test 归 app 层:各 gizmo 的 `draw(QPainter*)`、
|
||
`PointGizmo::get_clicking_rect()/get_drawing_rect()` 等删除;
|
||
`DraggableGizmo` 的拖拽信号改直调 `parent_node()->gizmo_drag_*()`;
|
||
drag 回调里的 `sender()` 由 `Node::current_gizmo()` 替代。
|
||
- footage 离线媒体警示帧:QImage/QPainter 改纯像素循环(深红底+斜纹),
|
||
"Media Offline" 文字叠层与抗锯齿丢失(被迫行为差异)。
|
||
- `:/ocioconf` Qt 资源路径不可用:ColorManager 默认配置的 qrc 提取必然
|
||
失败,需 `OCIO` 环境变量指向磁盘 config.ocio(测试用
|
||
`engine/render/ocioconf/config.ocio`)。
|
||
- `NodeGroupAddInputPassthrough` 的上游 bug 原样保留(去Qt化不改行为
|
||
逻辑,待单独裁决修复)。
|
||
- track.h 的 `QFontMetrics` 13px 常量:轨道默认高度原依赖
|
||
`QFontMetrics(qApp->font()).height()`,去Qt后固化为 13px 字面量,
|
||
换字体/DPI 不再自适应。
|
||
- `Footage::check_footage()` 的 QTimer 周期回调删除,函数本体保留为
|
||
public 由 facade 周期调用;`qApp->activeWindow()` 门槛移到 app 层。
|
||
- 序列化 XML 元素/属性名与读写顺序逐字节不变;`XmlStreamWriter` 输出
|
||
紧凑 XML(无声明无缩进);OVEC 压缩段保持 qCompress 兼容
|
||
(zlib + 4 字节大端长度)。
|
||
- 修复三个上游真实 bug(行为因此与旧版不同,特此记录):
|
||
`Project::clear()` 现重置 `root_`(clear 后可再次 initialize);
|
||
clear 不再先 `set_parent(nullptr)` 再 delete(否则 ~Node 的
|
||
disconnect_edge 触发 parent 不等的 assert);
|
||
`Sequence` 新增析构删除三个 `TrackList`(原来构造 new 后泄漏)。
|
||
- `sender()` 的其他替代:原 keyframe signal→Node 的 5 条失效通知链
|
||
(invalidate_from_keyframe_*)函数本体保留为 public 成员,带
|
||
`NodeKeyframe *key` 显式参数,待 facade 接线。
|
||
|
||
## 信号与槽的处理策略(2026-08-05)
|
||
|
||
去Qt化对 Qt 信号槽的统一处理模式,M1–M3 一致执行,后续模块照此:
|
||
|
||
1. **模块内通知改显式回调/直调(std::function)**:通知双方都在同一
|
||
模块内时,去掉 connect,改为 `std::function` 回调注册或成员直调。
|
||
例:oakundo `UndoStack::index_changed(int)` signal →
|
||
`set_index_changed_callback(std::function<void(int)>)`;oaknode
|
||
`Node::current_gizmo()/set_current_gizmo()` 机制替代 gizmo drag
|
||
回调里的 `sender()`;`DraggableGizmo` 的 handle_start/handle_movement
|
||
信号改直调 `parent_node()->gizmo_drag_start()/gizmo_drag_move()`;
|
||
TrackList 原 track_list_changed/length_changed 发射点直调
|
||
`sequence->update_track_cache()/verify_length()`。
|
||
2. **跨层/跨界通知删除,由 facade 经 oakengine_event 统一发出**:
|
||
一切指向 app/UI/其他模块的信号整组删除(Node 28 个、NodeKeyframe
|
||
5 个、Project/Folder/Sequence/Footage 全部),oaknode 自身不持有
|
||
任何上层回调;facade 在执行命令后经既有 `oakengine_event` 通道发
|
||
通知(事件 id 沿用 `oakengine/events.h` 70-95 段,值不变)。依据:
|
||
oaknode 的所有修改都经命令函数完成,调用方知道影响(M3 §2 特殊
|
||
约定 2,04 §3)。
|
||
3. **QObject 父子生命周期改显式所有权**:`setParent`/childEvent 机制
|
||
删除,所有权用显式容器与注册函数表达。例:Project 持有节点
|
||
(`add_node`/`remove_node`/`clear()`);`ColorManager` 由
|
||
`std::unique_ptr` 持有;nodeundo 用 `std::unique_ptr<Node>` 替代
|
||
`memory_manager_`;keyframe/gizmo 分别经 `add_keyframe()`/
|
||
`add_gizmo()` 显式注册;UndoCommand 树由 MultiUndoCommand 析构
|
||
删除 children。
|
||
4. **sender() 的替代**:两种形态——拖曳场景用
|
||
`Node::current_gizmo()`(DraggableGizmo 直调回调前后
|
||
`set_current_gizmo(this/nullptr)` 包一层);通知链场景改显式参数,
|
||
如 `invalidate_from_keyframe_*(NodeKeyframe *key)`。
|
||
5. **原 slot 函数本体保留为 public 成员,待 facade 接线**:signal 删了
|
||
但 slot 承载的业务逻辑不删,改为 public 成员函数由上层直调。清单
|
||
见 `src/node/DEQT.md` §7(如 `Sequence::update_track_cache()`、
|
||
`Footage::check_footage()/default_color_space_changed()/
|
||
proxy_ready()/proxy_finished()`、5 条 invalidate_from_keyframe_*)。
|
||
|
||
## oakrender 去Qt化的删除与语义变更(2026-08-05)
|
||
|
||
- `RenderTicket::finished` 不再跨线程补发:回调在调用 finish() 的
|
||
线程上触发;未决状态由 facade 自查 `is_running()`。
|
||
- PreviewAutoCacher 延迟重排队改显式标志:单次 QTimer 重排队删除,
|
||
`try_render()` 置 `delayed_requeue_pending_`,facade 在
|
||
`requeue_delay_ms()` 后重调 `try_render()`。
|
||
- DiskCacheFolder 周期存盘由 GUI 线程 QTimer 改后台线程,数据保护
|
||
用 `std::recursive_mutex`(原靠 QObject 线程亲和串行化)。
|
||
- PlaybackCache 的 Qt 信号改单回调注册:`set_invalidated_callback`/
|
||
`set_validated_callback`/`set_requested_callback`/
|
||
`set_cancel_all_callback`;跨层 invalidated/validated 通知由 facade
|
||
在命令后重发(M7 §2.2:oakrender 不持有上层回调)。
|
||
- `DiskManager::instance()` 惰性自建(原 app 启动时显式
|
||
create_instance;库消费者不经 facade 也能用)。
|
||
- FrameHashCache 帧缓存 JPEG 读写 QImage→OIIO/OpenEXR。
|
||
- AudioWaveformCache/PlaybackCache 的 QPainter 绘制归 app 层;
|
||
缓存指示条高度固化为常量 4(`oakrender_cache_indicator_height()`,
|
||
原 `QFontMetrics(QFont()).height()/4`)。
|
||
- 离屏 GL 上下文共享组需 app 显式传入(原 QOpenGLContext
|
||
globalShareContext 隐式共享)。
|
||
- OpenGLContext/Vulkan 上下文抽象层(OpenGLContextProvider 等)替代
|
||
QOpenGLContext 直用。
|
||
- WorkerProcess 仅 POSIX 实现(Windows 占位未做)。
|
||
- worker IPC 的 NDJSON 协议未变,workerjson 为本地(去 Qt)实现。
|
||
- `:/shaders` qrc 资源缺口:着色器源码的 Qt 资源路径在库形态下
|
||
不可用,需 app 侧提供文件映射。
|
||
- 删除 ipc/ipcmessage.cpp 等 3 个过期 .cpp(对应头已自包含 inline,
|
||
.cpp 内容失效)。
|
||
- displayinternal.h 分层违规(render→src/capi)并入 texturehandle.h。
|
||
- Renderer 线程亲和由 QObject::thread() 改显式 owner thread
|
||
(`set_owner_thread_to_current()`/`called_on_owner_thread()`)。
|
||
|
||
## oaktimeline 去Qt化的删除与语义变更(2026-08-05)
|
||
|
||
- TimelineMarker/TimelineWorkArea 的信号(time_changed/name_changed/
|
||
color_changed/enabled_changed/range_changed/marker_added/removed/
|
||
modified)全部删除,变更通知由 facade 层在命令后发出;list 的重排由
|
||
TimelineMarker::set_time 直调 parent_->resort(this)。
|
||
- TimelineMarker::draw()/get_marker_height()(QPainter/QFontMetrics)
|
||
删除,归 app 层。
|
||
- TimelineMarkerList 的 QObject childEvent 自动注册改为显式
|
||
add_marker(std::unique_ptr)/remove_marker 所有权转移;marker 构造
|
||
不再带 parent 参数(oaknode 的 4 个 serializer 调用点已适配)。
|
||
- ViewerOutput 的 workarea_/markers_ 由 QObject 父子管理改为
|
||
std::unique_ptr 持有。
|
||
- timeline 全部 undo 命令类改为持有 oaknode C 句柄
|
||
(OakNodeTrack/OakNodeBlock/OakNodeSequence),图操作全部经
|
||
oaknode C ABI(01 §0 铁律 6);为此 oaknode C API 新增:
|
||
copy_in_graph、clip_add_cache_passthrough_from、block_get_kind、
|
||
block_as_node/from_node、track_as_node、nearest_block_before/after_or_at、
|
||
command_create_remove_node/add_node/set_position_recursive、
|
||
node_get_project、input_array_insert/remove、connect/disconnect_element、
|
||
tracklist_get_sequence/track_input_id/array_append/array_remove_last/
|
||
get_array_index_from_cache_index、sequence_as_node、node_get_markers/
|
||
get_work_area(后两个为 oaktimeline 的借用出口)。
|
||
- UndoCommand 跨模块继承(oaktimeline 命令类继承 oakundo 的
|
||
olive::UndoCommand)保留——undo 架构的既有跨模块模式,记录为
|
||
01 §5 的明确例外(oaknode 的 nodeundo 同例)。
|
||
- **修复 de-Qt 断链**:Block 长度变化不再经信号通知 Track,改为
|
||
Block::InputValueChangedEvent 里对 track_->block_length_changed(this)
|
||
直调(原 Qt 版 connect 链,wave-2 遗留的 facade 接线项提前兑现)。
|
||
- 命令创建的 GapBlock 在插入 track 前必须先进项目图
|
||
(block_add_to_graph/block_remove_from_graph helper,对齐原版
|
||
setParent(graph)/setParent(memory) 语义);孤立句柄用 orphan 标志
|
||
跟踪,析构时 oaknode_block_free。
|
||
- oaknode↔oaktimeline 运行期互相解析(add_default_nodes →
|
||
TimelineAddTrackCommand),双方 dylib dynamic_lookup,测试二进制
|
||
必须同时链两个库(各 standalone 驱动已接线)。
|
||
- oakcommon xml C API 新增 get_native 借用访问器(C++ only),
|
||
oaktimeline 的 load/save 经它取回 XmlStreamReader/Writer。
|