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:
+148
-122
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
@@ -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(¶ms);
|
||||
} 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
@@ -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
@@ -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>);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user