R8: finish app/ pure C ABI migration (P3-P9) and make OTIO required

- app/ no longer includes engine C++ headers nor holds engine C++ types:
  engine access goes through the oakengine C ABI plus C++ wrappers
  (oakutil/oaknode.h, oakutil/oakvideo.h) and app-local mirror types
  (tooltypes, trackreferencehandle, timelinecommonapp, keyframetypes,
  subtitleapp, serializedlayoutinfoapp, nodevaluehandle, sliderdisplaytypeapp)
- engine: new C ABI functions for block/track/clip/transition navigation
  and predicates, links, caches, waveform/playback, disk folder,
  sequence_track_list, node_free, footage_is_valid, block_get_track,
  get_brush; loadotio/saveotio ported to the current engine API
- OTIO is now a required dependency: CI and CD build it on every
  platform, FindOpenTimelineIO fixed for OTIO 0.16/0.19 (the old deps
  include requirement silently disabled OTIO everywhere), runtime
  libraries are bundled into packages and copied next to macOS binaries
  (oak_copy_otio_runtime)
- fix ProjectViewModel drag&drop mime read/write size mismatch (segfault)
- unify color label naming (k_olive -> "Oak") in the app-side mirror
- docs: OTIO required, FFmpeg minimum corrected to 6.0 (en/zh)
- gtest suite: 1925 passed, 0 failed
This commit is contained in:
2026-07-31 22:46:52 +08:00
parent 18aed979a2
commit 66d761b4b7
285 changed files with 13261 additions and 5895 deletions
@@ -30,6 +30,7 @@
#include "core.h"
#include "oakengine/timeline.h"
#include "widget/timeruler/markerhandle.h"
namespace olive
{
@@ -37,7 +38,7 @@ namespace olive
#define super QDialog
MarkerPropertiesDialog::MarkerPropertiesDialog(
const std::vector<TimelineMarker *> &markers, const Rational &timebase,
const std::vector<OakEngineMarker *> &markers, const Rational &timebase,
QWidget *parent)
: super(parent)
, markers_(markers)
@@ -66,10 +67,11 @@ MarkerPropertiesDialog::MarkerPropertiesDialog(
}
if (markers.size() == 1) {
in_slider_->set_value(markers.front()->time().in());
const TimeRange marker_range = marker_time(markers.front());
in_slider_->set_value(marker_range.in());
in_slider_->set_display_type(slider::k_time);
in_slider_->set_timebase(timebase);
out_slider_->set_value(markers.front()->time().out());
out_slider_->set_value(marker_range.out());
out_slider_->set_display_type(slider::k_time);
out_slider_->set_timebase(timebase);
} else {
@@ -89,9 +91,9 @@ MarkerPropertiesDialog::MarkerPropertiesDialog(
color_menu_ = new ColorCodingComboBox();
layout->addWidget(color_menu_, row, 1);
color_menu_->set_color(markers.front()->color());
color_menu_->set_color(marker_color(markers.front()));
for (size_t i = 1; i < markers.size(); i++) {
if (markers.at(i)->color() != color_menu_->get_selected_color()) {
if (marker_color(markers.at(i)) != color_menu_->get_selected_color()) {
color_menu_->set_color(-1);
break;
}
@@ -107,9 +109,9 @@ MarkerPropertiesDialog::MarkerPropertiesDialog(
layout->addWidget(label_edit_, row, 1);
// Determine what the startup label text should be
label_edit_->setText(markers.front()->name());
label_edit_->setText(marker_name(markers.front()));
for (size_t i = 1; i < markers.size(); i++) {
if (markers.at(i)->name() != label_edit_->text()) {
if (marker_name(markers.at(i)) != label_edit_->text()) {
label_edit_->clear();
label_edit_->setPlaceholderText(tr("(multiple)"));
break;
@@ -143,8 +145,8 @@ void MarkerPropertiesDialog::accept()
// Batch-set properties via facade (one undoable command)
{
QVector<OakEngineMarker *> oak_markers;
foreach (TimelineMarker *m, markers_) {
oak_markers.append(reinterpret_cast<OakEngineMarker *>(m));
foreach (OakEngineMarker *m, markers_) {
oak_markers.append(m);
}
int color = color_menu_->get_selected_color();
QByteArray name_ba;