- oakrender: renderer/texture/frame/cache/colorprocessor/ticket/copier
all become by-value {ctx, addref, release, abi_version} handles over a
generic box; retain() folds into addref; new
oakrender_cache_wrap_borrowed for native caches from oaknode
- oaktimeline: marker list/workarea borrowed handles become value
handles (non-owning boxes) with explicit free
- oaktask: OakTaskTask becomes a value handle; ownership still moves
to the manager on start (owns flag flips)
- consumers (timeline/task/codec sources) migrated; tests everywhere
updated; suites green: render 45, timeline 117, task 106, node 96,
common 193, codec 18, audio 36
201 lines
4.7 KiB
C++
201 lines
4.7 KiB
C++
/***
|
|
|
|
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
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 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/>.
|
|
|
|
***/
|
|
|
|
#include "timeline/workarea.h"
|
|
|
|
#include <new>
|
|
|
|
#include "../src/timelineundoworkarea.h"
|
|
#include "../src/timelineworkarea.h"
|
|
#include "../../undo/c_api/commandhandle.h"
|
|
#include "timelinehandle.h"
|
|
|
|
namespace
|
|
{
|
|
|
|
olive::TimelineWorkArea *impl(OakTimelineWorkArea h)
|
|
{
|
|
return oaktimeline_capi::to_native<olive::TimelineWorkArea>(h);
|
|
}
|
|
|
|
OakUndoCommand wrap_command(olive::UndoCommand *command)
|
|
{
|
|
if (!command) {
|
|
return OakUndoCommand{};
|
|
}
|
|
return oakundo_capi::make_command_handle(command, true);
|
|
}
|
|
|
|
olive::core::Rational rat(int64_t n, int64_t d)
|
|
{
|
|
return olive::core::Rational(int(n), int(d));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
OakTimelineWorkArea oaktimeline_workarea_of(OakNodeNode owner)
|
|
{
|
|
if (!owner.ctx) {
|
|
return OakTimelineWorkArea{};
|
|
}
|
|
|
|
OakNodeWorkArea *workarea = NULL;
|
|
if (oaknode_node_get_work_area(owner, &workarea) != OAKNODE_OK) {
|
|
return OakTimelineWorkArea{};
|
|
}
|
|
// Borrowed box: the work area stays owned by the viewer node.
|
|
return oaktimeline_capi::make_handle<OakTimelineWorkArea>(
|
|
reinterpret_cast<olive::TimelineWorkArea *>(workarea));
|
|
}
|
|
|
|
void oaktimeline_workarea_free(OakTimelineWorkArea *w)
|
|
{
|
|
oaktimeline_capi::free_handle(w);
|
|
}
|
|
|
|
int oaktimeline_workarea_get(OakTimelineWorkArea w, int *in_num,
|
|
int *in_den, int *out_num, int *out_den,
|
|
int *enabled)
|
|
{
|
|
if (!w.ctx) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
if (in_num) {
|
|
*in_num = impl(w)->in().numerator();
|
|
}
|
|
if (in_den) {
|
|
*in_den = impl(w)->in().denominator();
|
|
}
|
|
if (out_num) {
|
|
*out_num = impl(w)->out().numerator();
|
|
}
|
|
if (out_den) {
|
|
*out_den = impl(w)->out().denominator();
|
|
}
|
|
if (enabled) {
|
|
*enabled = impl(w)->enabled() ? 1 : 0;
|
|
}
|
|
return OAKTIMELINE_OK;
|
|
}
|
|
|
|
int oaktimeline_workarea_set_range(OakTimelineWorkArea w, int in_num,
|
|
int in_den, int out_num, int out_den)
|
|
{
|
|
if (!w.ctx) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
try {
|
|
impl(w)->set_range(
|
|
olive::core::TimeRange(rat(in_num, in_den), rat(out_num, out_den)));
|
|
return OAKTIMELINE_OK;
|
|
} catch (...) {
|
|
return OAKTIMELINE_E_FAILED;
|
|
}
|
|
}
|
|
|
|
OakUndoCommand oaktimeline_workarea_set_range_command(
|
|
OakTimelineWorkArea w, int in_num, int in_den, int out_num,
|
|
int out_den, int old_in_num, int old_in_den, int old_out_num,
|
|
int old_out_den)
|
|
{
|
|
if (!w.ctx) {
|
|
return OakUndoCommand{};
|
|
}
|
|
|
|
try {
|
|
olive::core::TimeRange range(rat(in_num, in_den), rat(out_num, out_den));
|
|
olive::core::TimeRange old_range(rat(old_in_num, old_in_den),
|
|
rat(old_out_num, old_out_den));
|
|
return wrap_command(
|
|
new olive::WorkareaSetRangeCommand(impl(w), range, old_range));
|
|
} catch (...) {
|
|
return OakUndoCommand{};
|
|
}
|
|
}
|
|
|
|
OakUndoCommand oaktimeline_workarea_set_enabled_command(
|
|
OakTimelineWorkArea w, int enabled)
|
|
{
|
|
if (!w.ctx) {
|
|
return OakUndoCommand{};
|
|
}
|
|
|
|
try {
|
|
return wrap_command(
|
|
new olive::WorkareaSetEnabledCommand(impl(w), enabled != 0));
|
|
} catch (...) {
|
|
return OakUndoCommand{};
|
|
}
|
|
}
|
|
|
|
int oaktimeline_workarea_reset(int *in_num, int *in_den, int *out_num,
|
|
int *out_den)
|
|
{
|
|
if (!in_num || !in_den || !out_num || !out_den) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
*in_num = olive::TimelineWorkArea::k_reset_in.numerator();
|
|
*in_den = olive::TimelineWorkArea::k_reset_in.denominator();
|
|
*out_num = olive::TimelineWorkArea::k_reset_out.numerator();
|
|
*out_den = olive::TimelineWorkArea::k_reset_out.denominator();
|
|
return OAKTIMELINE_OK;
|
|
}
|
|
|
|
int oaktimeline_workarea_load(OakTimelineWorkArea w, OakXmlReader reader)
|
|
{
|
|
if (!w.ctx || !reader.ctx) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
olive::XmlStreamReader *native = oakcommon_xml_reader_get_native(reader);
|
|
if (!native) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
try {
|
|
return impl(w)->load(native) ? OAKTIMELINE_OK : OAKTIMELINE_E_FAILED;
|
|
} catch (...) {
|
|
return OAKTIMELINE_E_FAILED;
|
|
}
|
|
}
|
|
|
|
int oaktimeline_workarea_save(OakTimelineWorkArea w,
|
|
OakXmlWriter writer)
|
|
{
|
|
if (!w.ctx || !writer.ctx) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
olive::XmlStreamWriter *native = oakcommon_xml_writer_get_native(writer);
|
|
if (!native) {
|
|
return OAKTIMELINE_E_INVALID;
|
|
}
|
|
|
|
try {
|
|
impl(w)->save(native);
|
|
return OAKTIMELINE_OK;
|
|
} catch (...) {
|
|
return OAKTIMELINE_E_FAILED;
|
|
}
|
|
}
|