build: split the engine into liboakengine.so; worker drops the UI entirely
Physical split: app/{audio,cli,codec,common,config,node,pluginSupport,
render,task,timeline,undo,tool,shaders} plus coreengine, version and
ui/icons+colorcoding move to a new top-level engine/ tree, built as
liboakengine.so (shared). The render backends (oakgl/oakvulkan) move
with it and link the engine library instead of embedding a static
render-core subset (libolive-rendercore is gone).
- oak-render-worker now links liboakengine instead of the whole
libolive-editor object set: 336MB -> 2.9MB, no Qt Widgets UI
- the editor links liboakengine for the engine and keeps only UI
objects in libolive-editor
- install/packaging: GNUInstallDirs libdir on Linux, bundle copy on
macOS, oakengine.dll staged for NSIS, AppImage validation entry
- fix backend lookup for the new layout: DynamicRenderer searched
../app but backends now live in engine/; a stale pre-split liboakgl
in the build tree got dlopened instead, re-initialized and later
destroyed the interposed engine statics (full-suite segfault at
DialogSequenceParameterTab, found via gdb watchpoint)
This commit is contained in:
@@ -1,55 +0,0 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2022 Olive Team
|
||||
# Modifications Copyright (C) 2025 mikesolar
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
target_sources(libolive-editor PRIVATE
|
||||
cancelableobject.h
|
||||
commandlineparser.cpp
|
||||
commandlineparser.h
|
||||
crashpadinterface.cpp
|
||||
crashpadinterface.h
|
||||
crashpadutils.h
|
||||
current.cpp
|
||||
current.h
|
||||
debug.cpp
|
||||
debug.h
|
||||
decibel.h
|
||||
define.h
|
||||
ffmpegutils.cpp
|
||||
ffmpegutils.h
|
||||
filefunctions.cpp
|
||||
filefunctions.h
|
||||
html.cpp
|
||||
html.h
|
||||
jobtime.cpp
|
||||
jobtime.h
|
||||
lerp.h
|
||||
memorypool.h
|
||||
ocioutils.cpp
|
||||
ocioutils.h
|
||||
oiioutils.cpp
|
||||
oiioutils.h
|
||||
otioutils.h
|
||||
playbackaudioclock.h
|
||||
qtutils.cpp
|
||||
qtutils.h
|
||||
range.h
|
||||
threadsafemap.h
|
||||
tohex.h
|
||||
util.h
|
||||
xmlutils.cpp
|
||||
xmlutils.h
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_AUTOSCROLL_H
|
||||
#define OAK_AUTOSCROLL_H
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class AutoScroll {
|
||||
public:
|
||||
enum Method { k_none, k_page, k_smooth };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_AUTOSCROLL_H
|
||||
@@ -1,139 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_AVFRAMEPTR_H
|
||||
#define OAK_AVFRAMEPTR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <ffmpeg_bridge/ffmpeg_bridge.h>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief C++ adapter around the ffmpeg_bridge frame handle
|
||||
*
|
||||
* Mirrors the AVFrame field access the codebase used to perform directly,
|
||||
* but every operation goes through the pure C bridge API so the editor
|
||||
* never touches FFmpeg itself. The underlying frame object always lives
|
||||
* inside the bridge library.
|
||||
*/
|
||||
class AVFrame {
|
||||
public:
|
||||
AVFrame() :
|
||||
handle_(fb_frame_alloc())
|
||||
{
|
||||
}
|
||||
|
||||
explicit AVFrame(FBFrame *handle) :
|
||||
handle_(handle)
|
||||
{
|
||||
}
|
||||
|
||||
~AVFrame()
|
||||
{
|
||||
if (handle_) {
|
||||
fb_frame_free(&handle_);
|
||||
}
|
||||
}
|
||||
|
||||
AVFrame(const AVFrame &) = delete;
|
||||
AVFrame &operator=(const AVFrame &) = delete;
|
||||
|
||||
FBFrame *handle() const { return handle_; }
|
||||
|
||||
int width() const { return fb_frame_get_width(handle_); }
|
||||
void set_width(int w) { fb_frame_set_width(handle_, w); }
|
||||
int height() const { return fb_frame_get_height(handle_); }
|
||||
void set_height(int h) { fb_frame_set_height(handle_, h); }
|
||||
int format() const { return fb_frame_get_format(handle_); }
|
||||
void set_format(int f) { fb_frame_set_format(handle_, f); }
|
||||
int64_t pts() const { return fb_frame_get_pts(handle_); }
|
||||
void set_pts(int64_t p) { fb_frame_set_pts(handle_, p); }
|
||||
int64_t best_effort_timestamp() const
|
||||
{
|
||||
return fb_frame_get_best_effort_timestamp(handle_);
|
||||
}
|
||||
int nb_samples() const { return fb_frame_get_nb_samples(handle_); }
|
||||
void set_nb_samples(int n) { fb_frame_set_nb_samples(handle_, n); }
|
||||
int sample_rate() const { return fb_frame_get_sample_rate(handle_); }
|
||||
void set_sample_rate(int r) { fb_frame_set_sample_rate(handle_, r); }
|
||||
int color_range() const { return fb_frame_get_color_range(handle_); }
|
||||
void set_color_range(int r) { fb_frame_set_color_range(handle_, r); }
|
||||
int colorspace() const { return fb_frame_get_colorspace(handle_); }
|
||||
void set_colorspace(int cs) { fb_frame_set_colorspace(handle_, cs); }
|
||||
uint64_t channel_layout_mask() const
|
||||
{
|
||||
return fb_frame_get_channel_layout_mask(handle_);
|
||||
}
|
||||
void set_channel_layout_mask(uint64_t m)
|
||||
{
|
||||
fb_frame_set_channel_layout_mask(handle_, m);
|
||||
}
|
||||
|
||||
bool is_hw() const { return fb_frame_is_hw(handle_) != 0; }
|
||||
int hw_transfer_data(const AVFrame *src)
|
||||
{
|
||||
return fb_frame_hw_transfer_data(handle_, src->handle_);
|
||||
}
|
||||
int get_buffer(int align) { return fb_frame_get_buffer(handle_, align); }
|
||||
int make_writable() { return fb_frame_make_writable(handle_); }
|
||||
|
||||
uint8_t *data(int plane) { return fb_frame_get_data(handle_, plane); }
|
||||
const uint8_t *data(int plane) const
|
||||
{
|
||||
return fb_frame_get_data_const(handle_, plane);
|
||||
}
|
||||
void set_data(int plane, uint8_t *d)
|
||||
{
|
||||
fb_frame_set_data(handle_, plane, d);
|
||||
}
|
||||
int linesize(int plane) const
|
||||
{
|
||||
return fb_frame_get_linesize(handle_, plane);
|
||||
}
|
||||
void set_linesize(int plane, int l)
|
||||
{
|
||||
fb_frame_set_linesize(handle_, plane, l);
|
||||
}
|
||||
|
||||
private:
|
||||
FBFrame *handle_;
|
||||
};
|
||||
|
||||
using AVFramePtr = std::shared_ptr<AVFrame>;
|
||||
|
||||
inline AVFramePtr create_av_frame_ptr(FBFrame *f)
|
||||
{
|
||||
return std::make_shared<AVFrame>(f);
|
||||
}
|
||||
|
||||
inline AVFramePtr create_av_frame_ptr()
|
||||
{
|
||||
return std::make_shared<AVFrame>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_AVFRAMEPTR_H
|
||||
@@ -1,64 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_CANCELABLEOBJECT_H
|
||||
#define OAK_CANCELABLEOBJECT_H
|
||||
|
||||
#include "common/define.h"
|
||||
#include "render/cancelatom.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class CancelableObject {
|
||||
public:
|
||||
CancelableObject()
|
||||
{
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
cancel_.cancel();
|
||||
CancelEvent();
|
||||
}
|
||||
|
||||
CancelAtom *get_cancel_atom()
|
||||
{
|
||||
return &cancel_;
|
||||
}
|
||||
|
||||
bool is_cancelled()
|
||||
{
|
||||
return cancel_.is_cancelled();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void CancelEvent()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
CancelAtom cancel_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_CANCELABLEOBJECT_H
|
||||
@@ -1,179 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "commandlineparser.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
CommandLineParser::~CommandLineParser()
|
||||
{
|
||||
foreach (const KnownOption &o, options_) {
|
||||
delete o.option;
|
||||
}
|
||||
|
||||
foreach (const KnownPositionalArgument &a, positional_args_) {
|
||||
delete a.option;
|
||||
}
|
||||
}
|
||||
|
||||
const CommandLineParser::Option *
|
||||
CommandLineParser::add_option(const QStringList &strings,
|
||||
const QString &description, bool takes_arg,
|
||||
const QString &arg_placeholder, bool hidden)
|
||||
{
|
||||
Option *o = new Option();
|
||||
|
||||
options_.append(
|
||||
{ strings, description, o, takes_arg, arg_placeholder, hidden });
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
const CommandLineParser::PositionalArgument *
|
||||
CommandLineParser::add_positional_argument(const QString &name,
|
||||
const QString &description,
|
||||
bool required)
|
||||
{
|
||||
PositionalArgument *a = new PositionalArgument();
|
||||
|
||||
positional_args_.append({ name, description, a, required });
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void CommandLineParser::process(const QVector<QString> &argv)
|
||||
{
|
||||
int positional_index = 0;
|
||||
|
||||
for (int i = 1; i < argv.size(); i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
// Must be an option
|
||||
|
||||
// Skip past first dashes
|
||||
QString arg_basename = argv[i].mid(1);
|
||||
|
||||
bool matched_known = false;
|
||||
|
||||
for (int j = 0; j < options_.size(); j++) {
|
||||
KnownOption &o = options_[j];
|
||||
|
||||
foreach (const QString &s, o.args) {
|
||||
if (!s.compare(arg_basename, Qt::CaseInsensitive)) {
|
||||
// Flag discovered!
|
||||
o.option->set();
|
||||
|
||||
if (o.takes_arg && i + 1 < argv.size()) {
|
||||
o.option->set_setting(argv[i + 1]);
|
||||
i++;
|
||||
}
|
||||
|
||||
matched_known = true;
|
||||
goto found_flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found_flag:
|
||||
if (!matched_known) {
|
||||
qWarning() << "Unknown parameter:" << argv[i];
|
||||
}
|
||||
|
||||
} else {
|
||||
// Must be a positional flag
|
||||
if (positional_index < positional_args_.size()) {
|
||||
positional_args_[positional_index].option->set_setting(argv[i]);
|
||||
positional_index++;
|
||||
} else {
|
||||
qWarning() << "Unknown parameter:" << argv[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CommandLineParser::print_help(const char *filename)
|
||||
{
|
||||
printf("%s %s\n", QCoreApplication::applicationName().toUtf8().constData(),
|
||||
QCoreApplication::applicationVersion().toUtf8().constData());
|
||||
|
||||
printf("Copyright (C) 2018-2022 Oak Video Editor Team\n");
|
||||
|
||||
QString positional_args;
|
||||
for (int i = 0; i < positional_args_.size(); i++) {
|
||||
if (i > 0) {
|
||||
positional_args.append(' ');
|
||||
}
|
||||
|
||||
positional_args.append('[');
|
||||
positional_args.append(positional_args_.at(i).name);
|
||||
positional_args.append(']');
|
||||
}
|
||||
|
||||
const char *basename;
|
||||
#ifdef Q_OS_WINDOWS
|
||||
basename = strrchr(filename, '\\');
|
||||
if (!basename) {
|
||||
basename = strrchr(filename, '/');
|
||||
}
|
||||
#else
|
||||
basename = strrchr(filename, '/');
|
||||
#endif
|
||||
|
||||
if (basename) {
|
||||
// Slash found, increment pointer to avoid showing the slash itself
|
||||
basename++;
|
||||
} else {
|
||||
// If no slashes are found, assume string is already a basename
|
||||
basename = filename;
|
||||
}
|
||||
|
||||
printf("Usage: %s [options] %s\n\n", basename,
|
||||
positional_args.toUtf8().constData());
|
||||
foreach (const KnownOption &o, options_) {
|
||||
if (o.hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString all_args;
|
||||
|
||||
for (int i = 0; i < o.args.size(); i++) {
|
||||
if (i > 0) {
|
||||
all_args.append(QStringLiteral(", "));
|
||||
}
|
||||
|
||||
const QString &this_arg = o.args.at(i);
|
||||
|
||||
all_args.append('-');
|
||||
all_args.append(this_arg);
|
||||
}
|
||||
|
||||
if (o.arg_placeholder.isEmpty()) {
|
||||
printf(" %s\n", all_args.toUtf8().constData());
|
||||
} else {
|
||||
printf(" %s <%s>\n", all_args.toUtf8().constData(),
|
||||
o.arg_placeholder.toUtf8().constData());
|
||||
}
|
||||
|
||||
printf(" %s\n\n", o.description.toUtf8().constData());
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_COMMANDLINEPARSER_H
|
||||
#define OAK_COMMANDLINEPARSER_H
|
||||
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
/**
|
||||
* @brief Command-line argument parser
|
||||
*
|
||||
* You may be wondering why we don't use QCommandLineParser instead of a custom implementation like
|
||||
* this. The reason why is because QCommandLineParser requires a QApplication object of some kind
|
||||
* to already have been created before it can parse anything, but we need to be able to control
|
||||
* whether a QApplication (GUI-mode) or a QCoreApplication (CLI-mode) is created which is set by
|
||||
* the user as a command line argument. Therefore we needed a custom implementation that could
|
||||
* parse arguments without the need for a Q(Core)Application to be present already.
|
||||
*/
|
||||
class CommandLineParser {
|
||||
public:
|
||||
~CommandLineParser();
|
||||
|
||||
DISABLE_COPY_MOVE(CommandLineParser)
|
||||
|
||||
class PositionalArgument {
|
||||
public:
|
||||
PositionalArgument() = default;
|
||||
|
||||
const QString &get_setting() const
|
||||
{
|
||||
return setting_;
|
||||
}
|
||||
|
||||
void set_setting(const QString &s)
|
||||
{
|
||||
setting_ = s;
|
||||
}
|
||||
|
||||
private:
|
||||
QString setting_;
|
||||
};
|
||||
|
||||
class Option : public PositionalArgument {
|
||||
public:
|
||||
Option()
|
||||
{
|
||||
is_set_ = false;
|
||||
}
|
||||
|
||||
bool is_set() const
|
||||
{
|
||||
return is_set_;
|
||||
}
|
||||
|
||||
void set()
|
||||
{
|
||||
is_set_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_set_;
|
||||
};
|
||||
|
||||
CommandLineParser() = default;
|
||||
|
||||
const Option *add_option(const QStringList &strings,
|
||||
const QString &description, bool takes_arg = false,
|
||||
const QString &arg_placeholder = QString(),
|
||||
bool hidden = false);
|
||||
|
||||
const PositionalArgument *add_positional_argument(const QString &name,
|
||||
const QString &description,
|
||||
bool required = false);
|
||||
|
||||
void process(const QVector<QString> &argv);
|
||||
|
||||
void print_help(const char *filename);
|
||||
|
||||
private:
|
||||
struct KnownOption {
|
||||
QStringList args;
|
||||
QString description;
|
||||
Option *option;
|
||||
bool takes_arg;
|
||||
QString arg_placeholder;
|
||||
bool hidden;
|
||||
};
|
||||
|
||||
struct KnownPositionalArgument {
|
||||
QString name;
|
||||
QString description;
|
||||
PositionalArgument *option;
|
||||
bool required;
|
||||
};
|
||||
|
||||
QVector<KnownOption> options_;
|
||||
|
||||
QVector<KnownPositionalArgument> positional_args_;
|
||||
};
|
||||
|
||||
#endif // OAK_COMMANDLINEPARSER_H
|
||||
@@ -1,102 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "crashpadinterface.h"
|
||||
|
||||
#ifdef USE_CRASHPAD
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
|
||||
#include "crashpadutils.h"
|
||||
#include "filefunctions.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
crashpad::CrashpadClient *client;
|
||||
|
||||
bool InitializeCrashpad()
|
||||
{
|
||||
QString report_path = QDir(olive::FileFunctions::GetTempFilePath())
|
||||
.filePath(QStringLiteral("reports"));
|
||||
|
||||
QString handler_fn =
|
||||
olive::FileFunctions::GetFormattedExecutableForPlatform(
|
||||
QStringLiteral("crashpad_handler"));
|
||||
|
||||
// Generate absolute path
|
||||
QString handler_abs_path =
|
||||
QDir(QCoreApplication::applicationDirPath()).filePath(handler_fn);
|
||||
|
||||
bool status = false;
|
||||
|
||||
if (QFileInfo::exists(handler_abs_path)) {
|
||||
base::FilePath handler(QSTRING_TO_BASE_STRING(handler_abs_path));
|
||||
|
||||
base::FilePath reports_dir(QSTRING_TO_BASE_STRING(report_path));
|
||||
|
||||
base::FilePath metrics_dir(
|
||||
QSTRING_TO_BASE_STRING(QDir(olive::FileFunctions::GetTempFilePath())
|
||||
.filePath(QStringLiteral("metrics"))));
|
||||
|
||||
// Metadata that will be posted to the server with the crash report map
|
||||
std::map<std::string, std::string> annotations;
|
||||
|
||||
// Disable crashpad rate limiting so that all crashes have dmp files
|
||||
std::vector<std::string> arguments;
|
||||
arguments.push_back("--no-rate-limit");
|
||||
arguments.push_back("--no-upload-gzip");
|
||||
|
||||
// Initialize Crashpad database
|
||||
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
||||
crashpad::CrashReportDatabase::Initialize(reports_dir);
|
||||
if (database == NULL)
|
||||
return false;
|
||||
|
||||
// Disable automated crash uploads
|
||||
crashpad::Settings *settings = database->GetSettings();
|
||||
if (settings == NULL)
|
||||
return false;
|
||||
settings->SetUploadsEnabled(false);
|
||||
|
||||
// Start crash handler
|
||||
client = new crashpad::CrashpadClient();
|
||||
status = client->StartHandler(
|
||||
handler, reports_dir, metrics_dir,
|
||||
"https://olivevideoeditor.org/crashpad/report.php", annotations,
|
||||
arguments, true, true);
|
||||
}
|
||||
|
||||
// Override Crashpad exception filter with our own
|
||||
if (!status) {
|
||||
qWarning()
|
||||
<< "Failed to start Crashpad, automatic crash reporting will be disabled";
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif // USE_CRASHPAD
|
||||
@@ -1,33 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive 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_CRASHPAD_INTERFACE_H
|
||||
#define OAK_CRASHPAD_INTERFACE_H
|
||||
|
||||
#ifdef USE_CRASHPAD
|
||||
|
||||
#include <client/crash_report_database.h>
|
||||
#include <client/settings.h>
|
||||
|
||||
bool InitializeCrashpad();
|
||||
|
||||
#endif // USE_CRASHPAD
|
||||
|
||||
#endif // OAK_CRASHPAD_INTERFACE_H
|
||||
@@ -1,41 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_CRASHPADUTILS_H
|
||||
#define OAK_CRASHPADUTILS_H
|
||||
|
||||
#include <client/crashpad_client.h>
|
||||
|
||||
// Copied from base::FilePath to match its macro
|
||||
#if BUILDFLAG(IS_POSIX)
|
||||
// On most platforms, native pathnames are char arrays, and the encoding
|
||||
// may or may not be specified. On Mac OS X, native pathnames are encoded
|
||||
// in UTF-8.
|
||||
#define QSTRING_TO_BASE_STRING(x) x.toStdString()
|
||||
#define BASE_STRING_TO_QSTRING(x) QString::fromStdString(x)
|
||||
#elif BUILDFLAG(IS_WIN)
|
||||
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
|
||||
// arrays encoded in UTF-16.
|
||||
#define QSTRING_TO_BASE_STRING(x) x.toStdWString()
|
||||
#define BASE_STRING_TO_QSTRING(x) QString::fromStdWString(x)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#endif // OAK_CRASHPADUTILS_H
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "current.h"
|
||||
|
||||
Current Current::current;
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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_CURRENT_H
|
||||
#define OAK_CURRENT_H
|
||||
#include "pluginSupport/olivehost.h"
|
||||
#include "render/videoparams.h"
|
||||
#include "render/job/pluginjob.h"
|
||||
|
||||
class Current {
|
||||
public:
|
||||
static Current &getInstance()
|
||||
{
|
||||
return current;
|
||||
}
|
||||
olive::VideoParams ¤t_video_params()
|
||||
{
|
||||
return currentVideoParams_;
|
||||
}
|
||||
olive::AudioParams ¤t_audio_params()
|
||||
{
|
||||
return currentAudioParams_;
|
||||
}
|
||||
void setCurrentVideoParams(olive::VideoParams ¶ms)
|
||||
{
|
||||
currentVideoParams_ = params;
|
||||
}
|
||||
void setCurrentAudioParams(olive::AudioParams ¶ms)
|
||||
{
|
||||
currentAudioParams_ = params;
|
||||
}
|
||||
void setCurrentVideoParams(olive::VideoParams &¶ms)
|
||||
{
|
||||
currentVideoParams_ = params;
|
||||
}
|
||||
void setCurrentAudioParams(olive::AudioParams &¶ms)
|
||||
{
|
||||
currentAudioParams_ = params;
|
||||
}
|
||||
bool interactive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<olive::plugin::OliveHost> plugin_host()
|
||||
{
|
||||
return myHost_;
|
||||
}
|
||||
|
||||
void setPluginHost(std::shared_ptr<olive::plugin::OliveHost> host)
|
||||
{
|
||||
myHost_ = host;
|
||||
}
|
||||
|
||||
std::shared_ptr<OFX::Host::ImageEffect::PluginCache> plugin_cache()
|
||||
{
|
||||
return plugin_cache_;
|
||||
}
|
||||
|
||||
void
|
||||
setPluginCache(std::shared_ptr<OFX::Host::ImageEffect::PluginCache> cache)
|
||||
{
|
||||
plugin_cache_ = cache;
|
||||
}
|
||||
|
||||
private:
|
||||
static Current current;
|
||||
olive::VideoParams currentVideoParams_;
|
||||
olive::AudioParams currentAudioParams_;
|
||||
std::shared_ptr<olive::plugin::OliveHost> myHost_;
|
||||
std::shared_ptr<OFX::Host::ImageEffect::PluginCache> plugin_cache_;
|
||||
};
|
||||
|
||||
#endif //OAK_CURRENT_H
|
||||
@@ -1,61 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void debug_handler(QtMsgType type, const QMessageLogContext &context,
|
||||
const QString &msg)
|
||||
{
|
||||
QByteArray local_msg = msg.toLocal8Bit();
|
||||
|
||||
const char *msg_type = "UNKNOWN";
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
msg_type = "DEBUG";
|
||||
break;
|
||||
case QtInfoMsg:
|
||||
msg_type = "INFO";
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
msg_type = "WARNING";
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
msg_type = "ERROR";
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
msg_type = "FATAL";
|
||||
break;
|
||||
}
|
||||
|
||||
//fprintf(stderr, "[%s] %s (%s:%u)\n", msg_type, localMsg.constData(), context.function, context.line);
|
||||
fprintf(stderr, "[%s] %s\n", msg_type, local_msg.constData());
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// Windows still seems to buffer stderr and we want to see debug messages immediately, so here we make sure each line
|
||||
// is flushed
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_DEBUG_H
|
||||
#define OAK_DEBUG_H
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void debug_handler(QtMsgType type, const QMessageLogContext &context,
|
||||
const QString &msg);
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_DEBUG_H
|
||||
@@ -1,104 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_DECIBEL_H
|
||||
#define OAK_DECIBEL_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <cmath>
|
||||
|
||||
//#define ALLOW_RETURNING_INFINITY
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class Decibel {
|
||||
public:
|
||||
// In basically all circumstances, this should calculate to 0.0 linear
|
||||
static constexpr double minimum = -200.0;
|
||||
|
||||
static double from_linear(double linear)
|
||||
{
|
||||
double v = double(20.0) * std::log10(linear);
|
||||
#ifndef ALLOW_RETURNING_INFINITY
|
||||
if (std::isinf(v)) {
|
||||
return minimum;
|
||||
}
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
static double to_linear(double decibel)
|
||||
{
|
||||
double to_linear = std::pow(double(10.0), decibel / double(20.0));
|
||||
|
||||
// Minimum threshold that we figure is close enough to 0 that we may as well just return 0
|
||||
if (to_linear < 0.000001) {
|
||||
return 0;
|
||||
} else {
|
||||
return to_linear;
|
||||
}
|
||||
}
|
||||
|
||||
static double from_logarithmic(double logarithmic)
|
||||
{
|
||||
if (logarithmic < 0.001)
|
||||
#ifdef ALLOW_RETURNING_INFINITY
|
||||
return std::numeric_limits<double>::infinity();
|
||||
#else
|
||||
return minimum;
|
||||
#endif
|
||||
else if (logarithmic > 0.99)
|
||||
return 0;
|
||||
else
|
||||
return 20.0 * std::log10(-std::log(1 - logarithmic) / lo_g100);
|
||||
}
|
||||
|
||||
static double to_logarithmic(double decibel)
|
||||
{
|
||||
if (qFuzzyIsNull(decibel)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 1 - std::exp(-std::pow(10.0, decibel / 20.0) * lo_g100);
|
||||
}
|
||||
}
|
||||
|
||||
static double linear_to_logarithmic(double linear)
|
||||
{
|
||||
return 1 - std::exp(-linear * lo_g100);
|
||||
}
|
||||
|
||||
static double logarithmic_to_linear(double logarithmic)
|
||||
{
|
||||
if (logarithmic > 0.99) {
|
||||
return 1;
|
||||
} else {
|
||||
return -std::log(1 - logarithmic) / lo_g100;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr double lo_g100 = 4.60517018599;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_DECIBEL_H
|
||||
@@ -1,68 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_OLIVECOMMONDEFINE_H
|
||||
#define OAK_OLIVECOMMONDEFINE_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/// The minimum size an icon in ProjectExplorer can be
|
||||
const int k_project_icon_size_minimum = 16;
|
||||
|
||||
/// The maximum size an icon in ProjectExplorer can be
|
||||
const int k_project_icon_size_maximum = 256;
|
||||
|
||||
/// The default size an icon in ProjectExplorer can be
|
||||
const int k_project_icon_size_default = 64;
|
||||
|
||||
const int k_bytes_in_gigabyte = 1073741824;
|
||||
|
||||
}
|
||||
|
||||
#define MACRO_NAME_AS_STR(s) #s
|
||||
#define MACRO_VAL_AS_STR(s) MACRO_NAME_AS_STR(s)
|
||||
|
||||
#define OLIVE_NS_CONST_ARG(x, y) \
|
||||
QArgument<const olive::x>("const " MACRO_VAL_AS_STR(olive) "::" #x, y)
|
||||
#define OLIVE_NS_ARG(x, y) \
|
||||
QArgument<olive::x>(MACRO_VAL_AS_STR(olive) "::" #x, y)
|
||||
#define OLIVE_NS_RETURN_ARG(x, y) \
|
||||
QReturnArgument<olive::x>(MACRO_VAL_AS_STR(olive) "::" #x, y)
|
||||
|
||||
/**
|
||||
* Copy/move deleters. Similar to Q_DISABLE_COPY_MOVE, et al. but those functions are not present in Qt < 5.13 so we
|
||||
* use our own functions for portability.
|
||||
*/
|
||||
|
||||
#define DISABLE_COPY(Class) \
|
||||
Class(const Class &) = delete; \
|
||||
Class &operator=(const Class &) = delete;
|
||||
|
||||
#define DISABLE_MOVE(Class) \
|
||||
Class(Class &&) = delete; \
|
||||
Class &operator=(Class &&) = delete;
|
||||
|
||||
#define DISABLE_COPY_MOVE(Class) \
|
||||
DISABLE_COPY(Class) \
|
||||
DISABLE_MOVE(Class)
|
||||
|
||||
#endif // OAK_OLIVECOMMONDEFINE_H
|
||||
@@ -1,47 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_DIGIT_H
|
||||
#define OAK_DIGIT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
inline int64_t get_digit_count(int64_t input)
|
||||
{
|
||||
input = std::abs(input);
|
||||
|
||||
int64_t lim = 10;
|
||||
int64_t digit = 1;
|
||||
|
||||
while (input >= lim) {
|
||||
lim *= 10;
|
||||
digit++;
|
||||
}
|
||||
|
||||
return digit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_DIGIT_H
|
||||
@@ -1,43 +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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_DROPWORKFLOWBEHAVIOR_H
|
||||
#define OAK_DROPWORKFLOWBEHAVIOR_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Behavior when media is dropped onto a timeline without a sequence
|
||||
*
|
||||
* Shared by the config defaults (engine layer) and the timeline import
|
||||
* tool (UI layer). Enumerator order matches the previous
|
||||
* ImportTool::DropWithoutSequenceBehavior.
|
||||
*/
|
||||
enum DropWithoutSequenceBehavior {
|
||||
k_dws_ask,
|
||||
k_dws_auto,
|
||||
k_dws_manual,
|
||||
k_dws_disable
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_DROPWORKFLOWBEHAVIOR_H
|
||||
@@ -1,197 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "common/ffmpegutils.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
int FFmpegUtils::get_compatible_bridge_pixel_format(int pix_fmt,
|
||||
PixelFormat maximum)
|
||||
{
|
||||
int possible_pix_fmts[4];
|
||||
|
||||
possible_pix_fmts[0] = fb_pix_fmt_rgba;
|
||||
|
||||
if (maximum == PixelFormat::u8) {
|
||||
possible_pix_fmts[1] = fb_pix_fmt_none;
|
||||
} else {
|
||||
possible_pix_fmts[1] = fb_pix_fmt_rgb_a64_le;
|
||||
if (maximum == PixelFormat::f32) {
|
||||
possible_pix_fmts[2] = fb_pix_fmt_rgba_f32_le;
|
||||
possible_pix_fmts[3] = fb_pix_fmt_none;
|
||||
} else {
|
||||
possible_pix_fmts[2] = fb_pix_fmt_none;
|
||||
}
|
||||
}
|
||||
|
||||
return fb_find_best_pix_fmt_of_list(possible_pix_fmts, pix_fmt);
|
||||
}
|
||||
|
||||
SampleFormat FFmpegUtils::get_native_sample_format(int smp_fmt)
|
||||
{
|
||||
switch (smp_fmt) {
|
||||
case fb_sample_fmt_u8:
|
||||
return SampleFormat::u8;
|
||||
case fb_sample_fmt_s16:
|
||||
return SampleFormat::s16;
|
||||
case fb_sample_fmt_s32:
|
||||
return SampleFormat::s32;
|
||||
case fb_sample_fmt_s64:
|
||||
return SampleFormat::s64;
|
||||
case fb_sample_fmt_flt:
|
||||
return SampleFormat::f32;
|
||||
case fb_sample_fmt_dbl:
|
||||
return SampleFormat::f64;
|
||||
case fb_sample_fmt_u8_p:
|
||||
return SampleFormat::u8_p;
|
||||
case fb_sample_fmt_s16_p:
|
||||
return SampleFormat::s16_p;
|
||||
case fb_sample_fmt_s32_p:
|
||||
return SampleFormat::s32_p;
|
||||
case fb_sample_fmt_s64_p:
|
||||
return SampleFormat::s64_p;
|
||||
case fb_sample_fmt_fltp:
|
||||
return SampleFormat::f32_p;
|
||||
case fb_sample_fmt_dblp:
|
||||
return SampleFormat::f64_p;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SampleFormat::invalid;
|
||||
}
|
||||
|
||||
int FFmpegUtils::get_f_fmpeg_sample_format(const SampleFormat &smp_fmt)
|
||||
{
|
||||
switch (smp_fmt) {
|
||||
case SampleFormat::u8:
|
||||
return fb_sample_fmt_u8;
|
||||
case SampleFormat::s16:
|
||||
return fb_sample_fmt_s16;
|
||||
case SampleFormat::s32:
|
||||
return fb_sample_fmt_s32;
|
||||
case SampleFormat::s64:
|
||||
return fb_sample_fmt_s64;
|
||||
case SampleFormat::f32:
|
||||
return fb_sample_fmt_flt;
|
||||
case SampleFormat::f64:
|
||||
return fb_sample_fmt_dbl;
|
||||
case SampleFormat::u8_p:
|
||||
return fb_sample_fmt_u8_p;
|
||||
case SampleFormat::s16_p:
|
||||
return fb_sample_fmt_s16_p;
|
||||
case SampleFormat::s32_p:
|
||||
return fb_sample_fmt_s32_p;
|
||||
case SampleFormat::s64_p:
|
||||
return fb_sample_fmt_s64_p;
|
||||
case SampleFormat::f32_p:
|
||||
return fb_sample_fmt_fltp;
|
||||
case SampleFormat::f64_p:
|
||||
return fb_sample_fmt_dblp;
|
||||
case SampleFormat::invalid:
|
||||
case SampleFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return fb_sample_fmt_none;
|
||||
}
|
||||
|
||||
int FFmpegUtils::convert_jpeg_space_to_regular_space(int f)
|
||||
{
|
||||
switch (f) {
|
||||
case fb_pix_fmt_yuv_j420_p:
|
||||
return fb_pix_fmt_yu_v420_p;
|
||||
case fb_pix_fmt_yuv_j422_p:
|
||||
return fb_pix_fmt_yu_v422_p;
|
||||
case fb_pix_fmt_yuv_j444_p:
|
||||
return fb_pix_fmt_yu_v444_p;
|
||||
case fb_pix_fmt_yuv_j440_p:
|
||||
return fb_pix_fmt_yu_v440_p;
|
||||
case fb_pix_fmt_yuv_j411_p:
|
||||
return fb_pix_fmt_yu_v411_p;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int FFmpegUtils::get_f_fmpeg_pixel_format(const PixelFormat &pix_fmt,
|
||||
int channel_layout)
|
||||
{
|
||||
if (channel_layout == VideoParams::k_rgb_channel_count) {
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::u8:
|
||||
return fb_pix_fmt_rg_b24;
|
||||
case PixelFormat::u10:
|
||||
return fb_pix_fmt_none;
|
||||
case PixelFormat::u16:
|
||||
return fb_pix_fmt_rg_b48_le;
|
||||
case PixelFormat::f16:
|
||||
return fb_pix_fmt_rgb_f16_le;
|
||||
case PixelFormat::f32:
|
||||
return fb_pix_fmt_rgb_f32_le;
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
} else if (channel_layout == VideoParams::k_rgba_channel_count) {
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::u8:
|
||||
return fb_pix_fmt_rgba;
|
||||
case PixelFormat::u10:
|
||||
return fb_pix_fmt_none;
|
||||
case PixelFormat::u16:
|
||||
return fb_pix_fmt_rgb_a64_le;
|
||||
case PixelFormat::f16:
|
||||
return fb_pix_fmt_rgba_f16_le;
|
||||
case PixelFormat::f32:
|
||||
return fb_pix_fmt_rgba_f32_le;
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fb_pix_fmt_none;
|
||||
}
|
||||
|
||||
PixelFormat FFmpegUtils::get_compatible_pixel_format(const PixelFormat &pix_fmt)
|
||||
{
|
||||
switch (pix_fmt) {
|
||||
case PixelFormat::u8:
|
||||
return PixelFormat::u8;
|
||||
case PixelFormat::u10:
|
||||
return PixelFormat::u8;
|
||||
case PixelFormat::u16:
|
||||
case PixelFormat::f16:
|
||||
case PixelFormat::f32:
|
||||
return PixelFormat::u16;
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return PixelFormat::invalid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_FFMPEGABSTRACTION_H
|
||||
#define OAK_FFMPEGABSTRACTION_H
|
||||
|
||||
#include <ffmpeg_bridge/ffmpeg_bridge.h>
|
||||
|
||||
#include <olive/core/core.h>
|
||||
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
using namespace core;
|
||||
|
||||
/**
|
||||
* @brief C++ adapter mapping Olive's native enums to bridge pixel/sample
|
||||
* formats
|
||||
*
|
||||
* All "FFmpeg" formats here are actually the opaque FBPixelFormat /
|
||||
* FBSampleFormat constants of the ffmpeg_bridge library; no FFmpeg header
|
||||
* or structure is ever seen by the editor.
|
||||
*/
|
||||
class FFmpegUtils {
|
||||
public:
|
||||
/**
|
||||
* @brief Returns a bridge pixel format that can be used to convert a frame to a data type Olive supports with minimal data loss
|
||||
*
|
||||
* Named distinctly from the native PixelFormat overload below: with both
|
||||
* taking a single argument, an unscoped enum argument would silently
|
||||
* prefer an int overload over the PixelFormat one.
|
||||
*/
|
||||
static int get_compatible_bridge_pixel_format(
|
||||
int pix_fmt, PixelFormat maximum = PixelFormat::invalid);
|
||||
|
||||
/**
|
||||
* @brief Returns a native pixel format that can be used to convert from a native frame to a bridge frame with minimal data loss
|
||||
*/
|
||||
static PixelFormat get_compatible_pixel_format(const PixelFormat &pix_fmt);
|
||||
|
||||
/**
|
||||
* @brief Returns a bridge pixel format for a given native pixel format
|
||||
*/
|
||||
static int get_f_fmpeg_pixel_format(const PixelFormat &pix_fmt,
|
||||
int channel_layout);
|
||||
|
||||
/**
|
||||
* @brief Returns a native sample format type for a given bridge sample format
|
||||
*/
|
||||
static SampleFormat get_native_sample_format(int smp_fmt);
|
||||
|
||||
/**
|
||||
* @brief Returns a bridge sample format type for a given native type
|
||||
*/
|
||||
static int get_f_fmpeg_sample_format(const SampleFormat &smp_fmt);
|
||||
|
||||
/**
|
||||
* @brief Convert "JPEG"/full-range colorspace to its regular counterpart
|
||||
*
|
||||
* "JPEG "spaces are deprecated in favor of the regular space and setting `color_range`. For the
|
||||
* time being, FFmpeg still uses these JPEG spaces, so for simplicity (since we *are* color_range
|
||||
* aware), we use this function.
|
||||
*/
|
||||
static int convert_jpeg_space_to_regular_space(int f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_FFMPEGABSTRACTION_H
|
||||
@@ -1,253 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "filefunctions.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include "config/config.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
QString FileFunctions::get_unique_file_identifier(const QString &filename)
|
||||
{
|
||||
QFileInfo info(filename);
|
||||
|
||||
if (!info.exists()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
|
||||
hash.addData(info.absoluteFilePath().toUtf8());
|
||||
|
||||
hash.addData(
|
||||
QString::number(info.lastModified().toMSecsSinceEpoch()).toUtf8());
|
||||
|
||||
QByteArray result = hash.result();
|
||||
|
||||
return QString(result.toHex());
|
||||
}
|
||||
|
||||
QString FileFunctions::get_configuration_location()
|
||||
{
|
||||
if (is_portable()) {
|
||||
return get_application_path();
|
||||
} else {
|
||||
QString s =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir(s).mkpath(".");
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileFunctions::is_portable()
|
||||
{
|
||||
return QFileInfo::exists(QDir(get_application_path()).filePath("portable"));
|
||||
}
|
||||
|
||||
QString FileFunctions::get_application_path()
|
||||
{
|
||||
return QCoreApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
QString FileFunctions::get_temp_file_path()
|
||||
{
|
||||
QString temp_path =
|
||||
QDir(
|
||||
QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation))
|
||||
.filePath(QCoreApplication::organizationName()))
|
||||
.filePath(QCoreApplication::applicationName());
|
||||
|
||||
// Ensure it exists
|
||||
QDir(temp_path).mkpath(".");
|
||||
|
||||
return temp_path;
|
||||
}
|
||||
|
||||
bool FileFunctions::can_copy_directory_without_overwriting(const QString &source,
|
||||
const QString &dest)
|
||||
{
|
||||
QFileInfoList info_list = QDir(source).entryInfoList();
|
||||
|
||||
foreach (const QFileInfo &info, info_list) {
|
||||
// QDir::NoDotAndDotDot continues to not work, so we have to check manually
|
||||
if (info.fileName() == QStringLiteral(".") ||
|
||||
info.fileName() == QStringLiteral("..")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString dest_equivalent = QDir(dest).filePath(info.fileName());
|
||||
|
||||
if (info.isDir()) {
|
||||
if (!can_copy_directory_without_overwriting(info.absoluteFilePath(),
|
||||
dest_equivalent)) {
|
||||
return false;
|
||||
}
|
||||
} else if (QFileInfo::exists(dest_equivalent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileFunctions::copy_directory(const QString &source, const QString &dest,
|
||||
bool overwrite)
|
||||
{
|
||||
QDir d(source);
|
||||
|
||||
if (!d.exists()) {
|
||||
qCritical()
|
||||
<< "Failed to copy directory, source" << source << "didn't exist";
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dest_dir(dest);
|
||||
|
||||
if (!dest_dir.mkpath(QStringLiteral("."))) {
|
||||
qCritical() << "Failed to create destination directory" << dest;
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfoList l = d.entryInfoList();
|
||||
|
||||
foreach (const QFileInfo &info, l) {
|
||||
// QDir::NoDotAndDotDot continues to not work, so we have to check manually
|
||||
if (info.fileName() == QStringLiteral(".") ||
|
||||
info.fileName() == QStringLiteral("..")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString dest_file_path = dest_dir.filePath(info.fileName());
|
||||
|
||||
if (info.isDir()) {
|
||||
// Copy dir
|
||||
copy_directory(info.absoluteFilePath(), dest_file_path, overwrite);
|
||||
} else {
|
||||
// Copy file
|
||||
if (overwrite && QFile::exists(dest_file_path)) {
|
||||
QFile file(dest_file_path);
|
||||
file.setPermissions(
|
||||
file.permissions() | QFileDevice::WriteOwner |
|
||||
QFileDevice::WriteUser | QFileDevice::WriteGroup |
|
||||
QFileDevice::WriteOther);
|
||||
file.remove();
|
||||
}
|
||||
|
||||
QFile::copy(info.absoluteFilePath(), dest_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FileFunctions::directory_is_valid(const QDir &d,
|
||||
bool try_to_create_if_not_exists)
|
||||
{
|
||||
// Return whether the directory exists, or whether it could be created if it doesn't
|
||||
return d.exists() ||
|
||||
(try_to_create_if_not_exists && d.mkpath(QStringLiteral(".")));
|
||||
}
|
||||
|
||||
QString FileFunctions::ensure_filename_extension(QString fn,
|
||||
const QString &extension)
|
||||
{
|
||||
// No-op if either input is empty
|
||||
if (!fn.isEmpty() && !extension.isEmpty()) {
|
||||
QString extension_with_dot;
|
||||
|
||||
extension_with_dot.append('.');
|
||||
extension_with_dot.append(extension);
|
||||
|
||||
if (!fn.endsWith(extension_with_dot, Qt::CaseInsensitive)) {
|
||||
fn.append(extension_with_dot);
|
||||
}
|
||||
}
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
QString FileFunctions::read_file_as_string(const QString &filename)
|
||||
{
|
||||
QFile f(filename);
|
||||
QString file_data;
|
||||
if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream text_stream(&f);
|
||||
file_data = text_stream.readAll();
|
||||
f.close();
|
||||
}
|
||||
return file_data;
|
||||
}
|
||||
|
||||
QString FileFunctions::get_safe_temporary_filename(const QString &original)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
QFileInfo original_info(original);
|
||||
QString basename = original_info.baseName();
|
||||
QString complete_suffix = original_info.completeSuffix();
|
||||
|
||||
// If we have a complete suffix, make sure there's a period in it
|
||||
if (!complete_suffix.isEmpty()) {
|
||||
complete_suffix.prepend('.');
|
||||
}
|
||||
|
||||
QString temp_abs_path;
|
||||
do {
|
||||
temp_abs_path = original_info.dir().filePath(
|
||||
QStringLiteral("%1.tmp%2%3")
|
||||
.arg(basename, QString::number(counter), complete_suffix));
|
||||
counter++;
|
||||
} while (QFileInfo::exists(temp_abs_path));
|
||||
|
||||
return temp_abs_path;
|
||||
}
|
||||
|
||||
bool FileFunctions::rename_file_allow_overwrite(const QString &from,
|
||||
const QString &to)
|
||||
{
|
||||
if (QFileInfo::exists(to) && !QFile::remove(to)) {
|
||||
qCritical() << "Couldn't remove existing file" << to << "for overwrite";
|
||||
return false;
|
||||
}
|
||||
|
||||
// By this point, we can assume `to` either never existed or has now been deleted
|
||||
if (!QFile::rename(from, to)) {
|
||||
qCritical() << "Failed to rename file" << from << "to" << to;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString FileFunctions::get_auto_recovery_root()
|
||||
{
|
||||
return QDir(QStandardPaths::writableLocation(
|
||||
QStandardPaths::AppLocalDataLocation))
|
||||
.filePath(QStringLiteral("autorecovery"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_FILEFUNCTIONS_H
|
||||
#define OAK_FILEFUNCTIONS_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QString>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A collection of static file and directory functions
|
||||
*/
|
||||
class FileFunctions {
|
||||
public:
|
||||
/**
|
||||
* @brief Returns true if the application is running in portable mode
|
||||
*
|
||||
* In portable mode, any persistent configuration files should be made in a path relative to the application rather
|
||||
* than in the user's home folder.
|
||||
*/
|
||||
static bool is_portable();
|
||||
|
||||
static QString get_unique_file_identifier(const QString &filename);
|
||||
|
||||
static QString get_configuration_location();
|
||||
|
||||
static QString get_application_path();
|
||||
|
||||
static QString get_temp_file_path();
|
||||
|
||||
static bool can_copy_directory_without_overwriting(const QString &source,
|
||||
const QString &dest);
|
||||
|
||||
static void copy_directory(const QString &source, const QString &dest,
|
||||
bool overwrite = false);
|
||||
|
||||
static bool directory_is_valid(const QDir &dir,
|
||||
bool try_to_create_if_not_exists = true);
|
||||
|
||||
/**
|
||||
* @brief Ensures a given filename has a certain extension
|
||||
*
|
||||
* Checks if the filename has the extension provided and appends it if not. The extension is
|
||||
* checked case-insensitive. The extension should be provided with no dot (e.g. "ove" rather than
|
||||
* ".ove").
|
||||
|
||||
* @return The filename provided either untouched or with the extension appended to it.
|
||||
*/
|
||||
static QString ensure_filename_extension(QString fn,
|
||||
const QString &extension);
|
||||
|
||||
static QString read_file_as_string(const QString &filename);
|
||||
|
||||
/**
|
||||
* @brief Returns a temporary filename that can be used while writing rather than the original
|
||||
*
|
||||
* If overwriting a file, it's safest to write to a new file first and then only replace it at
|
||||
* the end so that if the program crashes or the user cancels the save half way through, the
|
||||
* original file is still intact.
|
||||
*
|
||||
* This function returns a slight variant of the filename provided that's guaranteed to not exist
|
||||
* and therefore won't overwrite anything important.
|
||||
*/
|
||||
static QString get_safe_temporary_filename(const QString &original);
|
||||
|
||||
/**
|
||||
* @brief Renames a file from `from` to `to`, deleting `to` if such a file already exists first
|
||||
*/
|
||||
static bool rename_file_allow_overwrite(const QString &from,
|
||||
const QString &to);
|
||||
|
||||
inline static QString get_formatted_executable_for_platform(QString unformatted)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
unformatted.append(QStringLiteral(".exe"));
|
||||
#endif
|
||||
|
||||
return unformatted;
|
||||
}
|
||||
|
||||
static QString get_auto_recovery_root();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_FILEFUNCTIONS_H
|
||||
@@ -1,494 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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/>.
|
||||
*/
|
||||
|
||||
#include "html.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTextBlock>
|
||||
|
||||
#include "xmlutils.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const QVector<QString> Html::k_block_tags = { QStringLiteral("p"),
|
||||
QStringLiteral("div") };
|
||||
|
||||
inline bool str_equals(const QStringView &a, const QStringView &b)
|
||||
{
|
||||
return !a.compare(b, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QString Html::doc_to_html(const QTextDocument *doc)
|
||||
{
|
||||
QString html;
|
||||
QXmlStreamWriter writer(&html);
|
||||
|
||||
//writer.setAutoFormatting(true);
|
||||
|
||||
for (auto it = doc->begin(); it != doc->end(); it = it.next()) {
|
||||
write_block(&writer, it);
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
struct HtmlNode {
|
||||
QString tag;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
|
||||
QTextCharFormat merge_html_formats(const QVector<HtmlNode> &stack)
|
||||
{
|
||||
QTextCharFormat f;
|
||||
|
||||
for (int i = 0; i < stack.size(); i++) {
|
||||
f.merge(stack.at(i).format);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void Html::html_to_doc(QTextDocument *doc, const QString &html)
|
||||
{
|
||||
// Empty doc
|
||||
doc->clear();
|
||||
bool inside_block = true;
|
||||
|
||||
// Create cursor, which appears to be Qt's official way of inserting blocks and fragments
|
||||
QTextCursor c(doc);
|
||||
|
||||
QString wrapped = QStringLiteral("<html>").append(html).append("</html>");
|
||||
QXmlStreamReader reader(wrapped);
|
||||
|
||||
QVector<HtmlNode> fmt_stack;
|
||||
|
||||
QTextCharFormat default_fmt;
|
||||
default_fmt.setFontWeight(QFont::Normal);
|
||||
fmt_stack.append({ QStringLiteral("html"), default_fmt });
|
||||
|
||||
QTextCharFormat current_fmt;
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement) {
|
||||
QString tag = reader.name().toString().toLower();
|
||||
|
||||
fmt_stack.append({ tag, read_char_format(reader.attributes()) });
|
||||
current_fmt = merge_html_formats(fmt_stack);
|
||||
|
||||
if (k_block_tags.contains(tag)) {
|
||||
QTextBlockFormat block_fmt =
|
||||
read_block_format(reader.attributes());
|
||||
if (inside_block) {
|
||||
c.setBlockFormat(block_fmt);
|
||||
c.setBlockCharFormat(current_fmt);
|
||||
} else {
|
||||
c.insertBlock(block_fmt, current_fmt);
|
||||
inside_block = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (reader.tokenType() == QXmlStreamReader::Characters) {
|
||||
QString characters = reader.text().toString();
|
||||
c.insertText(characters, current_fmt);
|
||||
|
||||
} else if (reader.tokenType() == QXmlStreamReader::EndElement) {
|
||||
QString tag = reader.name().toString().toLower();
|
||||
|
||||
for (int i = fmt_stack.size() - 1; i >= 0; i--) {
|
||||
if (fmt_stack.at(i).tag == tag) {
|
||||
fmt_stack.removeAt(i);
|
||||
current_fmt = merge_html_formats(fmt_stack);
|
||||
|
||||
if (k_block_tags.contains(tag)) {
|
||||
inside_block = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.error()) {
|
||||
qCritical() << "Failed to parse HTML:" << reader.errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void Html::write_block(QXmlStreamWriter *writer, const QTextBlock &block)
|
||||
{
|
||||
writer->writeStartElement(QStringLiteral("p"));
|
||||
|
||||
const QTextBlockFormat &fmt = block.blockFormat();
|
||||
|
||||
// Write block alignment
|
||||
if (!(fmt.alignment() & Qt::AlignLeft)) {
|
||||
if (fmt.alignment() & Qt::AlignRight) {
|
||||
writer->writeAttribute(QStringLiteral("align"),
|
||||
QStringLiteral("right"));
|
||||
} else if (fmt.alignment() & Qt::AlignHCenter) {
|
||||
writer->writeAttribute(QStringLiteral("align"),
|
||||
QStringLiteral("center"));
|
||||
} else if (fmt.alignment() & Qt::AlignJustify) {
|
||||
writer->writeAttribute(QStringLiteral("align"),
|
||||
QStringLiteral("justify"));
|
||||
}
|
||||
}
|
||||
|
||||
// RTL support
|
||||
if (block.textDirection() == Qt::RightToLeft) {
|
||||
writer->writeAttribute(QStringLiteral("dir"), QStringLiteral("rtl"));
|
||||
}
|
||||
|
||||
// Write CSS attributes
|
||||
QString style;
|
||||
|
||||
if (fmt.lineHeightType() != QTextBlockFormat::SingleHeight) {
|
||||
write_css_property(&style, QStringLiteral("line-height"),
|
||||
QStringLiteral("%1%").arg(fmt.lineHeight()));
|
||||
}
|
||||
|
||||
write_char_format(&style, block.charFormat());
|
||||
|
||||
if (!style.isEmpty()) {
|
||||
writer->writeAttribute(QStringLiteral("style"), style);
|
||||
}
|
||||
|
||||
auto it = block.begin();
|
||||
|
||||
if (it != block.end()) {
|
||||
for (; it != block.end(); it++) {
|
||||
write_fragment(writer, it.fragment());
|
||||
}
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // p
|
||||
}
|
||||
|
||||
void Html::write_fragment(QXmlStreamWriter *writer,
|
||||
const QTextFragment &fragment)
|
||||
{
|
||||
const QTextCharFormat &fmt = fragment.charFormat();
|
||||
|
||||
writer->writeStartElement(QStringLiteral("span"));
|
||||
|
||||
// Write CSS attributes
|
||||
QString style;
|
||||
|
||||
write_char_format(&style, fmt);
|
||||
|
||||
if (!style.isEmpty()) {
|
||||
writer->writeAttribute(QStringLiteral("style"), style);
|
||||
}
|
||||
|
||||
QStringList lines = fragment.text().split(QChar::LineSeparator);
|
||||
bool first_line = true;
|
||||
foreach (const QString &l, lines) {
|
||||
if (first_line) {
|
||||
first_line = false;
|
||||
} else {
|
||||
writer->writeEmptyElement(QStringLiteral("br"));
|
||||
}
|
||||
writer->writeCharacters(l);
|
||||
}
|
||||
|
||||
writer->writeEndElement(); // span
|
||||
}
|
||||
|
||||
void Html::write_css_property(QString *style, const QString &key,
|
||||
const QStringList &values)
|
||||
{
|
||||
QString value;
|
||||
foreach (QString v, values) {
|
||||
if (v.contains(' ')) {
|
||||
v = QStringLiteral("'%1'").arg(v);
|
||||
}
|
||||
|
||||
append_string_auto_space(&value, v);
|
||||
}
|
||||
|
||||
append_string_auto_space(style, QStringLiteral("%1: %2;").arg(key, value));
|
||||
}
|
||||
|
||||
void Html::write_char_format(QString *style, const QTextCharFormat &fmt)
|
||||
{
|
||||
QStringList families = fmt.fontFamilies().toStringList();
|
||||
if (!families.isEmpty()) {
|
||||
write_css_property(style, QStringLiteral("font-family"),
|
||||
families.first());
|
||||
}
|
||||
|
||||
if (fmt.hasProperty(QTextFormat::FontPointSize)) {
|
||||
write_css_property(
|
||||
style, QStringLiteral("font-size"),
|
||||
QStringLiteral("%1pt").arg(QString::number(fmt.fontPointSize())));
|
||||
}
|
||||
|
||||
if (fmt.hasProperty(QTextFormat::FontWeight)) {
|
||||
write_css_property(style, QStringLiteral("font-weight"),
|
||||
QString::number(fmt.fontWeight() * 8));
|
||||
}
|
||||
|
||||
if (fmt.hasProperty(QTextFormat::FontItalic)) {
|
||||
write_css_property(style, QStringLiteral("font-style"),
|
||||
fmt.fontItalic() ? QStringLiteral("italic") :
|
||||
QStringLiteral("normal"));
|
||||
}
|
||||
|
||||
if (fmt.hasProperty(QTextFormat::FontStyleName)) {
|
||||
write_css_property(style, QStringLiteral("-ove-font-style"),
|
||||
fmt.fontStyleName().toString());
|
||||
}
|
||||
|
||||
QStringList deco;
|
||||
|
||||
if (fmt.fontUnderline()) {
|
||||
deco.append(QStringLiteral("underline"));
|
||||
}
|
||||
|
||||
if (fmt.fontStrikeOut()) {
|
||||
deco.append(QStringLiteral("line-through"));
|
||||
}
|
||||
|
||||
if (fmt.fontOverline()) {
|
||||
deco.append(QStringLiteral("overline"));
|
||||
}
|
||||
|
||||
if (!deco.isEmpty()) {
|
||||
write_css_property(style, QStringLiteral("text-decoration"), deco);
|
||||
}
|
||||
|
||||
if (fmt.foreground().style() != Qt::NoBrush) {
|
||||
const QColor &color = fmt.foreground().color();
|
||||
QString cs;
|
||||
|
||||
if (color.alpha() == 255) {
|
||||
cs = color.name();
|
||||
} else if (color.alpha()) {
|
||||
cs = QStringLiteral("rgba(%1, %2, %3, %4)")
|
||||
.arg(QString::number(color.red()),
|
||||
QString::number(color.green()),
|
||||
QString::number(color.blue()),
|
||||
QString::number(color.alphaF()));
|
||||
}
|
||||
|
||||
write_css_property(style, QStringLiteral("color"), cs);
|
||||
}
|
||||
|
||||
if (fmt.fontCapitalization() != QFont::MixedCase) {
|
||||
if (fmt.fontCapitalization() == QFont::SmallCaps) {
|
||||
write_css_property(style, QStringLiteral("font-variant"),
|
||||
QStringLiteral("small-caps"));
|
||||
// TODO: Add others
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt.fontLetterSpacing() != 0.0) {
|
||||
write_css_property(style, QStringLiteral("letter-spacing"),
|
||||
QStringLiteral("%1%").arg(
|
||||
QString::number(fmt.fontLetterSpacing())));
|
||||
}
|
||||
|
||||
if (fmt.fontStretch() != 0) {
|
||||
write_css_property(
|
||||
style, QStringLiteral("font-stretch"),
|
||||
QStringLiteral("%1%").arg(QString::number(fmt.fontStretch())));
|
||||
}
|
||||
}
|
||||
|
||||
QTextCharFormat Html::read_char_format(const QXmlStreamAttributes &attributes)
|
||||
{
|
||||
QTextCharFormat fmt;
|
||||
|
||||
foreach (const QXmlStreamAttribute &attr, attributes) {
|
||||
if (str_equals(attr.name(), QStringLiteral("style"))) {
|
||||
auto css = get_css_from_style(attr.value().toString());
|
||||
|
||||
for (auto it = css.begin(); it != css.end(); it++) {
|
||||
const QString &first_val = it.value().first();
|
||||
|
||||
if (it.key() == QStringLiteral("font-family")) {
|
||||
fmt.setFontFamilies({ first_val });
|
||||
} else if (it.key() == QStringLiteral("font-size")) {
|
||||
if (first_val.endsWith(QStringLiteral("pt"),
|
||||
Qt::CaseInsensitive)) {
|
||||
fmt.setFontPointSize(first_val.chopped(2).toDouble());
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("font-weight")) {
|
||||
fmt.setFontWeight(first_val.toInt() / 8);
|
||||
} else if (it.key() == QStringLiteral("font-style")) {
|
||||
fmt.setFontItalic(
|
||||
str_equals(first_val, QStringLiteral("italic")));
|
||||
} else if (it.key() == QStringLiteral("text-decoration")) {
|
||||
foreach (const QString &v, it.value()) {
|
||||
if (str_equals(v, QStringLiteral("underline"))) {
|
||||
fmt.setFontUnderline(true);
|
||||
} else if (str_equals(v,
|
||||
QStringLiteral("line-through"))) {
|
||||
fmt.setFontStrikeOut(true);
|
||||
} else if (str_equals(v, QStringLiteral("overline"))) {
|
||||
fmt.setFontOverline(true);
|
||||
}
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("color")) {
|
||||
if (first_val.startsWith(QStringLiteral("rgba"),
|
||||
Qt::CaseInsensitive)) {
|
||||
QString vals_only = first_val;
|
||||
vals_only.remove(QStringLiteral("rgba"));
|
||||
vals_only.remove(QStringLiteral("("));
|
||||
vals_only.remove(QStringLiteral(")"));
|
||||
QStringList rgba = vals_only.split(',');
|
||||
if (rgba.size() == 4) {
|
||||
QColor c;
|
||||
c.setRed(rgba.at(0).toInt()); // Writer emits 0-255 RGB (CSS rgba() convention)
|
||||
c.setGreen(rgba.at(1).toInt());
|
||||
c.setBlue(rgba.at(2).toInt());
|
||||
c.setAlphaF(rgba.at(3).toDouble());
|
||||
fmt.setForeground(c);
|
||||
}
|
||||
} else {
|
||||
fmt.setForeground(QColor(first_val));
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("font-variant")) {
|
||||
if (str_equals(first_val, QStringLiteral("small-caps"))) {
|
||||
fmt.setFontCapitalization(QFont::SmallCaps);
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("letter-spacing")) {
|
||||
if (first_val.contains(QChar('%'))) {
|
||||
fmt.setFontLetterSpacing(
|
||||
first_val.chopped(1).toDouble());
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("font-stretch")) {
|
||||
if (first_val.contains(QChar('%'))) {
|
||||
fmt.setFontStretch(first_val.chopped(1).toInt());
|
||||
}
|
||||
} else if (it.key() == QStringLiteral("-ove-font-style")) {
|
||||
fmt.setFontStyleName(first_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
QTextBlockFormat Html::read_block_format(const QXmlStreamAttributes &attributes)
|
||||
{
|
||||
QTextBlockFormat block_fmt;
|
||||
|
||||
foreach (const QXmlStreamAttribute &attr, attributes) {
|
||||
if (str_equals(attr.name(), QStringLiteral("align"))) {
|
||||
if (str_equals(attr.value(), QStringLiteral("right"))) {
|
||||
block_fmt.setAlignment(Qt::AlignRight);
|
||||
} else if (str_equals(attr.value(), QStringLiteral("center"))) {
|
||||
block_fmt.setAlignment(Qt::AlignHCenter);
|
||||
} else if (str_equals(attr.value(), QStringLiteral("justify"))) {
|
||||
block_fmt.setAlignment(Qt::AlignJustify);
|
||||
}
|
||||
} else if (str_equals(attr.name(), QStringLiteral("dir"))) {
|
||||
if (str_equals(attr.value(), QStringLiteral("rtl"))) {
|
||||
block_fmt.setLayoutDirection(Qt::RightToLeft);
|
||||
}
|
||||
} else if (str_equals(attr.name(), QStringLiteral("style"))) {
|
||||
auto css = get_css_from_style(attr.value().toString());
|
||||
|
||||
for (auto it = css.begin(); it != css.end(); it++) {
|
||||
if (it.key() == QStringLiteral("line-height")) {
|
||||
const QString &first_val = it.value().constFirst();
|
||||
if (first_val.contains(QChar('%'))) {
|
||||
block_fmt.setLineHeight(
|
||||
first_val.chopped(1).toDouble(),
|
||||
QTextBlockFormat::ProportionalHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return block_fmt;
|
||||
}
|
||||
|
||||
void Html::append_string_auto_space(QString *s, const QString &append)
|
||||
{
|
||||
if (!s->isEmpty()) {
|
||||
s->append(QChar(' '));
|
||||
}
|
||||
|
||||
s->append(append);
|
||||
}
|
||||
|
||||
QMap<QString, QStringList> Html::get_css_from_style(const QString &s)
|
||||
{
|
||||
QMap<QString, QStringList> map;
|
||||
|
||||
QStringList list = s.split(QChar(';'));
|
||||
|
||||
foreach (const QString &a, list) {
|
||||
QStringList kv = a.split(QChar(':'));
|
||||
|
||||
if (kv.size() != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// I'm sure there's regex that could do this, but I couldn't figure it out. It needs to split
|
||||
// by space EXCEPT within quotes OR double-quotes, and said quotes should be EXCLUDED from each
|
||||
// match. Also commas should be filtered out.
|
||||
QStringList values;
|
||||
const QString &val = kv.at(1);
|
||||
QChar in_quote(0);
|
||||
QString current_str;
|
||||
for (int i = 0; i < val.size(); i++) {
|
||||
const QChar ¤t_char = val.at(i);
|
||||
|
||||
if (!in_quote.isNull()) {
|
||||
// If inside quotes and character isn't quote, indiscriminately append char
|
||||
if (current_char == in_quote) {
|
||||
in_quote = QChar(0);
|
||||
} else {
|
||||
current_str.append(current_char);
|
||||
}
|
||||
} else if (current_char.isSpace() || current_char == QChar(',')) {
|
||||
// Dump current
|
||||
if (!current_str.isEmpty()) {
|
||||
values.append(current_str);
|
||||
current_str.clear();
|
||||
}
|
||||
} else if (in_quote.isNull() && (current_char == QChar('\'') ||
|
||||
current_char == QChar('"'))) {
|
||||
in_quote = current_char;
|
||||
} else {
|
||||
current_str.append(current_char);
|
||||
}
|
||||
}
|
||||
|
||||
if (!current_str.isEmpty()) {
|
||||
values.append(current_str);
|
||||
}
|
||||
|
||||
// Not sure if this will ever happen, but just in case, we will avoid assert failures with this
|
||||
if (values.isEmpty()) {
|
||||
values.append(QString());
|
||||
}
|
||||
|
||||
map[kv.at(0).trimmed().toLower()] = values;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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_HTML_H
|
||||
#define OAK_HTML_H
|
||||
|
||||
#include <QTextDocument>
|
||||
#include <QTextFragment>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QXmlStreamWriter>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Functions for converting HTML to QTextDocument and vice versa
|
||||
*
|
||||
* Qt does contain its own functions for this, however they have some limitations. Some things that
|
||||
* we want to support (e.g. kerning/spacing and font stretch) are not implemented in Qt's
|
||||
* QTextHtmlExporter and QTextHtmlParser. Additionally, since these functions are not part of Qt's
|
||||
* public API, and make many references to other parts of Qt that are not part of the public API,
|
||||
* there is no way to subclass or extend their functionality without forking Qt as a whole.
|
||||
*
|
||||
* Therefore, it became necessary to write a custom class for the conversion so that we can
|
||||
* ensure support for the features we need.
|
||||
*
|
||||
* If someone wishes to extend this class for more feature support, feel free to open a pull
|
||||
* request. But this is NOT intended to be an exhaustive HTML implementation, and is primarily
|
||||
* designed to store rich text in a standard format for the purpose of text formatting for video.
|
||||
*/
|
||||
class Html {
|
||||
public:
|
||||
static QString doc_to_html(const QTextDocument *doc);
|
||||
|
||||
static void html_to_doc(QTextDocument *doc, const QString &html);
|
||||
|
||||
private:
|
||||
static void write_block(QXmlStreamWriter *writer, const QTextBlock &block);
|
||||
|
||||
static void write_fragment(QXmlStreamWriter *writer,
|
||||
const QTextFragment &fragment);
|
||||
|
||||
static void write_css_property(QString *style, const QString &key,
|
||||
const QStringList &value);
|
||||
static void write_css_property(QString *style, const QString &key,
|
||||
const QString &value)
|
||||
{
|
||||
write_css_property(style, key, QStringList({ value }));
|
||||
}
|
||||
|
||||
static void write_char_format(QString *style, const QTextCharFormat &fmt);
|
||||
|
||||
static QTextCharFormat
|
||||
read_char_format(const QXmlStreamAttributes &attributes);
|
||||
|
||||
static QTextBlockFormat
|
||||
read_block_format(const QXmlStreamAttributes &attributes);
|
||||
|
||||
static void append_string_auto_space(QString *s, const QString &append);
|
||||
|
||||
static QMap<QString, QStringList> get_css_from_style(const QString &s);
|
||||
|
||||
static const QVector<QString> k_block_tags;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_HTML_H
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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/>.
|
||||
*/
|
||||
|
||||
#include "jobtime.h"
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
uint64_t job_time_index = 0;
|
||||
QMutex job_time_mutex;
|
||||
|
||||
JobTime::JobTime()
|
||||
{
|
||||
acquire();
|
||||
}
|
||||
|
||||
void JobTime::acquire()
|
||||
{
|
||||
job_time_mutex.lock();
|
||||
|
||||
value_ = job_time_index;
|
||||
job_time_index++;
|
||||
|
||||
job_time_mutex.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const olive::JobTime &r)
|
||||
{
|
||||
return debug.space() << r.value();
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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_JOBTIME_H
|
||||
#define OAK_JOBTIME_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class JobTime {
|
||||
public:
|
||||
JobTime();
|
||||
|
||||
void acquire();
|
||||
|
||||
uint64_t value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool operator==(const JobTime &rhs) const
|
||||
{
|
||||
return value_ == rhs.value_;
|
||||
}
|
||||
|
||||
bool operator!=(const JobTime &rhs) const
|
||||
{
|
||||
return value_ != rhs.value_;
|
||||
}
|
||||
|
||||
bool operator<(const JobTime &rhs) const
|
||||
{
|
||||
return value_ < rhs.value_;
|
||||
}
|
||||
|
||||
bool operator>(const JobTime &rhs) const
|
||||
{
|
||||
return value_ > rhs.value_;
|
||||
}
|
||||
|
||||
bool operator<=(const JobTime &rhs) const
|
||||
{
|
||||
return value_ <= rhs.value_;
|
||||
}
|
||||
|
||||
bool operator>=(const JobTime &rhs) const
|
||||
{
|
||||
return value_ >= rhs.value_;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t value_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const olive::JobTime &r);
|
||||
|
||||
Q_DECLARE_METATYPE(olive::JobTime)
|
||||
|
||||
#endif // OAK_JOBTIME_H
|
||||
@@ -1,42 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_LERP_H
|
||||
#define OAK_LERP_H
|
||||
|
||||
template <typename T>
|
||||
/**
|
||||
* @brief Linearly interpolate a value between a and b using t
|
||||
*
|
||||
* t should be a number between 0.0 and 1.0. 0.0 will return a, 1.0 will return b, and between will return a value
|
||||
* in between a and b at that point linearly.
|
||||
*/
|
||||
T lerp(T a, T b, double t)
|
||||
{
|
||||
return (a * (1.0 - t)) + (b * t);
|
||||
}
|
||||
|
||||
template <typename T> T lerp(T a, T b, float t)
|
||||
{
|
||||
return (a * (1.0f - t)) + (b * t);
|
||||
}
|
||||
|
||||
#endif // OAK_LERP_H
|
||||
@@ -1,438 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_MEMORYPOOL_H
|
||||
#define OAK_MEMORYPOOL_H
|
||||
|
||||
#include <memory>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QMutex>
|
||||
#include <QTimer>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief MemoryPool base class
|
||||
*
|
||||
* A custom memory system that allocates can allocate several objects in a large chunk (as opposed to several small
|
||||
* allocations). Improves performance and memory consumption.
|
||||
*
|
||||
* As a class, this base is usable by setting the template to an object of your choosing. The pool will then allocate
|
||||
* `(element_count * sizeof(T))` per arena. Arenas are allocated and destroyed on the fly - when an arena fills up,
|
||||
* another is allocated.
|
||||
*
|
||||
* `Get()` will return an ElementPtr. The original desired data can be accessed through ElementPtr::data(). This data
|
||||
* will belong to the caller until ElementPtr goes out of scope and the memory is freed back into the pool.
|
||||
*/
|
||||
class MemoryPool : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param element_count
|
||||
*
|
||||
* Number of elements per arena
|
||||
*/
|
||||
MemoryPool(int element_count)
|
||||
{
|
||||
element_count_ = element_count;
|
||||
|
||||
clear_timer_ = new QTimer();
|
||||
clear_timer_->setInterval(kMaxEmptyArenaLife);
|
||||
clear_timer_->moveToThread(qApp->thread());
|
||||
connect(clear_timer_, &QTimer::timeout, this,
|
||||
&MemoryPool::ClearEmptyArenas, Qt::DirectConnection);
|
||||
QMetaObject::invokeMethod(clear_timer_, "start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*
|
||||
* Deletes all arenas.
|
||||
*/
|
||||
virtual ~MemoryPool()
|
||||
{
|
||||
Clear();
|
||||
clear_timer_->deleteLater();
|
||||
}
|
||||
|
||||
DISABLE_COPY_MOVE(MemoryPool)
|
||||
|
||||
/**
|
||||
* @brief Clears all arenas, freeing all of their memory
|
||||
*
|
||||
* Note that this function is not safe, any elements that are still out there will be invalid
|
||||
* and accessing them will cause a crash. You'll need to make sure all elements are already
|
||||
* relinquished before then.
|
||||
*/
|
||||
void Clear()
|
||||
{
|
||||
qDeleteAll(arenas_);
|
||||
arenas_.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether any arenas are successfully allocated
|
||||
*/
|
||||
inline bool IsAllocated() const
|
||||
{
|
||||
return !arenas_.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns current number of allocated arenas
|
||||
*/
|
||||
inline int GetArenaCount() const
|
||||
{
|
||||
return arenas_.size();
|
||||
}
|
||||
|
||||
class Arena;
|
||||
|
||||
/**
|
||||
* @brief A handle for a chunk of memory in an arena
|
||||
*
|
||||
* Calling Get() on the pool or arena will return a shared pointer to an element which will contain a pointer to
|
||||
* the desired object/data in data(). When Element is destroyed (i.e. when ElementPtr goes out of scope), the memory
|
||||
* is released back into the pool so it can be used by another class.
|
||||
*/
|
||||
class Element {
|
||||
public:
|
||||
/**
|
||||
* @brief Element Constructor
|
||||
*
|
||||
* There is no need to use this outside of the memory pool's internal functions.
|
||||
*/
|
||||
Element(Arena *parent, uint8_t *data)
|
||||
{
|
||||
parent_ = parent;
|
||||
data_ = data;
|
||||
accessed_ = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Element Destructor
|
||||
*
|
||||
* Automatically releases this element's memory back to the arena it was retrieved from.
|
||||
*/
|
||||
~Element()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
DISABLE_COPY_MOVE(Element)
|
||||
|
||||
/**
|
||||
* @brief Access data represented in the pool
|
||||
*/
|
||||
inline uint8_t *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline const int64_t ×tamp() const
|
||||
{
|
||||
return timestamp_;
|
||||
}
|
||||
|
||||
inline void set_timestamp(const int64_t ×tamp)
|
||||
{
|
||||
timestamp_ = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register that this element has been accessed
|
||||
*
|
||||
* \see last_accessed()
|
||||
*/
|
||||
inline void access()
|
||||
{
|
||||
accessed_ = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the last time `access()` was called on this function
|
||||
*
|
||||
* Useful for determining the relative age of an element (i.e. if it hasn't been accessed for a certain amount of
|
||||
* time, it can probably be freed back into the pool). This requires all usages to call `access()`.
|
||||
*/
|
||||
inline const int64_t &last_accessed() const
|
||||
{
|
||||
return accessed_;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (data_) {
|
||||
parent_->Release(this);
|
||||
data_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Arena *parent_;
|
||||
|
||||
uint8_t *data_;
|
||||
|
||||
int64_t timestamp_;
|
||||
|
||||
int64_t accessed_;
|
||||
};
|
||||
|
||||
using ElementPtr = std::shared_ptr<Element>;
|
||||
|
||||
/**
|
||||
* @brief A memory pool arena - a subsection of memory
|
||||
*
|
||||
* The pool itself does not store memory, it stores "arenas". This is so that the pool can handle the situation of
|
||||
* an arena becoming full with no more memory to lend. A pool can automatically allocate another arena and continue
|
||||
* providing memory (and freeing arenas when they're no longer in use).
|
||||
*/
|
||||
class Arena {
|
||||
public:
|
||||
Arena(MemoryPool *parent)
|
||||
{
|
||||
parent_ = parent;
|
||||
data_ = nullptr;
|
||||
allocated_sz_ = 0;
|
||||
empty_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
~Arena()
|
||||
{
|
||||
std::list<Element *> copy = lent_elements_;
|
||||
foreach (Element *e, copy) {
|
||||
e->release();
|
||||
}
|
||||
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
DISABLE_COPY_MOVE(Arena)
|
||||
|
||||
/**
|
||||
* @brief Returns an element if there is free memory to do so
|
||||
*/
|
||||
ElementPtr Get()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
for (int i = 0; i < available_.size(); i++) {
|
||||
if (available_.at(i)) {
|
||||
// This buffer is available
|
||||
available_.replace(i, false);
|
||||
|
||||
ElementPtr e = std::make_shared<Element>(
|
||||
this,
|
||||
reinterpret_cast<uint8_t *>(data_ + i * element_sz_));
|
||||
lent_elements_.push_back(e.get());
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases an element back into the pool for use elsewhere
|
||||
*/
|
||||
void Release(Element *e)
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
quintptr diff = reinterpret_cast<quintptr>(e->data()) -
|
||||
reinterpret_cast<quintptr>(data_);
|
||||
|
||||
int index = diff / element_sz_;
|
||||
|
||||
available_.replace(index, true);
|
||||
|
||||
lent_elements_.remove(e);
|
||||
|
||||
if (lent_elements_.empty()) {
|
||||
empty_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
}
|
||||
|
||||
int GetUsageCount()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
return lent_elements_.size();
|
||||
}
|
||||
|
||||
bool Allocate(size_t ele_sz, size_t nb_elements)
|
||||
{
|
||||
if (IsAllocated()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
element_sz_ = ele_sz;
|
||||
|
||||
allocated_sz_ = element_sz_ * nb_elements;
|
||||
|
||||
if ((data_ = new uint8_t[allocated_sz_])) {
|
||||
available_.resize(nb_elements);
|
||||
available_.fill(true);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
available_.clear();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline int GetElementCount() const
|
||||
{
|
||||
return available_.size();
|
||||
}
|
||||
|
||||
inline bool IsAllocated() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline qint64 GetTimeArenaWasMadeEmpty()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
return empty_time_;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool *parent_;
|
||||
|
||||
uint8_t *data_;
|
||||
|
||||
size_t allocated_sz_;
|
||||
|
||||
QVector<bool> available_;
|
||||
|
||||
QMutex lock_;
|
||||
|
||||
size_t element_sz_;
|
||||
|
||||
std::list<Element *> lent_elements_;
|
||||
|
||||
qint64 empty_time_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Retrieves an element from an available arena
|
||||
*/
|
||||
ElementPtr Get()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
// Attempt to get an element from an arena
|
||||
foreach (Arena *a, arenas_) {
|
||||
ElementPtr e = a->Get();
|
||||
|
||||
if (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
// All arenas were empty, we'll need to create a new one
|
||||
if (arenas_.empty()) {
|
||||
qDebug() << "No arenas, creating new...";
|
||||
} else {
|
||||
qDebug() << "All arenas are full, creating new...";
|
||||
}
|
||||
|
||||
size_t ele_sz = GetElementSize();
|
||||
|
||||
if (!ele_sz) {
|
||||
qCritical() << "Failed to create arena, element size was 0";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (element_count_ <= 0) {
|
||||
qCritical() << "Failed to create arena, element count was invalid:"
|
||||
<< element_count_;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Arena *a = new Arena(this);
|
||||
if (!a->Allocate(ele_sz, element_count_)) {
|
||||
qCritical()
|
||||
<< "Failed to create arena, allocation failed. Out of memory?";
|
||||
delete a;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
arenas_.push_back(a);
|
||||
return a->Get();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief The size of each element
|
||||
*
|
||||
* Override this to use a custom size (e.g. a char array where T = char but the element size is > 1)
|
||||
*/
|
||||
virtual size_t GetElementSize()
|
||||
{
|
||||
return sizeof(uint8_t);
|
||||
}
|
||||
|
||||
private:
|
||||
int element_count_;
|
||||
|
||||
std::list<Arena *> arenas_;
|
||||
|
||||
QMutex lock_;
|
||||
|
||||
QTimer *clear_timer_;
|
||||
|
||||
static const qint64 kMaxEmptyArenaLife = 5000;
|
||||
|
||||
private slots:
|
||||
void ClearEmptyArenas()
|
||||
{
|
||||
QMutexLocker locker(&lock_);
|
||||
|
||||
const qint64 min_time =
|
||||
QDateTime::currentMSecsSinceEpoch() - kMaxEmptyArenaLife;
|
||||
|
||||
for (auto it = arenas_.begin(); it != arenas_.end();) {
|
||||
Arena *arena = (*it);
|
||||
|
||||
if (arena->GetUsageCount() == 0 &&
|
||||
arena->GetTimeArenaWasMadeEmpty() <= min_time) {
|
||||
qDebug() << "Removing an empty arena";
|
||||
delete arena;
|
||||
it = arenas_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_MEMORYPOOL_H
|
||||
@@ -1,51 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "ocioutils.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ocio::BitDepth OCIOUtils::get_ocio_bit_depth_from_pixel_format(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::u8:
|
||||
return ocio::BIT_DEPTH_UINT8;
|
||||
case PixelFormat::u10:
|
||||
return ocio::BIT_DEPTH_UINT10;
|
||||
case PixelFormat::u16:
|
||||
return ocio::BIT_DEPTH_UINT16;
|
||||
break;
|
||||
case PixelFormat::f16:
|
||||
return ocio::BIT_DEPTH_F16;
|
||||
break;
|
||||
case PixelFormat::f32:
|
||||
return ocio::BIT_DEPTH_F32;
|
||||
break;
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return ocio::BIT_DEPTH_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_OCIOUTILS_H
|
||||
#define OAK_OCIOUTILS_H
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace ocio = OCIO_NAMESPACE;
|
||||
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class OCIOUtils {
|
||||
public:
|
||||
static ocio::BitDepth get_ocio_bit_depth_from_pixel_format(PixelFormat format);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_OCIOUTILS_H
|
||||
@@ -1,80 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "oiioutils.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
void OIIOUtils::frame_to_buffer(const Frame *frame, OIIO::ImageBuf *buf)
|
||||
{
|
||||
buf->set_pixels(OIIO::ROI(), buf->spec().format, frame->const_data(),
|
||||
OIIO::AutoStride, frame->linesize_bytes());
|
||||
}
|
||||
|
||||
void OIIOUtils::buffer_to_frame(OIIO::ImageBuf *buf, Frame *frame)
|
||||
{
|
||||
buf->get_pixels(OIIO::ROI(), buf->spec().format, frame->data(),
|
||||
OIIO::AutoStride, frame->linesize_bytes());
|
||||
}
|
||||
|
||||
Rational OIIOUtils::get_pixel_aspect_ratio_from_oiio(const OIIO::ImageSpec &spec)
|
||||
{
|
||||
return Rational::from_double(
|
||||
spec.get_float_attribute("PixelAspectRatio", 1));
|
||||
}
|
||||
|
||||
PixelFormat OIIOUtils::get_format_from_oiio_basetype(OIIO::TypeDesc::BASETYPE type)
|
||||
{
|
||||
switch (type) {
|
||||
case OIIO::TypeDesc::UNKNOWN:
|
||||
case OIIO::TypeDesc::NONE:
|
||||
break;
|
||||
|
||||
case OIIO::TypeDesc::INT8:
|
||||
case OIIO::TypeDesc::INT16:
|
||||
case OIIO::TypeDesc::INT32:
|
||||
case OIIO::TypeDesc::UINT32:
|
||||
case OIIO::TypeDesc::INT64:
|
||||
case OIIO::TypeDesc::UINT64:
|
||||
case OIIO::TypeDesc::STRING:
|
||||
case OIIO::TypeDesc::PTR:
|
||||
case OIIO::TypeDesc::LASTBASE:
|
||||
case OIIO::TypeDesc::DOUBLE:
|
||||
qDebug() << "Tried to use unknown OIIO base type";
|
||||
break;
|
||||
|
||||
case OIIO::TypeDesc::UINT8:
|
||||
return PixelFormat::u8;
|
||||
case OIIO::TypeDesc::UINT16:
|
||||
return PixelFormat::u16;
|
||||
case OIIO::TypeDesc::HALF:
|
||||
return PixelFormat::f16;
|
||||
case OIIO::TypeDesc::FLOAT:
|
||||
return PixelFormat::f32;
|
||||
}
|
||||
|
||||
return PixelFormat::invalid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_OIIOUTILS_H
|
||||
#define OAK_OIIOUTILS_H
|
||||
|
||||
#include <OpenImageIO/imagebuf.h>
|
||||
#include <OpenImageIO/typedesc.h>
|
||||
|
||||
#include "codec/frame.h"
|
||||
#include "render/videoparams.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class OIIOUtils {
|
||||
public:
|
||||
static OIIO::TypeDesc::BASETYPE
|
||||
get_oiio_base_type_from_format(PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::u8:
|
||||
return OIIO::TypeDesc::UINT8;
|
||||
case PixelFormat::u10:
|
||||
return OIIO::TypeDesc::UNKNOWN;
|
||||
case PixelFormat::u16:
|
||||
return OIIO::TypeDesc::UINT16;
|
||||
case PixelFormat::f16:
|
||||
return OIIO::TypeDesc::HALF;
|
||||
case PixelFormat::f32:
|
||||
return OIIO::TypeDesc::FLOAT;
|
||||
case PixelFormat::invalid:
|
||||
case PixelFormat::count:
|
||||
break;
|
||||
}
|
||||
|
||||
return OIIO::TypeDesc::UNKNOWN;
|
||||
}
|
||||
|
||||
static void frame_to_buffer(const Frame *frame, OIIO::ImageBuf *buf);
|
||||
|
||||
static void buffer_to_frame(OIIO::ImageBuf *buf, Frame *frame);
|
||||
|
||||
static PixelFormat get_format_from_oiio_basetype(OIIO::TypeDesc::BASETYPE type);
|
||||
|
||||
static Rational get_pixel_aspect_ratio_from_oiio(const OIIO::ImageSpec &spec);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_OIIOUTILS_H
|
||||
@@ -1,29 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive 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_OTIOUTILS_H
|
||||
#define OAK_OTIOUTILS_H
|
||||
|
||||
#ifdef USE_OTIO
|
||||
#include <opentimelineio/version.h>
|
||||
namespace OTIO = opentimelineio::OPENTIMELINEIO_VERSION;
|
||||
#endif
|
||||
|
||||
#endif // OTIOUTILS
|
||||
@@ -1,45 +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/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef OAK_PLAYBACKAUDIOCLOCK_H
|
||||
#define OAK_PLAYBACKAUDIOCLOCK_H
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Source of an audio output clock for playback timing
|
||||
*/
|
||||
class PlaybackAudioClock {
|
||||
public:
|
||||
virtual ~PlaybackAudioClock() = default;
|
||||
|
||||
/**
|
||||
* @brief Seconds of audio consumed by the output device
|
||||
*
|
||||
* Must return a negative value when no clocked output is running, in
|
||||
* which case the caller should fall back to the wall clock.
|
||||
*/
|
||||
virtual double seconds() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_PLAYBACKAUDIOCLOCK_H
|
||||
@@ -1,58 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_POWER_H
|
||||
#define OAK_POWER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
uint32_t ceil_to_power_of_2(uint32_t v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t floor_to_power_of_2(uint32_t x)
|
||||
{
|
||||
x = x | (x >> 1);
|
||||
x = x | (x >> 2);
|
||||
x = x | (x >> 4);
|
||||
x = x | (x >> 8);
|
||||
x = x | (x >> 16);
|
||||
|
||||
return x - (x >> 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_POWER_H
|
||||
@@ -1,203 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
int QtUtils::q_font_metrics_width(QFontMetrics fm, const QString &s)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
return fm.width(s);
|
||||
#else
|
||||
return fm.horizontalAdvance(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
QFrame *QtUtils::create_horizontal_line()
|
||||
{
|
||||
QFrame *horizontal_line = new QFrame();
|
||||
horizontal_line->setFrameShape(QFrame::HLine);
|
||||
horizontal_line->setFrameShadow(QFrame::Sunken);
|
||||
return horizontal_line;
|
||||
}
|
||||
|
||||
QFrame *QtUtils::create_vertical_line()
|
||||
{
|
||||
QFrame *l = create_horizontal_line();
|
||||
l->setFrameShape(QFrame::VLine);
|
||||
return l;
|
||||
}
|
||||
|
||||
QDateTime QtUtils::get_creation_date(const QFileInfo &info)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||
return info.created();
|
||||
#else
|
||||
QDateTime t = info.birthTime();
|
||||
if (!t.isValid()) {
|
||||
t = info.metadataChangeTime();
|
||||
}
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
QString QtUtils::get_formatted_date_time(const QDateTime &dt)
|
||||
{
|
||||
return dt.toString(Qt::TextDate);
|
||||
}
|
||||
|
||||
QStringList QtUtils::word_wrap_string(const QString &s, const QFontMetrics &fm,
|
||||
int bounding_width)
|
||||
{
|
||||
QStringList list;
|
||||
|
||||
QStringList lines = s.split('\n');
|
||||
|
||||
// Iterate every line
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
QString this_line = lines.at(i);
|
||||
|
||||
while (this_line.size() > 1 &&
|
||||
q_font_metrics_width(fm, this_line) >= bounding_width) {
|
||||
int old_size = this_line.size();
|
||||
int hard_break = -1;
|
||||
|
||||
for (int j = this_line.size() - 1; j >= 0; j--) {
|
||||
const QChar &char_test = this_line.at(j);
|
||||
|
||||
if (char_test.isSpace() || char_test == '-') {
|
||||
if (q_font_metrics_width(fm, this_line.left(j)) <
|
||||
bounding_width) {
|
||||
if (!char_test.isSpace()) {
|
||||
j++;
|
||||
}
|
||||
|
||||
QString chopped = this_line.left(j);
|
||||
|
||||
list.append(chopped);
|
||||
|
||||
while (j < this_line.size() &&
|
||||
this_line.at(j).isSpace()) {
|
||||
j++;
|
||||
}
|
||||
this_line.remove(0, j);
|
||||
break;
|
||||
}
|
||||
} else if (hard_break == -1 &&
|
||||
q_font_metrics_width(fm, this_line.left(j)) <
|
||||
bounding_width) {
|
||||
// In case we can't find a better place to split, split at the earliest time the line
|
||||
// goes under the width limit
|
||||
hard_break = j;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_size == this_line.size()) {
|
||||
if (hard_break != -1) {
|
||||
list.append(this_line.left(hard_break));
|
||||
this_line.remove(0, hard_break);
|
||||
} else {
|
||||
qWarning()
|
||||
<< "Failed to find anywhere to wrap. Returning full line.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this_line.isEmpty()) {
|
||||
list.append(this_line);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers
|
||||
QtUtils::flip_control_and_shift_modifiers(Qt::KeyboardModifiers e)
|
||||
{
|
||||
if (e & Qt::ControlModifier & Qt::ShiftModifier) {
|
||||
return e;
|
||||
}
|
||||
|
||||
if (e & Qt::ShiftModifier) {
|
||||
e |= Qt::ControlModifier;
|
||||
e &= ~Qt::ShiftModifier;
|
||||
} else if (e & Qt::ControlModifier) {
|
||||
e |= Qt::ShiftModifier;
|
||||
e &= ~Qt::ControlModifier;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void QtUtils::set_combo_box_data(QComboBox *cb, int data)
|
||||
{
|
||||
for (int i = 0; i < cb->count(); i++) {
|
||||
if (cb->itemData(i).toInt() == data) {
|
||||
cb->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtUtils::set_combo_box_data(QComboBox *cb, const QString &data)
|
||||
{
|
||||
for (int i = 0; i < cb->count(); i++) {
|
||||
if (cb->itemData(i).toString() == data) {
|
||||
cb->setCurrentIndex(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QColor QtUtils::to_q_color(const core::Color &i)
|
||||
{
|
||||
QColor c;
|
||||
|
||||
// QColor only supports values from 0.0 to 1.0 and are only used for UI representations
|
||||
c.setRedF(std::clamp(i.red(), 0.0f, 1.0f));
|
||||
c.setGreenF(std::clamp(i.green(), 0.0f, 1.0f));
|
||||
c.setBlueF(std::clamp(i.blue(), 0.0f, 1.0f));
|
||||
c.setAlphaF(std::clamp(i.alpha(), 0.0f, 1.0f));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
||||
uint qHash(const core::Rational &r, uint seed)
|
||||
{
|
||||
return ::qHash(r.to_double(), seed);
|
||||
}
|
||||
|
||||
uint qHash(const core::TimeRange &r, uint seed)
|
||||
{
|
||||
return qHash(r.in(), seed) ^ qHash(r.out(), seed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_QTVERSIONABSTRACTION_H
|
||||
#define OAK_QTVERSIONABSTRACTION_H
|
||||
|
||||
#include <olive/core/core.h>
|
||||
#include <QComboBox>
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QFontMetrics>
|
||||
#include <QFrame>
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class QtUtils {
|
||||
public:
|
||||
/**
|
||||
* @brief Retrieves the width of a string according to certain QFontMetrics
|
||||
*
|
||||
* QFontMetrics::width() has been deprecatd in favor of QFontMetrics::horizontalAdvance(), but the
|
||||
* latter was only introduced in 5.11+. This function wraps the latter for 5.11+ and the former for
|
||||
* earlier.
|
||||
*/
|
||||
static int q_font_metrics_width(QFontMetrics fm, const QString &s);
|
||||
|
||||
static QFrame *create_horizontal_line();
|
||||
|
||||
static QFrame *create_vertical_line();
|
||||
|
||||
static QDateTime get_creation_date(const QFileInfo &info);
|
||||
|
||||
static QString get_formatted_date_time(const QDateTime &dt);
|
||||
|
||||
static QStringList word_wrap_string(const QString &s, const QFontMetrics &fm,
|
||||
int bounding_width);
|
||||
|
||||
static Qt::KeyboardModifiers
|
||||
flip_control_and_shift_modifiers(Qt::KeyboardModifiers e);
|
||||
|
||||
static void set_combo_box_data(QComboBox *cb, int data);
|
||||
static void set_combo_box_data(QComboBox *cb, const QString &data);
|
||||
|
||||
template <typename T> static T *get_parent_of_type(const QObject *child)
|
||||
{
|
||||
QObject *t = child->parent();
|
||||
|
||||
while (t) {
|
||||
if (T *p = dynamic_cast<T *>(t)) {
|
||||
return p;
|
||||
}
|
||||
t = t->parent();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static QColor to_q_color(const core::Color &c);
|
||||
|
||||
/**
|
||||
* @brief Convert a pointer to a value that can be sent between NodeParams
|
||||
*/
|
||||
static QVariant ptr_to_value(void *ptr)
|
||||
{
|
||||
return reinterpret_cast<quintptr>(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a NodeParam value to a pointer of any kind
|
||||
*/
|
||||
template <class T> static T *value_to_ptr(const QVariant &ptr)
|
||||
{
|
||||
return reinterpret_cast<T *>(ptr.value<quintptr>());
|
||||
}
|
||||
};
|
||||
|
||||
namespace core
|
||||
{
|
||||
|
||||
uint qHash(const core::Rational &r, uint seed = 0);
|
||||
uint qHash(const core::TimeRange &r, uint seed = 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(olive::core::Rational)
|
||||
Q_DECLARE_METATYPE(olive::core::Color)
|
||||
Q_DECLARE_METATYPE(olive::core::TimeRange)
|
||||
Q_DECLARE_METATYPE(olive::core::Bezier)
|
||||
Q_DECLARE_METATYPE(olive::core::AudioParams)
|
||||
Q_DECLARE_METATYPE(olive::core::SampleBuffer)
|
||||
|
||||
#endif // OAK_QTVERSIONABSTRACTION_H
|
||||
@@ -1,30 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_RANGE_H
|
||||
#define OAK_RANGE_H
|
||||
|
||||
template <typename T> bool in_range(T a, T b, T range)
|
||||
{
|
||||
return (a >= b - range && a <= b + range);
|
||||
}
|
||||
|
||||
#endif // OAK_RANGE_H
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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_THREADSAFEMAP_H
|
||||
#define OAK_THREADSAFEMAP_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
|
||||
template <typename K, typename V> class ThreadSafeMap {
|
||||
public:
|
||||
ThreadSafeMap() = default;
|
||||
|
||||
void insert(K key, V value)
|
||||
{
|
||||
mutex_.lock();
|
||||
map_.insert(key, value);
|
||||
mutex_.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
QMutex mutex_;
|
||||
|
||||
QMap<K, V> map_;
|
||||
};
|
||||
|
||||
#endif // OAK_THREADSAFEMAP_H
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Oak Video Editor - Non-Linear Video Editor
|
||||
* Copyright (C) 2025 Olive CE 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_TOHEX_H
|
||||
#define OAK_TOHEX_H
|
||||
|
||||
#include <QString>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
inline QString to_hex(quint64 t)
|
||||
{
|
||||
return QStringLiteral("%1").arg(t, 0, 16);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_TOHEX_H
|
||||
@@ -1,30 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_UTIL_H
|
||||
#define OAK_UTIL_H
|
||||
|
||||
template <typename T> inline T mid(T a, T b)
|
||||
{
|
||||
return (a + b) * 0.5;
|
||||
}
|
||||
|
||||
#endif // OAK_UTIL_H
|
||||
@@ -1,47 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "xmlutils.h"
|
||||
|
||||
#include "node/block/block.h"
|
||||
#include "node/factory.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
bool xml_read_next_start_element(QXmlStreamReader *reader, CancelAtom *cancel_atom)
|
||||
{
|
||||
QXmlStreamReader::TokenType token;
|
||||
|
||||
while ((token = reader->readNext()) != QXmlStreamReader::Invalid &&
|
||||
token != QXmlStreamReader::EndDocument &&
|
||||
(!cancel_atom || !cancel_atom->is_cancelled())) {
|
||||
if (reader->isEndElement()) {
|
||||
return false;
|
||||
} else if (reader->isStartElement()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2022 Olive Team
|
||||
Modifications Copyright (C) 2025 mikesolar
|
||||
|
||||
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_XMLREADLOOP_H
|
||||
#define OAK_XMLREADLOOP_H
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
#include "node/param.h"
|
||||
#include "render/cancelatom.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class Block;
|
||||
class Node;
|
||||
class NodeInput;
|
||||
class NodeGroup;
|
||||
|
||||
#define XMLAttributeLoop(reader, item) \
|
||||
foreach (const QXmlStreamAttribute &item, reader->attributes())
|
||||
|
||||
/**
|
||||
* @brief Workaround for QXmlStreamReader::readNextStartElement not detecting the end of a document
|
||||
*
|
||||
* Since Qt's default function doesn't exit at the end of the document, it ends up consistently
|
||||
* throwing a "premature end of document" error. We have our own function here that does essentially
|
||||
* the same thing but fixes that issue.
|
||||
*
|
||||
* See also: https://stackoverflow.com/questions/46346450/qt-qxmlstreamreader-always-returns-premature-end-of-document-error
|
||||
*/
|
||||
bool xml_read_next_start_element(QXmlStreamReader *reader,
|
||||
CancelAtom *cancel_atom = nullptr);
|
||||
|
||||
}
|
||||
|
||||
#endif // OAK_XMLREADLOOP_H
|
||||
Reference in New Issue
Block a user