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
This commit is contained in:
2026-08-07 17:20:42 +08:00
parent 295ea1bfe5
commit 67176281d9
87 changed files with 4499 additions and 3431 deletions
+148 -122
View File
@@ -20,7 +20,8 @@
#include "node/block.h"
#include "alivecount.h"
#include "node/node.h"
#include "node/track.h"
#include "block/block.h"
#include "block/clip/clip.h"
@@ -30,27 +31,26 @@
#include "block/transition/transition.h"
#include "output/track/track.h"
#include "nodehandle.h"
using oaknode_c_api::delete_as;
using oaknode_c_api::free_handle;
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
namespace
{
olive::Block *impl(OakNodeBlock *h)
olive::ClipBlock *clip_impl(OakNodeBlock h)
{
return reinterpret_cast<olive::Block *>(h);
olive::Block *b = to_native<olive::Block>(h);
return b ? dynamic_cast<olive::ClipBlock *>(b) : nullptr;
}
olive::ClipBlock *clip_impl(OakNodeBlock *h)
olive::TransitionBlock *transition_impl(OakNodeBlock h)
{
return h ? dynamic_cast<olive::ClipBlock *>(impl(h)) : nullptr;
}
olive::TransitionBlock *transition_impl(OakNodeBlock *h)
{
return h ? dynamic_cast<olive::TransitionBlock *>(impl(h)) : nullptr;
}
OakNodeBlock *wrap(olive::Block *b)
{
return reinterpret_cast<OakNodeBlock *>(b);
olive::Block *b = to_native<olive::Block>(h);
return b ? dynamic_cast<olive::TransitionBlock *>(b) : nullptr;
}
int get_rational(const olive::core::Rational &r, int *numerator,
@@ -65,30 +65,29 @@ int get_rational(const olive::core::Rational &r, int *numerator,
}
template <typename T, typename... Args>
OakNodeBlock *create_block(Args &&...args)
OakNodeBlock create_block(Args &&...args)
{
try {
T *b = new T(std::forward<Args>(args)...);
oaknode_c_api::alive_inc();
return wrap(b);
return make_handle<OakNodeBlock>(new T(std::forward<Args>(args)...),
true, &delete_as<T>);
} catch (...) {
return nullptr;
return OakNodeBlock{};
}
}
} // namespace
OakNodeBlock *oaknode_block_clip_create(void)
OakNodeBlock oaknode_block_clip_create(void)
{
return create_block<olive::ClipBlock>();
}
OakNodeBlock *oaknode_block_gap_create(void)
OakNodeBlock oaknode_block_gap_create(void)
{
return create_block<olive::GapBlock>();
}
OakNodeBlock *oaknode_block_transition_create(int kind)
OakNodeBlock oaknode_block_transition_create(int kind)
{
switch (kind) {
case OAKNODE_TRANSITION_CROSS_DISSOLVE:
@@ -96,70 +95,72 @@ OakNodeBlock *oaknode_block_transition_create(int kind)
case OAKNODE_TRANSITION_DIP_TO_COLOR:
return create_block<olive::DipToColorTransition>();
default:
return nullptr;
return OakNodeBlock{};
}
}
void oaknode_block_free(OakNodeBlock *block)
{
if (!block) {
return;
}
delete impl(block);
oaknode_c_api::alive_dec();
free_handle(block);
}
int oaknode_block_get_in(OakNodeBlock *block, int *numerator, int *denominator)
int oaknode_block_get_in(OakNodeBlock block, int *numerator, int *denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(block)->in(), numerator, denominator);
return get_rational(b->in(), numerator, denominator);
}
int oaknode_block_set_in(OakNodeBlock *block, int numerator, int denominator)
int oaknode_block_set_in(OakNodeBlock block, int numerator, int denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
impl(block)->set_in(olive::core::Rational(numerator, denominator));
b->set_in(olive::core::Rational(numerator, denominator));
return OAKNODE_OK;
}
int oaknode_block_get_out(OakNodeBlock *block, int *numerator, int *denominator)
int oaknode_block_get_out(OakNodeBlock block, int *numerator, int *denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(block)->out(), numerator, denominator);
return get_rational(b->out(), numerator, denominator);
}
int oaknode_block_set_out(OakNodeBlock *block, int numerator, int denominator)
int oaknode_block_set_out(OakNodeBlock block, int numerator, int denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
impl(block)->set_out(olive::core::Rational(numerator, denominator));
b->set_out(olive::core::Rational(numerator, denominator));
return OAKNODE_OK;
}
int oaknode_block_get_length(OakNodeBlock *block, int *numerator,
int oaknode_block_get_length(OakNodeBlock block, int *numerator,
int *denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(block)->length(), numerator, denominator);
return get_rational(b->length(), numerator, denominator);
}
int oaknode_block_set_length_and_media_out(OakNodeBlock *block, int numerator,
int oaknode_block_set_length_and_media_out(OakNodeBlock block, int numerator,
int denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
try {
impl(block)->set_length_and_media_out(
b->set_length_and_media_out(
olive::core::Rational(numerator, denominator));
} catch (...) {
return OAKNODE_E_FAILED;
@@ -167,14 +168,15 @@ int oaknode_block_set_length_and_media_out(OakNodeBlock *block, int numerator,
return OAKNODE_OK;
}
int oaknode_block_set_length_and_media_in(OakNodeBlock *block, int numerator,
int oaknode_block_set_length_and_media_in(OakNodeBlock block, int numerator,
int denominator)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
try {
impl(block)->set_length_and_media_in(
b->set_length_and_media_in(
olive::core::Rational(numerator, denominator));
} catch (...) {
return OAKNODE_E_FAILED;
@@ -182,102 +184,123 @@ int oaknode_block_set_length_and_media_in(OakNodeBlock *block, int numerator,
return OAKNODE_OK;
}
int oaknode_block_get_enabled(OakNodeBlock *block, int *enabled)
int oaknode_block_get_enabled(OakNodeBlock block, int *enabled)
{
if (!block || !enabled) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !enabled) {
return OAKNODE_E_INVALID;
}
*enabled = impl(block)->is_enabled() ? 1 : 0;
*enabled = b->is_enabled() ? 1 : 0;
return OAKNODE_OK;
}
int oaknode_block_set_enabled(OakNodeBlock *block, int enabled)
int oaknode_block_set_enabled(OakNodeBlock block, int enabled)
{
if (!block) {
olive::Block *b = to_native<olive::Block>(block);
if (!b) {
return OAKNODE_E_INVALID;
}
impl(block)->set_enabled(enabled != 0);
b->set_enabled(enabled != 0);
return OAKNODE_OK;
}
int oaknode_block_get_previous(OakNodeBlock *block, OakNodeBlock **out)
int oaknode_block_get_previous(OakNodeBlock block, OakNodeBlock *out)
{
if (!block || !out) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap(impl(block)->previous());
// Borrowed (empty when there is no neighbour)
*out = make_handle<OakNodeBlock>(b->previous(), false,
&delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_block_get_next(OakNodeBlock *block, OakNodeBlock **out)
int oaknode_block_get_next(OakNodeBlock block, OakNodeBlock *out)
{
if (!block || !out) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap(impl(block)->next());
*out = make_handle<OakNodeBlock>(b->next(), false,
&delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_block_get_track(OakNodeBlock *block, OakNodeTrack **out)
int oaknode_block_get_track(OakNodeBlock block, OakNodeTrack *out)
{
if (!block || !out) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !out) {
return OAKNODE_E_INVALID;
}
*out = reinterpret_cast<OakNodeTrack *>(impl(block)->track());
// Borrowed (empty when the block is not on a track)
*out = make_handle<OakNodeTrack>(b->track(), false,
&delete_as<olive::Track>);
return OAKNODE_OK;
}
int oaknode_block_link(OakNodeBlock *a, OakNodeBlock *b)
int oaknode_block_link(OakNodeBlock a, OakNodeBlock b)
{
if (!a || !b) {
olive::Block *na = to_native<olive::Block>(a);
olive::Block *nb = to_native<olive::Block>(b);
if (!na || !nb) {
return OAKNODE_E_INVALID;
}
return olive::Node::link(impl(a), impl(b)) ? OAKNODE_OK : OAKNODE_E_FAILED;
return olive::Node::link(na, nb) ? OAKNODE_OK : OAKNODE_E_FAILED;
}
int oaknode_block_unlink(OakNodeBlock *a, OakNodeBlock *b)
int oaknode_block_unlink(OakNodeBlock a, OakNodeBlock b)
{
if (!a || !b) {
olive::Block *na = to_native<olive::Block>(a);
olive::Block *nb = to_native<olive::Block>(b);
if (!na || !nb) {
return OAKNODE_E_INVALID;
}
return olive::Node::unlink(impl(a), impl(b)) ? OAKNODE_OK : OAKNODE_E_FAILED;
return olive::Node::unlink(na, nb) ? OAKNODE_OK : OAKNODE_E_FAILED;
}
int oaknode_block_are_linked(OakNodeBlock *a, OakNodeBlock *b, int *linked)
int oaknode_block_are_linked(OakNodeBlock a, OakNodeBlock b, int *linked)
{
if (!a || !b || !linked) {
olive::Block *na = to_native<olive::Block>(a);
olive::Block *nb = to_native<olive::Block>(b);
if (!na || !nb || !linked) {
return OAKNODE_E_INVALID;
}
*linked = olive::Node::are_linked(impl(a), impl(b)) ? 1 : 0;
*linked = olive::Node::are_linked(na, nb) ? 1 : 0;
return OAKNODE_OK;
}
int oaknode_block_get_link_count(OakNodeBlock *block, int *count)
int oaknode_block_get_link_count(OakNodeBlock block, int *count)
{
if (!block || !count) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !count) {
return OAKNODE_E_INVALID;
}
*count = int(impl(block)->links().size());
*count = int(b->links().size());
return OAKNODE_OK;
}
int oaknode_block_get_link_at(OakNodeBlock *block, int index,
OakNodeBlock **out)
int oaknode_block_get_link_at(OakNodeBlock block, int index,
OakNodeBlock *out)
{
if (!block || !out || index < 0) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !out || index < 0) {
return OAKNODE_E_INVALID;
}
const auto &links = impl(block)->links();
const auto &links = b->links();
if (index >= int(links.size())) {
return OAKNODE_E_NOT_FOUND;
}
*out = wrap(static_cast<olive::Block *>(links.at(index)));
return OAKNODE_OK;
// Borrowed; the linked block stays owned by its graph
*out = make_handle<OakNodeBlock>(
static_cast<olive::Block *>(links.at(index)), false,
&delete_as<olive::Block>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
/* ---------------------------------------------------------------- Clip */
int oaknode_clip_get_media_in(OakNodeBlock *clip, int *numerator,
int oaknode_clip_get_media_in(OakNodeBlock clip, int *numerator,
int *denominator)
{
olive::ClipBlock *c = clip_impl(clip);
@@ -287,7 +310,7 @@ int oaknode_clip_get_media_in(OakNodeBlock *clip, int *numerator,
return get_rational(c->media_in(), numerator, denominator);
}
int oaknode_clip_set_media_in(OakNodeBlock *clip, int numerator,
int oaknode_clip_set_media_in(OakNodeBlock clip, int numerator,
int denominator)
{
olive::ClipBlock *c = clip_impl(clip);
@@ -298,7 +321,7 @@ int oaknode_clip_set_media_in(OakNodeBlock *clip, int numerator,
return OAKNODE_OK;
}
int oaknode_clip_get_speed(OakNodeBlock *clip, double *speed)
int oaknode_clip_get_speed(OakNodeBlock clip, double *speed)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c || !speed) {
@@ -308,7 +331,7 @@ int oaknode_clip_get_speed(OakNodeBlock *clip, double *speed)
return OAKNODE_OK;
}
int oaknode_clip_set_speed(OakNodeBlock *clip, double speed)
int oaknode_clip_set_speed(OakNodeBlock clip, double speed)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c) {
@@ -318,7 +341,7 @@ int oaknode_clip_set_speed(OakNodeBlock *clip, double speed)
return OAKNODE_OK;
}
int oaknode_clip_get_reverse(OakNodeBlock *clip, int *reverse)
int oaknode_clip_get_reverse(OakNodeBlock clip, int *reverse)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c || !reverse) {
@@ -328,7 +351,7 @@ int oaknode_clip_get_reverse(OakNodeBlock *clip, int *reverse)
return OAKNODE_OK;
}
int oaknode_clip_set_reverse(OakNodeBlock *clip, int reverse)
int oaknode_clip_set_reverse(OakNodeBlock clip, int reverse)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c) {
@@ -338,7 +361,7 @@ int oaknode_clip_set_reverse(OakNodeBlock *clip, int reverse)
return OAKNODE_OK;
}
int oaknode_clip_get_maintain_audio_pitch(OakNodeBlock *clip, int *maintain)
int oaknode_clip_get_maintain_audio_pitch(OakNodeBlock clip, int *maintain)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c || !maintain) {
@@ -348,7 +371,7 @@ int oaknode_clip_get_maintain_audio_pitch(OakNodeBlock *clip, int *maintain)
return OAKNODE_OK;
}
int oaknode_clip_set_maintain_audio_pitch(OakNodeBlock *clip, int maintain)
int oaknode_clip_set_maintain_audio_pitch(OakNodeBlock clip, int maintain)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c) {
@@ -358,7 +381,7 @@ int oaknode_clip_set_maintain_audio_pitch(OakNodeBlock *clip, int maintain)
return OAKNODE_OK;
}
int oaknode_clip_get_loop_mode(OakNodeBlock *clip, int *loop_mode)
int oaknode_clip_get_loop_mode(OakNodeBlock clip, int *loop_mode)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c || !loop_mode) {
@@ -368,7 +391,7 @@ int oaknode_clip_get_loop_mode(OakNodeBlock *clip, int *loop_mode)
return OAKNODE_OK;
}
int oaknode_clip_set_loop_mode(OakNodeBlock *clip, int loop_mode)
int oaknode_clip_set_loop_mode(OakNodeBlock clip, int loop_mode)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c) {
@@ -378,7 +401,7 @@ int oaknode_clip_set_loop_mode(OakNodeBlock *clip, int loop_mode)
return OAKNODE_OK;
}
int oaknode_clip_get_track_type(OakNodeBlock *clip, int *type)
int oaknode_clip_get_track_type(OakNodeBlock clip, int *type)
{
olive::ClipBlock *c = clip_impl(clip);
if (!c || !type) {
@@ -390,7 +413,7 @@ int oaknode_clip_get_track_type(OakNodeBlock *clip, int *type)
/* ----------------------------------------------------------- Transition */
int oaknode_transition_get_in_offset(OakNodeBlock *transition, int *numerator,
int oaknode_transition_get_in_offset(OakNodeBlock transition, int *numerator,
int *denominator)
{
olive::TransitionBlock *t = transition_impl(transition);
@@ -400,7 +423,7 @@ int oaknode_transition_get_in_offset(OakNodeBlock *transition, int *numerator,
return get_rational(t->in_offset(), numerator, denominator);
}
int oaknode_transition_get_out_offset(OakNodeBlock *transition, int *numerator,
int oaknode_transition_get_out_offset(OakNodeBlock transition, int *numerator,
int *denominator)
{
olive::TransitionBlock *t = transition_impl(transition);
@@ -410,7 +433,7 @@ int oaknode_transition_get_out_offset(OakNodeBlock *transition, int *numerator,
return get_rational(t->out_offset(), numerator, denominator);
}
int oaknode_transition_get_offset_center(OakNodeBlock *transition,
int oaknode_transition_get_offset_center(OakNodeBlock transition,
int *numerator, int *denominator)
{
olive::TransitionBlock *t = transition_impl(transition);
@@ -420,7 +443,7 @@ int oaknode_transition_get_offset_center(OakNodeBlock *transition,
return get_rational(t->offset_center(), numerator, denominator);
}
int oaknode_transition_set_offset_center(OakNodeBlock *transition,
int oaknode_transition_set_offset_center(OakNodeBlock transition,
int numerator, int denominator)
{
olive::TransitionBlock *t = transition_impl(transition);
@@ -431,7 +454,7 @@ int oaknode_transition_set_offset_center(OakNodeBlock *transition,
return OAKNODE_OK;
}
int oaknode_transition_set_offsets_and_length(OakNodeBlock *transition,
int oaknode_transition_set_offsets_and_length(OakNodeBlock transition,
int in_num, int in_den,
int out_num, int out_den)
{
@@ -444,7 +467,7 @@ int oaknode_transition_set_offsets_and_length(OakNodeBlock *transition,
return OAKNODE_OK;
}
int oaknode_transition_is_dual(OakNodeBlock *transition, int *dual)
int oaknode_transition_is_dual(OakNodeBlock transition, int *dual)
{
olive::TransitionBlock *t = transition_impl(transition);
if (!t || !dual) {
@@ -454,35 +477,34 @@ int oaknode_transition_is_dual(OakNodeBlock *transition, int *dual)
return OAKNODE_OK;
}
int oaknode_transition_get_connected_out_block(OakNodeBlock *transition,
OakNodeBlock **out)
int oaknode_transition_get_connected_out_block(OakNodeBlock transition,
OakNodeBlock *out)
{
olive::TransitionBlock *t = transition_impl(transition);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap(t->connected_out_block());
// Borrowed (empty when unconnected)
*out = make_handle<OakNodeBlock>(t->connected_out_block(), false,
&delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_transition_get_connected_in_block(OakNodeBlock *transition,
OakNodeBlock **out)
int oaknode_transition_get_connected_in_block(OakNodeBlock transition,
OakNodeBlock *out)
{
olive::TransitionBlock *t = transition_impl(transition);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap(t->connected_in_block());
*out = make_handle<OakNodeBlock>(t->connected_in_block(), false,
&delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_clip_add_cache_passthrough_from(OakNodeBlock *clip,
OakNodeBlock *other)
int oaknode_clip_add_cache_passthrough_from(OakNodeBlock clip,
OakNodeBlock other)
{
if (!clip || !other) {
return OAKNODE_E_INVALID;
}
olive::ClipBlock *c = clip_impl(clip);
olive::ClipBlock *o = clip_impl(other);
if (!c || !o) {
@@ -497,27 +519,31 @@ int oaknode_clip_add_cache_passthrough_from(OakNodeBlock *clip,
}
}
OakNodeNode *oaknode_block_as_node(OakNodeBlock *block)
OakNodeNode oaknode_block_as_node(OakNodeBlock block)
{
return reinterpret_cast<OakNodeNode *>(block);
// Borrowed; releasing the result never destroys the block
return make_handle<OakNodeNode>(to_native<olive::Block>(block), false,
&delete_as<olive::Node>);
}
OakNodeBlock *oaknode_block_from_node(OakNodeNode *node)
OakNodeBlock oaknode_block_from_node(OakNodeNode node)
{
if (!node) {
return NULL;
olive::Node *n = to_native<olive::Node>(node);
if (!n) {
return OakNodeBlock{};
}
olive::Node *n = reinterpret_cast<olive::Node *>(node);
return wrap(dynamic_cast<olive::Block *>(n));
// Borrowed (empty when the node is not a Block)
return make_handle<OakNodeBlock>(dynamic_cast<olive::Block *>(n), false,
&delete_as<olive::Block>);
}
int oaknode_block_get_kind(OakNodeBlock *block, int *out_kind)
int oaknode_block_get_kind(OakNodeBlock block, int *out_kind)
{
if (!block || !out_kind) {
olive::Block *b = to_native<olive::Block>(block);
if (!b || !out_kind) {
return OAKNODE_E_INVALID;
}
olive::Block *b = impl(block);
if (dynamic_cast<olive::TransitionBlock *>(b)) {
*out_kind = OAKNODE_BLOCK_TRANSITION;
} else if (dynamic_cast<olive::ClipBlock *>(b)) {
+132 -105
View File
@@ -22,15 +22,11 @@
#include <cstring>
#include "alivecount.h"
#include "color/colormanager/colormanager.h"
#include "colortransform.h"
#include "project.h"
struct OakNodeColorManager {
olive::ColorManager impl;
};
#include "nodehandle.h"
namespace
{
@@ -44,9 +40,9 @@ int copy_string(const std::string &value, char *buf, int buf_size)
return needed;
}
bool has_config(olive::ColorManager *cm)
bool has_config(const olive::ColorManager *cm)
{
return cm && cm->get_config() != nullptr;
return cm->get_config() != nullptr;
}
int list_at(const olive::StringList &list, int index, char *buf, int buf_size)
@@ -59,37 +55,35 @@ int list_at(const olive::StringList &list, int index, char *buf, int buf_size)
} // namespace
OakNodeColorManager *oaknode_colormanager_init(OakNodeProject *project)
OakNodeColorManager oaknode_colormanager_init(OakNodeProject project)
{
if (!project) {
return nullptr;
olive::Project *native = oaknode_c_api::to_native<olive::Project>(project);
if (!native) {
return OakNodeColorManager{};
}
try {
auto *m = new OakNodeColorManager{
olive::ColorManager(reinterpret_cast<olive::Project *>(project))};
oaknode_c_api::alive_inc();
return m;
return oaknode_c_api::make_handle<OakNodeColorManager>(
new olive::ColorManager(native), true,
&oaknode_c_api::delete_as<olive::ColorManager>);
} catch (...) {
return nullptr;
return OakNodeColorManager{};
}
}
void oaknode_colormanager_free(OakNodeColorManager *manager)
{
if (!manager) {
return;
}
delete manager;
oaknode_c_api::alive_dec();
oaknode_c_api::free_handle(manager);
}
int oaknode_colormanager_initialize(OakNodeColorManager *manager)
int oaknode_colormanager_initialize(OakNodeColorManager manager)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
try {
manager->impl.init();
cm->init();
} catch (...) {
return OAKNODE_E_FAILED;
}
@@ -106,33 +100,39 @@ int oaknode_colormanager_set_up_default_config(void)
return OAKNODE_OK;
}
int oaknode_colormanager_get_config_filename(OakNodeColorManager *manager,
int oaknode_colormanager_get_config_filename(OakNodeColorManager manager,
char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
return copy_string(manager->impl.get_config_filename(), buf, buf_size);
return copy_string(cm->get_config_filename(), buf, buf_size);
}
int oaknode_colormanager_set_config_filename(OakNodeColorManager *manager,
int oaknode_colormanager_set_config_filename(OakNodeColorManager manager,
const char *filename)
{
if (!manager || !filename) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !filename) {
return OAKNODE_E_INVALID;
}
manager->impl.set_config_filename(filename);
cm->set_config_filename(filename);
return OAKNODE_OK;
}
int oaknode_colormanager_update_config_from_filename(
OakNodeColorManager *manager)
OakNodeColorManager manager)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
try {
manager->impl.update_config_from_filename();
cm->update_config_from_filename();
} catch (...) {
return OAKNODE_E_FAILED;
}
@@ -140,212 +140,240 @@ int oaknode_colormanager_update_config_from_filename(
}
int oaknode_colormanager_get_default_input_color_space(
OakNodeColorManager *manager, char *buf, int buf_size)
OakNodeColorManager manager, char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
return copy_string(manager->impl.get_default_input_color_space(), buf,
buf_size);
return copy_string(cm->get_default_input_color_space(), buf, buf_size);
}
int oaknode_colormanager_set_default_input_color_space(
OakNodeColorManager *manager, const char *colorspace)
OakNodeColorManager manager, const char *colorspace)
{
if (!manager || !colorspace) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !colorspace) {
return OAKNODE_E_INVALID;
}
manager->impl.set_default_input_color_space(colorspace);
cm->set_default_input_color_space(colorspace);
return OAKNODE_OK;
}
int oaknode_colormanager_get_reference_color_space(
OakNodeColorManager *manager, char *buf, int buf_size)
OakNodeColorManager manager, char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
return copy_string(manager->impl.get_reference_color_space(), buf,
buf_size);
return copy_string(cm->get_reference_color_space(), buf, buf_size);
}
int oaknode_colormanager_get_compliant_color_space(
OakNodeColorManager *manager, const char *colorspace, char *buf,
OakNodeColorManager manager, const char *colorspace, char *buf,
int buf_size)
{
if (!manager || !colorspace) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !colorspace) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return copy_string(manager->impl.get_compliant_color_space(colorspace), buf,
return copy_string(cm->get_compliant_color_space(colorspace), buf,
buf_size);
}
int oaknode_colormanager_get_colorspace_for_ffmpeg_tags(
OakNodeColorManager *manager, int primaries, int trc, char *buf,
OakNodeColorManager manager, int primaries, int trc, char *buf,
int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return copy_string(
manager->impl.get_colorspace_for_ffmpeg_tags(primaries, trc), buf,
buf_size);
return copy_string(cm->get_colorspace_for_ffmpeg_tags(primaries, trc), buf,
buf_size);
}
int oaknode_colormanager_get_display_count(OakNodeColorManager *manager,
int oaknode_colormanager_get_display_count(OakNodeColorManager manager,
int *count)
{
if (!manager || !count) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !count) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
*count = int(manager->impl.list_available_displays().size());
*count = int(cm->list_available_displays().size());
return OAKNODE_OK;
}
int oaknode_colormanager_get_display_at(OakNodeColorManager *manager,
int oaknode_colormanager_get_display_at(OakNodeColorManager manager,
int index, char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return list_at(manager->impl.list_available_displays(), index, buf,
buf_size);
return list_at(cm->list_available_displays(), index, buf, buf_size);
}
int oaknode_colormanager_get_default_display(OakNodeColorManager *manager,
int oaknode_colormanager_get_default_display(OakNodeColorManager manager,
char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return copy_string(manager->impl.get_default_display(), buf, buf_size);
return copy_string(cm->get_default_display(), buf, buf_size);
}
int oaknode_colormanager_get_view_count(OakNodeColorManager *manager,
int oaknode_colormanager_get_view_count(OakNodeColorManager manager,
const char *display, int *count)
{
if (!manager || !display || !count) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !display || !count) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
*count = int(manager->impl.list_available_views(display).size());
*count = int(cm->list_available_views(display).size());
return OAKNODE_OK;
}
int oaknode_colormanager_get_view_at(OakNodeColorManager *manager,
int oaknode_colormanager_get_view_at(OakNodeColorManager manager,
const char *display, int index, char *buf,
int buf_size)
{
if (!manager || !display) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !display) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return list_at(manager->impl.list_available_views(display), index, buf,
buf_size);
return list_at(cm->list_available_views(display), index, buf, buf_size);
}
int oaknode_colormanager_get_default_view(OakNodeColorManager *manager,
int oaknode_colormanager_get_default_view(OakNodeColorManager manager,
const char *display, char *buf,
int buf_size)
{
if (!manager || !display) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !display) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return copy_string(manager->impl.get_default_view(display), buf, buf_size);
return copy_string(cm->get_default_view(display), buf, buf_size);
}
int oaknode_colormanager_get_look_count(OakNodeColorManager *manager,
int oaknode_colormanager_get_look_count(OakNodeColorManager manager,
int *count)
{
if (!manager || !count) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !count) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
*count = int(manager->impl.list_available_looks().size());
*count = int(cm->list_available_looks().size());
return OAKNODE_OK;
}
int oaknode_colormanager_get_look_at(OakNodeColorManager *manager, int index,
int oaknode_colormanager_get_look_at(OakNodeColorManager manager, int index,
char *buf, int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return list_at(manager->impl.list_available_looks(), index, buf, buf_size);
return list_at(cm->list_available_looks(), index, buf, buf_size);
}
int oaknode_colormanager_get_colorspace_count(OakNodeColorManager *manager,
int oaknode_colormanager_get_colorspace_count(OakNodeColorManager manager,
int *count)
{
if (!manager || !count) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !count) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
*count = int(manager->impl.list_available_colorspaces().size());
*count = int(cm->list_available_colorspaces().size());
return OAKNODE_OK;
}
int oaknode_colormanager_get_colorspace_at(OakNodeColorManager *manager,
int oaknode_colormanager_get_colorspace_at(OakNodeColorManager manager,
int index, char *buf,
int buf_size)
{
if (!manager) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
return list_at(manager->impl.list_available_colorspaces(), index, buf,
buf_size);
return list_at(cm->list_available_colorspaces(), index, buf, buf_size);
}
int oaknode_colormanager_get_default_luma_coefs(OakNodeColorManager *manager,
int oaknode_colormanager_get_default_luma_coefs(OakNodeColorManager manager,
double rgb[3])
{
if (!manager || !rgb) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !rgb) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
manager->impl.get_default_luma_coefs(rgb);
cm->get_default_luma_coefs(rgb);
return OAKNODE_OK;
}
int oaknode_colormanager_get_compliant_color_transform(
OakNodeColorManager *manager, OakColorTransform transform,
OakNodeColorManager manager, OakColorTransform transform,
int force_display, OakColorTransform *out)
{
if (!manager || !out) {
olive::ColorManager *cm =
oaknode_c_api::to_native<olive::ColorManager>(manager);
if (!cm || !out) {
return OAKNODE_E_INVALID;
}
const olive::ColorTransform *native =
@@ -353,13 +381,12 @@ int oaknode_colormanager_get_compliant_color_transform(
if (!native) {
return OAKNODE_E_INVALID;
}
if (!has_config(&manager->impl)) {
if (!has_config(cm)) {
return OAKNODE_E_STATE;
}
try {
const olive::ColorTransform compliant =
manager->impl.get_compliant_color_space(*native,
force_display != 0);
cm->get_compliant_color_space(*native, force_display != 0);
*out = oakcommon_colortransform_init_from_native(&compliant);
} catch (...) {
return OAKNODE_E_NOMEM;
+11 -19
View File
@@ -22,17 +22,10 @@
#include "factory.h"
#include "nodehandle.h"
#include "valueconvert.h"
namespace
{
inline OakNodeNode *from_node(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
}
using oaknode_c_api::make_handle;
int oaknode_factory_initialize(void)
{
@@ -104,24 +97,22 @@ int oaknode_factory_name_from_id(const char *type_id, char *buf,
}
}
OakNodeNode *oaknode_factory_create_from_id(const char *type_id)
OakNodeNode oaknode_factory_create_from_id(const char *type_id)
{
if (!type_id) {
return NULL;
return OakNodeNode{};
}
try {
olive::Node *node = olive::NodeFactory::create_from_id(type_id);
if (node) {
oaknode_c_api::alive_inc();
}
return from_node(node);
return make_handle<OakNodeNode>(
olive::NodeFactory::create_from_id(type_id), true,
oaknode_c_api::delete_as<olive::Node>);
} catch (...) {
return NULL;
return OakNodeNode{};
}
}
int oaknode_factory_node_at(int index, OakNodeNode **out_node)
int oaknode_factory_node_at(int index, OakNodeNode *out_node)
{
if (!out_node) {
return OAKNODE_E_INVALID;
@@ -136,7 +127,8 @@ int oaknode_factory_node_at(int index, OakNodeNode **out_node)
if (index < 0 || index >= static_cast<int>(library.size())) {
return OAKNODE_E_NOT_FOUND;
}
*out_node = from_node(library[size_t(index)]);
*out_node = make_handle<OakNodeNode>(library[size_t(index)], false,
nullptr);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
+71 -84
View File
@@ -24,97 +24,75 @@
#include <new>
#include "node/node.h"
#include "../src/project.h"
#include "../src/project/folder/folder.h"
namespace
{
#include "nodehandle.h"
olive::Folder *to_cpp(OakNodeFolder *folder)
{
return reinterpret_cast<olive::Folder *>(folder);
}
using oaknode_c_api::delete_as;
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
const olive::Folder *to_cpp(const OakNodeFolder *folder)
OakNodeFolder oaknode_folder_create(OakNodeProject project)
{
return reinterpret_cast<const olive::Folder *>(folder);
}
olive::Node *to_cpp(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
const olive::Node *to_cpp(const OakNodeNode *node)
{
return reinterpret_cast<const olive::Node *>(node);
}
OakNodeNode *to_c(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
olive::Project *to_cpp(OakNodeProject *project)
{
return reinterpret_cast<olive::Project *>(project);
}
} // namespace
OakNodeFolder *oaknode_folder_create(OakNodeProject *project)
{
if (!project) {
return NULL;
if (!project.ctx) {
return OakNodeFolder{};
}
try {
auto *folder = new (std::nothrow) olive::Folder();
if (!folder) {
return NULL;
return OakNodeFolder{};
}
to_cpp(project)->add_node(folder);
return reinterpret_cast<OakNodeFolder *>(folder);
to_native<olive::Project>(project)->add_node(folder);
// Borrowed handle: the project graph owns the folder.
return make_handle<OakNodeFolder>(folder, false,
&delete_as<olive::Folder>);
} catch (...) {
return NULL;
return OakNodeFolder{};
}
}
int oaknode_folder_child_count(const OakNodeFolder *folder)
int oaknode_folder_child_count(OakNodeFolder folder)
{
if (!folder) {
if (!folder.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(folder)->item_child_count();
return to_native<olive::Folder>(folder)->item_child_count();
} catch (...) {
return OAKNODE_E_FAILED;
}
}
OakNodeNode *oaknode_folder_child_at(const OakNodeFolder *folder, int index)
OakNodeNode oaknode_folder_child_at(OakNodeFolder folder, int index)
{
if (!folder || index < 0 || index >= to_cpp(folder)->item_child_count()) {
return NULL;
if (!folder.ctx || index < 0 ||
index >= to_native<olive::Folder>(folder)->item_child_count()) {
return OakNodeNode{};
}
try {
return to_c(to_cpp(folder)->item_child(index));
return make_handle<OakNodeNode>(
to_native<olive::Folder>(folder)->item_child(index), false,
&delete_as<olive::Node>);
} catch (...) {
return NULL;
return OakNodeNode{};
}
}
int oaknode_folder_add_child(OakNodeFolder *folder, OakNodeNode *child)
int oaknode_folder_add_child(OakNodeFolder folder, OakNodeNode child)
{
if (!folder || !child) {
if (!folder.ctx || !child.ctx) {
return OAKNODE_E_INVALID;
}
try {
olive::Folder *f = to_cpp(folder);
olive::Node *c = to_cpp(child);
olive::Folder *f = to_native<olive::Folder>(folder);
olive::Node *c = to_native<olive::Node>(child);
if (c->folder()) {
return OAKNODE_E_STATE;
@@ -122,21 +100,24 @@ int oaknode_folder_add_child(OakNodeFolder *folder, OakNodeNode *child)
olive::FolderAddChild cmd(f, c);
cmd.redo_now();
// The graph now owns the child; releasing `child` must not
// delete it.
oaknode_c_api::mark_container_owned(child);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_folder_remove_child(OakNodeFolder *folder, OakNodeNode *child)
int oaknode_folder_remove_child(OakNodeFolder folder, OakNodeNode child)
{
if (!folder || !child) {
if (!folder.ctx || !child.ctx) {
return OAKNODE_E_INVALID;
}
try {
olive::Folder *f = to_cpp(folder);
olive::Node *c = to_cpp(child);
olive::Folder *f = to_native<olive::Folder>(folder);
olive::Node *c = to_native<olive::Node>(child);
if (f->index_of_child(c) == -1) {
return OAKNODE_E_NOT_FOUND;
@@ -150,22 +131,22 @@ int oaknode_folder_remove_child(OakNodeFolder *folder, OakNodeNode *child)
}
}
int oaknode_folder_move_children(OakNodeNode *const *nodes, int count,
OakNodeFolder *dest_folder)
int oaknode_folder_move_children(const OakNodeNode *nodes, int count,
OakNodeFolder dest_folder)
{
if (!nodes || count < 0 || !dest_folder) {
if (!nodes || count < 0 || !dest_folder.ctx) {
return OAKNODE_E_INVALID;
}
try {
olive::Folder *dest = to_cpp(dest_folder);
olive::Folder *dest = to_native<olive::Folder>(dest_folder);
for (int i = 0; i < count; i++) {
if (!nodes[i]) {
if (!nodes[i].ctx) {
return OAKNODE_E_INVALID;
}
olive::Node *node = to_cpp(nodes[i]);
olive::Node *node = to_native<olive::Node>(nodes[i]);
olive::Folder *old_folder = node->folder();
if (old_folder == dest) {
@@ -179,6 +160,9 @@ int oaknode_folder_move_children(OakNodeNode *const *nodes, int count,
olive::FolderAddChild add_cmd(dest, node);
add_cmd.redo_now();
// The graph owns the moved node; releasing the caller's
// handle must not delete it.
oaknode_c_api::mark_container_owned(nodes[i]);
}
return OAKNODE_OK;
@@ -187,16 +171,16 @@ int oaknode_folder_move_children(OakNodeNode *const *nodes, int count,
}
}
int oaknode_folder_has_child_recursive(const OakNodeFolder *folder,
const OakNodeNode *child)
int oaknode_folder_has_child_recursive(OakNodeFolder folder,
OakNodeNode child)
{
if (!folder || !child) {
if (!folder.ctx || !child.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(folder)->has_child_recursive(
const_cast<olive::Node *>(to_cpp(child)))
return to_native<olive::Folder>(folder)->has_child_recursive(
to_native<olive::Node>(child))
? 1
: 0;
} catch (...) {
@@ -204,52 +188,55 @@ int oaknode_folder_has_child_recursive(const OakNodeFolder *folder,
}
}
int oaknode_folder_index_of_child(const OakNodeFolder *folder,
const OakNodeNode *child)
int oaknode_folder_index_of_child(OakNodeFolder folder,
OakNodeNode child)
{
if (!folder || !child) {
if (!folder.ctx || !child.ctx) {
return OAKNODE_E_INVALID;
}
try {
int index = to_cpp(folder)->index_of_child(
const_cast<olive::Node *>(to_cpp(child)));
int index = to_native<olive::Folder>(folder)->index_of_child(
to_native<olive::Node>(child));
return index == -1 ? OAKNODE_E_NOT_FOUND : index;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
OakNodeFolder *oaknode_folder_parent_of(const OakNodeNode *node)
OakNodeFolder oaknode_folder_parent_of(OakNodeNode node)
{
if (!node) {
return NULL;
if (!node.ctx) {
return OakNodeFolder{};
}
try {
return reinterpret_cast<OakNodeFolder *>(to_cpp(node)->folder());
return make_handle<OakNodeFolder>(
to_native<olive::Node>(node)->folder(), false,
&delete_as<olive::Folder>);
} catch (...) {
return NULL;
return OakNodeFolder{};
}
}
OakNodeNode *oaknode_folder_as_node(OakNodeFolder *folder)
OakNodeNode oaknode_folder_as_node(OakNodeFolder folder)
{
return reinterpret_cast<OakNodeNode *>(folder);
// Borrowed cast: same object, the handle only releases itself.
return make_handle<OakNodeNode>(to_native<olive::Folder>(folder), false,
&delete_as<olive::Node>);
}
OakUndoCommand oaknode_command_create_folder_add_child(
OakNodeFolder *folder, OakNodeNode *child)
OakNodeFolder folder, OakNodeNode child)
{
if (!folder || !child) {
if (!folder.ctx || !child.ctx) {
return OakUndoCommand{};
}
try {
return oakundo_capi::make_command_handle(
new olive::FolderAddChild(
reinterpret_cast<olive::Folder *>(folder),
reinterpret_cast<olive::Node *>(child)),
new olive::FolderAddChild(to_native<olive::Folder>(folder),
to_native<olive::Node>(child)),
true);
} catch (...) {
return OakUndoCommand{};
+86 -84
View File
@@ -27,27 +27,16 @@
#include <new>
#include <string>
#include "node/node.h"
#include "../src/project.h"
#include "../src/project/footage/footage.h"
#include "nodehandle.h"
namespace
{
olive::Footage *to_cpp(OakNodeFootage *footage)
{
return reinterpret_cast<olive::Footage *>(footage);
}
const olive::Footage *to_cpp(const OakNodeFootage *footage)
{
return reinterpret_cast<const olive::Footage *>(footage);
}
olive::Project *to_cpp(OakNodeProject *project)
{
return reinterpret_cast<olive::Project *>(project);
}
/**
* @brief Shared two-stage string getter.
*
@@ -72,167 +61,176 @@ int copy_string(const std::string &value, char *buf, int buf_size)
} // namespace
OakNodeFootage *oaknode_footage_create(OakNodeProject *project,
const char *filename)
using oaknode_c_api::delete_as;
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
OakNodeFootage oaknode_footage_create(OakNodeProject project,
const char *filename)
{
if (!project) {
return NULL;
if (!project.ctx) {
return OakNodeFootage{};
}
try {
auto *footage = new (std::nothrow)
olive::Footage(filename ? filename : "");
if (!footage) {
return NULL;
return OakNodeFootage{};
}
to_cpp(project)->add_node(footage);
return reinterpret_cast<OakNodeFootage *>(footage);
to_native<olive::Project>(project)->add_node(footage);
// Borrowed handle: the project graph owns the footage.
return make_handle<OakNodeFootage>(footage, false,
&delete_as<olive::Footage>);
} catch (...) {
return NULL;
return OakNodeFootage{};
}
}
int oaknode_footage_filename(const OakNodeFootage *footage, char *buf,
int oaknode_footage_filename(OakNodeFootage footage, char *buf,
int buf_size)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(footage)->filename(), buf, buf_size);
return copy_string(to_native<olive::Footage>(footage)->filename(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_set_filename(OakNodeFootage *footage, const char *filename)
int oaknode_footage_set_filename(OakNodeFootage footage, const char *filename)
{
if (!footage || !filename) {
if (!footage.ctx || !filename) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(footage)->set_filename(filename);
to_native<olive::Footage>(footage)->set_filename(filename);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_is_valid(const OakNodeFootage *footage)
int oaknode_footage_is_valid(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
return to_cpp(footage)->is_valid() ? 1 : 0;
return to_native<olive::Footage>(footage)->is_valid() ? 1 : 0;
}
int oaknode_footage_timestamp(const OakNodeFootage *footage,
int oaknode_footage_timestamp(OakNodeFootage footage,
int64_t *out_timestamp)
{
if (!footage || !out_timestamp) {
if (!footage.ctx || !out_timestamp) {
return OAKNODE_E_INVALID;
}
try {
*out_timestamp = to_cpp(footage)->timestamp();
*out_timestamp = to_native<olive::Footage>(footage)->timestamp();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_set_timestamp(OakNodeFootage *footage, int64_t timestamp)
int oaknode_footage_set_timestamp(OakNodeFootage footage, int64_t timestamp)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(footage)->set_timestamp(timestamp);
to_native<olive::Footage>(footage)->set_timestamp(timestamp);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_decoder(const OakNodeFootage *footage, char *buf,
int oaknode_footage_decoder(OakNodeFootage footage, char *buf,
int buf_size)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(footage)->decoder(), buf, buf_size);
return copy_string(to_native<olive::Footage>(footage)->decoder(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_total_stream_count(const OakNodeFootage *footage)
int oaknode_footage_total_stream_count(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(footage)->get_total_stream_count();
return to_native<olive::Footage>(footage)->get_total_stream_count();
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_video_stream_count(const OakNodeFootage *footage)
int oaknode_footage_video_stream_count(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(footage)->get_video_stream_count();
return to_native<olive::Footage>(footage)->get_video_stream_count();
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_audio_stream_count(const OakNodeFootage *footage)
int oaknode_footage_audio_stream_count(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(footage)->get_audio_stream_count();
return to_native<olive::Footage>(footage)->get_audio_stream_count();
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_subtitle_stream_count(const OakNodeFootage *footage)
int oaknode_footage_subtitle_stream_count(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return to_cpp(footage)->get_subtitle_stream_count();
return to_native<olive::Footage>(footage)->get_subtitle_stream_count();
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_duration(const OakNodeFootage *footage, int *out_numerator,
int oaknode_footage_duration(OakNodeFootage footage, int *out_numerator,
int *out_denominator)
{
if (!footage || !out_numerator || !out_denominator) {
if (!footage.ctx || !out_numerator || !out_denominator) {
return OAKNODE_E_INVALID;
}
try {
const olive::Rational &length = to_cpp(footage)->get_length();
const olive::Rational &length =
to_native<olive::Footage>(footage)->get_length();
*out_numerator = length.numerator();
*out_denominator = length.denominator();
return OAKNODE_OK;
@@ -241,66 +239,68 @@ int oaknode_footage_duration(const OakNodeFootage *footage, int *out_numerator,
}
}
int oaknode_footage_proxy_enabled(const OakNodeFootage *footage)
int oaknode_footage_proxy_enabled(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
return to_cpp(footage)->proxy_enabled() ? 1 : 0;
return to_native<olive::Footage>(footage)->proxy_enabled() ? 1 : 0;
}
int oaknode_footage_set_proxy_enabled(OakNodeFootage *footage, int enabled)
int oaknode_footage_set_proxy_enabled(OakNodeFootage footage, int enabled)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(footage)->set_proxy_enabled(enabled != 0);
to_native<olive::Footage>(footage)->set_proxy_enabled(enabled != 0);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_proxy_path(const OakNodeFootage *footage, char *buf,
int oaknode_footage_proxy_path(OakNodeFootage footage, char *buf,
int buf_size)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(footage)->proxy_path(), buf, buf_size);
return copy_string(to_native<olive::Footage>(footage)->proxy_path(),
buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_proxy_state(const OakNodeFootage *footage)
int oaknode_footage_proxy_state(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
return static_cast<int>(to_cpp(footage)->proxy_state());
return static_cast<int>(
to_native<olive::Footage>(footage)->proxy_state());
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_set_proxy(OakNodeFootage *footage, const char *path,
int oaknode_footage_set_proxy(OakNodeFootage footage, const char *path,
int state, int video_stream_index,
int preset_version, int enabled)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(footage)->set_proxy(
to_native<olive::Footage>(footage)->set_proxy(
path ? path : "",
static_cast<olive::ProxyManager::ProxyState>(state),
video_stream_index, preset_version, enabled != 0);
@@ -310,24 +310,24 @@ int oaknode_footage_set_proxy(OakNodeFootage *footage, const char *path,
}
}
int oaknode_footage_clear_proxy(OakNodeFootage *footage)
int oaknode_footage_clear_proxy(OakNodeFootage footage)
{
if (!footage) {
if (!footage.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(footage)->clear_proxy();
to_native<olive::Footage>(footage)->clear_proxy();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_footage_get_video_params(OakNodeFootage *footage, int index,
int oaknode_footage_get_video_params(OakNodeFootage footage, int index,
OakVideoParams *out)
{
olive::Footage *f = to_cpp(footage);
olive::Footage *f = to_native<olive::Footage>(footage);
if (!f || !out || index < 0) {
return OAKNODE_E_INVALID;
}
@@ -345,10 +345,10 @@ int oaknode_footage_get_video_params(OakNodeFootage *footage, int index,
}
}
int oaknode_footage_set_video_params(OakNodeFootage *footage, int index,
int oaknode_footage_set_video_params(OakNodeFootage footage, int index,
const OakVideoParams *params)
{
olive::Footage *f = to_cpp(footage);
olive::Footage *f = to_native<olive::Footage>(footage);
if (!f || !params || !params->ctx) {
return OAKNODE_E_INVALID;
}
@@ -367,10 +367,10 @@ int oaknode_footage_set_video_params(OakNodeFootage *footage, int index,
}
}
int oaknode_footage_get_video_length(OakNodeFootage *footage,
int oaknode_footage_get_video_length(OakNodeFootage footage,
int64_t *out_num, int64_t *out_den)
{
olive::Footage *f = to_cpp(footage);
olive::Footage *f = to_native<olive::Footage>(footage);
if (!f || !out_num || !out_den) {
return OAKNODE_E_INVALID;
}
@@ -381,10 +381,10 @@ int oaknode_footage_get_video_length(OakNodeFootage *footage,
return OAKNODE_OK;
}
int oaknode_footage_set_cancel_atom(OakNodeFootage *footage,
int oaknode_footage_set_cancel_atom(OakNodeFootage footage,
OakCancelAtom atom)
{
olive::Footage *f = to_cpp(footage);
olive::Footage *f = to_native<olive::Footage>(footage);
if (!f) {
return OAKNODE_E_INVALID;
}
@@ -394,7 +394,9 @@ int oaknode_footage_set_cancel_atom(OakNodeFootage *footage,
return OAKNODE_OK;
}
OakNodeNode *oaknode_footage_as_node(OakNodeFootage *footage)
OakNodeNode oaknode_footage_as_node(OakNodeFootage footage)
{
return reinterpret_cast<OakNodeNode *>(footage);
// Borrowed cast: same object, the handle only releases itself.
return make_handle<OakNodeNode>(to_native<olive::Footage>(footage), false,
&delete_as<olive::Node>);
}
+73 -88
View File
@@ -22,106 +22,82 @@
#include "group/group.h"
#include "nodehandle.h"
#include "valueconvert.h"
namespace
{
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
inline olive::NodeGroup *to_group(OakNodeGroup *group)
{
return reinterpret_cast<olive::NodeGroup *>(group);
}
inline const olive::NodeGroup *to_group(const OakNodeGroup *group)
{
return reinterpret_cast<const olive::NodeGroup *>(group);
}
inline olive::Node *to_node(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
inline OakNodeNode *from_node(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
}
OakNodeGroup *oaknode_group_create(void)
OakNodeGroup oaknode_group_create(void)
{
try {
olive::NodeGroup *group = new (std::nothrow) olive::NodeGroup();
if (group) {
oaknode_c_api::alive_inc();
}
return reinterpret_cast<OakNodeGroup *>(group);
return make_handle<OakNodeGroup>(new (std::nothrow) olive::NodeGroup(),
true,
oaknode_c_api::delete_as<olive::NodeGroup>);
} catch (...) {
return NULL;
return OakNodeGroup{};
}
}
OakNodeGroup *oaknode_group_cast(OakNodeNode *node)
OakNodeGroup oaknode_group_cast(OakNodeNode node)
{
if (!node) {
return NULL;
olive::Node *native = to_native<olive::Node>(node);
if (!native) {
return OakNodeGroup{};
}
try {
return reinterpret_cast<OakNodeGroup *>(
dynamic_cast<olive::NodeGroup *>(to_node(node)));
return make_handle<OakNodeGroup>(
dynamic_cast<olive::NodeGroup *>(native), false, nullptr);
} catch (...) {
return NULL;
return OakNodeGroup{};
}
}
void oaknode_group_free(OakNodeGroup *group)
{
if (!group) {
return;
}
try {
delete to_group(group);
oaknode_c_api::alive_dec();
oaknode_c_api::free_handle(group);
} catch (...) {
}
}
int oaknode_group_add_input_passthrough(OakNodeGroup *group,
OakNodeNode *node,
int oaknode_group_add_input_passthrough(OakNodeGroup group,
OakNodeNode node,
const char *input_id, int element,
char *buf, int buf_size)
{
if (!group || !node || !input_id) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
olive::Node *n = to_native<olive::Node>(node);
if (!g || !n || !input_id) {
return OAKNODE_E_INVALID;
}
try {
std::string id = to_group(group)->add_input_passthrough(
olive::NodeInput(to_node(node), input_id, element));
std::string id = g->add_input_passthrough(
olive::NodeInput(n, input_id, element));
return oaknode_c_api::copy_string(id, buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_group_add_input_passthrough_undoable(OakNodeGroup *group,
OakNodeNode *node,
int oaknode_group_add_input_passthrough_undoable(OakNodeGroup group,
OakNodeNode node,
const char *input_id,
int element,
OakUndoCommand *out_command)
{
if (!group || !node || !input_id || !out_command) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
olive::Node *n = to_native<olive::Node>(node);
if (!g || !n || !input_id || !out_command) {
return OAKNODE_E_INVALID;
}
try {
OakUndoCommand handle = oaknode_c_api::wrap_command(
new olive::NodeGroupAddInputPassthrough(
to_group(group),
olive::NodeInput(to_node(node), input_id, element)));
g, olive::NodeInput(n, input_id, element)));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -132,51 +108,54 @@ int oaknode_group_add_input_passthrough_undoable(OakNodeGroup *group,
}
}
int oaknode_group_remove_input_passthrough(OakNodeGroup *group,
OakNodeNode *node,
int oaknode_group_remove_input_passthrough(OakNodeGroup group,
OakNodeNode node,
const char *input_id, int element)
{
if (!group || !node || !input_id) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
olive::Node *n = to_native<olive::Node>(node);
if (!g || !n || !input_id) {
return OAKNODE_E_INVALID;
}
try {
olive::NodeInput input(to_node(node), input_id, element);
if (!to_group(group)->contains_input_passthrough(input)) {
olive::NodeInput input(n, input_id, element);
if (!g->contains_input_passthrough(input)) {
return OAKNODE_E_NOT_FOUND;
}
to_group(group)->remove_input_passthrough(input);
g->remove_input_passthrough(input);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_group_passthrough_count(const OakNodeGroup *group, int *out_count)
int oaknode_group_passthrough_count(OakNodeGroup group, int *out_count)
{
if (!group || !out_count) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g || !out_count) {
return OAKNODE_E_INVALID;
}
try {
*out_count =
static_cast<int>(to_group(group)->get_input_passthroughs().size());
*out_count = static_cast<int>(g->get_input_passthroughs().size());
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_group_passthrough_id_at(const OakNodeGroup *group, int index,
int oaknode_group_passthrough_id_at(OakNodeGroup group, int index,
char *buf, int buf_size)
{
if (!group) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeGroup::InputPassthroughs &passthroughs =
to_group(group)->get_input_passthroughs();
g->get_input_passthroughs();
if (index < 0 || index >= static_cast<int>(passthroughs.size())) {
return OAKNODE_E_NOT_FOUND;
}
@@ -187,24 +166,25 @@ int oaknode_group_passthrough_id_at(const OakNodeGroup *group, int index,
}
}
int oaknode_group_passthrough_input_at(const OakNodeGroup *group, int index,
OakNodeNode **out_node, char *buf,
int oaknode_group_passthrough_input_at(OakNodeGroup group, int index,
OakNodeNode *out_node, char *buf,
int buf_size, int *out_element)
{
if (!group) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeGroup::InputPassthroughs &passthroughs =
to_group(group)->get_input_passthroughs();
g->get_input_passthroughs();
if (index < 0 || index >= static_cast<int>(passthroughs.size())) {
return OAKNODE_E_NOT_FOUND;
}
const olive::NodeInput &input = passthroughs[size_t(index)].second;
if (out_node) {
*out_node = from_node(input.node());
*out_node = make_handle<OakNodeNode>(input.node(), false, nullptr);
}
if (out_element) {
*out_element = input.element();
@@ -215,30 +195,33 @@ int oaknode_group_passthrough_input_at(const OakNodeGroup *group, int index,
}
}
int oaknode_group_get_output_passthrough(const OakNodeGroup *group,
OakNodeNode **out_node)
int oaknode_group_get_output_passthrough(OakNodeGroup group,
OakNodeNode *out_node)
{
if (!group || !out_node) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g || !out_node) {
return OAKNODE_E_INVALID;
}
try {
*out_node = from_node(to_group(group)->get_output_passthrough());
*out_node =
make_handle<OakNodeNode>(g->get_output_passthrough(), false, nullptr);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_group_set_output_passthrough(OakNodeGroup *group,
OakNodeNode *node)
int oaknode_group_set_output_passthrough(OakNodeGroup group,
OakNodeNode node)
{
if (!group) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g) {
return OAKNODE_E_INVALID;
}
try {
to_group(group)->set_output_passthrough(to_node(node));
g->set_output_passthrough(to_native<olive::Node>(node));
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
@@ -246,16 +229,17 @@ int oaknode_group_set_output_passthrough(OakNodeGroup *group,
}
int oaknode_group_set_output_passthrough_undoable(
OakNodeGroup *group, OakNodeNode *node, OakUndoCommand *out_command)
OakNodeGroup group, OakNodeNode node, OakUndoCommand *out_command)
{
if (!group || !out_command) {
olive::NodeGroup *g = to_native<olive::NodeGroup>(group);
if (!g || !out_command) {
return OAKNODE_E_INVALID;
}
try {
OakUndoCommand handle = oaknode_c_api::wrap_command(
new olive::NodeGroupSetOutputPassthrough(to_group(group),
to_node(node)));
new olive::NodeGroupSetOutputPassthrough(
g, to_native<olive::Node>(node)));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -266,23 +250,24 @@ int oaknode_group_set_output_passthrough_undoable(
}
}
int oaknode_group_resolve_input(OakNodeNode *node, const char *input_id,
int element, OakNodeNode **out_node,
int oaknode_group_resolve_input(OakNodeNode node, const char *input_id,
int element, OakNodeNode *out_node,
char *buf, int buf_size, int *out_element)
{
if (!node || !input_id) {
olive::Node *n = to_native<olive::Node>(node);
if (!n || !input_id) {
return OAKNODE_E_INVALID;
}
try {
olive::NodeInput resolved = olive::NodeGroup::resolve_input(
olive::NodeInput(to_node(node), input_id, element));
olive::NodeInput(n, input_id, element));
if (!resolved.is_valid()) {
return OAKNODE_E_NOT_FOUND;
}
if (out_node) {
*out_node = from_node(resolved.node());
*out_node = make_handle<OakNodeNode>(resolved.node(), false, nullptr);
}
if (out_element) {
*out_element = resolved.element();
+104 -111
View File
@@ -24,31 +24,15 @@
#include "node.h"
#include "nodeundo.h"
#include "nodehandle.h"
#include "valueconvert.h"
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
namespace
{
inline olive::NodeKeyframe *to_key(OakNodeKeyframe *keyframe)
{
return reinterpret_cast<olive::NodeKeyframe *>(keyframe);
}
inline const olive::NodeKeyframe *to_key(const OakNodeKeyframe *keyframe)
{
return reinterpret_cast<const olive::NodeKeyframe *>(keyframe);
}
inline olive::Node *to_node(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
inline OakNodeNode *from_node(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
/**
* @brief Convert an oaknode_keyframe_type to olive::NodeKeyframe::Type.
* The oaknode enum mirrors the olive ordinals exactly (invalid = -1,
@@ -132,61 +116,56 @@ private:
}
OakNodeKeyframe *oaknode_keyframe_create(int64_t time_num, int64_t time_den,
const oaknode_value *value, int type,
int track, int element,
const char *input_id,
OakNodeNode *parent_or_null)
OakNodeKeyframe oaknode_keyframe_create(int64_t time_num, int64_t time_den,
const oaknode_value *value, int type,
int track, int element,
const char *input_id,
OakNodeNode parent_or_null)
{
olive::NodeKeyframe::Type keyframe_type;
if (!keyframe_type_from_oak(type, &keyframe_type)) {
return NULL;
return OakNodeKeyframe{};
}
try {
olive::Variant variant;
if (value) {
if (!oaknode_c_api::variant_from_value(value, &variant)) {
return NULL;
return OakNodeKeyframe{};
}
}
olive::core::Rational time(static_cast<int>(time_num),
static_cast<int>(time_den));
olive::NodeKeyframe *key = new (std::nothrow) olive::NodeKeyframe(
time, variant, keyframe_type, track, element,
input_id ? input_id : "", to_node(parent_or_null));
if (key) {
oaknode_c_api::alive_inc();
}
return reinterpret_cast<OakNodeKeyframe *>(key);
return make_handle<OakNodeKeyframe>(
new (std::nothrow) olive::NodeKeyframe(
time, variant, keyframe_type, track, element,
input_id ? input_id : "",
to_native<olive::Node>(parent_or_null)),
true, oaknode_c_api::delete_as<olive::NodeKeyframe>);
} catch (...) {
return NULL;
return OakNodeKeyframe{};
}
}
void oaknode_keyframe_free(OakNodeKeyframe *keyframe)
{
if (!keyframe) {
return;
}
try {
delete to_key(keyframe);
oaknode_c_api::alive_dec();
oaknode_c_api::free_handle(keyframe);
} catch (...) {
}
}
int oaknode_keyframe_get_time(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_time(OakNodeKeyframe keyframe,
int64_t *out_num, int64_t *out_den)
{
if (!keyframe || !out_num || !out_den) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_num || !out_den) {
return OAKNODE_E_INVALID;
}
try {
const olive::core::Rational &time = to_key(keyframe)->time();
const olive::core::Rational &time = key->time();
*out_num = time.numerator();
*out_den = time.denominator();
return OAKNODE_OK;
@@ -195,36 +174,37 @@ int oaknode_keyframe_get_time(const OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_set_time(OakNodeKeyframe *keyframe, int64_t time_num,
int oaknode_keyframe_set_time(OakNodeKeyframe keyframe, int64_t time_num,
int64_t time_den)
{
if (!keyframe) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key) {
return OAKNODE_E_INVALID;
}
try {
to_key(keyframe)->set_time(olive::core::Rational(
static_cast<int>(time_num), static_cast<int>(time_den)));
key->set_time(olive::core::Rational(static_cast<int>(time_num),
static_cast<int>(time_den)));
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_time_undoable(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_time_undoable(OakNodeKeyframe keyframe,
int64_t time_num, int64_t time_den,
OakUndoCommand *out_command)
{
if (!keyframe || !out_command) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_command) {
return OAKNODE_E_INVALID;
}
try {
OakUndoCommand handle = oaknode_c_api::wrap_command(
new olive::NodeParamSetKeyframeTimeCommand(
to_key(keyframe),
olive::core::Rational(static_cast<int>(time_num),
static_cast<int>(time_den))));
key, olive::core::Rational(static_cast<int>(time_num),
static_cast<int>(time_den))));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -235,15 +215,15 @@ int oaknode_keyframe_set_time_undoable(OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_get_value(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_value(OakNodeKeyframe keyframe,
oaknode_value *out)
{
if (!keyframe || !out) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeKeyframe *key = to_key(keyframe);
const olive::Variant &variant = key->value();
// Preferred path: the parent node's declared input type pins the
@@ -295,10 +275,11 @@ int oaknode_keyframe_get_value(const OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_set_value(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_value(OakNodeKeyframe keyframe,
const oaknode_value *v)
{
if (!keyframe || !v) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !v) {
return OAKNODE_E_INVALID;
}
@@ -307,18 +288,19 @@ int oaknode_keyframe_set_value(OakNodeKeyframe *keyframe,
if (!oaknode_c_api::variant_from_value(v, &variant)) {
return OAKNODE_E_INVALID;
}
to_key(keyframe)->set_value(variant);
key->set_value(variant);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_value_undoable(OakNodeKeyframe keyframe,
const oaknode_value *v,
OakUndoCommand *out_command)
{
if (!keyframe || !v || !out_command) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !v || !out_command) {
return OAKNODE_E_INVALID;
}
@@ -329,8 +311,7 @@ int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
}
OakUndoCommand handle = oaknode_c_api::wrap_command(
new olive::NodeParamSetKeyframeValueCommand(to_key(keyframe),
variant));
new olive::NodeParamSetKeyframeValueCommand(key, variant));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -341,48 +322,51 @@ int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_get_value_string(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_value_string(OakNodeKeyframe keyframe,
char *buf, int buf_size)
{
if (!keyframe) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key) {
return OAKNODE_E_INVALID;
}
try {
return oaknode_c_api::copy_string(to_key(keyframe)->value().to_string(),
buf, buf_size);
return oaknode_c_api::copy_string(key->value().to_string(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_value_string(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_value_string(OakNodeKeyframe keyframe,
const char *value)
{
if (!keyframe || !value) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !value) {
return OAKNODE_E_INVALID;
}
try {
to_key(keyframe)->set_value(olive::Variant(value));
key->set_value(olive::Variant(value));
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_value_string_undoable(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_value_string_undoable(OakNodeKeyframe keyframe,
const char *value,
OakUndoCommand *out_command)
{
if (!keyframe || !value || !out_command) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !value || !out_command) {
return OAKNODE_E_INVALID;
}
try {
OakUndoCommand handle = oaknode_c_api::wrap_command(
new olive::NodeParamSetKeyframeValueCommand(
to_key(keyframe), olive::Variant(value)));
new olive::NodeParamSetKeyframeValueCommand(key,
olive::Variant(value)));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -393,23 +377,25 @@ int oaknode_keyframe_set_value_string_undoable(OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_get_type(const OakNodeKeyframe *keyframe, int *out_type)
int oaknode_keyframe_get_type(OakNodeKeyframe keyframe, int *out_type)
{
if (!keyframe || !out_type) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_type) {
return OAKNODE_E_INVALID;
}
try {
*out_type = static_cast<int>(to_key(keyframe)->type());
*out_type = static_cast<int>(key->type());
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_type(OakNodeKeyframe *keyframe, int type)
int oaknode_keyframe_set_type(OakNodeKeyframe keyframe, int type)
{
if (!keyframe) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key) {
return OAKNODE_E_INVALID;
}
@@ -418,17 +404,18 @@ int oaknode_keyframe_set_type(OakNodeKeyframe *keyframe, int type)
if (!keyframe_type_from_oak(type, &keyframe_type)) {
return OAKNODE_E_INVALID;
}
to_key(keyframe)->set_type(keyframe_type);
key->set_type(keyframe_type);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
int oaknode_keyframe_set_type_undoable(OakNodeKeyframe keyframe, int type,
OakUndoCommand *out_command)
{
if (!keyframe || !out_command) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_command) {
return OAKNODE_E_INVALID;
}
@@ -439,7 +426,7 @@ int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
}
OakUndoCommand handle = oaknode_c_api::wrap_command(
new KeyframeSetTypeCommand(to_key(keyframe), keyframe_type));
new KeyframeSetTypeCommand(key, keyframe_type));
if (!handle.ctx) {
return OAKNODE_E_NOMEM;
}
@@ -450,20 +437,21 @@ int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
}
}
int oaknode_keyframe_get_bezier_control(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_bezier_control(OakNodeKeyframe keyframe,
int handle, double *out_x,
double *out_y)
{
if (!keyframe || !out_x || !out_y) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_x || !out_y) {
return OAKNODE_E_INVALID;
}
try {
olive::PointF point;
if (handle == OAKNODE_KEYFRAME_IN_HANDLE) {
point = to_key(keyframe)->bezier_control_in();
point = key->bezier_control_in();
} else if (handle == OAKNODE_KEYFRAME_OUT_HANDLE) {
point = to_key(keyframe)->bezier_control_out();
point = key->bezier_control_out();
} else {
return OAKNODE_E_INVALID;
}
@@ -475,18 +463,19 @@ int oaknode_keyframe_get_bezier_control(const OakNodeKeyframe *keyframe,
}
}
int oaknode_keyframe_set_bezier_control(OakNodeKeyframe *keyframe, int handle,
int oaknode_keyframe_set_bezier_control(OakNodeKeyframe keyframe, int handle,
double x, double y)
{
if (!keyframe) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key) {
return OAKNODE_E_INVALID;
}
try {
if (handle == OAKNODE_KEYFRAME_IN_HANDLE) {
to_key(keyframe)->set_bezier_control_in(olive::PointF(x, y));
key->set_bezier_control_in(olive::PointF(x, y));
} else if (handle == OAKNODE_KEYFRAME_OUT_HANDLE) {
to_key(keyframe)->set_bezier_control_out(olive::PointF(x, y));
key->set_bezier_control_out(olive::PointF(x, y));
} else {
return OAKNODE_E_INVALID;
}
@@ -496,11 +485,12 @@ int oaknode_keyframe_set_bezier_control(OakNodeKeyframe *keyframe, int handle,
}
}
int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe *keyframe,
int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe keyframe,
int handle, double x, double y,
OakUndoCommand *out_command)
{
if (!keyframe || !out_command) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_command) {
return OAKNODE_E_INVALID;
}
@@ -514,73 +504,76 @@ int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe *keyframe,
return OAKNODE_E_INVALID;
}
OakUndoCommand handle_ptr = oaknode_c_api::wrap_command(
new KeyframeSetBezierControlCommand(to_key(keyframe), bezier_handle,
OakUndoCommand command = oaknode_c_api::wrap_command(
new KeyframeSetBezierControlCommand(key, bezier_handle,
olive::PointF(x, y)));
if (!handle_ptr.ctx) {
if (!command.ctx) {
return OAKNODE_E_NOMEM;
}
*out_command = handle_ptr;
*out_command = command;
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_get_track(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_track(OakNodeKeyframe keyframe,
int *out_track)
{
if (!keyframe || !out_track) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_track) {
return OAKNODE_E_INVALID;
}
try {
*out_track = to_key(keyframe)->track();
*out_track = key->track();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_get_element(const OakNodeKeyframe *keyframe,
int oaknode_keyframe_get_element(OakNodeKeyframe keyframe,
int *out_element)
{
if (!keyframe || !out_element) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_element) {
return OAKNODE_E_INVALID;
}
try {
*out_element = to_key(keyframe)->element();
*out_element = key->element();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_get_input(const OakNodeKeyframe *keyframe, char *buf,
int oaknode_keyframe_get_input(OakNodeKeyframe keyframe, char *buf,
int buf_size)
{
if (!keyframe) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key) {
return OAKNODE_E_INVALID;
}
try {
return oaknode_c_api::copy_string(to_key(keyframe)->input(), buf,
buf_size);
return oaknode_c_api::copy_string(key->input(), buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_keyframe_get_parent(const OakNodeKeyframe *keyframe,
OakNodeNode **out_node)
int oaknode_keyframe_get_parent(OakNodeKeyframe keyframe,
OakNodeNode *out_node)
{
if (!keyframe || !out_node) {
olive::NodeKeyframe *key = to_native<olive::NodeKeyframe>(keyframe);
if (!key || !out_node) {
return OAKNODE_E_INVALID;
}
try {
*out_node = from_node(to_key(keyframe)->parent());
*out_node = make_handle<OakNodeNode>(key->parent(), false, nullptr);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
+375 -300
View File
File diff suppressed because it is too large Load Diff
+180
View File
@@ -0,0 +1,180 @@
/***
Oak Video Editor - Non-Linear Video Editor
Copyright (C) 2026 Oak Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
the GNU General Public License. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef OAK_EDITOR_NODE_NODEHANDLE_H
#define OAK_EDITOR_NODE_NODEHANDLE_H
#include <atomic>
#include <new>
#include "node/error.h"
#include "alivecount.h"
/**
* @brief Internal control block behind every OakNode* value handle,
* shared between the c_api translation units.
*
* All oaknode public handle structs have the identical layout
* (ctx/addref/release/abi_version), so a single generic box and
* addref/release pair serves every family; `deleter` knows the
* concrete C++ type to destroy.
*
* `owns` is true for objects created through init/create/factory
* functions (releasing the last reference destroys the object through
* `deleter`) and false for references into library-owned graphs
* (children, tracks in a track list, nodes in a project): releasing
* those only destroys the box. Functions that insert an owned object
* into a graph (oaknode_project_add_node(), oaknode_tracklist_add_track(),
* the track block operations, ...) flip `owns` to false through
* mark_container_owned() once the graph assumes the lifetime.
*
* Live-object accounting: make_handle() counts every owned handle it
* creates (alive_inc) and handle_release() un-counts an owned object
* right after destroying it (alive_dec), keeping
* oaknode_debug_alive_count() meaningful for leak checking.
*/
struct OakNodeBox {
void *object;
bool owns;
std::atomic<uint32_t> refs;
void (*deleter)(void *object);
OakNodeBox(void *o, bool own, void (*del)(void *))
: object(o)
, owns(own)
, refs(1)
, deleter(del)
{
}
};
namespace oaknode_c_api
{
inline void handle_addref(void *ctx)
{
if (ctx) {
static_cast<OakNodeBox *>(ctx)->refs.fetch_add(1);
}
}
inline void handle_release(void *ctx)
{
if (!ctx) {
return;
}
OakNodeBox *box = static_cast<OakNodeBox *>(ctx);
if (box->refs.fetch_sub(1) == 1) {
if (box->owns) {
box->deleter(box->object);
alive_dec();
}
delete box;
}
}
/**
* @brief Wrap `object` in a value handle with reference count 1.
*
* `owns` selects whether the final release destroys the object through
* `deleter`. Returns an empty handle (ctx == nullptr) for a null
* object or on allocation failure (an owned object is destroyed via
* `deleter` in the latter case).
*/
template <typename Handle>
inline Handle make_handle(void *object, bool owns, void (*deleter)(void *))
{
Handle handle = {};
if (!object) {
return handle;
}
OakNodeBox *box = new (std::nothrow) OakNodeBox(object, owns, deleter);
if (!box) {
if (owns && deleter) {
deleter(object);
}
return handle;
}
if (owns) {
alive_inc();
}
handle.ctx = box;
handle.addref = handle_addref;
handle.release = handle_release;
handle.abi_version = OAKNODE_ABI_VERSION;
return handle;
}
/**
* @brief Unwrap a value handle to the native C++ pointer (nullptr for
* an empty handle).
*/
template <typename T, typename Handle>
inline T *to_native(Handle h)
{
if (!h.ctx) {
return nullptr;
}
return static_cast<T *>(static_cast<OakNodeBox *>(h.ctx)->object);
}
/**
* @brief Mark a handle's object as owned by a container (graph), so
* releasing the handle no longer destroys the object.
*/
template <typename Handle>
inline void mark_container_owned(Handle h)
{
if (h.ctx) {
static_cast<OakNodeBox *>(h.ctx)->owns = false;
}
}
/**
* @brief Deleter callback stamping the concrete C++ type.
*/
template <typename T>
inline void delete_as(void *object)
{
delete static_cast<T *>(object);
}
/**
* @brief Generic free() implementation for every oaknode family:
* release the caller's reference and null out the handle. NULL and
* ctx == NULL are no-ops.
*/
template <typename Handle>
inline void free_handle(Handle *h)
{
if (!h || !h->ctx) {
return;
}
h->release(h->ctx);
h->ctx = nullptr;
}
} // namespace oaknode_c_api
#endif // OAK_EDITOR_NODE_NODEHANDLE_H
+130 -120
View File
@@ -25,31 +25,17 @@
#include <new>
#include <string>
#include "node/node.h"
#include "node/folder.h"
#include "../src/project.h"
#include "../src/project/folder/folder.h"
#include "nodehandle.h"
namespace
{
olive::Project *to_cpp(OakNodeProject *project)
{
return reinterpret_cast<olive::Project *>(project);
}
const olive::Project *to_cpp(const OakNodeProject *project)
{
return reinterpret_cast<const olive::Project *>(project);
}
olive::Node *to_cpp(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
OakNodeNode *to_c(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
/**
* @brief Shared two-stage string getter.
*
@@ -74,189 +60,202 @@ int copy_string(const std::string &value, char *buf, int buf_size)
} // namespace
OakNodeProject *oaknode_project_init(void)
using oaknode_c_api::delete_as;
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
OakNodeProject oaknode_project_init(void)
{
try {
return reinterpret_cast<OakNodeProject *>(
new (std::nothrow) olive::Project());
return make_handle<OakNodeProject>(new (std::nothrow) olive::Project(),
true,
&delete_as<olive::Project>);
} catch (...) {
return NULL;
return OakNodeProject{};
}
}
void oaknode_project_free(OakNodeProject *project)
{
delete to_cpp(project);
oaknode_c_api::free_handle(project);
}
int oaknode_project_initialize(OakNodeProject *project)
int oaknode_project_initialize(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
if (to_cpp(project)->root()) {
olive::Project *p = to_native<olive::Project>(project);
if (p->root()) {
return OAKNODE_E_STATE;
}
to_cpp(project)->initialize();
p->initialize();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_clear(OakNodeProject *project)
int oaknode_project_clear(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->clear();
to_native<olive::Project>(project)->clear();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
OakNodeFolder *oaknode_project_root(OakNodeProject *project)
OakNodeFolder oaknode_project_root(OakNodeProject project)
{
if (!project) {
return NULL;
if (!project.ctx) {
return OakNodeFolder{};
}
try {
return reinterpret_cast<OakNodeFolder *>(to_cpp(project)->root());
return make_handle<OakNodeFolder>(
to_native<olive::Project>(project)->root(), false,
&delete_as<olive::Folder>);
} catch (...) {
return NULL;
return OakNodeFolder{};
}
}
int oaknode_project_name(const OakNodeProject *project, char *buf, int buf_size)
int oaknode_project_name(OakNodeProject project, char *buf, int buf_size)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->name(), buf, buf_size);
return copy_string(to_native<olive::Project>(project)->name(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_filename(const OakNodeProject *project, char *buf,
int oaknode_project_filename(OakNodeProject project, char *buf,
int buf_size)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->filename(), buf, buf_size);
return copy_string(to_native<olive::Project>(project)->filename(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_pretty_filename(const OakNodeProject *project, char *buf,
int oaknode_project_pretty_filename(OakNodeProject project, char *buf,
int buf_size)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->pretty_filename(), buf, buf_size);
return copy_string(to_native<olive::Project>(project)->pretty_filename(),
buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_set_filename(OakNodeProject *project, const char *filename)
int oaknode_project_set_filename(OakNodeProject project, const char *filename)
{
if (!project || !filename) {
if (!project.ctx || !filename) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->set_filename(filename);
to_native<olive::Project>(project)->set_filename(filename);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_is_modified(const OakNodeProject *project)
int oaknode_project_is_modified(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
return to_cpp(project)->is_modified() ? 1 : 0;
return to_native<olive::Project>(project)->is_modified() ? 1 : 0;
}
int oaknode_project_set_modified(OakNodeProject *project, int modified)
int oaknode_project_set_modified(OakNodeProject project, int modified)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->set_modified(modified != 0);
to_native<olive::Project>(project)->set_modified(modified != 0);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_is_new(const OakNodeProject *project)
int oaknode_project_is_new(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
return to_cpp(project)->is_new() ? 1 : 0;
return to_native<olive::Project>(project)->is_new() ? 1 : 0;
}
int oaknode_project_cache_path(const OakNodeProject *project, char *buf,
int oaknode_project_cache_path(OakNodeProject project, char *buf,
int buf_size)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->cache_path(), buf, buf_size);
return copy_string(to_native<olive::Project>(project)->cache_path(),
buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_get_cache_location_setting(const OakNodeProject *project)
int oaknode_project_get_cache_location_setting(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return static_cast<int>(to_cpp(project)->get_cache_location_setting());
return static_cast<int>(
to_native<olive::Project>(project)->get_cache_location_setting());
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_set_cache_location_setting(OakNodeProject *project,
int oaknode_project_set_cache_location_setting(OakNodeProject project,
int setting)
{
if (!project || setting < 0 ||
if (!project.ctx || setting < 0 ||
setting > static_cast<int>(olive::Project::k_cache_custom_path)) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->set_cache_location_setting(
to_native<olive::Project>(project)->set_cache_location_setting(
static_cast<olive::Project::CacheSetting>(setting));
return OAKNODE_OK;
} catch (...) {
@@ -264,77 +263,85 @@ int oaknode_project_set_cache_location_setting(OakNodeProject *project,
}
}
int oaknode_project_get_custom_cache_path(const OakNodeProject *project,
int oaknode_project_get_custom_cache_path(OakNodeProject project,
char *buf, int buf_size)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->get_custom_cache_path(), buf,
return copy_string(
to_native<olive::Project>(project)->get_custom_cache_path(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_set_custom_cache_path(OakNodeProject project,
const char *path)
{
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_native<olive::Project>(project)->set_custom_cache_path(
path ? path : "");
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_get_uuid(OakNodeProject project, char *buf,
int buf_size)
{
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_native<olive::Project>(project)->get_uuid(), buf,
buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_set_custom_cache_path(OakNodeProject *project,
const char *path)
int oaknode_project_add_node(OakNodeProject project, OakNodeNode node)
{
if (!project) {
if (!project.ctx || !node.ctx) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->set_custom_cache_path(path ? path : "");
to_native<olive::Project>(project)->add_node(
to_native<olive::Node>(node));
// The graph now owns the node; releasing `node` must not delete it.
oaknode_c_api::mark_container_owned(node);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_get_uuid(const OakNodeProject *project, char *buf,
int buf_size)
int oaknode_project_remove_node(OakNodeProject project, OakNodeNode node)
{
if (!project) {
if (!project.ctx || !node.ctx) {
return OAKNODE_E_INVALID;
}
try {
return copy_string(to_cpp(project)->get_uuid(), buf, buf_size);
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_add_node(OakNodeProject *project, OakNodeNode *node)
{
if (!project || !node) {
return OAKNODE_E_INVALID;
}
try {
to_cpp(project)->add_node(to_cpp(node));
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_project_remove_node(OakNodeProject *project, OakNodeNode *node)
{
if (!project || !node) {
return OAKNODE_E_INVALID;
}
try {
olive::Project *p = to_cpp(project);
olive::Node *n = to_cpp(node);
olive::Project *p = to_native<olive::Project>(project);
olive::Node *n = to_native<olive::Node>(node);
const auto &nodes = p->nodes();
if (std::find(nodes.begin(), nodes.end(), n) == nodes.end()) {
return OAKNODE_E_NOT_FOUND;
}
// Detach without deleting (legacy semantics); the caller's handle
// keeps its current ownership state.
p->remove_node(n);
return OAKNODE_OK;
} catch (...) {
@@ -342,45 +349,48 @@ int oaknode_project_remove_node(OakNodeProject *project, OakNodeNode *node)
}
}
int oaknode_project_node_count(const OakNodeProject *project)
int oaknode_project_node_count(OakNodeProject project)
{
if (!project) {
if (!project.ctx) {
return OAKNODE_E_INVALID;
}
try {
return static_cast<int>(to_cpp(project)->nodes().size());
return static_cast<int>(
to_native<olive::Project>(project)->nodes().size());
} catch (...) {
return OAKNODE_E_FAILED;
}
}
OakNodeNode *oaknode_project_node_at(const OakNodeProject *project, int index)
OakNodeNode oaknode_project_node_at(OakNodeProject project, int index)
{
if (!project || index < 0) {
return NULL;
if (!project.ctx || index < 0) {
return OakNodeNode{};
}
try {
const auto &nodes = to_cpp(project)->nodes();
const auto &nodes = to_native<olive::Project>(project)->nodes();
if (static_cast<size_t>(index) >= nodes.size()) {
return NULL;
return OakNodeNode{};
}
return to_c(nodes[static_cast<size_t>(index)]);
return make_handle<OakNodeNode>(nodes[static_cast<size_t>(index)],
false, &delete_as<olive::Node>);
} catch (...) {
return NULL;
return OakNodeNode{};
}
}
int oaknode_project_copy_settings(OakNodeProject *dst,
const OakNodeProject *src)
int oaknode_project_copy_settings(OakNodeProject dst,
OakNodeProject src)
{
if (!dst || !src) {
if (!dst.ctx || !src.ctx) {
return OAKNODE_E_INVALID;
}
try {
olive::Project::copy_settings(const_cast<olive::Project *>(to_cpp(src)), to_cpp(dst));
olive::Project::copy_settings(to_native<olive::Project>(src),
to_native<olive::Project>(dst));
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
+116 -100
View File
@@ -20,7 +20,7 @@
#include "node/sequence.h"
#include "alivecount.h"
#include "node/node.h"
#include "node/track.h"
#include "globals.h"
@@ -28,14 +28,16 @@
#include "project/sequence/sequence.h"
#include "videoparams.h"
#include "nodehandle.h"
using oaknode_c_api::delete_as;
using oaknode_c_api::free_handle;
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
namespace
{
olive::Sequence *impl(OakNodeSequence *h)
{
return reinterpret_cast<olive::Sequence *>(h);
}
int get_rational(const olive::core::Rational &r, int *numerator,
int *denominator)
{
@@ -54,158 +56,165 @@ bool valid_track_type(int type)
} // namespace
OakNodeSequence *oaknode_sequence_create(void)
OakNodeSequence oaknode_sequence_create(void)
{
try {
olive::Sequence *s = new olive::Sequence();
oaknode_c_api::alive_inc();
return reinterpret_cast<OakNodeSequence *>(s);
return make_handle<OakNodeSequence>(new olive::Sequence(), true,
&delete_as<olive::Sequence>);
} catch (...) {
return nullptr;
return OakNodeSequence{};
}
}
void oaknode_sequence_free(OakNodeSequence *sequence)
{
if (!sequence) {
return;
}
olive::Sequence *s = impl(sequence);
// ~Sequence() deletes the owned TrackLists
delete s;
oaknode_c_api::alive_dec();
// The final release runs ~Sequence(), which deletes the owned TrackLists
free_handle(sequence);
}
int oaknode_sequence_get_track_list(OakNodeSequence *sequence, int type,
OakNodeTrackList **out)
int oaknode_sequence_get_track_list(OakNodeSequence sequence, int type,
OakNodeTrackList *out)
{
if (!sequence || !out) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !out) {
return OAKNODE_E_INVALID;
}
if (!valid_track_type(type)) {
return OAKNODE_E_NOT_FOUND;
}
*out = reinterpret_cast<OakNodeTrackList *>(
impl(sequence)->track_list(static_cast<olive::Track::Type>(type)));
return OAKNODE_OK;
// Borrowed; the track list stays owned by the sequence
*out = make_handle<OakNodeTrackList>(
s->track_list(static_cast<olive::Track::Type>(type)), false,
&delete_as<olive::TrackList>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_sequence_get_track_count(OakNodeSequence *sequence, int type,
int oaknode_sequence_get_track_count(OakNodeSequence sequence, int type,
int *count)
{
if (!sequence || !count) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !count) {
return OAKNODE_E_INVALID;
}
if (!valid_track_type(type)) {
return OAKNODE_E_NOT_FOUND;
}
*count = impl(sequence)
->track_list(static_cast<olive::Track::Type>(type))
*count = s->track_list(static_cast<olive::Track::Type>(type))
->get_track_count();
return OAKNODE_OK;
}
int oaknode_sequence_get_track_at(OakNodeSequence *sequence, int type,
int index, OakNodeTrack **out)
int oaknode_sequence_get_track_at(OakNodeSequence sequence, int type,
int index, OakNodeTrack *out)
{
if (!sequence || !out || index < 0) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !out || index < 0) {
return OAKNODE_E_INVALID;
}
if (!valid_track_type(type)) {
return OAKNODE_E_NOT_FOUND;
}
olive::TrackList *list =
impl(sequence)->track_list(static_cast<olive::Track::Type>(type));
s->track_list(static_cast<olive::Track::Type>(type));
if (index >= list->get_track_count()) {
return OAKNODE_E_NOT_FOUND;
}
*out = reinterpret_cast<OakNodeTrack *>(list->get_track_at(index));
// Borrowed; the track stays owned by the list
*out = make_handle<OakNodeTrack>(list->get_track_at(index), false,
&delete_as<olive::Track>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_sequence_get_all_track_count(OakNodeSequence sequence, int *count)
{
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !count) {
return OAKNODE_E_INVALID;
}
*count = int(s->get_tracks().size());
return OAKNODE_OK;
}
int oaknode_sequence_get_all_track_count(OakNodeSequence *sequence, int *count)
int oaknode_sequence_get_all_track_at(OakNodeSequence sequence, int index,
OakNodeTrack *out)
{
if (!sequence || !count) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !out || index < 0) {
return OAKNODE_E_INVALID;
}
*count = int(impl(sequence)->get_tracks().size());
return OAKNODE_OK;
}
int oaknode_sequence_get_all_track_at(OakNodeSequence *sequence, int index,
OakNodeTrack **out)
{
if (!sequence || !out || index < 0) {
return OAKNODE_E_INVALID;
}
const auto &tracks = impl(sequence)->get_tracks();
const auto &tracks = s->get_tracks();
if (index >= int(tracks.size())) {
return OAKNODE_E_NOT_FOUND;
}
*out = reinterpret_cast<OakNodeTrack *>(tracks.at(index));
return OAKNODE_OK;
// Borrowed; the track stays owned by its list
*out = make_handle<OakNodeTrack>(tracks.at(index), false,
&delete_as<olive::Track>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_sequence_get_playhead(OakNodeSequence *sequence, int *numerator,
int oaknode_sequence_get_playhead(OakNodeSequence sequence, int *numerator,
int *denominator)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(sequence)->get_playhead(), numerator, denominator);
return get_rational(s->get_playhead(), numerator, denominator);
}
int oaknode_sequence_set_playhead(OakNodeSequence *sequence, int numerator,
int oaknode_sequence_set_playhead(OakNodeSequence sequence, int numerator,
int denominator)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
try {
impl(sequence)->set_playhead(olive::core::Rational(numerator,
denominator));
s->set_playhead(olive::core::Rational(numerator, denominator));
} catch (...) {
return OAKNODE_E_FAILED;
}
return OAKNODE_OK;
}
int oaknode_sequence_get_length(OakNodeSequence *sequence, int *numerator,
int oaknode_sequence_get_length(OakNodeSequence sequence, int *numerator,
int *denominator)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(sequence)->get_length(), numerator, denominator);
return get_rational(s->get_length(), numerator, denominator);
}
int oaknode_sequence_get_video_length(OakNodeSequence *sequence, int *numerator,
int *denominator)
int oaknode_sequence_get_video_length(OakNodeSequence sequence,
int *numerator, int *denominator)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(sequence)->get_video_length(), numerator,
denominator);
return get_rational(s->get_video_length(), numerator, denominator);
}
int oaknode_sequence_get_audio_length(OakNodeSequence *sequence, int *numerator,
int *denominator)
int oaknode_sequence_get_audio_length(OakNodeSequence sequence,
int *numerator, int *denominator)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(sequence)->get_audio_length(), numerator,
denominator);
return get_rational(s->get_audio_length(), numerator, denominator);
}
int oaknode_sequence_verify_length(OakNodeSequence *sequence)
int oaknode_sequence_verify_length(OakNodeSequence sequence)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
try {
impl(sequence)->verify_length();
s->verify_length();
} catch (...) {
return OAKNODE_E_FAILED;
}
@@ -214,38 +223,40 @@ int oaknode_sequence_verify_length(OakNodeSequence *sequence)
/* --------------------------------------------------- Video/audio params */
int oaknode_sequence_get_video_stream_count(OakNodeSequence *sequence,
int oaknode_sequence_get_video_stream_count(OakNodeSequence sequence,
int *count)
{
if (!sequence || !count) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !count) {
return OAKNODE_E_INVALID;
}
*count = impl(sequence)->get_video_stream_count();
*count = s->get_video_stream_count();
return OAKNODE_OK;
}
int oaknode_sequence_get_audio_stream_count(OakNodeSequence *sequence,
int oaknode_sequence_get_audio_stream_count(OakNodeSequence sequence,
int *count)
{
if (!sequence || !count) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !count) {
return OAKNODE_E_INVALID;
}
*count = impl(sequence)->get_audio_stream_count();
*count = s->get_audio_stream_count();
return OAKNODE_OK;
}
int oaknode_sequence_get_video_params(OakNodeSequence *sequence, int index,
int oaknode_sequence_get_video_params(OakNodeSequence sequence, int index,
OakVideoParams *out)
{
if (!sequence || !out || index < 0) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !out || index < 0) {
return OAKNODE_E_INVALID;
}
if (index >= impl(sequence)->get_video_stream_count()) {
if (index >= s->get_video_stream_count()) {
return OAKNODE_E_NOT_FOUND;
}
try {
const olive::VideoParams params =
impl(sequence)->get_video_params(index);
const olive::VideoParams params = s->get_video_params(index);
*out = oakcommon_videoparams_init_from_native(&params);
} catch (...) {
return OAKNODE_E_NOMEM;
@@ -256,10 +267,11 @@ int oaknode_sequence_get_video_params(OakNodeSequence *sequence, int index,
return OAKNODE_OK;
}
int oaknode_sequence_set_video_params(OakNodeSequence *sequence, int index,
int oaknode_sequence_set_video_params(OakNodeSequence sequence, int index,
OakVideoParams params)
{
if (!sequence || index < 0) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || index < 0) {
return OAKNODE_E_INVALID;
}
const olive::VideoParams *native =
@@ -267,28 +279,29 @@ int oaknode_sequence_set_video_params(OakNodeSequence *sequence, int index,
if (!native) {
return OAKNODE_E_INVALID;
}
if (index >= impl(sequence)->get_video_stream_count()) {
if (index >= s->get_video_stream_count()) {
return OAKNODE_E_NOT_FOUND;
}
try {
impl(sequence)->set_video_params(*native, index);
s->set_video_params(*native, index);
} catch (...) {
return OAKNODE_E_FAILED;
}
return OAKNODE_OK;
}
int oaknode_sequence_get_audio_params(OakNodeSequence *sequence, int index,
int oaknode_sequence_get_audio_params(OakNodeSequence sequence, int index,
OakAudioParams **out)
{
if (!sequence || !out || index < 0) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !out || index < 0) {
return OAKNODE_E_INVALID;
}
if (index >= impl(sequence)->get_audio_stream_count()) {
if (index >= s->get_audio_stream_count()) {
return OAKNODE_E_NOT_FOUND;
}
OakAudioParams *copy =
oakcore_audioparams_copy(impl(sequence)->get_audio_params(index).handle());
oakcore_audioparams_copy(s->get_audio_params(index).handle());
if (!copy) {
return OAKNODE_E_NOMEM;
}
@@ -296,13 +309,14 @@ int oaknode_sequence_get_audio_params(OakNodeSequence *sequence, int index,
return OAKNODE_OK;
}
int oaknode_sequence_set_audio_params(OakNodeSequence *sequence, int index,
int oaknode_sequence_set_audio_params(OakNodeSequence sequence, int index,
const OakAudioParams *params)
{
if (!sequence || !params || index < 0) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s || !params || index < 0) {
return OAKNODE_E_INVALID;
}
if (index >= impl(sequence)->get_audio_stream_count()) {
if (index >= s->get_audio_stream_count()) {
return OAKNODE_E_NOT_FOUND;
}
OakAudioParams *copy = oakcore_audioparams_copy(params);
@@ -310,8 +324,7 @@ int oaknode_sequence_set_audio_params(OakNodeSequence *sequence, int index,
return OAKNODE_E_NOMEM;
}
try {
impl(sequence)->set_audio_params(
olive::core::AudioParams::from_handle(copy), index);
s->set_audio_params(olive::core::AudioParams::from_handle(copy), index);
} catch (...) {
oakcore_audioparams_free(copy);
return OAKNODE_E_FAILED;
@@ -319,19 +332,22 @@ int oaknode_sequence_set_audio_params(OakNodeSequence *sequence, int index,
return OAKNODE_OK;
}
OakNodeNode *oaknode_sequence_as_node(OakNodeSequence *sequence)
OakNodeNode oaknode_sequence_as_node(OakNodeSequence sequence)
{
return reinterpret_cast<OakNodeNode *>(sequence);
// Borrowed; releasing the result never destroys the sequence
return make_handle<OakNodeNode>(to_native<olive::Sequence>(sequence),
false, &delete_as<olive::Node>);
}
int oaknode_sequence_set_default_parameters(OakNodeSequence *sequence)
int oaknode_sequence_set_default_parameters(OakNodeSequence sequence)
{
if (!sequence) {
olive::Sequence *s = to_native<olive::Sequence>(sequence);
if (!s) {
return OAKNODE_E_INVALID;
}
try {
impl(sequence)->set_default_parameters();
s->set_default_parameters();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
+100 -92
View File
@@ -30,40 +30,13 @@
#include "../src/project/serializer/serializer.h"
#include "xmlutils.h"
struct OakNodeSerializerSaveData {
olive::ProjectSerializer::SaveData impl;
OakNodeSerializerSaveData(olive::ProjectSerializer::LoadType type,
olive::Project *project)
: impl(type, project)
{
}
};
struct OakNodeSerializerLoadData {
olive::ProjectSerializer::LoadData impl;
};
#include "nodehandle.h"
namespace
{
bool g_initialized = false;
olive::Project *to_cpp(OakNodeProject *project)
{
return reinterpret_cast<olive::Project *>(project);
}
olive::Node *to_cpp(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
OakNodeNode *to_c(olive::Node *node)
{
return reinterpret_cast<OakNodeNode *>(node);
}
bool is_valid_load_type(int load_type)
{
return load_type >= static_cast<int>(olive::ProjectSerializer::k_project) &&
@@ -126,31 +99,36 @@ void oaknode_serializer_shutdown(void)
g_initialized = false;
}
OakNodeSerializerSaveData *oaknode_serializer_savedata_create(
int load_type, OakNodeProject *project)
OakNodeSerializerSaveData oaknode_serializer_savedata_create(
int load_type, OakNodeProject project)
{
if (!is_valid_load_type(load_type)) {
return NULL;
return OakNodeSerializerSaveData{};
}
try {
return new (std::nothrow) OakNodeSerializerSaveData(
static_cast<olive::ProjectSerializer::LoadType>(load_type),
to_cpp(project));
return oaknode_c_api::make_handle<OakNodeSerializerSaveData>(
new olive::ProjectSerializer::SaveData(
static_cast<olive::ProjectSerializer::LoadType>(load_type),
oaknode_c_api::to_native<olive::Project>(project)),
true,
&oaknode_c_api::delete_as<olive::ProjectSerializer::SaveData>);
} catch (...) {
return NULL;
return OakNodeSerializerSaveData{};
}
}
void oaknode_serializer_savedata_free(OakNodeSerializerSaveData *save_data)
{
delete save_data;
oaknode_c_api::free_handle(save_data);
}
int oaknode_serializer_savedata_set_nodes(
OakNodeSerializerSaveData *save_data, OakNodeNode *const *nodes, int count)
OakNodeSerializerSaveData save_data, const OakNodeNode *nodes, int count)
{
if (!save_data || !nodes || count < 0) {
olive::ProjectSerializer::SaveData *sd =
oaknode_c_api::to_native<olive::ProjectSerializer::SaveData>(save_data);
if (!sd || !nodes || count < 0) {
return OAKNODE_E_INVALID;
}
@@ -158,13 +136,14 @@ int oaknode_serializer_savedata_set_nodes(
std::vector<olive::Node *> cpp_nodes;
cpp_nodes.reserve(static_cast<size_t>(count));
for (int i = 0; i < count; i++) {
if (!nodes[i]) {
olive::Node *node = oaknode_c_api::to_native<olive::Node>(nodes[i]);
if (!node) {
return OAKNODE_E_INVALID;
}
cpp_nodes.push_back(to_cpp(nodes[i]));
cpp_nodes.push_back(node);
}
save_data->impl.set_only_serialize_nodes(cpp_nodes);
sd->set_only_serialize_nodes(cpp_nodes);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
@@ -172,28 +151,33 @@ int oaknode_serializer_savedata_set_nodes(
}
int oaknode_serializer_savedata_set_property(
OakNodeSerializerSaveData *save_data, OakNodeNode *node, const char *key,
OakNodeSerializerSaveData save_data, OakNodeNode node, const char *key,
const char *value)
{
if (!save_data || !node || !key || !value) {
olive::ProjectSerializer::SaveData *sd =
oaknode_c_api::to_native<olive::ProjectSerializer::SaveData>(save_data);
olive::Node *native_node = oaknode_c_api::to_native<olive::Node>(node);
if (!sd || !native_node || !key || !value) {
return OAKNODE_E_INVALID;
}
try {
olive::ProjectSerializer::SerializedProperties properties =
save_data->impl.get_properties();
properties[to_cpp(node)][key] = value;
save_data->impl.set_properties(properties);
sd->get_properties();
properties[native_node][key] = value;
sd->set_properties(properties);
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_serializer_save_to_xml(OakNodeSerializerSaveData *save_data,
int oaknode_serializer_save_to_xml(OakNodeSerializerSaveData save_data,
char *buf, int buf_size)
{
if (!save_data) {
olive::ProjectSerializer::SaveData *sd =
oaknode_c_api::to_native<olive::ProjectSerializer::SaveData>(save_data);
if (!sd) {
return OAKNODE_E_INVALID;
}
if (!g_initialized) {
@@ -203,7 +187,7 @@ int oaknode_serializer_save_to_xml(OakNodeSerializerSaveData *save_data,
try {
olive::XmlStreamWriter writer;
olive::ProjectSerializer::Result result =
olive::ProjectSerializer::save(&writer, save_data->impl);
olive::ProjectSerializer::save(&writer, *sd);
if (result != olive::ProjectSerializer::k_success) {
return OAKNODE_E_FAILED;
}
@@ -213,9 +197,9 @@ int oaknode_serializer_save_to_xml(OakNodeSerializerSaveData *save_data,
}
}
int oaknode_serializer_load_from_xml(OakNodeProject *project, const char *xml,
int oaknode_serializer_load_from_xml(OakNodeProject project, const char *xml,
int load_type, int *out_result,
OakNodeSerializerLoadData **out_load_data,
OakNodeSerializerLoadData *out_load_data,
char *details_buf, int details_buf_size)
{
if (!xml || !out_result || !is_valid_load_type(load_type)) {
@@ -226,13 +210,13 @@ int oaknode_serializer_load_from_xml(OakNodeProject *project, const char *xml,
}
if (out_load_data) {
*out_load_data = NULL;
*out_load_data = OakNodeSerializerLoadData{};
}
try {
olive::XmlStreamReader reader(xml);
olive::ProjectSerializer::Result result = olive::ProjectSerializer::load(
to_cpp(project), &reader,
oaknode_c_api::to_native<olive::Project>(project), &reader,
static_cast<olive::ProjectSerializer::LoadType>(load_type));
*out_result = static_cast<int>(result.code());
@@ -242,12 +226,20 @@ int oaknode_serializer_load_from_xml(OakNodeProject *project, const char *xml,
}
if (result == olive::ProjectSerializer::k_success && out_load_data) {
auto *load_data = new (std::nothrow) OakNodeSerializerLoadData();
auto *load_data =
new (std::nothrow) olive::ProjectSerializer::LoadData();
if (!load_data) {
return OAKNODE_E_NOMEM;
}
load_data->impl = result.get_load_data();
*out_load_data = load_data;
*load_data = result.get_load_data();
*out_load_data =
oaknode_c_api::make_handle<OakNodeSerializerLoadData>(
load_data, true,
&oaknode_c_api::delete_as<
olive::ProjectSerializer::LoadData>);
if (!out_load_data->ctx) {
return OAKNODE_E_NOMEM;
}
}
return OAKNODE_OK;
@@ -258,49 +250,59 @@ int oaknode_serializer_load_from_xml(OakNodeProject *project, const char *xml,
void oaknode_serializer_loaddata_free(OakNodeSerializerLoadData *load_data)
{
delete load_data;
oaknode_c_api::free_handle(load_data);
}
int oaknode_serializer_loaddata_node_count(
const OakNodeSerializerLoadData *load_data)
OakNodeSerializerLoadData load_data)
{
if (!load_data) {
olive::ProjectSerializer::LoadData *ld =
oaknode_c_api::to_native<olive::ProjectSerializer::LoadData>(load_data);
if (!ld) {
return OAKNODE_E_INVALID;
}
try {
return static_cast<int>(load_data->impl.nodes.size());
return static_cast<int>(ld->nodes.size());
} catch (...) {
return OAKNODE_E_FAILED;
}
}
OakNodeNode *oaknode_serializer_loaddata_node_at(
const OakNodeSerializerLoadData *load_data, int index)
OakNodeNode oaknode_serializer_loaddata_node_at(
OakNodeSerializerLoadData load_data, int index)
{
if (!load_data || index < 0 ||
static_cast<size_t>(index) >= load_data->impl.nodes.size()) {
return NULL;
olive::ProjectSerializer::LoadData *ld =
oaknode_c_api::to_native<olive::ProjectSerializer::LoadData>(load_data);
if (!ld || index < 0 ||
static_cast<size_t>(index) >= ld->nodes.size()) {
return OakNodeNode{};
}
try {
return to_c(load_data->impl.nodes[static_cast<size_t>(index)]);
// Borrowed: the node is owned by the caller only in the sense of
// the documented adoption contract; see oaknode_project_add_node().
return oaknode_c_api::make_handle<OakNodeNode>(
ld->nodes[static_cast<size_t>(index)], false, nullptr);
} catch (...) {
return NULL;
return OakNodeNode{};
}
}
int oaknode_serializer_loaddata_get_property(
const OakNodeSerializerLoadData *load_data, OakNodeNode *node,
const char *key, char *buf, int buf_size)
OakNodeSerializerLoadData load_data, OakNodeNode node, const char *key,
char *buf, int buf_size)
{
if (!load_data || !node || !key) {
olive::ProjectSerializer::LoadData *ld =
oaknode_c_api::to_native<olive::ProjectSerializer::LoadData>(load_data);
olive::Node *native_node = oaknode_c_api::to_native<olive::Node>(node);
if (!ld || !native_node || !key) {
return OAKNODE_E_INVALID;
}
try {
auto node_it = load_data->impl.properties.find(to_cpp(node));
if (node_it == load_data->impl.properties.end()) {
auto node_it = ld->properties.find(native_node);
if (node_it == ld->properties.end()) {
return OAKNODE_E_NOT_FOUND;
}
auto key_it = node_it->second.find(key);
@@ -314,37 +316,43 @@ int oaknode_serializer_loaddata_get_property(
}
int oaknode_serializer_loaddata_connection_count(
const OakNodeSerializerLoadData *load_data)
OakNodeSerializerLoadData load_data)
{
if (!load_data) {
olive::ProjectSerializer::LoadData *ld =
oaknode_c_api::to_native<olive::ProjectSerializer::LoadData>(load_data);
if (!ld) {
return OAKNODE_E_INVALID;
}
try {
return static_cast<int>(load_data->impl.promised_connections.size());
return static_cast<int>(ld->promised_connections.size());
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_serializer_loaddata_connection_at(
const OakNodeSerializerLoadData *load_data, int index,
OakNodeNode **out_output_node, OakNodeNode **out_input_node,
OakNodeSerializerLoadData load_data, int index,
OakNodeNode *out_output_node, OakNodeNode *out_input_node,
char *input_id_buf, int input_id_buf_size, int *out_element)
{
if (!load_data || !out_output_node || !out_input_node || !out_element) {
olive::ProjectSerializer::LoadData *ld =
oaknode_c_api::to_native<olive::ProjectSerializer::LoadData>(load_data);
if (!ld || !out_output_node || !out_input_node || !out_element) {
return OAKNODE_E_INVALID;
}
if (index < 0 || static_cast<size_t>(index) >=
load_data->impl.promised_connections.size()) {
if (index < 0 ||
static_cast<size_t>(index) >= ld->promised_connections.size()) {
return OAKNODE_E_NOT_FOUND;
}
try {
const olive::Node::OutputConnection &connection =
load_data->impl.promised_connections[static_cast<size_t>(index)];
*out_output_node = to_c(connection.first);
*out_input_node = to_c(connection.second.node());
ld->promised_connections[static_cast<size_t>(index)];
*out_output_node = oaknode_c_api::make_handle<OakNodeNode>(
connection.first, false, nullptr);
*out_input_node = oaknode_c_api::make_handle<OakNodeNode>(
connection.second.node(), false, nullptr);
if (input_id_buf && input_id_buf_size > 0) {
copy_string(connection.second.input(), input_id_buf,
input_id_buf_size);
@@ -383,11 +391,12 @@ int report_serializer_result(const olive::ProjectSerializer::Result &result,
} // namespace
int oaknode_serializer_save_to_file(OakNodeProject *project,
int oaknode_serializer_save_to_file(OakNodeProject project,
const char *filename, int use_compression, int *out_code,
char *details, int details_size)
{
if (!project || !filename) {
olive::Project *native = oaknode_c_api::to_native<olive::Project>(project);
if (!native || !filename) {
return OAKNODE_E_INVALID;
}
@@ -395,8 +404,7 @@ int oaknode_serializer_save_to_file(OakNodeProject *project,
oaknode_serializer_initialize();
olive::ProjectSerializer::SaveData data(
olive::ProjectSerializer::k_project,
reinterpret_cast<olive::Project *>(project), filename);
olive::ProjectSerializer::k_project, native, filename);
olive::ProjectSerializer::Result result =
olive::ProjectSerializer::save(data, use_compression != 0);
@@ -408,11 +416,12 @@ int oaknode_serializer_save_to_file(OakNodeProject *project,
}
}
int oaknode_serializer_load_from_file(OakNodeProject *project,
int oaknode_serializer_load_from_file(OakNodeProject project,
const char *filename, int *out_code, char *details,
int details_size)
{
if (!project || !filename) {
olive::Project *native = oaknode_c_api::to_native<olive::Project>(project);
if (!native || !filename) {
return OAKNODE_E_INVALID;
}
@@ -420,9 +429,8 @@ int oaknode_serializer_load_from_file(OakNodeProject *project,
oaknode_serializer_initialize();
olive::ProjectSerializer::Result result =
olive::ProjectSerializer::load(
reinterpret_cast<olive::Project *>(project), filename,
olive::ProjectSerializer::k_project);
olive::ProjectSerializer::load(native, filename,
olive::ProjectSerializer::k_project);
return report_serializer_result(result, out_code, details,
details_size);
+252 -200
View File
@@ -22,7 +22,9 @@
#include <algorithm>
#include "alivecount.h"
#include "node/block.h"
#include "node/node.h"
#include "node/sequence.h"
#include "valueconvert.h"
@@ -31,34 +33,17 @@
#include "output/track/tracklist.h"
#include "project/sequence/sequence.h"
#include "nodehandle.h"
using oaknode_c_api::delete_as;
using oaknode_c_api::free_handle;
using oaknode_c_api::make_handle;
using oaknode_c_api::mark_container_owned;
using oaknode_c_api::to_native;
namespace
{
olive::Track *impl(OakNodeTrack *h)
{
return reinterpret_cast<olive::Track *>(h);
}
olive::TrackList *list_impl(OakNodeTrackList *h)
{
return reinterpret_cast<olive::TrackList *>(h);
}
olive::Block *block_impl(OakNodeBlock *h)
{
return reinterpret_cast<olive::Block *>(h);
}
OakNodeTrack *wrap(olive::Track *t)
{
return reinterpret_cast<OakNodeTrack *>(t);
}
OakNodeBlock *wrap_block(olive::Block *b)
{
return reinterpret_cast<OakNodeBlock *>(b);
}
bool valid_type(int type)
{
return type >= OAKNODE_TRACK_TYPE_VIDEO && type < OAKNODE_TRACK_TYPE_COUNT;
@@ -98,81 +83,82 @@ int get_rational(const olive::core::Rational &r, int *numerator,
/* ---------------------------------------------------------------- Track */
OakNodeTrack *oaknode_track_create(int type)
OakNodeTrack oaknode_track_create(int type)
{
if (!valid_type(type)) {
return nullptr;
return OakNodeTrack{};
}
try {
olive::Track *t = new olive::Track();
t->set_type(static_cast<olive::Track::Type>(type));
oaknode_c_api::alive_inc();
return wrap(t);
return make_handle<OakNodeTrack>(t, true, &delete_as<olive::Track>);
} catch (...) {
return nullptr;
return OakNodeTrack{};
}
}
void oaknode_track_free(OakNodeTrack *track)
{
if (!track) {
return;
}
delete impl(track);
oaknode_c_api::alive_dec();
free_handle(track);
}
int oaknode_track_get_type(OakNodeTrack *track, int *type)
int oaknode_track_get_type(OakNodeTrack track, int *type)
{
if (!track || !type) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !type) {
return OAKNODE_E_INVALID;
}
*type = int(impl(track)->type());
*type = int(t->type());
return OAKNODE_OK;
}
int oaknode_track_set_type(OakNodeTrack *track, int type)
int oaknode_track_set_type(OakNodeTrack track, int type)
{
if (!track || !valid_type(type)) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !valid_type(type)) {
return OAKNODE_E_INVALID;
}
impl(track)->set_type(static_cast<olive::Track::Type>(type));
t->set_type(static_cast<olive::Track::Type>(type));
return OAKNODE_OK;
}
int oaknode_track_get_height(OakNodeTrack *track, double *height)
int oaknode_track_get_height(OakNodeTrack track, double *height)
{
if (!track || !height) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !height) {
return OAKNODE_E_INVALID;
}
*height = impl(track)->get_track_height();
*height = t->get_track_height();
return OAKNODE_OK;
}
int oaknode_track_set_height(OakNodeTrack *track, double height)
int oaknode_track_set_height(OakNodeTrack track, double height)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
impl(track)->set_track_height(height);
t->set_track_height(height);
return OAKNODE_OK;
}
int oaknode_track_get_height_in_pixels(OakNodeTrack *track, int *height)
int oaknode_track_get_height_in_pixels(OakNodeTrack track, int *height)
{
if (!track || !height) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !height) {
return OAKNODE_E_INVALID;
}
*height = impl(track)->get_track_height_in_pixels();
*height = t->get_track_height_in_pixels();
return OAKNODE_OK;
}
int oaknode_track_set_height_in_pixels(OakNodeTrack *track, int height)
int oaknode_track_set_height_in_pixels(OakNodeTrack track, int height)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
impl(track)->set_track_height_in_pixels(height);
t->set_track_height_in_pixels(height);
return OAKNODE_OK;
}
@@ -186,223 +172,267 @@ int oaknode_track_get_minimum_height_in_pixels(void)
return olive::Track::get_minimum_track_height_in_pixels();
}
int oaknode_track_get_index(OakNodeTrack *track, int *index)
int oaknode_track_get_index(OakNodeTrack track, int *index)
{
if (!track || !index) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !index) {
return OAKNODE_E_INVALID;
}
*index = impl(track)->index();
*index = t->index();
return OAKNODE_OK;
}
int oaknode_track_set_index(OakNodeTrack *track, int index)
int oaknode_track_set_index(OakNodeTrack track, int index)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
impl(track)->set_index(index);
t->set_index(index);
return OAKNODE_OK;
}
int oaknode_track_get_muted(OakNodeTrack *track, int *muted)
int oaknode_track_get_muted(OakNodeTrack track, int *muted)
{
if (!track || !muted) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !muted) {
return OAKNODE_E_INVALID;
}
*muted = impl(track)->is_muted() ? 1 : 0;
*muted = t->is_muted() ? 1 : 0;
return OAKNODE_OK;
}
int oaknode_track_set_muted(OakNodeTrack *track, int muted)
int oaknode_track_set_muted(OakNodeTrack track, int muted)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
impl(track)->set_muted(muted != 0);
t->set_muted(muted != 0);
return OAKNODE_OK;
}
int oaknode_track_get_locked(OakNodeTrack *track, int *locked)
int oaknode_track_get_locked(OakNodeTrack track, int *locked)
{
if (!track || !locked) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !locked) {
return OAKNODE_E_INVALID;
}
*locked = impl(track)->is_locked() ? 1 : 0;
*locked = t->is_locked() ? 1 : 0;
return OAKNODE_OK;
}
int oaknode_track_set_locked(OakNodeTrack *track, int locked)
int oaknode_track_set_locked(OakNodeTrack track, int locked)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
impl(track)->set_locked(locked != 0);
t->set_locked(locked != 0);
return OAKNODE_OK;
}
int oaknode_track_get_reference(OakNodeTrack *track, int *type, int *index)
int oaknode_track_get_reference(OakNodeTrack track, int *type, int *index)
{
if (!track || !type || !index) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !type || !index) {
return OAKNODE_E_INVALID;
}
olive::Track::Reference ref = impl(track)->to_reference();
olive::Track::Reference ref = t->to_reference();
*type = int(ref.type());
*index = ref.index();
return OAKNODE_OK;
}
int oaknode_track_get_length(OakNodeTrack *track, int *numerator,
int oaknode_track_get_length(OakNodeTrack track, int *numerator,
int *denominator)
{
if (!track) {
olive::Track *t = to_native<olive::Track>(track);
if (!t) {
return OAKNODE_E_INVALID;
}
return get_rational(impl(track)->track_length(), numerator, denominator);
return get_rational(t->track_length(), numerator, denominator);
}
int oaknode_track_get_sequence(OakNodeTrack *track, OakNodeSequence **out)
int oaknode_track_get_sequence(OakNodeTrack track, OakNodeSequence *out)
{
if (!track || !out) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
*out = reinterpret_cast<OakNodeSequence *>(impl(track)->sequence());
// Borrowed (empty when the track is not in a sequence)
*out = make_handle<OakNodeSequence>(t->sequence(), false,
&delete_as<olive::Sequence>);
return OAKNODE_OK;
}
/* ------------------------------------------------------- Track blocks */
int oaknode_track_get_block_count(OakNodeTrack *track, int *count)
int oaknode_track_get_block_count(OakNodeTrack track, int *count)
{
if (!track || !count) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !count) {
return OAKNODE_E_INVALID;
}
*count = int(impl(track)->blocks().size());
*count = int(t->blocks().size());
return OAKNODE_OK;
}
int oaknode_track_get_block_at(OakNodeTrack *track, int index,
OakNodeBlock **out)
int oaknode_track_get_block_at(OakNodeTrack track, int index,
OakNodeBlock *out)
{
if (!track || !out || index < 0) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out || index < 0) {
return OAKNODE_E_INVALID;
}
const auto &blocks = impl(track)->blocks();
const auto &blocks = t->blocks();
if (index >= int(blocks.size())) {
return OAKNODE_E_NOT_FOUND;
}
*out = wrap_block(blocks.at(index));
return OAKNODE_OK;
// Borrowed; the block stays owned by the track
*out = make_handle<OakNodeBlock>(blocks.at(index), false,
&delete_as<olive::Block>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_track_append_block(OakNodeTrack *track, OakNodeBlock *block)
int oaknode_track_append_block(OakNodeTrack track, OakNodeBlock block)
{
if (!track || !block) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
if (!t || !b) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->append_block(block_impl(block));
t->append_block(b);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
// The track now owns the block; the caller's handle becomes a
// non-owning reference (its release no longer deletes)
mark_container_owned(block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_prepend_block(OakNodeTrack *track, OakNodeBlock *block)
int oaknode_track_prepend_block(OakNodeTrack track, OakNodeBlock block)
{
if (!track || !block) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
if (!t || !b) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->prepend_block(block_impl(block));
t->prepend_block(b);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
mark_container_owned(block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_insert_block_at_index(OakNodeTrack *track,
OakNodeBlock *block, int index)
int oaknode_track_insert_block_at_index(OakNodeTrack track,
OakNodeBlock block, int index)
{
if (!track || !block) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
if (!t || !b) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->insert_block_at_index(block_impl(block), index);
t->insert_block_at_index(b, index);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
mark_container_owned(block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_insert_block_after(OakNodeTrack *track, OakNodeBlock *block,
OakNodeBlock *before)
int oaknode_track_insert_block_after(OakNodeTrack track, OakNodeBlock block,
OakNodeBlock before)
{
if (!track || !block || !before) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
olive::Block *bf = to_native<olive::Block>(before);
if (!t || !b || !bf) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->insert_block_after(block_impl(block), block_impl(before));
t->insert_block_after(b, bf);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
mark_container_owned(block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_insert_block_before(OakNodeTrack *track, OakNodeBlock *block,
OakNodeBlock *after)
int oaknode_track_insert_block_before(OakNodeTrack track, OakNodeBlock block,
OakNodeBlock after)
{
if (!track || !block || !after) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
olive::Block *af = to_native<olive::Block>(after);
if (!t || !b || !af) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->insert_block_before(block_impl(block), block_impl(after));
t->insert_block_before(b, af);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
mark_container_owned(block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_ripple_remove_block(OakNodeTrack *track, OakNodeBlock *block)
int oaknode_track_ripple_remove_block(OakNodeTrack track, OakNodeBlock block)
{
if (!track || !block) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
if (!t || !b) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->ripple_remove_block(block_impl(block));
t->ripple_remove_block(b);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_replace_block(OakNodeTrack *track, OakNodeBlock *old_block,
OakNodeBlock *new_block)
int oaknode_track_replace_block(OakNodeTrack track, OakNodeBlock old_block,
OakNodeBlock new_block)
{
if (!track || !old_block || !new_block) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *old_b = to_native<olive::Block>(old_block);
olive::Block *new_b = to_native<olive::Block>(new_block);
if (!t || !old_b || !new_b) {
return OAKNODE_E_INVALID;
}
try {
impl(track)->replace_block(block_impl(old_block), block_impl(new_block));
t->replace_block(old_b, new_b);
} catch (...) {
return OAKNODE_E_FAILED;
}
refresh_lengths(impl(track));
// The track takes over the replacement; the caller's handle to it
// becomes non-owning
mark_container_owned(new_block);
refresh_lengths(t);
return OAKNODE_OK;
}
int oaknode_track_get_block_index(OakNodeTrack *track, OakNodeBlock *block,
int oaknode_track_get_block_index(OakNodeTrack track, OakNodeBlock block,
int *index)
{
if (!track || !block || !index) {
olive::Track *t = to_native<olive::Track>(track);
olive::Block *b = to_native<olive::Block>(block);
if (!t || !b || !index) {
return OAKNODE_E_INVALID;
}
int i = impl(track)->get_array_index_from_block(block_impl(block));
int i = t->get_array_index_from_block(b);
if (i < 0) {
return OAKNODE_E_NOT_FOUND;
}
@@ -410,48 +440,51 @@ int oaknode_track_get_block_index(OakNodeTrack *track, OakNodeBlock *block,
return OAKNODE_OK;
}
int oaknode_track_get_block_containing_time(OakNodeTrack *track, int numerator,
int oaknode_track_get_block_containing_time(OakNodeTrack track, int numerator,
int denominator,
OakNodeBlock **out)
OakNodeBlock *out)
{
if (!track || !out) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
olive::Block *b = impl(track)->block_containing_time(
olive::Block *b = t->block_containing_time(
olive::core::Rational(numerator, denominator));
if (!b) {
return OAKNODE_E_NOT_FOUND;
}
*out = wrap_block(b);
return OAKNODE_OK;
*out = make_handle<OakNodeBlock>(b, false, &delete_as<olive::Block>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_track_get_visible_block_at_time(OakNodeTrack *track, int numerator,
int oaknode_track_get_visible_block_at_time(OakNodeTrack track, int numerator,
int denominator,
OakNodeBlock **out)
OakNodeBlock *out)
{
if (!track || !out) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
olive::Block *b = impl(track)->visible_block_at_time(
olive::Block *b = t->visible_block_at_time(
olive::core::Rational(numerator, denominator));
if (!b) {
return OAKNODE_E_NOT_FOUND;
}
*out = wrap_block(b);
return OAKNODE_OK;
*out = make_handle<OakNodeBlock>(b, false, &delete_as<olive::Block>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_track_is_range_free(OakNodeTrack *track, int in_num, int in_den,
int oaknode_track_is_range_free(OakNodeTrack track, int in_num, int in_den,
int out_num, int out_den, int *is_free)
{
if (!track || !is_free) {
olive::Track *t = to_native<olive::Track>(track);
if (!t || !is_free) {
return OAKNODE_E_INVALID;
}
*is_free = impl(track)->is_range_free(
olive::core::TimeRange(
olive::core::Rational(in_num, in_den),
olive::core::Rational(out_num, out_den))) ?
*is_free = t->is_range_free(
olive::core::TimeRange(
olive::core::Rational(in_num, in_den),
olive::core::Rational(out_num, out_den))) ?
1 :
0;
return OAKNODE_OK;
@@ -459,63 +492,69 @@ int oaknode_track_is_range_free(OakNodeTrack *track, int in_num, int in_den,
/* ------------------------------------------------------------ TrackList */
int oaknode_tracklist_get_type(OakNodeTrackList *list, int *type)
int oaknode_tracklist_get_type(OakNodeTrackList list, int *type)
{
if (!list || !type) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !type) {
return OAKNODE_E_INVALID;
}
*type = int(list_impl(list)->type());
*type = int(l->type());
return OAKNODE_OK;
}
int oaknode_tracklist_get_track_count(OakNodeTrackList *list, int *count)
int oaknode_tracklist_get_track_count(OakNodeTrackList list, int *count)
{
if (!list || !count) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !count) {
return OAKNODE_E_INVALID;
}
*count = list_impl(list)->get_track_count();
*count = l->get_track_count();
return OAKNODE_OK;
}
int oaknode_tracklist_get_track_at(OakNodeTrackList *list, int index,
OakNodeTrack **out)
int oaknode_tracklist_get_track_at(OakNodeTrackList list, int index,
OakNodeTrack *out)
{
if (!list || !out || index < 0) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !out || index < 0) {
return OAKNODE_E_INVALID;
}
if (index >= list_impl(list)->get_track_count()) {
if (index >= l->get_track_count()) {
return OAKNODE_E_NOT_FOUND;
}
*out = wrap(list_impl(list)->get_track_at(index));
return OAKNODE_OK;
// Borrowed; the track stays owned by the list
*out = make_handle<OakNodeTrack>(l->get_track_at(index), false,
&delete_as<olive::Track>);
return out->ctx ? OAKNODE_OK : OAKNODE_E_NOMEM;
}
int oaknode_tracklist_get_total_length(OakNodeTrackList *list, int *numerator,
int oaknode_tracklist_get_total_length(OakNodeTrackList list, int *numerator,
int *denominator)
{
if (!list) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l) {
return OAKNODE_E_INVALID;
}
return get_rational(list_impl(list)->get_total_length(), numerator,
denominator);
return get_rational(l->get_total_length(), numerator, denominator);
}
int oaknode_tracklist_get_array_size(OakNodeTrackList *list, int *size)
int oaknode_tracklist_get_array_size(OakNodeTrackList list, int *size)
{
if (!list || !size) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !size) {
return OAKNODE_E_INVALID;
}
*size = list_impl(list)->array_size();
*size = l->array_size();
return OAKNODE_OK;
}
int oaknode_tracklist_add_track(OakNodeTrackList *list, OakNodeTrack *track)
int oaknode_tracklist_add_track(OakNodeTrackList list, OakNodeTrack track)
{
if (!list || !track) {
olive::TrackList *l = to_native<olive::TrackList>(list);
olive::Track *t = to_native<olive::Track>(track);
if (!l || !t) {
return OAKNODE_E_INVALID;
}
olive::TrackList *l = list_impl(list);
olive::Track *t = impl(track);
olive::Sequence *sequence = l->parent();
if (!sequence) {
return OAKNODE_E_STATE;
@@ -537,16 +576,19 @@ int oaknode_tracklist_add_track(OakNodeTrackList *list, OakNodeTrack *track)
} catch (...) {
return OAKNODE_E_FAILED;
}
// The graph now owns the track; the caller's handle becomes a
// non-owning reference (its release no longer deletes)
mark_container_owned(track);
return OAKNODE_OK;
}
int oaknode_tracklist_remove_track(OakNodeTrackList *list, OakNodeTrack *track)
int oaknode_tracklist_remove_track(OakNodeTrackList list, OakNodeTrack track)
{
if (!list || !track) {
olive::TrackList *l = to_native<olive::TrackList>(list);
olive::Track *t = to_native<olive::Track>(track);
if (!l || !t) {
return OAKNODE_E_INVALID;
}
olive::TrackList *l = list_impl(list);
olive::Track *t = impl(track);
olive::Sequence *sequence = l->parent();
if (!sequence) {
return OAKNODE_E_STATE;
@@ -575,70 +617,78 @@ int oaknode_tracklist_remove_track(OakNodeTrackList *list, OakNodeTrack *track)
return OAKNODE_OK;
}
int oaknode_track_get_nearest_block_before_or_at(OakNodeTrack *track,
int numerator, int denominator, OakNodeBlock **out)
int oaknode_track_get_nearest_block_before_or_at(OakNodeTrack track,
int numerator, int denominator, OakNodeBlock *out)
{
olive::Track *t = impl(track);
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap_block(
t->nearest_block_before_or_at(olive::core::Rational(numerator, denominator)));
// Borrowed (empty when there is no such block)
*out = make_handle<OakNodeBlock>(
t->nearest_block_before_or_at(olive::core::Rational(numerator, denominator)),
false, &delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_track_get_nearest_block_after_or_at(OakNodeTrack *track,
int numerator, int denominator, OakNodeBlock **out)
int oaknode_track_get_nearest_block_after_or_at(OakNodeTrack track,
int numerator, int denominator, OakNodeBlock *out)
{
olive::Track *t = impl(track);
olive::Track *t = to_native<olive::Track>(track);
if (!t || !out) {
return OAKNODE_E_INVALID;
}
*out = wrap_block(
t->nearest_block_after_or_at(olive::core::Rational(numerator, denominator)));
*out = make_handle<OakNodeBlock>(
t->nearest_block_after_or_at(olive::core::Rational(numerator, denominator)),
false, &delete_as<olive::Block>);
return OAKNODE_OK;
}
int oaknode_tracklist_get_sequence(OakNodeTrackList *list,
OakNodeSequence **out)
int oaknode_tracklist_get_sequence(OakNodeTrackList list,
OakNodeSequence *out)
{
if (!list || !out) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !out) {
return OAKNODE_E_INVALID;
}
*out = reinterpret_cast<OakNodeSequence *>(list_impl(list)->parent());
// Borrowed; the sequence owns the list
*out = make_handle<OakNodeSequence>(l->parent(), false,
&delete_as<olive::Sequence>);
return OAKNODE_OK;
}
int oaknode_tracklist_get_track_input_id(OakNodeTrackList *list, char *buf,
int oaknode_tracklist_get_track_input_id(OakNodeTrackList list, char *buf,
int buf_size)
{
if (!list) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l) {
return OAKNODE_E_INVALID;
}
return oaknode_c_api::copy_string(list_impl(list)->track_input(), buf,
buf_size);
return oaknode_c_api::copy_string(l->track_input(), buf, buf_size);
}
int oaknode_tracklist_array_append(OakNodeTrackList *list)
int oaknode_tracklist_array_append(OakNodeTrackList list)
{
if (!list) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l) {
return OAKNODE_E_INVALID;
}
try {
list_impl(list)->array_append();
l->array_append();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
}
}
int oaknode_tracklist_array_remove_last(OakNodeTrackList *list)
int oaknode_tracklist_array_remove_last(OakNodeTrackList list)
{
if (!list) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l) {
return OAKNODE_E_INVALID;
}
try {
list_impl(list)->array_remove_last();
l->array_remove_last();
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
@@ -646,17 +696,19 @@ int oaknode_tracklist_array_remove_last(OakNodeTrackList *list)
}
int oaknode_tracklist_get_array_index_from_cache_index(
OakNodeTrackList *list, int cache_index, int *out_index)
OakNodeTrackList list, int cache_index, int *out_index)
{
if (!list || !out_index) {
olive::TrackList *l = to_native<olive::TrackList>(list);
if (!l || !out_index) {
return OAKNODE_E_INVALID;
}
*out_index =
list_impl(list)->get_array_index_from_cache_index(cache_index);
*out_index = l->get_array_index_from_cache_index(cache_index);
return OAKNODE_OK;
}
OakNodeNode *oaknode_track_as_node(OakNodeTrack *track)
OakNodeNode oaknode_track_as_node(OakNodeTrack track)
{
return reinterpret_cast<OakNodeNode *>(track);
// Borrowed; releasing the result never destroys the track
return make_handle<OakNodeNode>(to_native<olive::Track>(track), false,
&delete_as<olive::Node>);
}
+55 -59
View File
@@ -25,32 +25,22 @@
#include "traverser.h"
#include "valuedatabase.h"
#include "nodehandle.h"
#include "valueconvert.h"
struct OakNodeValueDatabase {
olive::NodeValueDatabase impl;
};
using oaknode_c_api::make_handle;
using oaknode_c_api::to_native;
namespace
{
inline olive::NodeTraverser *to_traverser(OakNodeTraverser *traverser)
{
return reinterpret_cast<olive::NodeTraverser *>(traverser);
}
inline olive::Node *to_node(OakNodeNode *node)
{
return reinterpret_cast<olive::Node *>(node);
}
/**
* @brief Find the table named `key`, or NULL when absent.
*/
const olive::NodeValueTable *find_table(const OakNodeValueDatabase *db,
const olive::NodeValueTable *find_table(const olive::NodeValueDatabase *db,
const char *key)
{
for (auto it = db->impl.cbegin(); it != db->impl.cend(); ++it) {
for (auto it = db->cbegin(); it != db->cend(); ++it) {
if (it->first == key) {
return &it->second;
}
@@ -60,39 +50,34 @@ const olive::NodeValueTable *find_table(const OakNodeValueDatabase *db,
}
OakNodeTraverser *oaknode_traverser_init(void)
OakNodeTraverser oaknode_traverser_init(void)
{
try {
olive::NodeTraverser *traverser = new (std::nothrow) olive::NodeTraverser();
if (traverser) {
oaknode_c_api::alive_inc();
}
return reinterpret_cast<OakNodeTraverser *>(traverser);
return make_handle<OakNodeTraverser>(
new (std::nothrow) olive::NodeTraverser(), true,
oaknode_c_api::delete_as<olive::NodeTraverser>);
} catch (...) {
return NULL;
return OakNodeTraverser{};
}
}
void oaknode_traverser_free(OakNodeTraverser *traverser)
{
if (!traverser) {
return;
}
try {
delete to_traverser(traverser);
oaknode_c_api::alive_dec();
oaknode_c_api::free_handle(traverser);
} catch (...) {
}
}
int oaknode_traverser_generate_database(OakNodeTraverser *traverser,
OakNodeNode *node, int64_t in_num,
int oaknode_traverser_generate_database(OakNodeTraverser traverser,
OakNodeNode node, int64_t in_num,
int64_t in_den, int64_t out_num,
int64_t out_den,
OakNodeValueDatabase **out_db)
OakNodeValueDatabase *out_db)
{
if (!traverser || !node || !out_db) {
olive::NodeTraverser *t = to_native<olive::NodeTraverser>(traverser);
olive::Node *n = to_native<olive::Node>(node);
if (!t || !n || !out_db) {
return OAKNODE_E_INVALID;
}
@@ -102,16 +87,19 @@ int oaknode_traverser_generate_database(OakNodeTraverser *traverser,
olive::core::Rational out(static_cast<int>(out_num),
static_cast<int>(out_den));
OakNodeValueDatabase *db = new (std::nothrow) OakNodeValueDatabase();
olive::NodeValueDatabase *db =
new (std::nothrow) olive::NodeValueDatabase();
if (!db) {
return OAKNODE_E_NOMEM;
}
db->impl = to_traverser(traverser)->generate_database(
to_node(node), olive::core::TimeRange(in, out));
*db = t->generate_database(n, olive::core::TimeRange(in, out));
*out_db = db;
oaknode_c_api::alive_inc();
*out_db = make_handle<OakNodeValueDatabase>(
db, true, oaknode_c_api::delete_as<olive::NodeValueDatabase>);
if (!out_db->ctx) {
return OAKNODE_E_NOMEM;
}
return OAKNODE_OK;
} catch (...) {
return OAKNODE_E_FAILED;
@@ -120,24 +108,24 @@ int oaknode_traverser_generate_database(OakNodeTraverser *traverser,
void oaknode_traverser_database_free(OakNodeValueDatabase *db)
{
if (!db) {
return;
try {
oaknode_c_api::free_handle(db);
} catch (...) {
}
delete db;
oaknode_c_api::alive_dec();
}
int oaknode_traverser_database_row_count(const OakNodeValueDatabase *db,
int oaknode_traverser_database_row_count(OakNodeValueDatabase db,
int *out_count)
{
if (!db || !out_count) {
const olive::NodeValueDatabase *impl =
to_native<olive::NodeValueDatabase>(db);
if (!impl || !out_count) {
return OAKNODE_E_INVALID;
}
try {
int count = 0;
for (auto it = db->impl.cbegin(); it != db->impl.cend(); ++it) {
for (auto it = impl->cbegin(); it != impl->cend(); ++it) {
count++;
}
*out_count = count;
@@ -147,10 +135,12 @@ int oaknode_traverser_database_row_count(const OakNodeValueDatabase *db,
}
}
int oaknode_traverser_database_row_key_at(const OakNodeValueDatabase *db,
int oaknode_traverser_database_row_key_at(OakNodeValueDatabase db,
int index, char *buf, int buf_size)
{
if (!db) {
const olive::NodeValueDatabase *impl =
to_native<olive::NodeValueDatabase>(db);
if (!impl) {
return OAKNODE_E_INVALID;
}
@@ -158,10 +148,10 @@ int oaknode_traverser_database_row_key_at(const OakNodeValueDatabase *db,
if (index < 0) {
return OAKNODE_E_NOT_FOUND;
}
auto it = db->impl.cbegin();
for (int i = 0; i < index && it != db->impl.cend(); i++, ++it) {
auto it = impl->cbegin();
for (int i = 0; i < index && it != impl->cend(); i++, ++it) {
}
if (it == db->impl.cend()) {
if (it == impl->cend()) {
return OAKNODE_E_NOT_FOUND;
}
return oaknode_c_api::copy_string(it->first, buf, buf_size);
@@ -170,16 +160,18 @@ int oaknode_traverser_database_row_key_at(const OakNodeValueDatabase *db,
}
}
int oaknode_traverser_database_row_value_count(const OakNodeValueDatabase *db,
int oaknode_traverser_database_row_value_count(OakNodeValueDatabase db,
const char *key,
int *out_count)
{
if (!db || !key || !out_count) {
const olive::NodeValueDatabase *impl =
to_native<olive::NodeValueDatabase>(db);
if (!impl || !key || !out_count) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeValueTable *table = find_table(db, key);
const olive::NodeValueTable *table = find_table(impl, key);
if (!table) {
return OAKNODE_E_NOT_FOUND;
}
@@ -190,16 +182,18 @@ int oaknode_traverser_database_row_value_count(const OakNodeValueDatabase *db,
}
}
int oaknode_traverser_database_value_at(const OakNodeValueDatabase *db,
int oaknode_traverser_database_value_at(OakNodeValueDatabase db,
const char *key, int index,
oaknode_value *out)
{
if (!db || !key || !out) {
const olive::NodeValueDatabase *impl =
to_native<olive::NodeValueDatabase>(db);
if (!impl || !key || !out) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeValueTable *table = find_table(db, key);
const olive::NodeValueTable *table = find_table(impl, key);
if (!table || index < 0 || index >= table->count()) {
return OAKNODE_E_NOT_FOUND;
}
@@ -212,16 +206,18 @@ int oaknode_traverser_database_value_at(const OakNodeValueDatabase *db,
}
}
int oaknode_traverser_database_value_string_at(const OakNodeValueDatabase *db,
int oaknode_traverser_database_value_string_at(OakNodeValueDatabase db,
const char *key, int index,
char *buf, int buf_size)
{
if (!db || !key) {
const olive::NodeValueDatabase *impl =
to_native<olive::NodeValueDatabase>(db);
if (!impl || !key) {
return OAKNODE_E_INVALID;
}
try {
const olive::NodeValueTable *table = find_table(db, key);
const olive::NodeValueTable *table = find_table(impl, key);
if (!table || index < 0 || index >= table->count()) {
return OAKNODE_E_NOT_FOUND;
}