- 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.
126 lines
5.3 KiB
Markdown
126 lines
5.3 KiB
Markdown
# M9 · oakplugin 拆分手册 + facade 装配层裁决
|
||
|
||
> 内容:`engine/pluginSupport/`(OpenFX host:OliveHost、
|
||
> OlivePluginInstance、PluginNode、PluginProgressReporter)。
|
||
> 依赖:node 6、render 6、common 6、core 2、undo 2、coreengine 2。
|
||
> 拆分顺序第 9 位(最后拆的实体模块)。文末 §4 是 liboakengine
|
||
> 装配层的最终裁决。
|
||
|
||
## 1. 目标形态
|
||
|
||
```
|
||
oakplugin/
|
||
include/oakplugin/{host.h, instance.h, progress.h, types.h, export.h}
|
||
src/
|
||
tests/ # oakplugin_gtest
|
||
```
|
||
|
||
## 2. 冻结 C API
|
||
|
||
### 2.1 `oakplugin/host.h`
|
||
|
||
```c
|
||
OAKPL_API int oakplugin_host_init(void);
|
||
OAKPL_API void oakplugin_host_shutdown(void);
|
||
OAKPL_API int oakplugin_host_scan(const char *const *bundle_dirs,
|
||
int dir_count);
|
||
OAKPL_API int oakplugin_host_plugin_count(void);
|
||
OAKPL_API int oakplugin_host_plugin_id_at(int i, char *buf, int n);
|
||
OAKPL_API int oakplugin_host_plugin_label(const char *plugin_id,
|
||
char *buf, int n);
|
||
```
|
||
|
||
### 2.2 `oakplugin/instance.h`
|
||
|
||
```c
|
||
typedef struct OakPluginInstance OakPluginInstance;
|
||
OAKPL_API OakPluginInstance *oakplugin_instance_create(
|
||
const char *plugin_id);
|
||
OAKPL_API void oakplugin_instance_free(OakPluginInstance *i);
|
||
OAKPL_API int oakplugin_instance_set_param(OakPluginInstance *i,
|
||
const char *param_id, const oak_node_value *v);
|
||
OAKPL_API int oakplugin_instance_get_param(OakPluginInstance *i,
|
||
const char *param_id, oak_node_value *out);
|
||
OAKPL_API int oakplugin_instance_render(OakPluginInstance *i,
|
||
OakCodecFrame *dst, const OakCodecFrame *src, int64_t ts);
|
||
/* 进度回调:instance_render 是异步命令(渲染中进行),进度/取消回调
|
||
* 即其返回通道——04 §3 唯一例外情形(R6 已把 cancelled 信号改成 C
|
||
* 回调,沿用该机制)。非异步接口一律不配回调。 */
|
||
OAKPL_API void oakplugin_instance_set_progress_cb(OakPluginInstance *i,
|
||
oakplugin_progress_fn fn, void *userdata);
|
||
OAKPL_API void oakplugin_instance_cancel(OakPluginInstance *i);
|
||
```
|
||
|
||
### 2.3 `oakplugin/progress.h`
|
||
|
||
```c
|
||
typedef struct OakPluginProgress OakPluginProgress; /* 报告器句柄 */
|
||
OAKPL_API OakPluginProgress *oakplugin_progress_create_dialog(
|
||
const char *message, const char *title); /* UI 侧实现 */
|
||
OAKPL_API void oakplugin_progress_free(OakPluginProgress *p);
|
||
```
|
||
|
||
## 3. 切割点
|
||
|
||
| 现状 | 处理 |
|
||
|---|---|
|
||
| plugin → node/ 6(plugins/plugin.h 3 等) | 经 oaknode C ABI(PluginNode 是节点,留在 oaknode;oakplugin 只经 factory/host 接口交互)——**PluginNode 归属裁决:PluginNode 类随 oaknode 走**(它是节点体系成员),oakplugin 提供 host/instance |
|
||
| plugin → render/ 6(videoparams 3 等) | videoparams 已下沉;其余经 oakrender C ABI |
|
||
| plugin → undo/ 2 | oakundo 适配类 |
|
||
| plugin → coreengine.h 2 | 插件注册点内聚进 oakplugin_host_init |
|
||
|
||
## 4. facade 装配层最终裁决(liboakengine 的终态)
|
||
|
||
M1-M9 全部完成后,`engine/src/capi` + `coreengine` + `tool/` +
|
||
`ui/` 残余构成 liboakengine。裁决(选定):
|
||
|
||
**facade 直链各模块,不绕 C ABI 自调**。即:facade 的 `oakengine_*`
|
||
实现可以继续直接调用各模块的 C++ 内部(链接 oaknode/oakrender 等
|
||
的静态或共享库),不要求 facade 经各模块的公共 C ABI 兜圈。
|
||
理由:facade 与 app 的边界(oakengine_*)已经纯 C 且 nm=0,模块间
|
||
边界是给"模块互相调用"用的;facade 是装配层,自家人不绕远路。
|
||
**但**:`coreengine.h` 被 node/render/task/plugin 引用的 5+2+2+2
|
||
处必须内聚(各模块的初始化改由各自的 `oak<mod>_init` 完成,
|
||
coreengine 只做编排调用)。
|
||
|
||
终态验证:
|
||
|
||
```
|
||
nm -D --defined-only liboakengine.so | grep -c " T _Z" # 0(R7-B)
|
||
nm -D --defined-only liboaknode.so | grep -c " T _Z" # 0(每模块同查)
|
||
ldd liboakengine.so | grep oak # 只见 oak* 模块库
|
||
全量构建 0 error;全量 ctest 绿
|
||
```
|
||
|
||
## 5. 测试(映射 03 §2/§3)
|
||
|
||
- host:init/scan/枚举(照现有 OliveHost 测试的 bundle fixture)。
|
||
- instance:Shadertoy 类插件(CI 里可用的)创建/参数/渲染一帧非空。
|
||
- progress:回调触发与 cancel。
|
||
- `oakplugin_debug_alive_count()` 泄漏断言。
|
||
|
||
## 6. 实施现状(2026-08-05)
|
||
|
||
已完成。src/plugin/src/ 六个类(olivehost/oliveplugininstance/
|
||
oliveclip/paraminstance/image/pluginprogressreporter)全部去Qt,
|
||
QMessageBox/QApplication 依赖删除,改为 §4 裁决的 facade 回调
|
||
装配。C ABI 落在 include/plugin/{error,host,instance}.h,
|
||
OakPluginInstance 为引用计数值句柄(ctx/addref/release/
|
||
abi_version)。
|
||
|
||
偏离手册之处:
|
||
|
||
- paraminstance 不直接持有 Node*,改持 OakNodeNode 值句柄,参数
|
||
读写全部经 oaknode C ABI;node↔instance 的身份路由用新增的
|
||
oaknode_node_identity() 注册表实现。
|
||
- oliveclip 的纹理为 OakRenderTexture 值句柄,oakrender 因此补了
|
||
texture/copier/ticket 一族 C API。
|
||
- oaknode 的 transition stub(src/node/transition/pluginSupport/)
|
||
桥接 oakplugin 真身头,liboaknode 运行期引用 oakplugin 符号
|
||
(dynamic_lookup);所有构建 oaknode 的 standalone 树都要把
|
||
src/plugin 加进构建,测试二进制必须链接 oakplugin。
|
||
|
||
验证:build-oakplugin 100/100;codec 22/22、audio 40/40、
|
||
task 110/110、render 49/49、timeline 121/121(均含 oakplugin
|
||
接入后的全量回归)。
|