build/ci: green builds and tests on all three platforms

Compiler hygiene (all platforms):
- Silence warnings across the tree: missing override, -Wreorder ctor
  init, -Wshadow, -Wsign-compare, missing switch cases, unused
  functions/captures, Qt 6.11 deprecations (QMouseEvent/QDropEvent
  accessors, qAsConst, Q_FOREACH over non-shared containers,
  AA_UseHighDpiPixmaps) and the .bak/ backup tree removal.
- Fix regressions from the cleanup: missing clip decls in
  capi/timeline.cpp, plugin.cpp rename fallout, panel setFocus
  ambiguity, QGraphicsItem::pos vs event->position(), duplicate
  k_push_button case, boolean test variable.

Windows:
- Qt portability: CommandLineParser is_set/add_option, QTimeZone
  systemTimeZone (QTimeZone::LocalTime is 6.11-only), k_progress_* enum.
- Linking: stop adding oakengine to OLIVE_LIBRARIES (import lib plus
  oakengine-obj caused multiple definitions); add OAKENGINE_STATIC so
  internal consumers no longer reference __imp_* stubs.
- oakengine.ver: export olive::Renderer typeinfo so liboakgl.so can be
  dlopened (Linux), DynamicRenderer no longer dlcloses backend libraries
  (crash in RenderManager's dtor calling into unmapped memory).
- OTIO runtime: copy DLLs next to every binary on Windows instead of
  relying on PATH (0xc0000135 in gtest discovery).
- Headless GL: the runner only has GDI OpenGL 1.1, killing every render
  worker. Deploy Mesa llvmpipe as opengl32sw.dll (Qt's software-GL
  channel) with QT_OPENGL=software, and let QT_OPENGL override the
  AA_UseDesktopOpenGL default. ExportTask fails fast after 8 consecutive
  undelivered frames instead of segfaulting or grinding forever;
  FFmpegEncoder::write_frame tolerates null frames.
- Tests: GetTempPathA+PID temp dirs, GetLongPathNameA for 8.3 names,
  forward-slash normalization when comparing project filenames.

Linux:
- Install libshaderc-dev so oakvulkan compiles GLSL (Vulkan tests).
- Accept UNORM floor-or-round (63/64) in the blit ping-pong test.
- Skip MainWindow construction test on the offscreen QPA (cannot paint
  QOpenGLWidget).

Also: oak_cli_transcode gets a 300s ctest timeout, worker logs GL
context version and LoadGraph/render_frame stages, and
docs/plans/eliminate-event-bridge-issues.md (English translation).
This commit is contained in:
2026-08-04 21:34:31 +08:00
parent 5006382790
commit 712badbaa7
127 changed files with 826 additions and 8498 deletions
+3
View File
@@ -114,6 +114,9 @@ target_include_directories(oakengine
target_link_libraries(oakengine PUBLIC ${OLIVE_LIBRARIES} OfxHost)
# OAKENGINE_BUILD marks the library side of the C ABI export macros (dllexport)
target_compile_definitions(oakengine-obj PRIVATE ${OLIVE_DEFINITIONS} OAKENGINE_BUILD)
# Consumers that link the object library directly (app, tests, Windows oakgl)
# must see plain C declarations, not __declspec(dllimport) ones.
target_compile_definitions(oakengine-obj INTERFACE OAKENGINE_STATIC)
target_compile_options(oakengine-obj PRIVATE ${OLIVE_COMPILE_OPTIONS})
# Version script: only oakengine_* + render-backend plugin ABI are exported;
+8
View File
@@ -324,6 +324,14 @@ bool FFmpegEncoder::open()
bool FFmpegEncoder::write_frame(FramePtr frame, Rational time)
{
// The render worker pool finishes tickets without a result when no
// worker is available (or the worker crashed); a null frame must fail
// the encode cleanly instead of crashing the export task.
if (!frame) {
qWarning() << "FFmpegEncoder::write_frame called with null frame";
return false;
}
// We may need to convert this frame to a frame that the bridge will understand
if (frame->format() != video_conversion_fmt_) {
frame = frame->convert(video_conversion_fmt_);
+1 -1
View File
@@ -275,7 +275,7 @@ void Html::write_char_format(QString *style, const QTextCharFormat &fmt)
}
if (fmt.foreground().style() != Qt::NoBrush) {
const QColor &color = fmt.foreground().color();
const QColor color = fmt.foreground().color();
QString cs;
if (color.alpha() == 255) {
+2 -2
View File
@@ -225,7 +225,7 @@ public:
~Arena()
{
std::list<Element *> copy = lent_elements_;
foreach (Element *e, copy) {
for (Element *e : copy) {
e->release();
}
@@ -348,7 +348,7 @@ public:
QMutexLocker locker(&lock_);
// Attempt to get an element from an arena
foreach (Arena *a, arenas_) {
for (Arena *a : arenas_) {
ElementPtr e = a->Get();
if (e) {
+4
View File
@@ -49,6 +49,10 @@ PixelFormat OIIOUtils::get_format_from_oiio_basetype(OIIO::TypeDesc::BASETYPE ty
switch (type) {
case OIIO::TypeDesc::UNKNOWN:
case OIIO::TypeDesc::NONE:
#if OIIO_VERSION >= 20500
case OIIO::TypeDesc::USTRINGHASH:
#endif
default:
break;
case OIIO::TypeDesc::INT8:
+5 -4
View File
@@ -544,10 +544,11 @@ void EngineCore::save_autorecovery()
{
QFile realname_file(project_autorecovery_dir.filePath(
QStringLiteral("realname.txt")));
realname_file.open(QFile::WriteOnly);
realname_file.write(
open_project_->pretty_filename().toUtf8());
realname_file.close();
if (realname_file.open(QFile::WriteOnly)) {
realname_file.write(
open_project_->pretty_filename().toUtf8());
realname_file.close();
}
}
int64_t max_recoveries_per_file =
+5 -1
View File
@@ -30,7 +30,11 @@
* is still built with default symbol visibility, so the legacy C++ symbols
* remain exported alongside the C ABI.
*/
#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(OAKENGINE_STATIC)
/* Internal consumers link the engine object files directly (oakengine-obj)
instead of the shared library; no dllimport/dllexport is wanted. */
#define OAKENGINE_API
#elif defined(_WIN32) || defined(__CYGWIN__)
#ifdef OAKENGINE_BUILD
#define OAKENGINE_API __declspec(dllexport)
#else
+3 -3
View File
@@ -2386,14 +2386,14 @@ TimeRange Node::transform_time_to(TimeRange time, Node *target,
Node *from = this;
Node *to = target;
if (dir == k_transform_towards_input) {
if (dir == k_towards_input) {
std::swap(from, to);
}
std::list<NodeInput> path = find_path(from, to, path_index);
if (!path.empty()) {
if (dir == k_transform_towards_input) {
if (dir == k_towards_input) {
for (auto it = path.crbegin(); it != path.crend(); it++) {
const NodeInput &i = (*it);
time = i.node()->input_time_adjustment(i.input(), i.element(),
@@ -2614,7 +2614,7 @@ void Node::invalidate_from_keyframe_time_change()
// Invalidate entire area surrounding the keyframe (either where it currently is, or where it used to be before it
// was resorted in the if block above)
foreach (const TimeRange &r, invalidate_range) {
for (const TimeRange &r : invalidate_range) {
parameter_value_changed(key->key_track_ref().input(), r);
}
+2 -2
View File
@@ -929,8 +929,8 @@ public:
static QString get_category_name(const CategoryID &c);
enum TransformTimeDirection {
k_transform_towards_input,
k_transform_towards_output
k_towards_input,
k_towards_output
};
/**
+5 -7
View File
@@ -232,8 +232,6 @@ QHash<QString, QVariant> build_default_values(
ofx_type == kOfxParamTypePushButton) {
continue;
}
const auto &props = param.second->getProperties();
bool is_secret = props.getIntProperty(kOfxParamPropSecret) != 0;
const QString input_id =
QString::fromStdString(param.second->getName());
if (input_id.isEmpty()) {
@@ -263,10 +261,10 @@ clip_label_for_name(const std::string &name,
}
if (desc) {
const std::string &label =
const std::string &param_label =
desc->getProps().getStringProperty(kOfxPropLabel);
if (!label.empty()) {
return QString::fromStdString(label);
if (!param_label.empty()) {
return QString::fromStdString(param_label);
}
}
@@ -432,9 +430,9 @@ olive::plugin::PluginNode::PluginNode(OFX::Host::ImageEffect::Instance *plugin)
const int value_count = props.getDimension(kOfxParamPropChoiceEnum);
for (int i = 0; i < label_count; ++i) {
const std::string &label =
const std::string &choice_label =
props.getStringProperty(kOfxParamPropChoiceOption, i);
option_labels.append(QString::fromStdString(label));
option_labels.append(QString::fromStdString(choice_label));
}
for (int i = 0; i < value_count; ++i) {
+2 -2
View File
@@ -62,7 +62,7 @@ public:
*/
virtual void process_samples(const NodeValueRow &values,
const SampleBuffer &input, SampleBuffer &output,
int index) const;
int index) const override;
/**
* @brief If Value() pushes a GenerateJob, override this function for the image to create
@@ -71,7 +71,7 @@ public:
*
* The destination buffer. It will already be allocated and ready for writing to.
*/
virtual void generate_frame(FramePtr frame, const GenerateJob &job) const;
virtual void generate_frame(FramePtr frame, const GenerateJob &job) const override;
private:
QString sub_category_;
+7 -6
View File
@@ -377,8 +377,8 @@ void Footage::value(const NodeValueRow &value, const NodeGlobals &globals,
this, QStringLiteral("length"));
// Push each stream as a footage job
for (int i = 0; i < get_total_stream_count(); i++) {
Track::Reference ref = get_reference_from_real_index(i);
for (int si = 0; si < get_total_stream_count(); si++) {
Track::Reference ref = get_reference_from_real_index(si);
FootageJob job(globals.time(), decoder_, filename(), ref.type(),
get_length(), globals.loop_mode());
@@ -427,9 +427,10 @@ void Footage::value(const NodeValueRow &value, const NodeGlobals &globals,
ProxyManager::k_proxy_ready &&
ProxyManager::proxy_filename_has_audio(proxy_path_)) {
int audio_rank = 0;
for (int i = 0; i < get_total_stream_count(); i++) {
for (int sj = 0; sj < get_total_stream_count(); sj++) {
const Track::Reference other =
get_reference_from_real_index(i);
get_reference_from_real_index(sj);
if (other.type() == Track::k_audio &&
get_audio_params(other.index()).stream_index() <
ap.stream_index()) {
@@ -448,8 +449,8 @@ void Footage::value(const NodeValueRow &value, const NodeGlobals &globals,
// Media is offline: push a generated warning frame for each video
// stream so missing media is clearly visible in the timeline instead
// of a transparent/black hole. generate_frame() draws the slat.
for (int i = 0; i < get_total_stream_count(); i++) {
Track::Reference ref = get_reference_from_real_index(i);
for (int si = 0; si < get_total_stream_count(); si++) {
Track::Reference ref = get_reference_from_real_index(si);
if (ref.type() != Track::k_video) {
continue;
}
@@ -28,7 +28,7 @@ void SerializedLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("folders"));
foreach (Folder *folder, open_folders) {
for (Folder *folder : open_folders) {
writer->writeTextElement(
QStringLiteral("folder"),
QString::number(reinterpret_cast<quintptr>(folder)));
@@ -38,7 +38,7 @@ void SerializedLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("timeline"));
foreach (Sequence *sequence, open_sequences) {
for (Sequence *sequence : open_sequences) {
writer->writeTextElement(
QStringLiteral("sequence"),
QString::number(reinterpret_cast<quintptr>(sequence)));
@@ -48,7 +48,7 @@ void SerializedLayoutInfo::to_xml(QXmlStreamWriter *writer) const
writer->writeStartElement(QStringLiteral("viewers"));
foreach (ViewerOutput *viewer, open_viewers) {
for (ViewerOutput *viewer : open_viewers) {
writer->writeTextElement(
QStringLiteral("viewer"),
QString::number(reinterpret_cast<quintptr>(viewer)));
+3 -1
View File
@@ -22,6 +22,7 @@
#include "timeformat.h"
#include <QDateTime>
#include <QTimeZone>
namespace olive
{
@@ -75,7 +76,8 @@ void TimeFormatNode::value(const NodeValueRow &value,
qint64 ms_since_epoch = value[k_time_input].to_double() * 1000;
bool time_is_local = value[k_local_time_input].to_bool();
QDateTime dt = QDateTime::fromMSecsSinceEpoch(
ms_since_epoch, time_is_local ? Qt::LocalTime : Qt::UTC);
ms_since_epoch,
time_is_local ? QTimeZone::systemTimeZone() : QTimeZone::utc());
QString format = value[k_format_input].to_string();
QString output = dt.toString(format);
table->push(NodeValue(NodeValue::k_text, output, this));
+1 -3
View File
@@ -502,9 +502,7 @@ void NodeTraverser::resolve_jobs(NodeValue &val)
}
val.set_value(tex);
} else if (plugin::PluginJob *plugin_job =
dynamic_cast<plugin::PluginJob *>(
base_job)) {
} else if (dynamic_cast<plugin::PluginJob *>(base_job)) {
VideoParams tex_params = job_tex->params();
// Force internal working format (F32) for plugin processing,
// matching FootageJob/GenerateJob behavior.
+2
View File
@@ -4,6 +4,8 @@
/* Render backend plugin ABI (oakgl / oakvulkan dlopen) */
_ZN5olive8Renderer*;
_ZTVN5olive8RendererE;
_ZTIN5olive8RendererE;
_ZTSN5olive8RendererE;
_ZN5olive11VideoParams19get_bytes_per_pixelE*;
_ZN5olive11VideoParams21get_bytes_per_channelE*;
_ZN5olive13FileFunctions19read_file_as_stringE*;
+3
View File
@@ -37,8 +37,11 @@ static const char *pixel_depth_to_ofx(core::PixelFormat format)
return kOfxBitDepthShort;
case core::PixelFormat::f16:
return kOfxBitDepthHalf;
default:
break;
case core::PixelFormat::f32:
return kOfxBitDepthFloat;
case core::PixelFormat::u10:
case core::PixelFormat::invalid:
case core::PixelFormat::count:
break;
+6 -6
View File
@@ -79,18 +79,18 @@ public:
makeDescriptor(const std::string &bundle_path,
OFX::Host::ImageEffect::ImageEffectPlugin *plugin) override;
/// vmessage
virtual OfxStatus vmessage(const char *type, const char *id,
const char *format, va_list args);
OfxStatus vmessage(const char *type, const char *id,
const char *format, va_list args) override;
/// vmessage
virtual OfxStatus setPersistentMessage(const char *type, const char *id,
const char *format, va_list args);
OfxStatus setPersistentMessage(const char *type, const char *id,
const char *format, va_list args) override;
/// vmessage
virtual OfxStatus clearPersistentMessage();
OfxStatus clearPersistentMessage() override;
#ifdef OFX_SUPPORTS_OPENGLRENDER
/// @see OfxImageEffectOpenGLRenderSuiteV1.flushResources()
virtual OfxStatus flushOpenGLResources() const
virtual OfxStatus flushOpenGLResources() const override
{
return kOfxStatFailed;
};
+3 -3
View File
@@ -209,13 +209,13 @@ public:
/// get the current time on the timeline. This is not necessarily the same
/// time as being passed to an action (eg render)
virtual double timeLineGetTime();
double timeLineGetTime() override;
/// set the timeline to a specific time
virtual void timeLineGotoTime(double t);
void timeLineGotoTime(double t) override;
/// get the first and last times available on the effect's timeline
virtual void timeLineGetBounds(double &t1, double &t2);
void timeLineGetBounds(double &t1, double &t2) override;
void setCustomInArgs(const std::string &action,
OFX::Host::Property::Set &in_args) override;
+50 -50
View File
@@ -132,7 +132,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(int &a)
OfxStatus get(int &a) override
{
if (!node_) {
std::lock_guard<std::mutex> lock(no_node_mutex_);
@@ -151,7 +151,7 @@ public:
a = 0;
return kOfxStatErrValue;
}
OfxStatus get(OfxTime time, int &data)
OfxStatus get(OfxTime time, int &data) override
{
if (!node_) {
std::lock_guard<std::mutex> lock(no_node_mutex_);
@@ -170,7 +170,7 @@ public:
data = 0;
return kOfxStatErrValue;
}
OfxStatus set(int data)
OfxStatus set(int data) override
{
if (!node_) {
std::lock_guard<std::mutex> lock(no_node_mutex_);
@@ -186,7 +186,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, int data)
OfxStatus set(OfxTime time, int data) override
{
if (!node_) {
std::lock_guard<std::mutex> lock(no_node_mutex_);
@@ -233,7 +233,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(double &data)
OfxStatus get(double &data) override
{
if (!node_) {
data = has_value_ ? value_ : 0.0;
@@ -253,7 +253,7 @@ public:
data = 0.0;
return kOfxStatErrValue;
}
OfxStatus get(OfxTime time, double &data)
OfxStatus get(OfxTime time, double &data) override
{
if (!node_) {
data = has_value_ ? value_ : 0.0;
@@ -273,7 +273,7 @@ public:
data = 0.0;
return kOfxStatErrValue;
}
OfxStatus set(double data)
OfxStatus set(double data) override
{
if (!node_) {
value_ = data;
@@ -293,7 +293,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, double data)
OfxStatus set(OfxTime time, double data) override
{
if (!node_) {
value_ = data;
@@ -313,11 +313,11 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus derive(OfxTime, double &)
OfxStatus derive(OfxTime, double &) override
{
return kOfxStatErrUnsupported;
}
OfxStatus integrate(OfxTime, OfxTime, double &)
OfxStatus integrate(OfxTime, OfxTime, double &) override
{
return kOfxStatErrUnsupported;
}
@@ -352,7 +352,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(bool &data)
OfxStatus get(bool &data) override
{
if (!node_) {
data = has_value_ ? value_ : false;
@@ -367,7 +367,7 @@ public:
data = default_value();
return kOfxStatOK;
}
OfxStatus get(OfxTime time, bool &data)
OfxStatus get(OfxTime time, bool &data) override
{
if (!node_) {
data = has_value_ ? value_ : false;
@@ -392,7 +392,7 @@ public:
data = default_value();
return kOfxStatOK;
}
OfxStatus set(bool data)
OfxStatus set(bool data) override
{
if (!node_) {
value_ = data;
@@ -406,7 +406,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, bool data)
OfxStatus set(OfxTime time, bool data) override
{
if (!node_) {
value_ = data;
@@ -452,7 +452,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(int &data)
OfxStatus get(int &data) override
{
if (!node_) {
data = has_value_ ? value_ : 0;
@@ -467,7 +467,7 @@ public:
data = 0;
return kOfxStatErrValue;
}
OfxStatus get(OfxTime time, int &data)
OfxStatus get(OfxTime time, int &data) override
{
if (!node_) {
data = has_value_ ? value_ : 0;
@@ -482,7 +482,7 @@ public:
data = 0;
return kOfxStatErrValue;
}
OfxStatus set(int data)
OfxStatus set(int data) override
{
if (!node_) {
value_ = data;
@@ -496,7 +496,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, int data)
OfxStatus set(OfxTime time, int data) override
{
if (!node_) {
value_ = data;
@@ -534,7 +534,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(double &r, double &g, double &b, double &a)
OfxStatus get(double &r, double &g, double &b, double &a) override
{
if (!node_) {
if (has_value_) {
@@ -557,7 +557,7 @@ public:
a = static_cast<double>(c.alpha());
return kOfxStatOK;
}
OfxStatus get(OfxTime time, double &r, double &g, double &b, double &a)
OfxStatus get(OfxTime time, double &r, double &g, double &b, double &a) override
{
if (!node_) {
if (has_value_) {
@@ -581,7 +581,7 @@ public:
a = static_cast<double>(c.alpha());
return kOfxStatOK;
}
OfxStatus set(double r, double g, double b, double a)
OfxStatus set(double r, double g, double b, double a) override
{
if (!node_) {
value_[0] = r;
@@ -599,7 +599,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, double r, double g, double b, double a)
OfxStatus set(OfxTime time, double r, double g, double b, double a) override
{
if (!node_) {
value_[0] = r;
@@ -646,7 +646,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(double &r, double &g, double &b)
OfxStatus get(double &r, double &g, double &b) override
{
if (!node_) {
if (has_value_) {
@@ -667,7 +667,7 @@ public:
b = static_cast<double>(c.blue());
return kOfxStatOK;
}
OfxStatus get(OfxTime time, double &r, double &g, double &b)
OfxStatus get(OfxTime time, double &r, double &g, double &b) override
{
if (!node_) {
if (has_value_) {
@@ -689,7 +689,7 @@ public:
b = static_cast<double>(c.blue());
return kOfxStatOK;
}
OfxStatus set(double r, double g, double b)
OfxStatus set(double r, double g, double b) override
{
if (!node_) {
value_[0] = r;
@@ -706,7 +706,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, double r, double g, double b)
OfxStatus set(OfxTime time, double r, double g, double b) override
{
if (!node_) {
value_[0] = r;
@@ -751,7 +751,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(double &x, double &y)
OfxStatus get(double &x, double &y) override
{
if (!node_) {
if (has_value_) {
@@ -774,7 +774,7 @@ public:
}
return kOfxStatOK;
}
OfxStatus get(OfxTime time, double &x, double &y)
OfxStatus get(OfxTime time, double &x, double &y) override
{
if (!node_) {
if (has_value_) {
@@ -798,7 +798,7 @@ public:
}
return kOfxStatOK;
}
OfxStatus set(double x, double y)
OfxStatus set(double x, double y) override
{
if (!node_) {
value_[0] = x;
@@ -820,7 +820,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, double x, double y)
OfxStatus set(OfxTime time, double x, double y) override
{
if (!node_) {
value_[0] = x;
@@ -869,7 +869,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(int &x, int &y)
OfxStatus get(int &x, int &y) override
{
if (!node_) {
if (has_value_) {
@@ -886,7 +886,7 @@ public:
y = static_cast<int>(vec.y());
return kOfxStatOK;
}
OfxStatus get(OfxTime time, int &x, int &y)
OfxStatus get(OfxTime time, int &x, int &y) override
{
if (!node_) {
if (has_value_) {
@@ -904,7 +904,7 @@ public:
y = static_cast<int>(vec.y());
return kOfxStatOK;
}
OfxStatus set(int x, int y)
OfxStatus set(int x, int y) override
{
if (!node_) {
value_[0] = x;
@@ -919,7 +919,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, int x, int y)
OfxStatus set(OfxTime time, int x, int y) override
{
if (!node_) {
value_[0] = x;
@@ -961,7 +961,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(double &x, double &y, double &z)
OfxStatus get(double &x, double &y, double &z) override
{
if (!node_) {
if (has_value_) {
@@ -987,7 +987,7 @@ public:
}
return kOfxStatOK;
}
OfxStatus get(OfxTime time, double &x, double &y, double &z)
OfxStatus get(OfxTime time, double &x, double &y, double &z) override
{
if (!node_) {
if (has_value_) {
@@ -1014,7 +1014,7 @@ public:
}
return kOfxStatOK;
}
OfxStatus set(double x, double y, double z)
OfxStatus set(double x, double y, double z) override
{
if (!node_) {
value_[0] = x;
@@ -1038,7 +1038,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, double x, double y, double z)
OfxStatus set(OfxTime time, double x, double y, double z) override
{
if (!node_) {
value_[0] = x;
@@ -1091,7 +1091,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(int &x, int &y, int &z)
OfxStatus get(int &x, int &y, int &z) override
{
if (!node_) {
if (has_value_) {
@@ -1110,7 +1110,7 @@ public:
z = static_cast<int>(vec.z());
return kOfxStatOK;
}
OfxStatus get(OfxTime time, int &x, int &y, int &z)
OfxStatus get(OfxTime time, int &x, int &y, int &z) override
{
if (!node_) {
if (has_value_) {
@@ -1130,7 +1130,7 @@ public:
z = static_cast<int>(vec.z());
return kOfxStatOK;
}
OfxStatus set(int x, int y, int z)
OfxStatus set(int x, int y, int z) override
{
if (!node_) {
value_[0] = x;
@@ -1146,7 +1146,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, int x, int y, int z)
OfxStatus set(OfxTime time, int x, int y, int z) override
{
if (!node_) {
value_[0] = x;
@@ -1198,7 +1198,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(std::string &data)
OfxStatus get(std::string &data) override
{
if (!node_) {
data = has_value_ ? value_ : std::string();
@@ -1213,7 +1213,7 @@ public:
data.clear();
return kOfxStatErrValue;
}
OfxStatus get(OfxTime time, std::string &data)
OfxStatus get(OfxTime time, std::string &data) override
{
if (!node_) {
data = has_value_ ? value_ : std::string();
@@ -1228,7 +1228,7 @@ public:
data.clear();
return kOfxStatErrValue;
}
OfxStatus set(const char *data)
OfxStatus set(const char *data) override
{
if (!node_) {
value_ = data ? data : "";
@@ -1243,7 +1243,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, const char *data)
OfxStatus set(OfxTime time, const char *data) override
{
if (!node_) {
value_ = data ? data : "";
@@ -1282,7 +1282,7 @@ public:
{
node_ = new_node;
}
OfxStatus get(std::string &data)
OfxStatus get(std::string &data) override
{
if (!node_) {
data = has_value_ ? value_ : std::string();
@@ -1301,7 +1301,7 @@ public:
data.clear();
return kOfxStatErrValue;
}
OfxStatus get(OfxTime time, std::string &data)
OfxStatus get(OfxTime time, std::string &data) override
{
if (!node_) {
data = has_value_ ? value_ : std::string();
@@ -1320,7 +1320,7 @@ public:
data.clear();
return kOfxStatErrValue;
}
OfxStatus set(const char *data)
OfxStatus set(const char *data) override
{
if (!node_) {
value_ = data ? data : "";
@@ -1335,7 +1335,7 @@ public:
submit_undo_command(node_, command, param_change_label(descriptor_));
return kOfxStatOK;
}
OfxStatus set(OfxTime time, const char *data)
OfxStatus set(OfxTime time, const char *data) override
{
if (!node_) {
value_ = data ? data : "";
+1 -1
View File
@@ -37,7 +37,7 @@ void AudioWaveformCache::write_waveform(const TimeRange &range,
const AudioVisualWaveform *waveform)
{
// Write each valid range to the segments
foreach (const TimeRange &r, valid_ranges) {
for (const TimeRange &r : valid_ranges) {
if (waveform) {
waveforms_->overwrite_sums(*waveform, r.in(), r.in() - range.in(),
r.length());
+5 -4
View File
@@ -18,7 +18,11 @@ DynamicRenderer::DynamicRenderer(const QString &backend, QObject *parent)
}
// Tears down the backend in the reverse order used by Load(): release renderer
// resources, destroy the opaque backend object, then unload the shared library.
// resources, then destroy the opaque backend object. The shared library itself
// is deliberately NOT unloaded: multiple DynamicRenderer instances can wrap the
// same backend library, and one instance's dlclose can unmap code that other
// instances (or Qt) still reference, producing calls into unmapped memory.
// Backend libraries stay mapped until process exit.
DynamicRenderer::~DynamicRenderer()
{
destroy();
@@ -27,9 +31,6 @@ DynamicRenderer::~DynamicRenderer()
destroy_(handle_);
handle_ = nullptr;
}
if (library_.isLoaded()) {
library_.unload();
}
}
// Builds the private backend library path for the current platform.
+1 -1
View File
@@ -373,7 +373,7 @@ bool DiskCacheFolder::delete_least_recent()
auto hash_to_delete = disk_data_.begin();
if (disk_data_.begin() != disk_data_.end()) {
for (auto it = disk_data_.begin() + 1; it != disk_data_.end(); it++) {
for (auto it = std::next(disk_data_.begin()); it != disk_data_.end(); it++) {
if (it->access_time < hash_to_delete->access_time) {
hash_to_delete = it;
}
+3 -2
View File
@@ -558,6 +558,8 @@ void OpenGLRenderer::blit(QVariant s, AcceleratedJob &a_job,
// over/underflows if the number is large enough, but the likelihood of that is quite low.
functions_->glUniform1i(variable_location, value.to_int());
break;
default:
break;
case NodeValue::k_float:
// kFloat technically specifies a double but as above, OpenGL doesn't support those.
functions_->glUniform1f(variable_location, value.to_double());
@@ -828,7 +830,7 @@ void OpenGLRenderer::blit(QVariant s, AcceleratedJob &a_job,
vert_vbo.destroy();
vao.release();
vao.destroy();
} catch (std::bad_cast e) {
} catch (const std::bad_cast &e) {
}
}
@@ -975,7 +977,6 @@ GLuint OpenGLRenderer::compile_shader(GLenum type, const QString &code)
{
const bool is_gles = context_ && context_->isOpenGLES();
const int major = context_ ? context_->format().majorVersion() : 0;
const int minor = context_ ? context_->format().minorVersion() : 0;
const bool is_gles2 = is_gles && (major < 3);
const QString gles_preamble =
is_gles2 ? QStringLiteral("#version 100\n\n"
+3 -3
View File
@@ -191,7 +191,7 @@ void PlaybackCache::draw(QPainter *p, const Rational &start, double scale,
{
p->fillRect(rect, Qt::red);
foreach (const TimeRange &range, get_validated_ranges()) {
for (const TimeRange &range : get_validated_ranges()) {
int range_left = rect.left() + (range.in() - start).to_double() * scale;
if (range_left >= rect.right()) {
continue;
@@ -288,11 +288,11 @@ TimeRangeList PlaybackCache::get_invalidated_ranges(TimeRange intersecting) cons
invalidated.insert(intersecting);
foreach (const TimeRange &range, validated_) {
for (const TimeRange &range : validated_) {
invalidated.remove(range);
}
foreach (const TimeRange &range, passthroughs_) {
for (const TimeRange &range : passthroughs_) {
invalidated.remove(range);
}
+16 -17
View File
@@ -69,9 +69,9 @@ static int
get_ofx_av_pixel_format(const OFX::Host::ImageEffect::Image &image,
int *bytes_per_pixel)
{
const std::string &depth =
[[maybe_unused]] const std::string &depth =
image.getStringProperty(kOfxImageEffectPropPixelDepth);
const std::string &components =
[[maybe_unused]] const std::string &components =
image.getStringProperty(kOfxImageEffectPropComponents);
olive::core::PixelFormat pixel_format = olive::core::PixelFormat::invalid;
@@ -289,7 +289,7 @@ get_destination_av_pixel_format(const olive::VideoParams &params);
// 作用:读取 clip 偏好(像素深度与分量)并更新 VideoParams。
// Purpose: Apply clip preferences (depth/components) into VideoParams.
static bool
[[maybe_unused]] static bool
apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &clip,
olive::VideoParams *params)
{
@@ -298,7 +298,7 @@ apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &cli
}
olive::core::PixelFormat format = olive::core::PixelFormat::invalid;
const std::string &depth = clip.getPixelDepth();
[[maybe_unused]] const std::string &depth = clip.getPixelDepth();
if (depth == kOfxBitDepthByte) {
format = olive::core::PixelFormat::u8;
} else if (depth == kOfxBitDepthShort) {
@@ -310,7 +310,7 @@ apply_clip_preferences_to_params(const OFX::Host::ImageEffect::ClipInstance &cli
}
int channels = 0;
const std::string &components = clip.getComponents();
[[maybe_unused]] const std::string &components = clip.getComponents();
if (components == kOfxImageComponentRGBA) {
channels = 4;
} else if (components == kOfxImageComponentRGB) {
@@ -359,6 +359,8 @@ static const char *ofx_depth_from_pixel_format(olive::core::PixelFormat format)
return kOfxBitDepthShort;
case olive::core::PixelFormat::f16:
return kOfxBitDepthHalf;
default:
break;
case olive::core::PixelFormat::f32:
return kOfxBitDepthFloat;
case olive::core::PixelFormat::invalid:
@@ -460,7 +462,7 @@ static bool params_convertible(const olive::VideoParams &params)
// 作用:在 clip 偏好无效时,选择一个插件支持的输出格式。
// Purpose: Pick a supported output format when clip preferences are invalid.
static void
[[maybe_unused]] static void
choose_supported_output_params(const OFX::Host::ImageEffect::Instance &instance,
const OFX::Host::ImageEffect::ClipInstance &clip,
const olive::VideoParams &preferred,
@@ -522,7 +524,7 @@ convert_texture_for_params(olive::TexturePtr src,
// 作用:根据插件能力与偏好选择输入格式并执行转换。
// Purpose: Select a supported input format and convert texture for the clip.
static olive::TexturePtr
[[maybe_unused]] static olive::TexturePtr
convert_texture_for_clip(const OFX::Host::ImageEffect::Instance &instance,
const OFX::Host::ImageEffect::ClipInstance &clip,
olive::TexturePtr src,
@@ -670,7 +672,7 @@ convert_texture_for_clip(const OFX::Host::ImageEffect::Instance &instance,
// 作用:从 OFX Image 复制数据到 AVFrame(按图像属性推导格式)。
// Purpose: Copy OFX Image data into an AVFrame with inferred format.
static olive::AVFramePtr
[[maybe_unused]] static olive::AVFramePtr
create_avframe_from_ofx_image(OFX::Host::ImageEffect::Image &image)
{
void *data_ptr = image.getPointerProperty(kOfxImagePropData);
@@ -1323,10 +1325,9 @@ static void log_image_props(const char *label,
int rod[4] = { 0, 0, 0, 0 };
image->getIntPropertyN(kOfxImagePropBounds, bounds, 4);
image->getIntPropertyN(kOfxImagePropRegionOfDefinition, rod, 4);
const int row_bytes = image->getIntProperty(kOfxImagePropRowBytes);
const std::string &depth =
[[maybe_unused]] const std::string &depth =
image->getStringProperty(kOfxImageEffectPropPixelDepth);
const std::string &components =
[[maybe_unused]] const std::string &components =
image->getStringProperty(kOfxImageEffectPropComponents);
/*qWarning().noquote()
<< "OFX image props" << label
@@ -1370,7 +1371,7 @@ static void schedule_error_dialog_and_undo(const QString &message)
}
}
static olive::AVFramePtr download_texture_to_frame(const olive::TexturePtr &tex)
[[maybe_unused]] static olive::AVFramePtr download_texture_to_frame(const olive::TexturePtr &tex)
{
if (!tex || tex->is_dummy() || !tex->renderer()) {
return nullptr;
@@ -1425,7 +1426,7 @@ select_best_plugin_input_format(const OFX::Host::ImageEffect::Descriptor &desc)
bool supports_f16 = false;
for (int i = 0; i < dim; ++i) {
const std::string &depth =
[[maybe_unused]] const std::string &depth =
props.getStringProperty(kOfxImageEffectPropSupportedPixelDepths, i);
if (depth == kOfxBitDepthFloat) {
supports_f32 = true;
@@ -1541,8 +1542,8 @@ void olive::plugin::PluginRenderer::render_plugin(
if (!tex->is_dummy() && tex->renderer()) {
return true;
}
AVFramePtr frame = tex->frame();
return frame && frame->data(0);
AVFramePtr av_frame = tex->frame();
return av_frame && av_frame->data(0);
};
std::map<std::string, TexturePtr> input_textures;
std::map<std::string, OliveClipInstance *> input_clips;
@@ -1817,12 +1818,10 @@ void olive::plugin::PluginRenderer::render_plugin(
}
// Diagnostic: peek at first few pixels
void *img_data = output_image->getPointerProperty(kOfxImagePropData);
bool img_black = true;
if (img_data) {
float *f = static_cast<float *>(img_data);
for (int i = 0; i < 16; ++i) {
if (f[i] != 0.0f) {
img_black = false;
break;
}
}
+1 -1
View File
@@ -36,7 +36,7 @@ void RenderJobTracker::insert(const TimeRange &range, JobTime job_time)
void RenderJobTracker::insert(const TimeRangeList &ranges, JobTime job_time)
{
foreach (const TimeRange &r, ranges) {
for (const TimeRange &r : ranges) {
insert(r, job_time);
}
}
+1 -1
View File
@@ -189,7 +189,7 @@ bool connect_node_event(olive::Node *node, int32_t event_id,
case OAKENGINE_EVENT_NODE_INPUT_DISCONNECTED: {
const bool connected =
event_id == OAKENGINE_EVENT_NODE_INPUT_CONNECTED;
auto deliver = [fn, userdata, node, connected, event_id](
auto deliver = [fn, userdata, node, event_id](
Node *output, const NodeInput &input) {
const QByteArray utf = input.input().toUtf8();
invoke(fn, userdata, event_id, node, input.element(), 0, output, 0,
+4
View File
@@ -328,7 +328,11 @@ bool video_stream_at(const olive::Footage *f, int index,
// Internal cross-family accessor (not part of the public C ABI): returns
// the borrowed project node of an import handle, or nullptr for probe
// handles and NULL. Used by the timeline editing primitives.
#if defined(_WIN32)
extern "C" void *
#else
extern "C" __attribute__((visibility("hidden"))) void *
#endif
oakengine_capi_footage_node(OakEngineFootage *h)
{
if (!h) {
+4 -4
View File
@@ -61,13 +61,13 @@ int oakengine_plugin_set_progress_reporter_factory(
oakengine_plugin_reporter_create_fn create,
oakengine_plugin_reporter_destroy_fn destroy,
oakengine_plugin_reporter_is_cancelled_fn is_cancelled,
oakengine_plugin_reporter_set_progress_fn set_progress,
oakengine_plugin_reporter_set_progress_fn set_progress_fn,
void *userdata)
{
g_reporter_create = create;
g_reporter_destroy = destroy;
g_reporter_is_cancelled = is_cancelled;
g_reporter_set_progress = set_progress;
g_reporter_set_progress = set_progress_fn;
g_reporter_userdata = userdata;
// Register factory with the engine.
@@ -90,12 +90,12 @@ int oakengine_plugin_set_progress_reporter_factory(
CAdapter(void *reporter,
oakengine_plugin_reporter_destroy_fn destroy,
oakengine_plugin_reporter_is_cancelled_fn is_cancelled,
oakengine_plugin_reporter_set_progress_fn set_progress,
oakengine_plugin_reporter_set_progress_fn set_progress_fn,
void *userdata)
: PluginProgressReporter()
, reporter_(reporter)
, destroy_(destroy)
, set_progress_(set_progress)
, set_progress_(set_progress_fn)
, userdata_(userdata) {}
~CAdapter() override
{
+7 -1
View File
@@ -2390,7 +2390,9 @@ int oakengine_clip_set_media_in(OakEngineClip *self, int64_t media_in_ts,
set_seq_error(QStringLiteral("invalid clip handle"));
return OAKENGINE_E_INVALID;
}
olive::ClipBlock *clip = reinterpret_cast<olive::ClipBlock *>(self);
const olive::Sequence *sequence =
clip->track() ? clip->track()->sequence() : nullptr;
if (!sequence) {
@@ -2427,7 +2429,9 @@ int oakengine_clip_set_media_in_rational(OakEngineClip *self, int64_t num,
set_seq_error(QStringLiteral("invalid rational denominator"));
return OAKENGINE_E_INVALID;
}
olive::ClipBlock *clip = reinterpret_cast<olive::ClipBlock *>(self);
const olive::Rational time(static_cast<int>(num), static_cast<int>(den));
if (undoable) {
push_or_run(new olive::BlockSetMediaInCommand(clip, time),
@@ -2444,7 +2448,7 @@ void oakengine_clip_request_invalidate(OakEngineClip *self, int64_t in_ts,
if (!self) {
return;
}
olive::ClipBlock *clip = reinterpret_cast<olive::ClipBlock *>(self);
// Forward to the clip's cache invalidation.
Q_UNUSED(in_ts)
Q_UNUSED(out_ts)
@@ -2489,7 +2493,9 @@ void oakengine_clip_request_invalidate_connected(OakEngineClip *self,
if (!self) {
return;
}
olive::ClipBlock *clip = reinterpret_cast<olive::ClipBlock *>(self);
olive::TimeRange intersect;
if (in_den != 0 && out_den != 0) {
intersect = olive::TimeRange(
+21 -1
View File
@@ -410,6 +410,8 @@ private:
it.key());
}
log_error(QStringLiteral("LoadGraph: deserialized ok, %1 nodes")
.arg(node_by_token.size()));
QJsonObject ack;
ack["type"] = QStringLiteral("graph_loaded");
ack["nodes"] = node_by_token.size();
@@ -449,6 +451,9 @@ private:
return true;
}
log_error(QStringLiteral("render_frame: ticket %1 node %2")
.arg(message.ticket_id)
.arg(message.node_uuid));
olive::Node *node = find_node(message.node_uuid);
if (!node) {
*response =
@@ -726,6 +731,17 @@ olive::Renderer *create_renderer(const char *backend, bool *valid)
}
if (!ctx || !ctx->isValid()) {
renderer_valid = false;
} else {
// Windows CI runners without a GPU hand back the GDI software
// OpenGL 1.1 implementation here; log what we actually got so a
// later crash in 3.2 core calls is attributable.
log_error(QStringLiteral("OpenGL context version: %1.%2 (%3)")
.arg(ctx->format().majorVersion())
.arg(ctx->format().minorVersion())
.arg(ctx->format().profile() ==
QSurfaceFormat::CoreProfile ?
"core" :
"compatibility/none"));
}
}
if (!renderer_valid) {
@@ -849,7 +865,11 @@ int oakengine_worker_session_shutdown_requested(const OakWorkerSession *self)
int oakengine_worker_main(int argc, char **argv)
{
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
// QT_OPENGL (e.g. "software" with Mesa opengl32sw.dll on GPU-less CI)
// takes precedence over this default.
if (!qEnvironmentVariableIsSet("QT_OPENGL")) {
QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
}
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
install_surface_format();
+15
View File
@@ -211,6 +211,21 @@ bool ExportTask::run()
bool ExportTask::frame_downloaded(FramePtr f, const Rational &time)
{
// The worker pool finishes tickets without a result when no worker is
// available (or every worker crashed). Grinding through the whole
// timeline at several seconds per dead worker looks like a hang, so
// fail the export after a short streak of missing frames.
if (!f) {
if (++null_frame_streak_ >= 8) {
set_error(tr("Render workers failed to deliver %1 consecutive "
"frames; aborting export")
.arg(null_frame_streak_));
return false;
}
} else {
null_frame_streak_ = 0;
}
Rational actual_time = time - export_range_.in();
time_map_.insert(actual_time, f);
+2
View File
@@ -74,6 +74,8 @@ private:
int64_t frame_time_;
int null_frame_streak_ = 0;
Rational audio_time_;
TimeRange export_range_;
+2 -2
View File
@@ -109,7 +109,7 @@ bool LoadOTIOTask::run()
// Generate a list of sequences with the same names as the timelines.
// Assumes each timeline has a unique name.
int unnamed_sequence_count = 0;
foreach (auto timeline, timelines) {
for (auto timeline : timelines) {
Sequence *sequence = new Sequence();
if (!timeline->name().empty()) {
sequence->set_label(QString::fromStdString(timeline->name()));
@@ -124,7 +124,7 @@ bool LoadOTIOTask::run()
timeline_sequnce_map.insert(timeline, sequence);
// Get number of clips for loading bar
foreach (auto track, timeline->tracks()->children()) {
for (auto track : timeline->tracks()->children()) {
auto otio_track = static_cast<OTIO::Track *>(track.value);
number_of_clips += otio_track->children().size();
}
+2 -2
View File
@@ -64,7 +64,7 @@ bool SaveOTIOTask::run()
serialized.push_back(otio_timeline);
} else {
// Delete all existing timelines
foreach (auto s, serialized) {
for (auto s : serialized) {
s->possibly_delete();
}
@@ -91,7 +91,7 @@ bool SaveOTIOTask::run()
collection->possibly_delete();
// Delete all existing timelines
foreach (auto s, serialized) {
for (auto s : serialized) {
s->possibly_delete();
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ bool RenderTask::render(ColorManager *manager, const TimeRangeList &video_range,
// Store real time before any rendering takes place
// Queue audio jobs
foreach (const TimeRange &range, audio_range) {
for (const TimeRange &range : audio_range) {
// Don't count audio progress, since it's generally a lot faster than video and is weighted at
// 50%, which makes the progress bar look weird to the uninitiated
//total_length += r.length().toDouble();
+28 -33
View File
@@ -32,6 +32,7 @@
#if defined(_WIN32)
#include <direct.h>
#include <io.h>
#include <windows.h>
#else
#include <sys/stat.h>
#include <unistd.h>
@@ -113,20 +114,18 @@ static void test_open_folder_handle(void)
EXPECT_TRUE(empty_folder == folder);
// A different path opens a distinct folder.
char tmp[256];
snprintf(tmp, sizeof(tmp),
char tmp[512];
#if defined(_WIN32)
"%s\\oakengine_disk_test_folder_XXXXXX",
#else
"%s/oakengine_disk_test_folder_XXXXXX",
#endif
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
#if defined(_WIN32)
char *tmpdir = _mktemp(tmp);
EXPECT_TRUE(tmpdir != NULL);
char base[MAX_PATH];
const DWORD len = GetTempPathA(MAX_PATH, base);
EXPECT_TRUE(len > 0 && len < MAX_PATH);
snprintf(tmp, sizeof(tmp), "%soakengine_disk_test_folder_%lu", base,
(unsigned long)GetCurrentProcessId());
char *tmpdir = tmp;
EXPECT_TRUE(_mkdir(tmpdir) == 0);
#else
snprintf(tmp, sizeof(tmp), "%s/oakengine_disk_test_folder_XXXXXX",
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
char *tmpdir = mkdtemp(tmp);
EXPECT_TRUE(tmpdir != NULL);
#endif
@@ -149,20 +148,18 @@ static void test_open_folder_handle(void)
static void test_clear_cache(void)
{
// Create a temporary cache directory and seed it with a file.
char path[256];
snprintf(path, sizeof(path),
char path[512];
#if defined(_WIN32)
"%s\\oakengine_disk_test_cache_XXXXXX",
#else
"%s/oakengine_disk_test_cache_XXXXXX",
#endif
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
#if defined(_WIN32)
char *tmpdir = _mktemp(path);
EXPECT_TRUE(tmpdir != NULL);
char base[MAX_PATH];
const DWORD len = GetTempPathA(MAX_PATH, base);
EXPECT_TRUE(len > 0 && len < MAX_PATH);
snprintf(path, sizeof(path), "%soakengine_disk_test_cache_%lu", base,
(unsigned long)GetCurrentProcessId());
char *tmpdir = path;
EXPECT_TRUE(_mkdir(tmpdir) == 0);
#else
snprintf(path, sizeof(path), "%s/oakengine_disk_test_cache_XXXXXX",
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
char *tmpdir = mkdtemp(path);
EXPECT_TRUE(tmpdir != NULL);
#endif
@@ -244,20 +241,18 @@ static void test_set_default_cache_path(void)
EXPECT_TRUE(oakengine_disk_get_default_cache_path(original, sizeof(original)) >
0);
char tmp[256];
snprintf(tmp, sizeof(tmp),
char tmp[512];
#if defined(_WIN32)
"%s\\oakengine_disk_test_default_XXXXXX",
#else
"%s/oakengine_disk_test_default_XXXXXX",
#endif
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
#if defined(_WIN32)
char *tmpdir = _mktemp(tmp);
EXPECT_TRUE(tmpdir != NULL);
char base[MAX_PATH];
const DWORD len = GetTempPathA(MAX_PATH, base);
EXPECT_TRUE(len > 0 && len < MAX_PATH);
snprintf(tmp, sizeof(tmp), "%soakengine_disk_test_default_%lu", base,
(unsigned long)GetCurrentProcessId());
char *tmpdir = tmp;
EXPECT_TRUE(_mkdir(tmpdir) == 0);
#else
snprintf(tmp, sizeof(tmp), "%s/oakengine_disk_test_default_XXXXXX",
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp");
char *tmpdir = mkdtemp(tmp);
EXPECT_TRUE(tmpdir != NULL);
#endif
+18 -1
View File
@@ -49,12 +49,27 @@
static char g_tmpdir[4096];
// The engine stores project filenames with native separators (backslashes on
// Windows); normalize a returned path to forward slashes before comparing
// against the paths these tests construct.
static void to_forward_slashes(char *s)
{
for (; *s; ++s) {
if (*s == '\\') {
*s = '/';
}
}
}
static void make_tmpdir(void)
{
#if defined(_WIN32)
char base[MAX_PATH];
const DWORD len = GetTempPathA(MAX_PATH, base);
EXPECT_TRUE(len > 0 && len < MAX_PATH);
// Resolve 8.3 short names (e.g. RUNNER~1) so string comparisons
// against engine-canonicalized paths hold.
GetLongPathNameA(base, base, MAX_PATH);
snprintf(g_tmpdir, sizeof(g_tmpdir), "%soakengine_footage_test_%lu", base,
(unsigned long)GetCurrentProcessId());
EXPECT_TRUE(_mkdir(g_tmpdir) == 0);
@@ -607,9 +622,11 @@ static void test_project_extras(void)
// set_filename round-trips through the plain filename getter.
char target[4096];
snprintf(target, sizeof(target), "%s/roundtrip.ove", g_tmpdir);
to_forward_slashes(target);
EXPECT_TRUE(oakengine_project_set_filename(project, target) == OAKENGINE_OK);
EXPECT_TRUE(oakengine_project_filename(project, buf, sizeof(buf)) > 0);
EXPECT_TRUE(strcmp(buf, target) == 0);
to_forward_slashes(buf);
EXPECT_STREQ(buf, target);
EXPECT_TRUE(oakengine_project_set_filename(project, NULL) ==
OAKENGINE_E_INVALID);
EXPECT_TRUE(oakengine_project_set_filename(NULL, target) ==
+23 -2
View File
@@ -49,12 +49,27 @@
static char g_tmpdir[4096];
// The engine stores project filenames with native separators (backslashes on
// Windows); normalize a returned path to forward slashes before comparing
// against the paths these tests construct.
static void to_forward_slashes(char *s)
{
for (; *s; ++s) {
if (*s == '\\') {
*s = '/';
}
}
}
static void make_tmpdir(void)
{
#if defined(_WIN32)
char base[MAX_PATH];
const DWORD len = GetTempPathA(MAX_PATH, base);
EXPECT_TRUE(len > 0 && len < MAX_PATH);
// Resolve 8.3 short names (e.g. RUNNER~1) so string comparisons
// against engine-canonicalized paths hold.
GetLongPathNameA(base, base, MAX_PATH);
snprintf(g_tmpdir, sizeof(g_tmpdir), "%soakengine_init_test_%lu", base,
(unsigned long)GetCurrentProcessId());
EXPECT_TRUE(_mkdir(g_tmpdir) == 0);
@@ -68,6 +83,10 @@ static void make_path(char *dst, size_t cap, const char *filename)
{
const int n = snprintf(dst, cap, "%s/%s", g_tmpdir, filename);
EXPECT_TRUE(n > 0 && (size_t)n < cap);
// g_tmpdir comes from GetTempPathA on Windows (backslashes); the
// engine's forward-slash-normalized filename must compare against the
// same form.
to_forward_slashes(dst);
}
static int file_exists(const char *path)
@@ -231,7 +250,8 @@ static void test_sequence_and_save_load(void)
char filename[4096];
EXPECT_TRUE(oakengine_project_filename(p, filename, sizeof(filename)) ==
(int)strlen(path));
EXPECT_TRUE(strcmp(filename, path) == 0);
to_forward_slashes(filename);
EXPECT_STREQ(filename, path);
// Undo removes the sequence, redo brings the same object back.
EXPECT_TRUE(oakengine_project_undo(p) == OAKENGINE_OK);
@@ -258,7 +278,8 @@ static void test_sequence_and_save_load(void)
EXPECT_TRUE(strcmp(name, "roundtrip") == 0);
EXPECT_TRUE(oakengine_project_filename(q, filename, sizeof(filename)) ==
(int)strlen(path));
EXPECT_TRUE(strcmp(filename, path) == 0);
to_forward_slashes(filename);
EXPECT_STREQ(filename, path);
// The sequence survived the round trip, workarea included (the workarea
// is serialized by ViewerOutput::save_custom()).
+2 -1
View File
@@ -19,6 +19,7 @@
***/
#include <utility>
#include "timelineundogeneral.h"
#include "node/block/clip/clip.h"
@@ -322,7 +323,7 @@ void TrackListInsertGaps::prepare()
QVector<Block *> blocks_to_append_gap_to;
QVector<Track *> tracks_to_append_gap_to;
for (Track *track : qAsConst(working_tracks_)) {
for (Track *track : std::as_const(working_tracks_)) {
for (Block *b : track->blocks()) {
if (dynamic_cast<GapBlock *>(b) && b->in() <= point_ &&
b->out() >= point_) {
+2 -1
View File
@@ -19,6 +19,7 @@
***/
#include <utility>
#include "timelineundoripple.h"
#include "timelineundocommon.h"
@@ -391,7 +392,7 @@ void TimelineRippleDeleteGapsAtRegionsCommand::prepare()
QHash<Track *, QVector<RemovalRequest>> requested_gaps;
// Convert regions to gaps
for (const QPair<Track *, TimeRange> &region : qAsConst(regions_)) {
for (const QPair<Track *, TimeRange> &region : std::as_const(regions_)) {
Track *track = region.first;
const TimeRange &range = region.second;