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:
@@ -25,7 +25,7 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
QVector<Color> ColorCoding::colors = {
|
||||
QVector<Color> AppColorCoding::colors = {
|
||||
Color(0.545f, 0.255f, 0.255f), Color(0.412f, 0.188f, 0.259f),
|
||||
Color(0.561f, 0.427f, 0.239f), Color(0.486f, 0.306f, 0.235f),
|
||||
Color(0.631f, 0.612f, 0.212f), Color(0.404f, 0.478f, 0.243f),
|
||||
@@ -36,12 +36,12 @@ QVector<Color> ColorCoding::colors = {
|
||||
Color(0.800f, 0.800f, 0.800f), Color(0.502f, 0.502f, 0.502f)
|
||||
};
|
||||
|
||||
const QVector<Color> &ColorCoding::standard_colors()
|
||||
const QVector<Color> &AppColorCoding::standard_colors()
|
||||
{
|
||||
return colors;
|
||||
}
|
||||
|
||||
QString ColorCoding::get_color_name(int c)
|
||||
QString AppColorCoding::get_color_name(int c)
|
||||
{
|
||||
switch (c) {
|
||||
case k_red: return QObject::tr("Red");
|
||||
@@ -49,7 +49,7 @@ QString ColorCoding::get_color_name(int c)
|
||||
case k_orange: return QObject::tr("Orange");
|
||||
case k_brown: return QObject::tr("Brown");
|
||||
case k_yellow: return QObject::tr("Yellow");
|
||||
case k_olive: return QObject::tr("Olive");
|
||||
case k_olive: return QObject::tr("Oak");
|
||||
case k_lime: return QObject::tr("Lime");
|
||||
case k_green: return QObject::tr("Green");
|
||||
case k_cyan: return QObject::tr("Cyan");
|
||||
@@ -64,12 +64,12 @@ QString ColorCoding::get_color_name(int c)
|
||||
return QString();
|
||||
}
|
||||
|
||||
Color ColorCoding::get_color(int c)
|
||||
Color AppColorCoding::get_color(int c)
|
||||
{
|
||||
return colors.at(c);
|
||||
}
|
||||
|
||||
Qt::GlobalColor ColorCoding::get_ui_selector_color(const Color &c)
|
||||
Qt::GlobalColor AppColorCoding::get_ui_selector_color(const Color &c)
|
||||
{
|
||||
if (c.get_rough_luminance() > 0.40f) {
|
||||
return Qt::black;
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace olive
|
||||
using namespace core;
|
||||
|
||||
/**
|
||||
* @brief App-side ColorCoding (moved from engine/ui/colorcoding.h)
|
||||
* @brief App-side color label mapping (moved from engine/ui/colorcoding.h)
|
||||
*
|
||||
* Provides the same static color-label mapping as the engine version but
|
||||
* without QObject inheritance (no moc symbols). Only the static methods
|
||||
* used by app code are included.
|
||||
*/
|
||||
class ColorCoding {
|
||||
class AppColorCoding {
|
||||
public:
|
||||
enum Code {
|
||||
k_red,
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
// App-side implementations of qHash overloads and stream operators
|
||||
// used by QHash containers and QDataStream serialization in app code.
|
||||
// Provides local definitions so the app doesn't import these from liboakengine.
|
||||
|
||||
#include "node/param.h"
|
||||
#include "node/output/track/track.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
uint qHash(const NodeInput &i)
|
||||
{
|
||||
return qHash(i.node()) ^ qHash(i.input()) ^ ::qHash(i.element());
|
||||
}
|
||||
|
||||
uint qHash(const NodeInputPair &i)
|
||||
{
|
||||
return qHash(i.node) ^ qHash(i.input);
|
||||
}
|
||||
|
||||
uint qHash(const NodeKeyframeTrackReference &i)
|
||||
{
|
||||
return qHash(i.input()) ^ ::qHash(i.track());
|
||||
}
|
||||
|
||||
uint qHash(const Track::Reference &r, uint seed)
|
||||
{
|
||||
return ::qHash(QStringLiteral("%1:%2").arg(QString::number(r.type()),
|
||||
QString::number(r.index())),
|
||||
seed);
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const Track::Reference &ref)
|
||||
{
|
||||
out << static_cast<int>(ref.type()) << ref.index();
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, Track::Reference &ref)
|
||||
{
|
||||
int type, index;
|
||||
in >> type >> index;
|
||||
ref = Track::Reference(static_cast<Track::Type>(type), index);
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_KEYFRAMETYPES_H
|
||||
#define OAK_KEYFRAMETYPES_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side keyframe enum mirrors.
|
||||
*
|
||||
* The engine olive::NodeKeyframe::Type mirror lives in
|
||||
* app/common/nodevaluehandle.h as NodeKeyframeType (kept with the
|
||||
* NodeValueType mirror); the enums below cover the remaining keyframe
|
||||
* domains. Enumerator ordinals must stay in sync with the engine / facade:
|
||||
* the C ABI transports these as ints.
|
||||
*/
|
||||
class KeyframeTypes {
|
||||
public:
|
||||
/// Mirror of engine's olive::NodeKeyframe::BezierType
|
||||
/// (engine/node/keyframe.h; oakengine_keyframe_opposing_bezier_type()
|
||||
/// transports these ordinals).
|
||||
enum BezierType { k_in_handle, k_out_handle };
|
||||
|
||||
/**
|
||||
* @brief Facade easing order used by the C ABI
|
||||
* (oakengine_keyframe_get_type(), oak::Keyframe::type()): NOT the same
|
||||
* order as the engine Type enum (see NodeKeyframeType in
|
||||
* common/nodevaluehandle.h).
|
||||
*/
|
||||
enum FacadeType {
|
||||
k_facade_invalid = -1,
|
||||
k_facade_linear = 0,
|
||||
k_facade_bezier = 1,
|
||||
k_facade_hold = 2
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_KEYFRAMETYPES_H
|
||||
@@ -0,0 +1,46 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_NODEDATATYPES_H
|
||||
#define OAK_NODEDATATYPES_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of engine's olive::Node::DataType
|
||||
* (engine/node/node.h).
|
||||
*
|
||||
* Enumerator ordinals must stay in sync with the engine enum: the C ABI
|
||||
* oakengine_node_get_data() (and the oak::Node::data() wrapper) takes the
|
||||
* `role` argument as a plain int carrying these ordinals.
|
||||
*/
|
||||
enum NodeDataType {
|
||||
k_node_data_icon,
|
||||
k_node_data_duration,
|
||||
k_node_data_created_time,
|
||||
k_node_data_modified_time,
|
||||
k_node_data_frequency_rate,
|
||||
k_node_data_tooltip
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_NODEDATATYPES_H
|
||||
@@ -21,44 +21,117 @@
|
||||
#ifndef OAK_NODEVALUEHANDLE_H
|
||||
#define OAK_NODEVALUEHANDLE_H
|
||||
|
||||
#include "node/value.h"
|
||||
#include "oakengine/node.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Convert engine NodeValue::Type to oak_node_value_type (app-side).
|
||||
* @brief App-side mirror of engine NodeValue::Type (engine/node/value.h).
|
||||
*
|
||||
* The two enums do NOT share ordinals (e.g. k_boolean=4 vs BOOL=3), so a
|
||||
* plain int cast is a bug. Mirrors from_c_type() in
|
||||
* engine/src/capi/node.cpp. Lives in an app header, NOT in the public
|
||||
* facade headers — the C ABI surface stays pure C (see
|
||||
* Ordinals MUST stay in sync with the engine enum: call sites that still
|
||||
* hold an engine NodeValue::Type reach the helpers below through an
|
||||
* implicit int conversion. The static_asserts pin the engine ordinals as
|
||||
* of the R8 wave 1 migration; update both sides together.
|
||||
*
|
||||
* NOTE: the C ABI oak_node_value_type (OAK_NODE_VALUE_*) does NOT share
|
||||
* these ordinals (e.g. k_boolean=4 vs OAK_NODE_VALUE_BOOL=3), so a plain
|
||||
* int cast between the two domains is a bug. Convert with
|
||||
* node_value_type_to_c().
|
||||
*/
|
||||
class NodeValueType
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
k_none = 0,
|
||||
k_int,
|
||||
k_float,
|
||||
k_rational,
|
||||
k_boolean,
|
||||
k_color,
|
||||
k_matrix,
|
||||
k_text,
|
||||
k_font,
|
||||
k_file,
|
||||
k_texture,
|
||||
k_samples,
|
||||
k_vec2,
|
||||
k_vec3,
|
||||
k_vec4,
|
||||
k_bezier,
|
||||
k_combo,
|
||||
k_str_combo,
|
||||
k_video_params,
|
||||
k_audio_params,
|
||||
k_subtitle_params,
|
||||
k_binary,
|
||||
k_push_button,
|
||||
k_data_type_count
|
||||
};
|
||||
};
|
||||
|
||||
// Ordinal sync guards against engine/node/value.h.
|
||||
static_assert(NodeValueType::k_boolean == 4,
|
||||
"NodeValueType out of sync with engine NodeValue::Type");
|
||||
static_assert(NodeValueType::k_vec2 == 12,
|
||||
"NodeValueType out of sync with engine NodeValue::Type");
|
||||
static_assert(NodeValueType::k_data_type_count == 23,
|
||||
"NodeValueType out of sync with engine NodeValue::Type");
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of engine NodeKeyframe::Type
|
||||
* (engine/node/keyframe.h).
|
||||
*
|
||||
* Ordinals MUST stay in sync with the engine enum (k_invalid=-1,
|
||||
* k_linear=0, k_hold=1, k_bezier=2). The facade easing type transported
|
||||
* over the C ABI is a DIFFERENT numbering: 0=linear, 1=bezier, 2=hold
|
||||
* (see oakengine/node.h) — convert with NodeKeyframeTypeToFacade() in
|
||||
* oakvaluehelper.h, never with a plain cast.
|
||||
*/
|
||||
class NodeKeyframeType
|
||||
{
|
||||
public:
|
||||
enum Type { k_invalid = -1, k_linear = 0, k_hold = 1, k_bezier = 2 };
|
||||
};
|
||||
|
||||
// Ordinal sync guard against engine/node/keyframe.h.
|
||||
static_assert(NodeKeyframeType::k_bezier == 2,
|
||||
"NodeKeyframeType out of sync with engine NodeKeyframe::Type");
|
||||
|
||||
/**
|
||||
* @brief Convert engine NodeValue::Type ordinals to oak_node_value_type (app-side).
|
||||
*
|
||||
* `t` uses engine NodeValue::Type ordinals (see the NodeValueType mirror
|
||||
* above); callers holding an engine NodeValue::Type pass it through an
|
||||
* implicit int conversion. The two enums do NOT share ordinals (e.g.
|
||||
* k_boolean=4 vs BOOL=3), so a plain int cast is a bug. Mirrors
|
||||
* from_c_type() in engine/src/capi/node.cpp. Lives in an app header, NOT
|
||||
* in the public facade headers — the C ABI surface stays pure C (see
|
||||
* docs/zh/r6-cleanup-plan.md red line 3 context). Returns -1 for types the
|
||||
* facade cannot represent (caller falls back to the input's declared type).
|
||||
*/
|
||||
inline int node_value_type_to_c(NodeValue::Type t)
|
||||
inline int node_value_type_to_c(int t)
|
||||
{
|
||||
switch (t) {
|
||||
case NodeValue::k_int: return OAK_NODE_VALUE_INT;
|
||||
case NodeValue::k_float: return OAK_NODE_VALUE_FLOAT;
|
||||
case NodeValue::k_boolean: return OAK_NODE_VALUE_BOOL;
|
||||
case NodeValue::k_rational: return OAK_NODE_VALUE_RATIONAL;
|
||||
case NodeValue::k_color: return OAK_NODE_VALUE_COLOR;
|
||||
case NodeValue::k_vec2: return OAK_NODE_VALUE_VEC2;
|
||||
case NodeValue::k_vec3: return OAK_NODE_VALUE_VEC3;
|
||||
case NodeValue::k_vec4: return OAK_NODE_VALUE_VEC4;
|
||||
case NodeValue::k_combo: return OAK_NODE_VALUE_COMBO;
|
||||
case NodeValue::k_file: return OAK_NODE_VALUE_STRING;
|
||||
case NodeValue::k_text: return OAK_NODE_VALUE_TEXT;
|
||||
case NodeValue::k_font: return OAK_NODE_VALUE_FONT;
|
||||
case NodeValue::k_str_combo: return OAK_NODE_VALUE_STR_COMBO;
|
||||
case NodeValue::k_binary: return OAK_NODE_VALUE_BINARY;
|
||||
case NodeValue::k_bezier: return OAK_NODE_VALUE_BEZIER;
|
||||
case NodeValue::k_texture: return OAK_NODE_VALUE_TEXTURE;
|
||||
case NodeValue::k_samples: return OAK_NODE_VALUE_SAMPLES;
|
||||
case NodeValue::k_video_params: return OAK_NODE_VALUE_VIDEO_PARAMS;
|
||||
case NodeValue::k_audio_params: return OAK_NODE_VALUE_AUDIO_PARAMS;
|
||||
case NodeValueType::k_int: return OAK_NODE_VALUE_INT;
|
||||
case NodeValueType::k_float: return OAK_NODE_VALUE_FLOAT;
|
||||
case NodeValueType::k_boolean: return OAK_NODE_VALUE_BOOL;
|
||||
case NodeValueType::k_rational: return OAK_NODE_VALUE_RATIONAL;
|
||||
case NodeValueType::k_color: return OAK_NODE_VALUE_COLOR;
|
||||
case NodeValueType::k_vec2: return OAK_NODE_VALUE_VEC2;
|
||||
case NodeValueType::k_vec3: return OAK_NODE_VALUE_VEC3;
|
||||
case NodeValueType::k_vec4: return OAK_NODE_VALUE_VEC4;
|
||||
case NodeValueType::k_combo: return OAK_NODE_VALUE_COMBO;
|
||||
case NodeValueType::k_file: return OAK_NODE_VALUE_STRING;
|
||||
case NodeValueType::k_text: return OAK_NODE_VALUE_TEXT;
|
||||
case NodeValueType::k_font: return OAK_NODE_VALUE_FONT;
|
||||
case NodeValueType::k_str_combo: return OAK_NODE_VALUE_STR_COMBO;
|
||||
case NodeValueType::k_binary: return OAK_NODE_VALUE_BINARY;
|
||||
case NodeValueType::k_bezier: return OAK_NODE_VALUE_BEZIER;
|
||||
case NodeValueType::k_texture: return OAK_NODE_VALUE_TEXTURE;
|
||||
case NodeValueType::k_samples: return OAK_NODE_VALUE_SAMPLES;
|
||||
case NodeValueType::k_video_params: return OAK_NODE_VALUE_VIDEO_PARAMS;
|
||||
case NodeValueType::k_audio_params: return OAK_NODE_VALUE_AUDIO_PARAMS;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
+45
-38
@@ -21,53 +21,57 @@
|
||||
#ifndef OAKVALUEHELPER_H
|
||||
#define OAKVALUEHELPER_H
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <QVariant>
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
|
||||
#include "node/keyframe.h"
|
||||
#include "node/value.h"
|
||||
#include "nodevaluehandle.h"
|
||||
#include "oakengine/node.h"
|
||||
#include "olive/core/util/color.h"
|
||||
#include "olive/core/util/rational.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
/**
|
||||
* @brief Convert a per-track component QVariant into the C ABI oak_node_value POD.
|
||||
*
|
||||
* `type` is the declared input data type (e.g. k_float/k_color). For split-track
|
||||
* types the component is the track-0 scalar (float for k_color's red channel, etc.).
|
||||
* Returns false for types that have no POD representation.
|
||||
* `type` uses engine NodeValue::Type ordinals (see the NodeValueType mirror
|
||||
* in nodevaluehandle.h; an engine NodeValue::Type converts implicitly) and
|
||||
* is the declared input data type (e.g. k_float/k_color). For split-track
|
||||
* types the component is the track-0 scalar (float for k_color's red
|
||||
* channel, etc.). Returns false for types that have no POD representation.
|
||||
*/
|
||||
static inline bool QVariantToOakNodeValue(NodeValue::Type type, const QVariant &v,
|
||||
static inline bool QVariantToOakNodeValue(int type, const QVariant &v,
|
||||
oak_node_value *out)
|
||||
{
|
||||
memset(out, 0, sizeof(*out));
|
||||
switch (type) {
|
||||
case NodeValue::k_int:
|
||||
case NodeValue::k_combo:
|
||||
out->type = (type == NodeValue::k_combo) ? OAK_NODE_VALUE_COMBO
|
||||
: OAK_NODE_VALUE_INT;
|
||||
case NodeValueType::k_int:
|
||||
case NodeValueType::k_combo:
|
||||
out->type = (type == NodeValueType::k_combo) ? OAK_NODE_VALUE_COMBO
|
||||
: OAK_NODE_VALUE_INT;
|
||||
out->num = v.toLongLong();
|
||||
return true;
|
||||
case NodeValue::k_float:
|
||||
case NodeValueType::k_float:
|
||||
out->type = OAK_NODE_VALUE_FLOAT;
|
||||
out->f[0] = v.toDouble();
|
||||
return true;
|
||||
case NodeValue::k_boolean:
|
||||
case NodeValueType::k_boolean:
|
||||
out->type = OAK_NODE_VALUE_BOOL;
|
||||
out->num = v.toBool() ? 1 : 0;
|
||||
return true;
|
||||
case NodeValue::k_rational:
|
||||
case NodeValueType::k_rational:
|
||||
out->type = OAK_NODE_VALUE_RATIONAL;
|
||||
{
|
||||
const Rational r = v.value<Rational>();
|
||||
const core::Rational r = v.value<core::Rational>();
|
||||
out->num = r.numerator();
|
||||
out->den = r.denominator();
|
||||
}
|
||||
return true;
|
||||
case NodeValue::k_color:
|
||||
case NodeValueType::k_color:
|
||||
out->type = OAK_NODE_VALUE_COLOR;
|
||||
{
|
||||
const core::Color c = v.value<core::Color>();
|
||||
@@ -77,7 +81,7 @@ static inline bool QVariantToOakNodeValue(NodeValue::Type type, const QVariant &
|
||||
out->f[3] = c.alpha();
|
||||
}
|
||||
return true;
|
||||
case NodeValue::k_vec2:
|
||||
case NodeValueType::k_vec2:
|
||||
out->type = OAK_NODE_VALUE_VEC2;
|
||||
{
|
||||
const QVector2D vec = v.value<QVector2D>();
|
||||
@@ -85,7 +89,7 @@ static inline bool QVariantToOakNodeValue(NodeValue::Type type, const QVariant &
|
||||
out->f[1] = vec.y();
|
||||
}
|
||||
return true;
|
||||
case NodeValue::k_vec3:
|
||||
case NodeValueType::k_vec3:
|
||||
out->type = OAK_NODE_VALUE_VEC3;
|
||||
{
|
||||
const QVector3D vec = v.value<QVector3D>();
|
||||
@@ -94,7 +98,7 @@ static inline bool QVariantToOakNodeValue(NodeValue::Type type, const QVariant &
|
||||
out->f[2] = vec.z();
|
||||
}
|
||||
return true;
|
||||
case NodeValue::k_vec4:
|
||||
case NodeValueType::k_vec4:
|
||||
out->type = OAK_NODE_VALUE_VEC4;
|
||||
{
|
||||
const QVector4D vec = v.value<QVector4D>();
|
||||
@@ -116,49 +120,51 @@ static inline bool QVariantToOakNodeValue(NodeValue::Type type, const QVariant &
|
||||
* single track's component (e.g. one float for a k_color channel). The resulting
|
||||
* POD has the input's declared type with the component in f[0]/num, exactly what
|
||||
* the per-track facade commands expect.
|
||||
*
|
||||
* `type` uses engine NodeValue::Type ordinals (NodeValueType mirror).
|
||||
*/
|
||||
static inline bool NodeTrackComponentToOakNodeValue(NodeValue::Type type,
|
||||
static inline bool NodeTrackComponentToOakNodeValue(int type,
|
||||
const QVariant &v,
|
||||
oak_node_value *out)
|
||||
{
|
||||
memset(out, 0, sizeof(*out));
|
||||
switch (type) {
|
||||
case NodeValue::k_int:
|
||||
case NodeValue::k_combo:
|
||||
out->type = (type == NodeValue::k_combo) ? OAK_NODE_VALUE_COMBO
|
||||
: OAK_NODE_VALUE_INT;
|
||||
case NodeValueType::k_int:
|
||||
case NodeValueType::k_combo:
|
||||
out->type = (type == NodeValueType::k_combo) ? OAK_NODE_VALUE_COMBO
|
||||
: OAK_NODE_VALUE_INT;
|
||||
out->num = v.toLongLong();
|
||||
return true;
|
||||
case NodeValue::k_float:
|
||||
case NodeValue::k_bezier:
|
||||
case NodeValueType::k_float:
|
||||
case NodeValueType::k_bezier:
|
||||
out->type = OAK_NODE_VALUE_FLOAT;
|
||||
out->f[0] = v.toDouble();
|
||||
return true;
|
||||
case NodeValue::k_boolean:
|
||||
case NodeValueType::k_boolean:
|
||||
out->type = OAK_NODE_VALUE_BOOL;
|
||||
out->num = v.toBool() ? 1 : 0;
|
||||
return true;
|
||||
case NodeValue::k_rational:
|
||||
case NodeValueType::k_rational:
|
||||
out->type = OAK_NODE_VALUE_RATIONAL;
|
||||
{
|
||||
const Rational r = v.value<Rational>();
|
||||
const core::Rational r = v.value<core::Rational>();
|
||||
out->num = r.numerator();
|
||||
out->den = r.denominator();
|
||||
}
|
||||
return true;
|
||||
case NodeValue::k_color:
|
||||
case NodeValueType::k_color:
|
||||
out->type = OAK_NODE_VALUE_COLOR;
|
||||
out->f[0] = v.toFloat();
|
||||
return true;
|
||||
case NodeValue::k_vec2:
|
||||
case NodeValueType::k_vec2:
|
||||
out->type = OAK_NODE_VALUE_VEC2;
|
||||
out->f[0] = v.toFloat();
|
||||
return true;
|
||||
case NodeValue::k_vec3:
|
||||
case NodeValueType::k_vec3:
|
||||
out->type = OAK_NODE_VALUE_VEC3;
|
||||
out->f[0] = v.toFloat();
|
||||
return true;
|
||||
case NodeValue::k_vec4:
|
||||
case NodeValueType::k_vec4:
|
||||
out->type = OAK_NODE_VALUE_VEC4;
|
||||
out->f[0] = v.toFloat();
|
||||
return true;
|
||||
@@ -185,7 +191,7 @@ static inline QVariant OakNodeValueToQVariant(const oak_node_value &v)
|
||||
return QVariant::fromValue(v.num != 0);
|
||||
case OAK_NODE_VALUE_RATIONAL:
|
||||
return QVariant::fromValue(
|
||||
Rational(int(v.num), int(v.den)));
|
||||
core::Rational(int(v.num), int(v.den)));
|
||||
case OAK_NODE_VALUE_COLOR:
|
||||
return QVariant::fromValue(core::Color(
|
||||
float(v.f[0]), float(v.f[1]), float(v.f[2]), float(v.f[3])));
|
||||
@@ -206,16 +212,17 @@ static inline QVariant OakNodeValueToQVariant(const oak_node_value &v)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Map an engine NodeKeyframe::Type to the facade easing type.
|
||||
* @brief Map engine NodeKeyframe::Type ordinals (NodeKeyframeType mirror)
|
||||
* to the facade easing type (0=linear, 1=bezier, 2=hold).
|
||||
*/
|
||||
static inline int NodeKeyframeTypeToFacade(NodeKeyframe::Type type)
|
||||
static inline int NodeKeyframeTypeToFacade(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case NodeKeyframe::k_bezier:
|
||||
case NodeKeyframeType::k_bezier:
|
||||
return 1;
|
||||
case NodeKeyframe::k_hold:
|
||||
case NodeKeyframeType::k_hold:
|
||||
return 2;
|
||||
case NodeKeyframe::k_linear:
|
||||
case NodeKeyframeType::k_linear:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_PROJECTTYPES_H
|
||||
#define OAK_PROJECTTYPES_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of the engine's olive::Project enum(s)
|
||||
* (engine/node/project.h).
|
||||
*
|
||||
* Enumerator ordinals must stay in sync with the engine enum: the C ABI
|
||||
* (oakengine_project_get_cache_location_setting() etc.) transports these
|
||||
* values as plain ints.
|
||||
*/
|
||||
class Project {
|
||||
public:
|
||||
enum CacheSetting {
|
||||
k_cache_use_default_location,
|
||||
k_cache_store_alongside_project,
|
||||
k_cache_custom_path
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_PROJECTTYPES_H
|
||||
@@ -0,0 +1,76 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_SERIALIZEDLAYOUTINFOAPP_H
|
||||
#define OAK_SERIALIZEDLAYOUTINFOAPP_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
#include "oakengine/node.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of the engine's olive::SerializedLayoutInfo
|
||||
* (engine/node/project/serializer/serializedlayoutinfo.h).
|
||||
*
|
||||
* SYNC OBLIGATION: the data member layout (types AND order) must stay
|
||||
* identical to the engine type. Instances of this struct cross the engine
|
||||
* boundary as `void *` (Core::save_project_internal() passes one to
|
||||
* oakengine_task_create_project_save(), and the engine hands one back
|
||||
* through the load_layout callback); the engine side reinterprets the
|
||||
* pointer as its own olive::SerializedLayoutInfo and copies the members,
|
||||
* so any layout divergence is silent memory corruption.
|
||||
*
|
||||
* The engine's std::vector<Folder*> / std::vector<Sequence*> /
|
||||
* std::vector<ViewerOutput*> members are mirrored as
|
||||
* std::vector<OakEngineNode*> (same pointer size and semantics: borrowed
|
||||
* node handles). panel_data mirrors
|
||||
* std::map<QString, PanelLayoutInfo> where PanelLayoutInfo is
|
||||
* std::map<QString, QString> (identical to PanelWidget::Info).
|
||||
*
|
||||
* Only the data members are mirrored; the engine type's XML
|
||||
* (de)serialization methods (to_xml/from_xml) stay engine-side.
|
||||
*/
|
||||
class SerializedLayoutInfo {
|
||||
public:
|
||||
SerializedLayoutInfo() = default;
|
||||
|
||||
QByteArray state;
|
||||
|
||||
std::vector<OakEngineNode *> open_folders;
|
||||
|
||||
std::vector<OakEngineNode *> open_sequences;
|
||||
|
||||
std::vector<OakEngineNode *> open_viewers;
|
||||
|
||||
std::map<QString, std::map<QString, QString>> panel_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::SerializedLayoutInfo)
|
||||
|
||||
#endif // OAK_SERIALIZEDLAYOUTINFOAPP_H
|
||||
@@ -0,0 +1,87 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_SUBTITLEAPP_H
|
||||
#define OAK_SUBTITLEAPP_H
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include <olive/core/util/timerange.h>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
using olive::core::TimeRange;
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of the engine Subtitle value class
|
||||
* (engine/render/subtitleparams.h).
|
||||
*
|
||||
* Pure value type (time range + text), identical semantics to the engine
|
||||
* version. It is named SubtitleApp (not Subtitle) because the engine class
|
||||
* still reaches some app translation units transitively (e.g. via
|
||||
* engine/node/output/viewer/viewer.h) and an identical name would be an
|
||||
* ODR redefinition there.
|
||||
*
|
||||
* The member layout MUST stay in sync with the engine class:
|
||||
* oakengine_viewer_get_subtitle_at() returns pointers to engine Subtitle
|
||||
* objects which the app reads through this mirror. Update both sides
|
||||
* together.
|
||||
*/
|
||||
class SubtitleApp {
|
||||
public:
|
||||
SubtitleApp() = default;
|
||||
|
||||
SubtitleApp(const TimeRange &time, const QString &text)
|
||||
: range_(time)
|
||||
, text_(text)
|
||||
{
|
||||
}
|
||||
|
||||
const TimeRange &time() const
|
||||
{
|
||||
return range_;
|
||||
}
|
||||
void set_time(const TimeRange &t)
|
||||
{
|
||||
range_ = t;
|
||||
}
|
||||
|
||||
const QString &text() const
|
||||
{
|
||||
return text_;
|
||||
}
|
||||
void set_text(const QString &t)
|
||||
{
|
||||
text_ = t;
|
||||
}
|
||||
|
||||
private:
|
||||
TimeRange range_;
|
||||
|
||||
QString text_;
|
||||
};
|
||||
|
||||
} // namespace olive
|
||||
|
||||
Q_DECLARE_METATYPE(olive::SubtitleApp)
|
||||
|
||||
#endif // OAK_SUBTITLEAPP_H
|
||||
@@ -0,0 +1,168 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_TOOLTYPES_H
|
||||
#define OAK_TOOLTYPES_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of engine's olive::Tool (engine/tool/tool.h).
|
||||
*
|
||||
* Pure enum + static string mapping, identical to the engine version.
|
||||
* Enumerator ordinals must stay in sync with the engine enum: the C ABI
|
||||
* (oakengine_app_tool() etc.) transports these as ints.
|
||||
*/
|
||||
class Tool {
|
||||
public:
|
||||
/**
|
||||
* @brief A list of tools that can be used throughout the application
|
||||
*/
|
||||
enum Item {
|
||||
/// No tool. This should never be set as the application tool, its only real purpose is to indicate the lack of
|
||||
/// a tool somewhere similar to nullptr.
|
||||
k_none,
|
||||
|
||||
/// Pointer tool
|
||||
k_pointer,
|
||||
|
||||
/// Edit tool
|
||||
k_edit,
|
||||
|
||||
/// Ripple tool
|
||||
k_ripple,
|
||||
|
||||
/// Rolling tool
|
||||
k_rolling,
|
||||
|
||||
/// Razor tool
|
||||
k_razor,
|
||||
|
||||
/// Slip tool
|
||||
k_slip,
|
||||
|
||||
/// Slide tool
|
||||
k_slide,
|
||||
|
||||
/// Hand tool
|
||||
k_hand,
|
||||
|
||||
/// Zoom tool
|
||||
k_zoom,
|
||||
|
||||
/// Transition tool
|
||||
k_transition,
|
||||
|
||||
/// Record tool
|
||||
k_record,
|
||||
|
||||
/// Add tool
|
||||
k_add,
|
||||
|
||||
/// Track select tool
|
||||
k_track_select,
|
||||
|
||||
k_count
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Tools that can be added using the kAdd tool
|
||||
*/
|
||||
enum AddableObject {
|
||||
/// An empty clip
|
||||
k_addable_empty,
|
||||
|
||||
/// A video clip showing a generic video placeholder
|
||||
k_addable_bars,
|
||||
|
||||
/// A video clip showing a primitive shape
|
||||
k_addable_shape,
|
||||
|
||||
/// A video clip with a solid connected
|
||||
k_addable_solid,
|
||||
|
||||
/// A video clip with a title connected
|
||||
k_addable_title,
|
||||
|
||||
/// An audio clip with a sine connected to it
|
||||
k_addable_tone,
|
||||
|
||||
/// A subtitle clip
|
||||
k_addable_subtitle,
|
||||
|
||||
k_addable_count
|
||||
};
|
||||
|
||||
static QString get_addable_object_name(const AddableObject &a)
|
||||
{
|
||||
switch (a) {
|
||||
case k_addable_empty:
|
||||
return QCoreApplication::translate("Tool", "Empty");
|
||||
case k_addable_bars:
|
||||
return QCoreApplication::translate("Tool", "Bars");
|
||||
case k_addable_shape:
|
||||
return QCoreApplication::translate("Tool", "Shape");
|
||||
case k_addable_solid:
|
||||
return QCoreApplication::translate("Tool", "Solid");
|
||||
case k_addable_title:
|
||||
return QCoreApplication::translate("Tool", "Title");
|
||||
case k_addable_tone:
|
||||
return QCoreApplication::translate("Tool", "Tone");
|
||||
case k_addable_subtitle:
|
||||
return QCoreApplication::translate("Tool", "Subtitle");
|
||||
case k_addable_count:
|
||||
break;
|
||||
}
|
||||
|
||||
return QCoreApplication::translate("Tool", "Unknown");
|
||||
}
|
||||
|
||||
static QString get_addable_object_id(const AddableObject &a)
|
||||
{
|
||||
switch (a) {
|
||||
case k_addable_empty:
|
||||
return QStringLiteral("empty");
|
||||
case k_addable_bars:
|
||||
return QStringLiteral("bars");
|
||||
case k_addable_shape:
|
||||
return QStringLiteral("shape");
|
||||
case k_addable_solid:
|
||||
return QStringLiteral("solid");
|
||||
case k_addable_title:
|
||||
return QStringLiteral("title");
|
||||
case k_addable_tone:
|
||||
return QStringLiteral("tone");
|
||||
case k_addable_subtitle:
|
||||
return QStringLiteral("subtitle");
|
||||
case k_addable_count:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_TOOLTYPES_H
|
||||
@@ -0,0 +1,220 @@
|
||||
/***
|
||||
|
||||
Oak - 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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_TRACKREFERENCEHANDLE_H
|
||||
#define OAK_TRACKREFERENCEHANDLE_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDataStream>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "oakengine/timeline.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief App-side mirror of the engine Track::Reference value class
|
||||
* (engine/node/output/track/track.h).
|
||||
*
|
||||
* Pure value type (track type + index) used throughout timeline UI code.
|
||||
* Semantics are identical to the engine version. The nested Type enum
|
||||
* mirrors engine Track::Type; ordinals MUST stay in sync with the engine
|
||||
* enum — the C ABI transports track types as ints
|
||||
* (OAKENGINE_TRACK_TYPE_* in oakengine/timeline.h), pinned by the
|
||||
* static_asserts below. Update both sides together.
|
||||
*/
|
||||
class TrackReference
|
||||
{
|
||||
public:
|
||||
enum Type { k_none = -1, k_video, k_audio, k_subtitle, k_count };
|
||||
|
||||
TrackReference()
|
||||
: type_(k_none)
|
||||
, index_(-1)
|
||||
{
|
||||
}
|
||||
|
||||
TrackReference(const Type &type, const int &index)
|
||||
: type_(type)
|
||||
, index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
const Type &type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
const int &index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
bool operator==(const TrackReference &ref) const
|
||||
{
|
||||
return type_ == ref.type_ && index_ == ref.index_;
|
||||
}
|
||||
|
||||
bool operator!=(const TrackReference &ref) const
|
||||
{
|
||||
return !(*this == ref);
|
||||
}
|
||||
|
||||
bool operator<(const TrackReference &rhs) const
|
||||
{
|
||||
if (type_ != rhs.type_) {
|
||||
return type_ < rhs.type_;
|
||||
}
|
||||
|
||||
return index_ < rhs.index_;
|
||||
}
|
||||
|
||||
QString to_string() const
|
||||
{
|
||||
QString type_string = type_to_string(type_);
|
||||
if (type_string.isEmpty()) {
|
||||
return QString();
|
||||
} else {
|
||||
return QStringLiteral("%1:%2").arg(type_string,
|
||||
QString::number(index_));
|
||||
}
|
||||
}
|
||||
|
||||
/// For IDs that shouldn't change between localizations
|
||||
static QString type_to_string(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case k_video:
|
||||
return QStringLiteral("v");
|
||||
case k_audio:
|
||||
return QStringLiteral("a");
|
||||
case k_subtitle:
|
||||
return QStringLiteral("s");
|
||||
case k_count:
|
||||
case k_none:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
/// For human-facing strings (translation context "Track" kept
|
||||
/// identical to the engine version)
|
||||
static QString type_to_translated_string(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case k_video:
|
||||
return QCoreApplication::translate("Track", "V");
|
||||
case k_audio:
|
||||
return QCoreApplication::translate("Track", "A");
|
||||
case k_subtitle:
|
||||
return QCoreApplication::translate("Track", "S");
|
||||
case k_count:
|
||||
case k_none:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
static Type type_from_string(const QString &s)
|
||||
{
|
||||
if (s.size() >= 3) {
|
||||
if (s.at(1) == ':') {
|
||||
if (s.at(0) == 'v') {
|
||||
// Video stream
|
||||
return k_video;
|
||||
} else if (s.at(0) == 'a') {
|
||||
// Audio stream
|
||||
return k_audio;
|
||||
} else if (s.at(0) == 's') {
|
||||
// Subtitle stream
|
||||
return k_subtitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return k_none;
|
||||
}
|
||||
|
||||
static TrackReference from_string(const QString &s)
|
||||
{
|
||||
TrackReference ref;
|
||||
Type parse_type = type_from_string(s);
|
||||
|
||||
if (parse_type != k_none) {
|
||||
bool ok;
|
||||
int parse_index = s.mid(2).toInt(&ok);
|
||||
|
||||
if (ok) {
|
||||
ref.type_ = parse_type;
|
||||
ref.index_ = parse_index;
|
||||
}
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return type_ > k_none && type_ < k_count && index_ >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
int index_;
|
||||
};
|
||||
|
||||
// Ordinal sync guards: C ABI OAKENGINE_TRACK_TYPE_* (oakengine/timeline.h)
|
||||
// carry the same values as engine Track::Type, and this mirror matches both.
|
||||
static_assert(TrackReference::k_video == OAKENGINE_TRACK_TYPE_VIDEO,
|
||||
"TrackReference::Type out of sync with C ABI track types");
|
||||
static_assert(TrackReference::k_audio == OAKENGINE_TRACK_TYPE_AUDIO,
|
||||
"TrackReference::Type out of sync with C ABI track types");
|
||||
static_assert(TrackReference::k_subtitle == OAKENGINE_TRACK_TYPE_SUBTITLE,
|
||||
"TrackReference::Type out of sync with C ABI track types");
|
||||
|
||||
inline uint qHash(const TrackReference &r, uint seed = 0)
|
||||
{
|
||||
return ::qHash(QStringLiteral("%1:%2").arg(QString::number(r.type()),
|
||||
QString::number(r.index())),
|
||||
seed);
|
||||
}
|
||||
|
||||
inline QDataStream &operator<<(QDataStream &out, const TrackReference &ref)
|
||||
{
|
||||
out << static_cast<int>(ref.type()) << ref.index();
|
||||
return out;
|
||||
}
|
||||
|
||||
inline QDataStream &operator>>(QDataStream &in, TrackReference &ref)
|
||||
{
|
||||
int type, index;
|
||||
in >> type >> index;
|
||||
ref = TrackReference(static_cast<TrackReference::Type>(type), index);
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace olive
|
||||
|
||||
#endif // OAK_TRACKREFERENCEHANDLE_H
|
||||
Reference in New Issue
Block a user