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
This commit is contained in:
2026-08-07 14:01:23 +08:00
parent 66831a870e
commit 6ded1d2d63
54 changed files with 5937 additions and 1 deletions
+14
View File
@@ -22,6 +22,7 @@
#define OAK_EDITOR_NODE_FOLDER_H
#include "node/error.h"
#include "undo/undocommand.h"
#include "node/project.h"
#ifdef __cplusplus
@@ -73,6 +74,19 @@ OakNodeNode *oaknode_folder_child_at(const OakNodeFolder *folder, int index);
*/
int oaknode_folder_add_child(OakNodeFolder *folder, OakNodeNode *child);
/**
* @brief Borrowed cast from a folder handle to its node handle.
* NULL for NULL.
*/
OakNodeNode *oaknode_folder_as_node(OakNodeFolder *folder);
/**
* @brief Create an undoable FolderAddChild command. Owned; free with
* oakundo_command_free().
*/
OakUndoCommand *oaknode_command_create_folder_add_child(
OakNodeFolder *folder, OakNodeNode *child);
/**
* @brief Remove `child` from `folder` without deleting it (live,
* non-undoable; executes Folder::RemoveElementCommand::redo()).
+41
View File
@@ -23,7 +23,12 @@
#include <stdint.h>
#include "common/videoparams.h"
#include "node/error.h"
// NOTE: quoted-relative to bypass the "render/cancelatom.h" transition
// bridge (oakrender's C++ olive::CancelAtom) that shadows the C ABI
// header on oaknode's include path.
#include "../../include/render/cancelatom.h"
#include "node/project.h"
#ifdef __cplusplus
@@ -60,6 +65,12 @@ typedef struct OakNodeFootage OakNodeFootage;
OakNodeFootage *oaknode_footage_create(OakNodeProject *project,
const char *filename);
/**
* @brief Borrowed cast from a footage handle to its node handle.
* NULL for NULL.
*/
OakNodeNode *oaknode_footage_as_node(OakNodeFootage *footage);
/**
* @brief Current media path (Footage::filename()). Two-stage string getter.
*
@@ -192,6 +203,36 @@ int oaknode_footage_set_proxy(OakNodeFootage *footage, const char *path,
*/
int oaknode_footage_clear_proxy(OakNodeFootage *footage);
/**
* @brief Video stream parameters as an oakcommon video-params handle
* (ViewerOutput::get_video_params()). `out` receives a handle with
* reference count 1 (release with oakcommon_videoparams_free()).
* OAKNODE_E_NOT_FOUND for an out-of-range index.
*/
int oaknode_footage_get_video_params(OakNodeFootage *footage, int index,
OakVideoParams *out);
/**
* @brief Set a video stream's parameters from an oakcommon handle
* (ViewerOutput::set_video_params()).
*/
int oaknode_footage_set_video_params(OakNodeFootage *footage, int index,
const OakVideoParams *params);
/**
* @brief Video length as a rational pair (ViewerOutput::get_video_length()).
*/
int oaknode_footage_get_video_length(OakNodeFootage *footage,
int64_t *out_num, int64_t *out_den);
/**
* @brief Set the footage's cancellation atom used during probing
* (Footage::set_cancel_pointer()). `atom` may be an empty OakCancelAtom
* (ctx == NULL) to clear.
*/
int oaknode_footage_set_cancel_atom(OakNodeFootage *footage,
OakCancelAtom atom);
#ifdef __cplusplus
}
#endif
+41
View File
@@ -242,3 +242,44 @@ int oaknode_serializer_loaddata_connection_at(
#endif
#endif //OAK_EDITOR_NODE_SERIALIZER_H
/**
* @brief Result codes for file-level save/load (mirror
* ProjectSerializer::ResultCode; pinned by test).
*/
enum OakNodeSerializerResultCode {
OAKNODE_SERIALIZER_RESULT_SUCCESS = 0,
OAKNODE_SERIALIZER_RESULT_PROJECT_TOO_OLD = 1,
OAKNODE_SERIALIZER_RESULT_PROJECT_TOO_NEW = 2,
OAKNODE_SERIALIZER_RESULT_UNKNOWN_VERSION = 3,
OAKNODE_SERIALIZER_RESULT_FILE_ERROR = 4,
OAKNODE_SERIALIZER_RESULT_XML_ERROR = 5,
OAKNODE_SERIALIZER_RESULT_OVERWRITE_ERROR = 6,
OAKNODE_SERIALIZER_RESULT_NO_DATA = 7
};
/**
* @brief Save a project to a file (ProjectSerializer::save(), project
* type, optional OVEC compression). Layout data is not serialized
* through this API (app-layer concern, see oakstorage/M10).
*
* @param out_code Receives an OakNodeSerializerResultCode (may be NULL).
* @param details Optional two-stage buffer for the result details
* string (e.g. the fallback filename on overwrite errors).
* @return OAKNODE_OK when the result code is
* OAKNODE_SERIALIZER_RESULT_SUCCESS, OAKNODE_E_FAILED otherwise
* (details in out_code/details), OAKNODE_E_INVALID for NULL args.
*/
int oaknode_serializer_save_to_file(OakNodeProject *project,
const char *filename, int use_compression, int *out_code,
char *details, int details_size);
/**
* @brief Load a project from a file into `project`
* (ProjectSerializer::load(), project type).
*
* Same return/out-param convention as oaknode_serializer_save_to_file().
*/
int oaknode_serializer_load_from_file(OakNodeProject *project,
const char *filename, int *out_code, char *details,
int details_size);