app: migrate all engine access to the C ABI facade (nm U _ZN5olive = 0)

Every app module now reaches liboakengine exclusively through
oakengine_* C calls, EngineEventBridge subscriptions and app-side
handle headers (cliphandle/keyframehandle/nodevaluehandle/oakvaluehelper).
Direct C++ command construction, engine signal connect()s, and engine
type usage in MOC-visible signatures are gone: 557 -> 0 undefined
olive:: symbols in oak-editor.
This commit is contained in:
2026-07-26 22:43:21 +08:00
parent f95590e924
commit 0aa5879f35
256 changed files with 12357 additions and 4044 deletions
+146 -70
View File
@@ -25,15 +25,20 @@
#include "common/autoscroll.h"
#include "common/range.h"
#include "config/config.h"
#include "common/configwrapper.h"
#include "core.h"
#include "engineeventbridge.h"
#include "common/current.h"
#include "dialog/markerproperties/markerpropertiesdialog.h"
#include "node/project/sequence/sequence.h"
#include "oakengine/timeline.h"
#include "timeline/timelineundoworkarea.h"
#include "oakengine/viewer.h"
#include "oakengine/timeline.h"
#include "oakengine/undo.h"
#include "widget/timeruler/timeruler.h"
#include "widget/timelinewidget/cliphandle.h"
#include "widget/viewer/vieweroutpututils.h"
namespace olive
{
@@ -42,6 +47,7 @@ TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible,
QWidget *parent)
: TimelineScaledWidget(parent)
, viewer_node_(nullptr)
, bridge_(new EngineEventBridge(this))
, auto_max_scrollbar_(false)
, toggle_show_all_(false)
, auto_set_timebase_(true)
@@ -95,33 +101,28 @@ void TimeBasedWidget::connect_viewer_node(ViewerOutput *node)
// Set viewer node
ViewerOutput *old = viewer_node_.data();
viewer_node_ = node;
// Disconnect old bridge subscriptions and connections
disconnect(bridge_, nullptr, this, nullptr);
bridge_->unsubscribe_all();
if (viewer_node_) {
oak_video_params vp;
oakengine_viewer_get_video_params(
reinterpret_cast<OakEngineNode *>(viewer_node_.data()), 0, &vp);
// We still need Current class - keep using it for now
Current::getInstance().setCurrentVideoParams(
viewer_node_->get_video_params());
viewer_output_video_params(viewer_node_));
Current::getInstance().setCurrentAudioParams(
viewer_node_->get_audio_params());
viewer_output_audio_params(viewer_node_));
} else {
Current::getInstance().setCurrentVideoParams(VideoParams());
Current::getInstance().setCurrentVideoParams(empty_video_params());
Current::getInstance().setCurrentAudioParams(AudioParams());
}
if (old) {
// Call potential derivative functions for disconnecting the viewer node
DisconnectNodeEvent(old);
// Disconnect length changed signal
disconnect(old, &ViewerOutput::length_changed, this,
&TimeBasedWidget::update_maximum_scroll);
disconnect(old, &ViewerOutput::removed_from_graph, this,
&TimeBasedWidget::connected_node_removed_from_graph);
disconnect(old, &ViewerOutput::playhead_changed, this,
&TimeBasedWidget::playhead_time_changed);
// Disconnect rate change signals if they were connected
disconnect(old, &ViewerOutput::frame_rate_changed, this,
&TimeBasedWidget::auto_update_timebase);
disconnect(old, &ViewerOutput::sample_rate_changed, this,
&TimeBasedWidget::auto_update_timebase);
// Reset timebase to null
SetTimebase(Rational());
@@ -137,13 +138,28 @@ void TimeBasedWidget::connect_viewer_node(ViewerOutput *node)
ConnectedNodeChangeEvent(viewer_node_.data());
if (viewer_node_) {
// Connect length changed signal
connect(viewer_node_.data(), &ViewerOutput::length_changed, this,
&TimeBasedWidget::update_maximum_scroll);
connect(viewer_node_.data(), &ViewerOutput::removed_from_graph, this,
&TimeBasedWidget::connected_node_removed_from_graph);
connect(viewer_node_.data(), &ViewerOutput::playhead_changed, this,
&TimeBasedWidget::playhead_time_changed);
OakEngineNode *handle =
reinterpret_cast<OakEngineNode *>(viewer_node_.data());
// Subscribe to viewer events via bridge
bridge_->subscribe(handle, OAKENGINE_EVENT_VIEWER_LENGTH_CHANGED);
bridge_->subscribe(handle, OAKENGINE_EVENT_VIEWER_PLAYHEAD_CHANGED);
bridge_->subscribe(handle, OAKENGINE_EVENT_NODE_REMOVED_FROM_GRAPH);
connect(bridge_, &EngineEventBridge::viewer_length_changed, this,
[this](OakEngineNode *, qint64, qint64) {
update_maximum_scroll();
});
connect(bridge_, &EngineEventBridge::viewer_playhead_changed, this,
[this](OakEngineNode *, qint64 num, qint64 den) {
playhead_time_changed(Rational(num, den));
});
// Node removed from graph - use the bridge signal
connect(bridge_, &EngineEventBridge::node_removed_from_graph, this,
[this](OakEngineNode *, OakEngineNode *) {
connected_node_removed_from_graph();
});
// Connect ruler and scrollbar to timeline points
connect_work_area(viewer_node_->get_work_area());
@@ -152,10 +168,16 @@ void TimeBasedWidget::connect_viewer_node(ViewerOutput *node)
// If we're setting the timebase, set it automatically based on the video and audio parameters
if (auto_set_timebase_) {
auto_update_timebase();
connect(viewer_node_.data(), &ViewerOutput::frame_rate_changed, this,
&TimeBasedWidget::auto_update_timebase);
connect(viewer_node_.data(), &ViewerOutput::sample_rate_changed, this,
&TimeBasedWidget::auto_update_timebase);
bridge_->subscribe(handle, OAKENGINE_EVENT_VIEWER_FRAME_RATE_CHANGED);
bridge_->subscribe(handle, OAKENGINE_EVENT_VIEWER_SAMPLE_RATE_CHANGED);
connect(bridge_, &EngineEventBridge::viewer_frame_rate_changed, this,
[this](OakEngineNode *, qint64, qint64) {
auto_update_timebase();
});
connect(bridge_, &EngineEventBridge::viewer_sample_rate_changed, this,
[this](OakEngineNode *, int) {
auto_update_timebase();
});
}
// Call derivatives
@@ -164,7 +186,8 @@ void TimeBasedWidget::connect_viewer_node(ViewerOutput *node)
update_maximum_scroll();
emit connected_node_changed(old, node);
emit connected_node_changed(reinterpret_cast<OakEngineNode *>(old),
reinterpret_cast<OakEngineNode *>(node));
}
void TimeBasedWidget::connect_work_area(TimelineWorkArea *workarea)
@@ -287,13 +310,13 @@ void TimeBasedWidget::auto_update_timebase()
return;
}
Rational video_tb =
viewer_node_->get_video_params().frame_rate_as_time_base();
viewer_output_video_params(viewer_node_).frame_rate_as_time_base();
if (!video_tb.isNull()) {
SetTimebase(video_tb);
} else {
Rational audio_tb =
viewer_node_->get_audio_params().sample_rate_as_time_base();
viewer_output_audio_params(viewer_node_).sample_rate_as_time_base();
if (!audio_tb.isNull()) {
SetTimebase(audio_tb);
@@ -489,7 +512,9 @@ void TimeBasedWidget::go_to_prev_cut()
closest_cut = qMax(closest_cut, this_track_closest_cut);
}
get_connected_node()->set_playhead(closest_cut);
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(get_connected_node()),
closest_cut.numerator(), closest_cut.denominator());
}
void TimeBasedWidget::go_to_next_cut()
@@ -521,14 +546,17 @@ void TimeBasedWidget::go_to_next_cut()
}
if (closest_cut < RATIONAL_MAX) {
get_connected_node()->set_playhead(closest_cut);
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(get_connected_node()),
closest_cut.numerator(), closest_cut.denominator());
}
}
void TimeBasedWidget::go_to_start()
{
if (viewer_node_) {
viewer_node_->set_playhead(0);
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(viewer_node_.data()), 0, 1);
}
}
@@ -542,7 +570,12 @@ void TimeBasedWidget::prev_frame()
// Catch rounding error, assume this time is snapped and just subtract a timebase
proposed_time -= timebase();
}
viewer_node_->set_playhead(qMax(Rational(0), proposed_time));
{
Rational _pt = qMax(Rational(0), proposed_time);
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(viewer_node_.data()),
_pt.numerator(), _pt.denominator());
}
}
}
@@ -556,14 +589,19 @@ void TimeBasedWidget::next_frame()
// Catch rounding error, assume this time is snapped and just add a timebase
proposed_time += timebase();
}
viewer_node_->set_playhead(proposed_time);
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(viewer_node_.data()),
proposed_time.numerator(), proposed_time.denominator());
}
}
void TimeBasedWidget::go_to_end()
{
if (viewer_node_) {
viewer_node_->set_playhead(viewer_node_->get_length());
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(viewer_node_.data()),
viewer_node_->get_length().numerator(),
viewer_node_->get_length().denominator());
}
}
@@ -587,13 +625,13 @@ void TimeBasedWidget::set_point(Timeline::MovementMode m, const Rational &time)
return;
}
MultiUndoCommand *command = new MultiUndoCommand();
void *command = oakengine_undo_command_create_multi();
TimelineWorkArea *points = viewer_node_->get_work_area();
// Enable workarea if it isn't already enabled
if (!points->enabled()) {
command->add_child(new WorkareaSetEnabledCommand(
viewer_node_->project(), points, true));
oakengine_workarea_set_enabled_undoable(
reinterpret_cast<OakEngineWorkarea *>(points), 1, command);
}
// Determine our new range
@@ -603,7 +641,7 @@ void TimeBasedWidget::set_point(Timeline::MovementMode m, const Rational &time)
in_point = time;
if (!points->enabled() || points->out() < in_point) {
out_point = TimelineWorkArea::k_reset_out;
out_point = RATIONAL_MAX;
} else {
out_point = points->out();
}
@@ -611,17 +649,28 @@ void TimeBasedWidget::set_point(Timeline::MovementMode m, const Rational &time)
out_point = time;
if (!points->enabled() || points->in() > out_point) {
in_point = TimelineWorkArea::k_reset_in;
in_point = Rational(0, 1);
} else {
in_point = points->in();
}
}
// Set workarea
command->add_child(
new WorkareaSetRangeCommand(points, TimeRange(in_point, out_point)));
{
int64_t old_in_num, old_in_den, old_out_num, old_out_den;
int old_enabled;
oakengine_workarea_get(
reinterpret_cast<OakEngineWorkarea *>(points),
&old_in_num, &old_in_den, &old_out_num, &old_out_den,
&old_enabled);
oakengine_workarea_set_range_undoable(
reinterpret_cast<OakEngineWorkarea *>(points),
in_point.numerator(), in_point.denominator(),
out_point.numerator(), out_point.denominator(),
old_in_num, old_in_den, old_out_num, old_out_den, command);
}
Core::instance()->undo_stack()->push(command, tr("Set In/Out Point"));
oakengine_undo_push(command, tr("Set In/Out Point").toUtf8().constData());
}
void TimeBasedWidget::reset_point(Timeline::MovementMode m)
@@ -639,13 +688,27 @@ void TimeBasedWidget::reset_point(Timeline::MovementMode m)
TimeRange r = points->range();
if (m == Timeline::k_trim_in) {
r.set_in(TimelineWorkArea::k_reset_in);
r.set_in(Rational(0, 1));
} else {
r.set_out(TimelineWorkArea::k_reset_out);
r.set_out(RATIONAL_MAX);
}
Core::instance()->undo_stack()->push(new WorkareaSetRangeCommand(points, r),
tr("Reset In/Out Points"));
{
auto reset_cmd = oakengine_undo_command_create_multi();
int64_t old_in_num, old_in_den, old_out_num, old_out_den;
int old_enabled;
oakengine_workarea_get(
reinterpret_cast<OakEngineWorkarea *>(points),
&old_in_num, &old_in_den, &old_out_num, &old_out_den,
&old_enabled);
oakengine_workarea_set_range_undoable(
reinterpret_cast<OakEngineWorkarea *>(points),
r.in().numerator(), r.in().denominator(),
r.out().numerator(), r.out().denominator(),
old_in_num, old_in_den, old_out_num, old_out_den, reset_cmd);
oakengine_undo_push(reset_cmd,
tr("Reset In/Out Points").toUtf8().constData());
}
}
void TimeBasedWidget::page_scroll_internal(QScrollBar *bar, int maximum,
@@ -717,10 +780,15 @@ void TimeBasedWidget::clear_in_out_points()
return;
}
Core::instance()->undo_stack()->push(
new WorkareaSetEnabledCommand(get_connected_node()->project(),
get_connected_node()->get_work_area(), false),
tr("Cleared In/Out Points"));
{
auto clear_cmd = oakengine_undo_command_create_multi();
oakengine_workarea_set_enabled_undoable(
reinterpret_cast<OakEngineWorkarea *>(
get_connected_node()->get_work_area()),
0, clear_cmd);
oakengine_undo_push(clear_cmd,
tr("Cleared In/Out Points").toUtf8().constData());
}
}
void TimeBasedWidget::set_marker()
@@ -748,16 +816,20 @@ void TimeBasedWidget::set_marker()
color = OAK_CONFIG("MarkerColor").toInt();
}
TimelineMarker *marker = new TimelineMarker(
color, TimeRange(get_connected_node()->get_playhead(),
get_connected_node()->get_playhead()));
const Rational playhead = get_connected_node()->get_playhead();
OakEngineMarker *marker = oakengine_marker_create(
color, playhead.numerator(), playhead.denominator(),
playhead.numerator(), playhead.denominator(), "");
TimelineMarker *cpp_marker =
reinterpret_cast<TimelineMarker *>(marker);
bool edited_in_dialog = false;
if (OAK_CONFIG("SetNameWithMarker").toBool()) {
MarkerPropertiesDialog mpd({ marker }, timebase(), this);
MarkerPropertiesDialog mpd({ cpp_marker }, timebase(), this);
if (mpd.exec() != QDialog::Accepted) {
delete marker;
oakengine_marker_free(marker);
marker = nullptr;
cpp_marker = nullptr;
} else {
edited_in_dialog = true;
}
@@ -767,19 +839,19 @@ void TimeBasedWidget::set_marker()
if (edited_in_dialog) {
// The dialog pushed undo commands referencing this exact
// marker object, so it must be the one added to the list.
Core::instance()->undo_stack()->push(
new MarkerAddCommand(markers, marker), tr("Added Marker"));
oakengine_marker_list_add_existing(
reinterpret_cast<OakEngineMarkerList *>(markers), marker);
} else {
// Pristine marker: add through the liboakengine C ABI
// facade (one undoable command) and drop the temporary.
oakengine_sequence_marker_add_ex(
reinterpret_cast<OakEngineSequence *>(
get_connected_node()),
Timecode::time_to_timestamp(marker->time().in(),
Timecode::time_to_timestamp(cpp_marker->time().in(),
timebase(),
Timecode::k_round),
"", marker->color());
delete marker;
"", cpp_marker->color());
oakengine_marker_free(marker);
}
}
}
@@ -820,8 +892,10 @@ void TimeBasedWidget::go_to_in()
{
if (get_connected_node()) {
if (get_connected_node()->get_work_area()->enabled()) {
get_connected_node()->set_playhead(
get_connected_node()->get_work_area()->in());
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(get_connected_node()),
get_connected_node()->get_work_area()->in().numerator(),
get_connected_node()->get_work_area()->in().denominator());
} else {
go_to_start();
}
@@ -832,8 +906,10 @@ void TimeBasedWidget::go_to_out()
{
if (get_connected_node()) {
if (get_connected_node()->get_work_area()->enabled()) {
get_connected_node()->set_playhead(
get_connected_node()->get_work_area()->out());
oakengine_viewer_set_playhead(
reinterpret_cast<OakEngineNode *>(get_connected_node()),
get_connected_node()->get_work_area()->out().numerator(),
get_connected_node()->get_work_area()->out().denominator());
} else {
go_to_end();
}
@@ -913,7 +989,7 @@ bool TimeBasedWidget::snap_point(const std::vector<Rational> &start_times,
TimelineMarker *marker = *jt;
TimeRange marker_range =
marker->time() + clip->in() - clip->media_in();
marker->time() + clip->in() - clip_media_in(clip);
qreal marker_in_screen =
time_to_scene(marker_range.in());