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:
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "multicamdisplay.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "oakengine/display.h"
|
||||
#include "oakengine/node.h"
|
||||
|
||||
@@ -51,7 +53,7 @@ void MulticamDisplay::on_paint()
|
||||
int rows, cols;
|
||||
oakengine_multicam_get_rows_and_columns(
|
||||
oakengine_multicam_get_source_count(
|
||||
reinterpret_cast<OakEngineNode *>(node_)),
|
||||
node_),
|
||||
&rows, &cols);
|
||||
|
||||
int multi = std::max(rows, cols);
|
||||
@@ -60,7 +62,7 @@ void MulticamDisplay::on_paint()
|
||||
|
||||
int col, row;
|
||||
int current_source = oakengine_multicam_get_current_source(
|
||||
reinterpret_cast<OakEngineNode *>(node_));
|
||||
node_);
|
||||
oakengine_multicam_index_to_row_cols(
|
||||
current_source, rows, cols, &row, &col);
|
||||
|
||||
@@ -211,7 +213,7 @@ QString MulticamDisplay::generate_shader_code(int rows, int cols)
|
||||
return shader.join('\n');
|
||||
}
|
||||
|
||||
void MulticamDisplay::set_multicam_node(MultiCamNode *n)
|
||||
void MulticamDisplay::set_multicam_node(OakEngineNode *n)
|
||||
{
|
||||
node_ = n;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#ifndef OAK_MULTICAMDISPLAY_H
|
||||
#define OAK_MULTICAMDISPLAY_H
|
||||
|
||||
#include "node/input/multicam/multicamnode.h"
|
||||
#include "widget/viewer/viewerdisplay.h"
|
||||
|
||||
namespace olive
|
||||
@@ -33,7 +32,7 @@ class MulticamDisplay : public ViewerDisplayWidget {
|
||||
public:
|
||||
explicit MulticamDisplay(QWidget *parent = nullptr);
|
||||
|
||||
void set_multicam_node(MultiCamNode *n);
|
||||
void set_multicam_node(OakEngineNode *n);
|
||||
|
||||
protected:
|
||||
virtual void on_paint() override;
|
||||
@@ -45,7 +44,7 @@ protected:
|
||||
private:
|
||||
static QString generate_shader_code(int rows, int cols);
|
||||
|
||||
MultiCamNode *node_;
|
||||
OakEngineNode *node_;
|
||||
|
||||
void *shader_;
|
||||
int rows_;
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "oakengine/viewer.h"
|
||||
#include "oakengine/timeline.h"
|
||||
#include "oakengine/undo.h"
|
||||
#include "timeline/timelineundosplit.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
namespace olive
|
||||
@@ -71,8 +70,9 @@ MulticamWidget::MulticamWidget(QWidget *parent)
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::set_multicam_node_internal(ViewerOutput *viewer,
|
||||
MultiCamNode *n, ClipBlock *clip)
|
||||
void MulticamWidget::set_multicam_node_internal(OakEngineNode *viewer,
|
||||
OakEngineNode *n,
|
||||
OakEngineBlock *clip)
|
||||
{
|
||||
if (get_connected_node() != viewer) {
|
||||
connect_viewer_node(viewer);
|
||||
@@ -88,11 +88,12 @@ void MulticamWidget::set_multicam_node_internal(ViewerOutput *viewer,
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::set_multicam_node(ViewerOutput *viewer, MultiCamNode *n,
|
||||
ClipBlock *clip, const Rational &time)
|
||||
void MulticamWidget::set_multicam_node(OakEngineNode *viewer,
|
||||
OakEngineNode *n, OakEngineBlock *clip,
|
||||
const Rational &time)
|
||||
{
|
||||
if (time.isNaN() || !get_connected_node() ||
|
||||
time == get_connected_node()->get_playhead()) {
|
||||
time == viewer_output_playhead(get_connected_node())) {
|
||||
set_multicam_node_internal(viewer, n, clip);
|
||||
play_queue_.clear();
|
||||
} else {
|
||||
@@ -101,10 +102,8 @@ void MulticamWidget::set_multicam_node(ViewerOutput *viewer, MultiCamNode *n,
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
void MulticamWidget::ConnectNodeEvent(OakEngineNode *handle)
|
||||
{
|
||||
OakEngineNode *handle = reinterpret_cast<OakEngineNode *>(n);
|
||||
|
||||
viewer_sub_ = oakengine_event_subscribe(
|
||||
handle, OAKENGINE_EVENT_VIEWER_SIZE_CHANGED,
|
||||
[](const oakengine_event *event, void *userdata) {
|
||||
@@ -128,7 +127,7 @@ void MulticamWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
Rational(vp.pixel_aspect_num, vp.pixel_aspect_den));
|
||||
}
|
||||
|
||||
void MulticamWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
void MulticamWidget::DisconnectNodeEvent(OakEngineNode *n)
|
||||
{
|
||||
if (viewer_sub_ > 0) {
|
||||
oakengine_event_unsubscribe(viewer_sub_);
|
||||
@@ -159,37 +158,53 @@ void MulticamWidget::Switch(int source, bool split_clip)
|
||||
return;
|
||||
}
|
||||
|
||||
MultiCamNode *cam = node_;
|
||||
ClipBlock *clip = clip_;
|
||||
OakEngineNode *cam = node_;
|
||||
OakEngineBlock *clip = clip_;
|
||||
|
||||
const QByteArray undo_name = tr("Switched Multi-Camera Source").toUtf8();
|
||||
oakengine_undo_group_begin(undo_name.constData());
|
||||
|
||||
// Block range via the C ABI (clip is an opaque block handle; the facade
|
||||
// returns rational seconds, comparable to get_playhead()).
|
||||
int clip_in_num = 0, clip_in_den = 1, clip_out_num = 0, clip_out_den = 1;
|
||||
if (clip_) {
|
||||
oakengine_block_get_in_rational(
|
||||
reinterpret_cast<OakEngineNode *>(clip_), &clip_in_num,
|
||||
&clip_in_den);
|
||||
oakengine_block_get_out_rational(
|
||||
reinterpret_cast<OakEngineNode *>(clip_), &clip_out_num,
|
||||
&clip_out_den);
|
||||
}
|
||||
|
||||
if (clip_ && split_clip &&
|
||||
clip_->in() < get_connected_node()->get_playhead() &&
|
||||
clip_->out() > get_connected_node()->get_playhead()) {
|
||||
QVector<Block *> blocks;
|
||||
Rational(clip_in_num, clip_in_den) <
|
||||
viewer_output_playhead(get_connected_node()) &&
|
||||
Rational(clip_out_num, clip_out_den) >
|
||||
viewer_output_playhead(get_connected_node())) {
|
||||
QVector<OakEngineBlock *> blocks;
|
||||
|
||||
blocks.append(clip_);
|
||||
blocks.append(clip_->block_links());
|
||||
// ClipBlock::block_links() via the C ABI link enumeration
|
||||
const int link_count = oakengine_block_link_count(clip_);
|
||||
for (int i = 0; i < link_count; i++) {
|
||||
blocks.append(oakengine_block_link_at(clip_, i));
|
||||
}
|
||||
|
||||
int split_tbn = 0, split_tbd = 0;
|
||||
oakengine_node_frame_time_base(
|
||||
reinterpret_cast<OakEngineNode *>(get_connected_node()),
|
||||
oakengine_node_frame_time_base(get_connected_node(),
|
||||
&split_tbn, &split_tbd);
|
||||
void *split = oakengine_block_split_preserving_links_command(
|
||||
reinterpret_cast<void *const *>(blocks.data()), blocks.size(),
|
||||
olive::core::Timecode::time_to_timestamp(
|
||||
get_connected_node()->get_playhead(),
|
||||
viewer_output_playhead(get_connected_node()),
|
||||
olive::Rational(split_tbn, split_tbd),
|
||||
olive::core::Timecode::k_round));
|
||||
oakengine_undo_push(split, undo_name.constData());
|
||||
clip = reinterpret_cast<ClipBlock *>(
|
||||
oakengine_block_split_get_split(
|
||||
split, reinterpret_cast<void *>(clip_), 0));
|
||||
clip = reinterpret_cast<OakEngineBlock *>(
|
||||
oakengine_block_split_get_split(split, clip_, 0));
|
||||
|
||||
cam = reinterpret_cast<MultiCamNode *>(
|
||||
oakengine_clip_find_multicam(reinterpret_cast<OakEngineNode *>(clip)));
|
||||
cam = oakengine_clip_find_multicam(
|
||||
reinterpret_cast<OakEngineNode *>(clip));
|
||||
}
|
||||
|
||||
oak_node_value val;
|
||||
@@ -199,18 +214,19 @@ void MulticamWidget::Switch(int source, bool split_clip)
|
||||
|
||||
if (cam) {
|
||||
oakengine_node_set_input(
|
||||
reinterpret_cast<OakEngineNode *>(cam),
|
||||
oakengine_multicam_input_current(), &val);
|
||||
cam, oakengine_multicam_input_current(), &val);
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
for (Block *link : clip->block_links()) {
|
||||
if (ClipBlock *clink = dynamic_cast<ClipBlock *>(link)) {
|
||||
if (MultiCamNode *mlink = reinterpret_cast<MultiCamNode *>(
|
||||
oakengine_clip_find_multicam(reinterpret_cast<OakEngineNode *>(clink)))) {
|
||||
const int link_count = oakengine_block_link_count(clip);
|
||||
for (int i = 0; i < link_count; i++) {
|
||||
OakEngineNode *link = reinterpret_cast<OakEngineNode *>(
|
||||
oakengine_block_link_at(clip, i));
|
||||
if (oakengine_node_is_clip(link)) {
|
||||
if (OakEngineNode *mlink =
|
||||
oakengine_clip_find_multicam(link)) {
|
||||
oakengine_node_set_input(
|
||||
reinterpret_cast<OakEngineNode *>(mlink),
|
||||
oakengine_multicam_input_current(), &val);
|
||||
mlink, oakengine_multicam_input_current(), &val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,8 +256,7 @@ void MulticamWidget::display_clicked(const QPoint &p)
|
||||
|
||||
int rows, cols;
|
||||
oakengine_multicam_get_rows_and_columns(
|
||||
oakengine_multicam_get_source_count(
|
||||
reinterpret_cast<OakEngineNode *>(node_)),
|
||||
oakengine_multicam_get_source_count(node_),
|
||||
&rows, &cols);
|
||||
|
||||
int multi = std::max(cols, rows);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "multicamdisplay.h"
|
||||
#include <cstdint>
|
||||
|
||||
#include "node/input/multicam/multicamnode.h"
|
||||
#include "oakengine/timeline.h"
|
||||
#include "widget/viewer/viewer.h"
|
||||
|
||||
namespace olive
|
||||
@@ -41,20 +41,20 @@ public:
|
||||
return display_;
|
||||
}
|
||||
|
||||
void set_multicam_node(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip,
|
||||
const Rational &time);
|
||||
void set_multicam_node(OakEngineNode *viewer, OakEngineNode *n,
|
||||
OakEngineBlock *clip, const Rational &time);
|
||||
|
||||
protected:
|
||||
virtual void ConnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void ConnectNodeEvent(OakEngineNode *n) override;
|
||||
virtual void DisconnectNodeEvent(OakEngineNode *n) override;
|
||||
virtual void TimeChangedEvent(const Rational &t) override;
|
||||
|
||||
signals:
|
||||
void switched();
|
||||
|
||||
private:
|
||||
void set_multicam_node_internal(ViewerOutput *viewer, MultiCamNode *n,
|
||||
ClipBlock *clip);
|
||||
void set_multicam_node_internal(OakEngineNode *viewer, OakEngineNode *n,
|
||||
OakEngineBlock *clip);
|
||||
|
||||
void Switch(int source, bool split_clip);
|
||||
|
||||
@@ -65,15 +65,15 @@ private:
|
||||
|
||||
MulticamDisplay *display_;
|
||||
|
||||
MultiCamNode *node_;
|
||||
OakEngineNode *node_;
|
||||
|
||||
ClipBlock *clip_;
|
||||
OakEngineBlock *clip_;
|
||||
|
||||
struct MulticamNodeQueue {
|
||||
Rational time;
|
||||
ViewerOutput *viewer;
|
||||
MultiCamNode *node;
|
||||
ClipBlock *clip;
|
||||
OakEngineNode *viewer;
|
||||
OakEngineNode *node;
|
||||
OakEngineBlock *clip;
|
||||
};
|
||||
|
||||
std::list<MulticamNodeQueue> play_queue_;
|
||||
|
||||
Reference in New Issue
Block a user