Merge pull request #339 from olive-editor/frei0r
added frei0r support for windows/mac/linux
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ before_install:
|
||||
- sudo apt-get update -qq
|
||||
|
||||
install:
|
||||
- sudo apt-get -y install qt59base qt59multimedia libavformat-dev libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev libswresample-dev
|
||||
- sudo apt-get -y install qt59base qt59multimedia libavformat-dev libavcodec-dev libavfilter-dev libavutil-dev libswscale-dev libswresample-dev frei0r-plugins-dev frei0r-plugins
|
||||
- source /opt/qt*/bin/qt*-env.sh
|
||||
|
||||
script:
|
||||
|
||||
Vendored
+2
-2
@@ -2,12 +2,12 @@ Source: olive-editor
|
||||
Section: video
|
||||
Priority: optional
|
||||
Maintainer: Olive Team <itsmattkc@gmail.com>
|
||||
Build-Depends: debhelper (>=9), build-essential, qt5-default, qtmultimedia5-dev, libqt5opengl5-dev, libqt5multimedia5-plugins, libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev, libswresample-dev, libavfilter-dev, libpostproc-dev, git
|
||||
Build-Depends: debhelper (>=9), build-essential, qt5-default, qtmultimedia5-dev, libqt5opengl5-dev, libqt5multimedia5-plugins, libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev, libswresample-dev, libavfilter-dev, libpostproc-dev, git, frei0r-plugins-dev
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://olivevideoeditor.org/
|
||||
|
||||
Package: olive-editor
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}, libqt5multimedia5-plugins
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}, libqt5multimedia5-plugins, frei0r-plugins
|
||||
Description: Nonlinear video editor focused on performance and simplicity
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
#include "frei0reffect.h"
|
||||
|
||||
#ifndef NOFREI0R
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
|
||||
typedef f0r_instance_t (*f0rConstructFunc)(unsigned int width, unsigned int height);
|
||||
typedef int (*f0rInitFunc) ();
|
||||
typedef void (*f0rDeinitFunc) ();
|
||||
typedef void (*f0rUpdateFunc) (f0r_instance_t instance,
|
||||
double time, const uint32_t* inframe, uint32_t* outframe);
|
||||
typedef void (*f0rDestructFunc)(f0r_instance_t instance);
|
||||
typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info);
|
||||
typedef void (*f0rSetParamValue) (f0r_instance_t instance,
|
||||
f0r_param_t param, int param_index);
|
||||
|
||||
Frei0rEffect::Frei0rEffect(Clip *c, const EffectMeta *em) : Effect(c, em) {
|
||||
enable_image = true;
|
||||
|
||||
// Windows DLL loading routine
|
||||
QString dll_fn = QDir(em->path).filePath(em->filename);
|
||||
|
||||
handle = LibLoad(dll_fn);
|
||||
if(handle == nullptr) {
|
||||
QString dll_error;
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD dll_err = GetLastError();
|
||||
dll_error = QString::number(dll_err);
|
||||
#elif __linux__
|
||||
dll_error = dlerror();
|
||||
#endif
|
||||
qCritical() << "Failed to load Frei0r plugin" << dll_fn << "-" << dll_error;
|
||||
|
||||
QString msg_err = tr("Failed to load Frei0r plugin \"%1\": %2").arg(dll_fn, dll_error);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (dll_err == 193) {
|
||||
#ifdef _WIN64
|
||||
msg_err += "\n\n" + tr("NOTE: You can't load 32-bit Frei0r plugins into a 64-bit build of Olive. Please find a 64-bit version of this plugin or switch to a 32-bit build of Olive.");
|
||||
#elif _WIN32
|
||||
msg_err += "\n\n" + tr("NOTE: You can't load 64-bit Frei0r plugins into a 32-bit build of Olive. Please find a 32-bit version of this plugin or switch to a 64-bit build of Olive.");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
QMessageBox::critical(nullptr, tr("Error loading Frei0r plugin"), msg_err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
f0rInitFunc init = reinterpret_cast<f0rInitFunc>(LibAddress(handle, "f0r_init"));
|
||||
init();
|
||||
|
||||
f0rConstructFunc construct = reinterpret_cast<f0rConstructFunc>(LibAddress(handle, "f0r_construct"));
|
||||
instance = construct(1920, 1080);
|
||||
|
||||
f0r_plugin_info_t info;
|
||||
f0rGetPluginInfo info_func = reinterpret_cast<f0rGetPluginInfo>(LibAddress(handle, "f0r_get_plugin_info"));
|
||||
info_func(&info);
|
||||
|
||||
param_count = info.num_params;
|
||||
|
||||
// qDebug() << "Frei0r Name:" << info.name;
|
||||
// qDebug() << "Frei0r Param Count:" << info.num_params;
|
||||
// qDebug() << "Frei0r Explanation:" << info.explanation;
|
||||
|
||||
get_param_info = reinterpret_cast<f0rGetParamInfo>(LibAddress(handle, "f0r_get_param_info"));
|
||||
for (int i=0;i<param_count;i++) {
|
||||
f0r_param_info_t param_info;
|
||||
get_param_info(¶m_info, i);
|
||||
|
||||
if (param_info.type >= 0 && param_info.type <= F0R_PARAM_STRING) {
|
||||
EffectRow* row = add_row(param_info.name);
|
||||
switch (param_info.type) {
|
||||
case F0R_PARAM_BOOL:
|
||||
row->add_field(EFFECT_FIELD_BOOL, QString::number(i));
|
||||
break;
|
||||
case F0R_PARAM_DOUBLE:
|
||||
{
|
||||
EffectField* f = row->add_field(EFFECT_FIELD_DOUBLE, QString::number(i));
|
||||
f->set_double_minimum_value(0);
|
||||
f->set_double_maximum_value(100);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_COLOR:
|
||||
row->add_field(EFFECT_FIELD_COLOR, QString::number(i));
|
||||
break;
|
||||
case F0R_PARAM_POSITION:
|
||||
{
|
||||
EffectField* fx = row->add_field(EFFECT_FIELD_DOUBLE, QString("%1X").arg(QString::number(i)));
|
||||
fx->set_double_minimum_value(0);
|
||||
fx->set_double_maximum_value(100);
|
||||
EffectField* fy = row->add_field(EFFECT_FIELD_DOUBLE, QString("%1Y").arg(QString::number(i)));
|
||||
fy->set_double_minimum_value(0);
|
||||
fy->set_double_maximum_value(100);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_STRING:
|
||||
row->add_field(EFFECT_FIELD_STRING, QString::number(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Frei0rEffect::~Frei0rEffect() {
|
||||
if (handle != nullptr) {
|
||||
f0rDestructFunc destruct = reinterpret_cast<f0rDestructFunc>(LibAddress(handle, "f0r_destruct"));
|
||||
destruct(instance);
|
||||
|
||||
f0rDeinitFunc deinit = reinterpret_cast<f0rDeinitFunc>(LibAddress(handle, "f0r_deinit"));
|
||||
deinit();
|
||||
|
||||
LibClose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *output, int) {
|
||||
f0rUpdateFunc update_func = reinterpret_cast<f0rUpdateFunc>(LibAddress(handle, "f0r_update"));
|
||||
|
||||
for (int i=0;i<param_count;i++) {
|
||||
EffectRow* param_row = row(i);
|
||||
|
||||
f0r_param_info_t param_info;
|
||||
get_param_info(¶m_info, i);
|
||||
|
||||
f0rSetParamValue set_param = reinterpret_cast<f0rSetParamValue>(LibAddress(handle, "f0r_set_param_value"));
|
||||
switch (param_info.type) {
|
||||
case F0R_PARAM_BOOL:
|
||||
{
|
||||
double b = param_row->field(0)->get_bool_value(timecode);
|
||||
set_param(instance, &b, i);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_DOUBLE:
|
||||
{
|
||||
double d = param_row->field(0)->get_double_value(timecode)*0.01;
|
||||
set_param(instance, &d, i);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_COLOR:
|
||||
{
|
||||
QColor qcolor = param_row->field(0)->get_color_value(timecode);;
|
||||
|
||||
f0r_param_color fcolor;
|
||||
fcolor.r = float(qcolor.redF());
|
||||
fcolor.g = float(qcolor.greenF());
|
||||
fcolor.b = float(qcolor.blueF());
|
||||
|
||||
set_param(instance, &fcolor, i);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_POSITION:
|
||||
{
|
||||
f0r_param_position pos;
|
||||
pos.x = param_row->field(0)->get_double_value(timecode);
|
||||
pos.y = param_row->field(1)->get_double_value(timecode);
|
||||
set_param(instance, &pos, i);
|
||||
}
|
||||
break;
|
||||
case F0R_PARAM_STRING:
|
||||
{
|
||||
QByteArray bytes = param_row->field(0)->get_string_value(timecode).toUtf8();
|
||||
char* byte_data = bytes.data();
|
||||
set_param(instance, &byte_data, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
update_func(instance, timecode, reinterpret_cast<uint32_t*>(input), reinterpret_cast<uint32_t*>(output));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef FREI0REFFECT_H
|
||||
#define FREI0REFFECT_H
|
||||
|
||||
#ifndef NOFREI0R
|
||||
|
||||
#include "project/effect.h"
|
||||
|
||||
#include <frei0r.h>
|
||||
|
||||
#include "io/crossplatformlib.h"
|
||||
|
||||
typedef void (*f0rGetParamInfo)(f0r_param_info_t * info,
|
||||
int param_index );
|
||||
|
||||
class Frei0rEffect : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Frei0rEffect(Clip* c, const EffectMeta* em);
|
||||
~Frei0rEffect();
|
||||
|
||||
virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
|
||||
private:
|
||||
ModulePtr handle;
|
||||
f0r_instance_t instance;
|
||||
int param_count;
|
||||
f0rGetParamInfo get_param_info;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // FREI0REFFECT_H
|
||||
+4
-4
@@ -5,15 +5,15 @@ extern "C" {
|
||||
}
|
||||
|
||||
enum QOpenGLTexture::PixelFormat get_gl_pix_fmt_from_av(int format) {
|
||||
switch (format) {
|
||||
/*switch (format) {
|
||||
case AV_PIX_FMT_RGB24: return QOpenGLTexture::RGB;
|
||||
}
|
||||
}*/
|
||||
return QOpenGLTexture::RGBA;
|
||||
}
|
||||
|
||||
enum QOpenGLTexture::TextureFormat get_gl_tex_fmt_from_av(int format) {
|
||||
switch (format) {
|
||||
/*switch (format) {
|
||||
case AV_PIX_FMT_RGB24: return QOpenGLTexture::RGB8_UNorm;
|
||||
}
|
||||
}*/
|
||||
return QOpenGLTexture::RGBA8_UNorm;
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#define SAVE_VERSION 190104 // YYMMDD
|
||||
#define SAVE_VERSION 190120 // YYMMDD
|
||||
#define MIN_SAVE_VERSION 190104 // lowest compatible project version
|
||||
|
||||
#define TIMECODE_DROP 0
|
||||
@@ -63,7 +63,7 @@ struct Config {
|
||||
bool seek_also_selects;
|
||||
QString css_path;
|
||||
int effect_textbox_lines;
|
||||
bool use_software_fallback;
|
||||
bool use_software_fallback;
|
||||
|
||||
void load(QString path);
|
||||
void save(QString path);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "crossplatformlib.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ModulePtr LibLoad(const QString &filename) {
|
||||
#ifdef _WIN32
|
||||
LPCWSTR dll_fn_w = reinterpret_cast<const wchar_t*>(filename.utf16());
|
||||
return LoadLibrary(dll_fn_w);
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
return dlopen(filename.toUtf8(), RTLD_LAZY);
|
||||
#else
|
||||
qWarning() << "Olive doesn't know how to open dynamic libraries on this platform, external libraries will not be functional";
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
QStringList LibFilter() {
|
||||
#ifdef _WIN32
|
||||
return QStringList("*.dll");
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
return {"*.so", "*.dylib"};
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef CROSSPLATFORMLIB_H
|
||||
#define CROSSPLATFORMLIB_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#define LibAddress GetProcAddress
|
||||
#define LibClose FreeModule
|
||||
#define ModulePtr HMODULE
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
#include <dlfcn.h>
|
||||
#define LibAddress dlsym
|
||||
#define LibClose dlclose
|
||||
#define ModulePtr void*
|
||||
#endif
|
||||
|
||||
ModulePtr LibLoad(const QString& filename);
|
||||
QStringList LibFilter();
|
||||
|
||||
#endif // CROSSPLATFORMLIB_H
|
||||
+46
-18
@@ -18,7 +18,6 @@
|
||||
#include "debug.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QMessageBox>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
struct TransitionData {
|
||||
@@ -35,11 +34,21 @@ LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a), cancelle
|
||||
connect(this, SIGNAL(error()), this, SLOT(error_func()));
|
||||
connect(this, SIGNAL(start_create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)), this, SLOT(create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)));
|
||||
connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)));
|
||||
connect(this, SIGNAL(start_question(const QString&, const QString &, int)), this, SLOT(question_func(const QString &, const QString &, int)));
|
||||
}
|
||||
|
||||
const EffectMeta* get_meta_from_name(const QString& name) {
|
||||
const EffectMeta* get_meta_from_name(const QString& input) {
|
||||
int split_index = input.indexOf('/');
|
||||
QString category;
|
||||
if (split_index > -1) {
|
||||
category = input.left(split_index);
|
||||
}
|
||||
QString name = input.mid(split_index + 1);
|
||||
|
||||
for (int j=0;j<effects.size();j++) {
|
||||
if (effects.at(j).name == name) {
|
||||
if (effects.at(j).name == name
|
||||
&& (effects.at(j).category == category
|
||||
|| category.isEmpty())) {
|
||||
return &effects.at(j);
|
||||
}
|
||||
}
|
||||
@@ -152,13 +161,14 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
if (stream.name() == root_search) {
|
||||
if (type == LOAD_TYPE_VERSION) {
|
||||
int proj_version = stream.readElementText().toInt();
|
||||
if (proj_version < MIN_SAVE_VERSION && proj_version > SAVE_VERSION) {
|
||||
if (QMessageBox::warning(
|
||||
mainWindow,
|
||||
tr("Version Mismatch"),
|
||||
tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
if (proj_version < MIN_SAVE_VERSION || proj_version > SAVE_VERSION) {
|
||||
emit start_question(
|
||||
tr("Version Mismatch"),
|
||||
tr("This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?"),
|
||||
QMessageBox::Yes | QMessageBox::No
|
||||
);
|
||||
waitCond.wait(&mutex);
|
||||
if (question_btn == QMessageBox::No) {
|
||||
show_err = false;
|
||||
return false;
|
||||
}
|
||||
@@ -444,11 +454,14 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
if (!found) {
|
||||
correct_clip->linked.removeAt(j);
|
||||
j--;
|
||||
if (QMessageBox::warning(mainWindow,
|
||||
tr("Invalid Clip Link"),
|
||||
tr("This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?"),
|
||||
QMessageBox::Yes,
|
||||
QMessageBox::No) == QMessageBox::No) {
|
||||
|
||||
emit start_question(
|
||||
tr("Invalid Clip Link"),
|
||||
tr("This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?"),
|
||||
QMessageBox::Yes | QMessageBox::No
|
||||
);
|
||||
waitCond.wait(&mutex);
|
||||
if (question_btn == QMessageBox::No) {
|
||||
delete s;
|
||||
return false;
|
||||
}
|
||||
@@ -565,10 +578,14 @@ void LoadThread::run() {
|
||||
cont = !cancelled;
|
||||
|
||||
// find project file version
|
||||
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
|
||||
if (cont) {
|
||||
cont = load_worker(file, stream, LOAD_TYPE_VERSION);
|
||||
}
|
||||
|
||||
// find project's internal URL
|
||||
cont = load_worker(file, stream, LOAD_TYPE_URL);
|
||||
if (cont) {
|
||||
cont = load_worker(file, stream, LOAD_TYPE_URL);
|
||||
}
|
||||
|
||||
// load folders first
|
||||
if (cont) {
|
||||
@@ -605,7 +622,6 @@ void LoadThread::run() {
|
||||
xml_error = true;
|
||||
emit error();
|
||||
cont = false;
|
||||
|
||||
} else {
|
||||
// attach nested sequence clips to their sequences
|
||||
for (int i=0;i<loaded_clips.size();i++) {
|
||||
@@ -626,6 +642,9 @@ void LoadThread::run() {
|
||||
for (int i=0;i<loaded_media_items.size();i++) {
|
||||
panel_project->start_preview_generator(loaded_media_items.at(i), true);
|
||||
}
|
||||
} else {
|
||||
error_str = tr("User aborted loading");
|
||||
emit error();
|
||||
}
|
||||
|
||||
file.close();
|
||||
@@ -638,6 +657,15 @@ void LoadThread::cancel() {
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
void LoadThread::question_func(const QString &title, const QString &text, int buttons) {
|
||||
question_btn = QMessageBox::warning(
|
||||
mainWindow,
|
||||
title,
|
||||
text,
|
||||
static_cast<enum QMessageBox::StandardButton>(buttons));
|
||||
waitCond.wakeAll();
|
||||
}
|
||||
|
||||
void LoadThread::error_func() {
|
||||
if (xml_error) {
|
||||
qCritical() << "Error parsing XML." << error_str;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <QXmlStreamReader>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QMessageBox>
|
||||
|
||||
class Media;
|
||||
struct Footage;
|
||||
@@ -23,12 +24,14 @@ public:
|
||||
void run();
|
||||
void cancel();
|
||||
signals:
|
||||
void start_question(const QString &title, const QString &text, int buttons);
|
||||
void success();
|
||||
void error();
|
||||
void start_create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
|
||||
void start_create_dual_transition(const TransitionData* td, Clip* primary, Clip* secondary, const EffectMeta* meta);
|
||||
void report_progress(int p);
|
||||
private slots:
|
||||
void question_func(const QString &title, const QString &text, int buttons);
|
||||
void error_func();
|
||||
void success_func();
|
||||
void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
|
||||
@@ -67,6 +70,8 @@ private:
|
||||
|
||||
bool cancelled;
|
||||
bool xml_error;
|
||||
|
||||
QMessageBox::StandardButton question_btn;
|
||||
};
|
||||
|
||||
#endif // LOADTHREAD_H
|
||||
|
||||
@@ -32,3 +32,12 @@ QString get_config_path() {
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
}
|
||||
}
|
||||
|
||||
QList<QString> get_effects_paths() {
|
||||
QList<QString> effects_paths;
|
||||
effects_paths.append(get_app_dir() + "/effects");
|
||||
effects_paths.append(get_app_dir() + "/../share/olive-editor/effects");
|
||||
QString env_path(qgetenv("OLIVE_EFFECTS_PATH"));
|
||||
if (!env_path.isEmpty()) effects_paths.append(env_path);
|
||||
return effects_paths;
|
||||
}
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
QString get_app_dir();
|
||||
QString get_data_path();
|
||||
QString get_config_path();
|
||||
QList<QString> get_effects_paths();
|
||||
|
||||
#endif // PATH_H
|
||||
|
||||
@@ -20,9 +20,7 @@ int main(int argc, char *argv[]) {
|
||||
bool launch_fullscreen = false;
|
||||
QString load_proj;
|
||||
|
||||
#ifndef NODEBUG
|
||||
qInstallMessageHandler(debug_message_handler);
|
||||
#endif
|
||||
bool use_internal_logger = true;
|
||||
|
||||
if (argc > 1) {
|
||||
for (int i=1;i<argc;i++) {
|
||||
@@ -40,7 +38,8 @@ int main(int argc, char *argv[]) {
|
||||
launch_fullscreen = true;
|
||||
} else if (!strcmp(argv[i], "--disable-shaders")) {
|
||||
shaders_are_enabled = false;
|
||||
|
||||
} else if (!strcmp(argv[i], "--no-debug")) {
|
||||
use_internal_logger = false;
|
||||
} else {
|
||||
printf("[ERROR] Unknown argument '%s'\n", argv[1]);
|
||||
return 1;
|
||||
@@ -51,6 +50,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (use_internal_logger) {
|
||||
qInstallMessageHandler(debug_message_handler);
|
||||
}
|
||||
|
||||
// init ffmpeg subsystem
|
||||
av_register_all();
|
||||
avfilter_register_all();
|
||||
|
||||
@@ -1,286 +1,293 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-05-11T10:31:59
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui multimedia opengl
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
mac {
|
||||
TARGET = Olive
|
||||
}
|
||||
!mac {
|
||||
TARGET = olive-editor
|
||||
}
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
# Tries to get the current Git short hash
|
||||
system("which git") {
|
||||
GITHASHVAR = $$system(git --git-dir $$PWD/.git --work-tree $$PWD log -1 --format=%h)
|
||||
DEFINES += GITHASH=\\"\"$$GITHASHVAR\\"\"
|
||||
}
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
panels/project.cpp \
|
||||
panels/effectcontrols.cpp \
|
||||
panels/viewer.cpp \
|
||||
panels/timeline.cpp \
|
||||
ui/sourcetable.cpp \
|
||||
dialogs/aboutdialog.cpp \
|
||||
ui/timelinewidget.cpp \
|
||||
project/media.cpp \
|
||||
project/footage.cpp \
|
||||
project/sequence.cpp \
|
||||
project/clip.cpp \
|
||||
playback/playback.cpp \
|
||||
playback/audio.cpp \
|
||||
io/config.cpp \
|
||||
dialogs/newsequencedialog.cpp \
|
||||
ui/viewerwidget.cpp \
|
||||
ui/viewercontainer.cpp \
|
||||
dialogs/exportdialog.cpp \
|
||||
ui/collapsiblewidget.cpp \
|
||||
panels/panels.cpp \
|
||||
playback/cacher.cpp \
|
||||
io/exportthread.cpp \
|
||||
ui/timelineheader.cpp \
|
||||
io/previewgenerator.cpp \
|
||||
ui/labelslider.cpp \
|
||||
dialogs/preferencesdialog.cpp \
|
||||
ui/audiomonitor.cpp \
|
||||
project/undo.cpp \
|
||||
ui/scrollarea.cpp \
|
||||
ui/comboboxex.cpp \
|
||||
ui/colorbutton.cpp \
|
||||
dialogs/replaceclipmediadialog.cpp \
|
||||
ui/fontcombobox.cpp \
|
||||
ui/checkboxex.cpp \
|
||||
ui/keyframeview.cpp \
|
||||
ui/texteditex.cpp \
|
||||
dialogs/demonotice.cpp \
|
||||
project/marker.cpp \
|
||||
dialogs/speeddialog.cpp \
|
||||
dialogs/mediapropertiesdialog.cpp \
|
||||
io/crc32.cpp \
|
||||
project/projectmodel.cpp \
|
||||
io/loadthread.cpp \
|
||||
dialogs/loaddialog.cpp \
|
||||
debug.cpp \
|
||||
io/path.cpp \
|
||||
effects/internal/linearfadetransition.cpp \
|
||||
effects/internal/transformeffect.cpp \
|
||||
effects/internal/solideffect.cpp \
|
||||
effects/internal/texteffect.cpp \
|
||||
effects/internal/timecodeeffect.cpp \
|
||||
effects/internal/audionoiseeffect.cpp \
|
||||
effects/internal/paneffect.cpp \
|
||||
effects/internal/toneeffect.cpp \
|
||||
effects/internal/volumeeffect.cpp \
|
||||
effects/internal/crossdissolvetransition.cpp \
|
||||
effects/internal/shakeeffect.cpp \
|
||||
effects/internal/exponentialfadetransition.cpp \
|
||||
effects/internal/logarithmicfadetransition.cpp \
|
||||
effects/internal/cornerpineffect.cpp \
|
||||
io/math.cpp \
|
||||
io/qpainterwrapper.cpp \
|
||||
project/effect.cpp \
|
||||
project/transition.cpp \
|
||||
project/effectrow.cpp \
|
||||
project/effectfield.cpp \
|
||||
effects/internal/cubetransition.cpp \
|
||||
project/effectgizmo.cpp \
|
||||
io/clipboard.cpp \
|
||||
dialogs/stabilizerdialog.cpp \
|
||||
io/avtogl.cpp \
|
||||
ui/resizablescrollbar.cpp \
|
||||
ui/sourceiconview.cpp \
|
||||
project/sourcescommon.cpp \
|
||||
ui/keyframenavigator.cpp \
|
||||
panels/grapheditor.cpp \
|
||||
ui/graphview.cpp \
|
||||
ui/keyframedrawing.cpp \
|
||||
ui/clickablelabel.cpp \
|
||||
project/keyframe.cpp \
|
||||
ui/rectangleselect.cpp \
|
||||
dialogs/actionsearch.cpp \
|
||||
ui/embeddedfilechooser.cpp \
|
||||
effects/internal/fillleftrighteffect.cpp \
|
||||
effects/internal/voideffect.cpp \
|
||||
dialogs/texteditdialog.cpp \
|
||||
dialogs/debugdialog.cpp \
|
||||
ui/renderthread.cpp \
|
||||
ui/renderfunctions.cpp \
|
||||
ui/viewerwindow.cpp \
|
||||
project/projectfilter.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
panels/project.h \
|
||||
panels/effectcontrols.h \
|
||||
panels/viewer.h \
|
||||
panels/timeline.h \
|
||||
ui/sourcetable.h \
|
||||
dialogs/aboutdialog.h \
|
||||
ui/timelinewidget.h \
|
||||
project/media.h \
|
||||
project/footage.h \
|
||||
project/sequence.h \
|
||||
project/clip.h \
|
||||
playback/playback.h \
|
||||
playback/audio.h \
|
||||
io/config.h \
|
||||
dialogs/newsequencedialog.h \
|
||||
ui/viewerwidget.h \
|
||||
ui/viewercontainer.h \
|
||||
dialogs/exportdialog.h \
|
||||
ui/collapsiblewidget.h \
|
||||
panels/panels.h \
|
||||
playback/cacher.h \
|
||||
io/exportthread.h \
|
||||
ui/timelinetools.h \
|
||||
ui/timelineheader.h \
|
||||
io/previewgenerator.h \
|
||||
ui/labelslider.h \
|
||||
dialogs/preferencesdialog.h \
|
||||
ui/audiomonitor.h \
|
||||
project/undo.h \
|
||||
ui/scrollarea.h \
|
||||
ui/comboboxex.h \
|
||||
ui/colorbutton.h \
|
||||
dialogs/replaceclipmediadialog.h \
|
||||
ui/fontcombobox.h \
|
||||
ui/checkboxex.h \
|
||||
ui/keyframeview.h \
|
||||
ui/texteditex.h \
|
||||
dialogs/demonotice.h \
|
||||
project/marker.h \
|
||||
project/selection.h \
|
||||
dialogs/speeddialog.h \
|
||||
dialogs/mediapropertiesdialog.h \
|
||||
io/crc32.h \
|
||||
project/projectmodel.h \
|
||||
io/loadthread.h \
|
||||
dialogs/loaddialog.h \
|
||||
debug.h \
|
||||
io/path.h \
|
||||
effects/internal/transformeffect.h \
|
||||
effects/internal/solideffect.h \
|
||||
effects/internal/texteffect.h \
|
||||
effects/internal/timecodeeffect.h \
|
||||
effects/internal/audionoiseeffect.h \
|
||||
effects/internal/paneffect.h \
|
||||
effects/internal/toneeffect.h \
|
||||
effects/internal/volumeeffect.h \
|
||||
effects/internal/shakeeffect.h \
|
||||
effects/internal/linearfadetransition.h \
|
||||
effects/internal/crossdissolvetransition.h \
|
||||
effects/internal/exponentialfadetransition.h \
|
||||
effects/internal/logarithmicfadetransition.h \
|
||||
effects/internal/cornerpineffect.h \
|
||||
io/math.h \
|
||||
io/qpainterwrapper.h \
|
||||
project/effect.h \
|
||||
project/transition.h \
|
||||
project/effectrow.h \
|
||||
project/effectfield.h \
|
||||
effects/internal/cubetransition.h \
|
||||
project/effectgizmo.h \
|
||||
io/clipboard.h \
|
||||
dialogs/stabilizerdialog.h \
|
||||
io/avtogl.h \
|
||||
ui/resizablescrollbar.h \
|
||||
ui/sourceiconview.h \
|
||||
project/sourcescommon.h \
|
||||
ui/keyframenavigator.h \
|
||||
panels/grapheditor.h \
|
||||
ui/graphview.h \
|
||||
ui/keyframedrawing.h \
|
||||
ui/clickablelabel.h \
|
||||
project/keyframe.h \
|
||||
ui/rectangleselect.h \
|
||||
dialogs/actionsearch.h \
|
||||
ui/embeddedfilechooser.h \
|
||||
effects/internal/fillleftrighteffect.h \
|
||||
effects/internal/voideffect.h \
|
||||
dialogs/texteditdialog.h \
|
||||
dialogs/debugdialog.h \
|
||||
ui/renderthread.h \
|
||||
ui/renderfunctions.h \
|
||||
ui/viewerwindow.h \
|
||||
project/projectfilter.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
win32 {
|
||||
RC_FILE = packaging/windows/resources.rc
|
||||
LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -lopengl32 -luser32
|
||||
|
||||
SOURCES += effects/internal/vsthostwin.cpp
|
||||
HEADERS += effects/internal/vsthostwin.h
|
||||
}
|
||||
|
||||
mac {
|
||||
LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample
|
||||
ICON = packaging/macos/olive.icns
|
||||
INCLUDEPATH = /usr/local/include
|
||||
}
|
||||
|
||||
unix:!mac {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libavutil libavformat libavcodec libavfilter libswscale libswresample
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
icons/icons.qrc
|
||||
|
||||
unix:!mac:isEmpty(PREFIX) {
|
||||
PREFIX = /usr/local
|
||||
}
|
||||
|
||||
unix:!mac:target.path = $$PREFIX/bin
|
||||
|
||||
effects.files = $$PWD/effects/*.frag $$PWD/effects/*.xml $$PWD/effects/*.vert
|
||||
unix:!mac:effects.path = $$PREFIX/share/olive-editor/effects
|
||||
|
||||
unix:!mac {
|
||||
metainfo.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.appdata.xml
|
||||
metainfo.path = $$PREFIX/share/metainfo
|
||||
desktop.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.desktop
|
||||
desktop.path = $$PREFIX/share/applications
|
||||
mime.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.xml
|
||||
mime.path = $$PREFIX/share/mime/packages
|
||||
icon16.files = $$PWD/packaging/linux/icons/16x16/org.olivevideoeditor.Olive.png
|
||||
icon16.path = $$PREFIX/share/icons/hicolor/16x16/apps
|
||||
icon32.files = $$PWD/packaging/linux/icons/32x32/org.olivevideoeditor.Olive.png
|
||||
icon32.path = $$PREFIX/share/icons/hicolor/32x32/apps
|
||||
icon48.files = $$PWD/packaging/linux/icons/48x48/org.olivevideoeditor.Olive.png
|
||||
icon48.path = $$PREFIX/share/icons/hicolor/48x48/apps
|
||||
icon64.files = $$PWD/packaging/linux/icons/64x64/org.olivevideoeditor.Olive.png
|
||||
icon64.path = $$PREFIX/share/icons/hicolor/64x64/apps
|
||||
icon128.files = $$PWD/packaging/linux/icons/128x128/org.olivevideoeditor.Olive.png
|
||||
icon128.path = $$PREFIX/share/icons/hicolor/128x128/apps
|
||||
icon256.files = $$PWD/packaging/linux/icons/256x256/org.olivevideoeditor.Olive.png
|
||||
icon256.path = $$PREFIX/share/icons/hicolor/256x256/apps
|
||||
icon512.files = $$PWD/packaging/linux/icons/512x512/org.olivevideoeditor.Olive.png
|
||||
icon512.path = $$PREFIX/share/icons/hicolor/512x512/apps
|
||||
icon1024.files = $$PWD/packaging/linux/icons/1024x1024/org.olivevideoeditor.Olive.png
|
||||
icon1024.path = $$PREFIX/share/icons/hicolor/1024x1024/apps
|
||||
INSTALLS += target effects metainfo desktop mime icon16 icon32 icon48 icon64 icon128 icon256 icon512 icon1024
|
||||
}
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-05-11T10:31:59
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui multimedia opengl
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
mac {
|
||||
TARGET = Olive
|
||||
}
|
||||
!mac {
|
||||
TARGET = olive-editor
|
||||
}
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
# Tries to get the current Git short hash
|
||||
system("which git") {
|
||||
GITHASHVAR = $$system(git --git-dir $$PWD/.git --work-tree $$PWD log -1 --format=%h)
|
||||
DEFINES += GITHASH=\\"\"$$GITHASHVAR\\"\"
|
||||
}
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
panels/project.cpp \
|
||||
panels/effectcontrols.cpp \
|
||||
panels/viewer.cpp \
|
||||
panels/timeline.cpp \
|
||||
ui/sourcetable.cpp \
|
||||
dialogs/aboutdialog.cpp \
|
||||
ui/timelinewidget.cpp \
|
||||
project/media.cpp \
|
||||
project/footage.cpp \
|
||||
project/sequence.cpp \
|
||||
project/clip.cpp \
|
||||
playback/playback.cpp \
|
||||
playback/audio.cpp \
|
||||
io/config.cpp \
|
||||
dialogs/newsequencedialog.cpp \
|
||||
ui/viewerwidget.cpp \
|
||||
ui/viewercontainer.cpp \
|
||||
dialogs/exportdialog.cpp \
|
||||
ui/collapsiblewidget.cpp \
|
||||
panels/panels.cpp \
|
||||
playback/cacher.cpp \
|
||||
io/exportthread.cpp \
|
||||
ui/timelineheader.cpp \
|
||||
io/previewgenerator.cpp \
|
||||
ui/labelslider.cpp \
|
||||
dialogs/preferencesdialog.cpp \
|
||||
ui/audiomonitor.cpp \
|
||||
project/undo.cpp \
|
||||
ui/scrollarea.cpp \
|
||||
ui/comboboxex.cpp \
|
||||
ui/colorbutton.cpp \
|
||||
dialogs/replaceclipmediadialog.cpp \
|
||||
ui/fontcombobox.cpp \
|
||||
ui/checkboxex.cpp \
|
||||
ui/keyframeview.cpp \
|
||||
ui/texteditex.cpp \
|
||||
dialogs/demonotice.cpp \
|
||||
project/marker.cpp \
|
||||
dialogs/speeddialog.cpp \
|
||||
dialogs/mediapropertiesdialog.cpp \
|
||||
io/crc32.cpp \
|
||||
project/projectmodel.cpp \
|
||||
io/loadthread.cpp \
|
||||
dialogs/loaddialog.cpp \
|
||||
debug.cpp \
|
||||
io/path.cpp \
|
||||
effects/internal/linearfadetransition.cpp \
|
||||
effects/internal/transformeffect.cpp \
|
||||
effects/internal/solideffect.cpp \
|
||||
effects/internal/texteffect.cpp \
|
||||
effects/internal/timecodeeffect.cpp \
|
||||
effects/internal/audionoiseeffect.cpp \
|
||||
effects/internal/paneffect.cpp \
|
||||
effects/internal/toneeffect.cpp \
|
||||
effects/internal/volumeeffect.cpp \
|
||||
effects/internal/crossdissolvetransition.cpp \
|
||||
effects/internal/shakeeffect.cpp \
|
||||
effects/internal/exponentialfadetransition.cpp \
|
||||
effects/internal/logarithmicfadetransition.cpp \
|
||||
effects/internal/cornerpineffect.cpp \
|
||||
io/math.cpp \
|
||||
io/qpainterwrapper.cpp \
|
||||
project/effect.cpp \
|
||||
project/transition.cpp \
|
||||
project/effectrow.cpp \
|
||||
project/effectfield.cpp \
|
||||
effects/internal/cubetransition.cpp \
|
||||
project/effectgizmo.cpp \
|
||||
io/clipboard.cpp \
|
||||
dialogs/stabilizerdialog.cpp \
|
||||
io/avtogl.cpp \
|
||||
ui/resizablescrollbar.cpp \
|
||||
ui/sourceiconview.cpp \
|
||||
project/sourcescommon.cpp \
|
||||
ui/keyframenavigator.cpp \
|
||||
panels/grapheditor.cpp \
|
||||
ui/graphview.cpp \
|
||||
ui/keyframedrawing.cpp \
|
||||
ui/clickablelabel.cpp \
|
||||
project/keyframe.cpp \
|
||||
ui/rectangleselect.cpp \
|
||||
dialogs/actionsearch.cpp \
|
||||
ui/embeddedfilechooser.cpp \
|
||||
effects/internal/fillleftrighteffect.cpp \
|
||||
effects/internal/voideffect.cpp \
|
||||
dialogs/texteditdialog.cpp \
|
||||
dialogs/debugdialog.cpp \
|
||||
ui/renderthread.cpp \
|
||||
ui/renderfunctions.cpp \
|
||||
ui/viewerwindow.cpp \
|
||||
project/projectfilter.cpp \
|
||||
effects/internal/frei0reffect.cpp \
|
||||
project/effectloaders.cpp \
|
||||
io/crossplatformlib.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
panels/project.h \
|
||||
panels/effectcontrols.h \
|
||||
panels/viewer.h \
|
||||
panels/timeline.h \
|
||||
ui/sourcetable.h \
|
||||
dialogs/aboutdialog.h \
|
||||
ui/timelinewidget.h \
|
||||
project/media.h \
|
||||
project/footage.h \
|
||||
project/sequence.h \
|
||||
project/clip.h \
|
||||
playback/playback.h \
|
||||
playback/audio.h \
|
||||
io/config.h \
|
||||
dialogs/newsequencedialog.h \
|
||||
ui/viewerwidget.h \
|
||||
ui/viewercontainer.h \
|
||||
dialogs/exportdialog.h \
|
||||
ui/collapsiblewidget.h \
|
||||
panels/panels.h \
|
||||
playback/cacher.h \
|
||||
io/exportthread.h \
|
||||
ui/timelinetools.h \
|
||||
ui/timelineheader.h \
|
||||
io/previewgenerator.h \
|
||||
ui/labelslider.h \
|
||||
dialogs/preferencesdialog.h \
|
||||
ui/audiomonitor.h \
|
||||
project/undo.h \
|
||||
ui/scrollarea.h \
|
||||
ui/comboboxex.h \
|
||||
ui/colorbutton.h \
|
||||
dialogs/replaceclipmediadialog.h \
|
||||
ui/fontcombobox.h \
|
||||
ui/checkboxex.h \
|
||||
ui/keyframeview.h \
|
||||
ui/texteditex.h \
|
||||
dialogs/demonotice.h \
|
||||
project/marker.h \
|
||||
project/selection.h \
|
||||
dialogs/speeddialog.h \
|
||||
dialogs/mediapropertiesdialog.h \
|
||||
io/crc32.h \
|
||||
project/projectmodel.h \
|
||||
io/loadthread.h \
|
||||
dialogs/loaddialog.h \
|
||||
debug.h \
|
||||
io/path.h \
|
||||
effects/internal/transformeffect.h \
|
||||
effects/internal/solideffect.h \
|
||||
effects/internal/texteffect.h \
|
||||
effects/internal/timecodeeffect.h \
|
||||
effects/internal/audionoiseeffect.h \
|
||||
effects/internal/paneffect.h \
|
||||
effects/internal/toneeffect.h \
|
||||
effects/internal/volumeeffect.h \
|
||||
effects/internal/shakeeffect.h \
|
||||
effects/internal/linearfadetransition.h \
|
||||
effects/internal/crossdissolvetransition.h \
|
||||
effects/internal/exponentialfadetransition.h \
|
||||
effects/internal/logarithmicfadetransition.h \
|
||||
effects/internal/cornerpineffect.h \
|
||||
io/math.h \
|
||||
io/qpainterwrapper.h \
|
||||
project/effect.h \
|
||||
project/transition.h \
|
||||
project/effectrow.h \
|
||||
project/effectfield.h \
|
||||
effects/internal/cubetransition.h \
|
||||
project/effectgizmo.h \
|
||||
io/clipboard.h \
|
||||
dialogs/stabilizerdialog.h \
|
||||
io/avtogl.h \
|
||||
ui/resizablescrollbar.h \
|
||||
ui/sourceiconview.h \
|
||||
project/sourcescommon.h \
|
||||
ui/keyframenavigator.h \
|
||||
panels/grapheditor.h \
|
||||
ui/graphview.h \
|
||||
ui/keyframedrawing.h \
|
||||
ui/clickablelabel.h \
|
||||
project/keyframe.h \
|
||||
ui/rectangleselect.h \
|
||||
dialogs/actionsearch.h \
|
||||
ui/embeddedfilechooser.h \
|
||||
effects/internal/fillleftrighteffect.h \
|
||||
effects/internal/voideffect.h \
|
||||
dialogs/texteditdialog.h \
|
||||
dialogs/debugdialog.h \
|
||||
ui/renderthread.h \
|
||||
ui/renderfunctions.h \
|
||||
ui/viewerwindow.h \
|
||||
project/projectfilter.h \
|
||||
effects/internal/frei0reffect.h \
|
||||
project/effectloaders.h \
|
||||
io/crossplatformlib.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
win32 {
|
||||
RC_FILE = packaging/windows/resources.rc
|
||||
LIBS += -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample -lopengl32 -luser32
|
||||
|
||||
SOURCES += effects/internal/vsthostwin.cpp
|
||||
HEADERS += effects/internal/vsthostwin.h
|
||||
}
|
||||
|
||||
mac {
|
||||
LIBS += -L/usr/local/lib -lavutil -lavformat -lavcodec -lavfilter -lswscale -lswresample
|
||||
ICON = packaging/macos/olive.icns
|
||||
INCLUDEPATH = /usr/local/include
|
||||
}
|
||||
|
||||
unix:!mac {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libavutil libavformat libavcodec libavfilter libswscale libswresample
|
||||
LIBS += -ldl
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
icons/icons.qrc
|
||||
|
||||
unix:!mac:isEmpty(PREFIX) {
|
||||
PREFIX = /usr/local
|
||||
}
|
||||
|
||||
unix:!mac:target.path = $$PREFIX/bin
|
||||
|
||||
effects.files = $$PWD/effects/*.frag $$PWD/effects/*.xml $$PWD/effects/*.vert
|
||||
unix:!mac:effects.path = $$PREFIX/share/olive-editor/effects
|
||||
|
||||
unix:!mac {
|
||||
metainfo.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.appdata.xml
|
||||
metainfo.path = $$PREFIX/share/metainfo
|
||||
desktop.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.desktop
|
||||
desktop.path = $$PREFIX/share/applications
|
||||
mime.files = $$PWD/packaging/linux/org.olivevideoeditor.Olive.xml
|
||||
mime.path = $$PREFIX/share/mime/packages
|
||||
icon16.files = $$PWD/packaging/linux/icons/16x16/org.olivevideoeditor.Olive.png
|
||||
icon16.path = $$PREFIX/share/icons/hicolor/16x16/apps
|
||||
icon32.files = $$PWD/packaging/linux/icons/32x32/org.olivevideoeditor.Olive.png
|
||||
icon32.path = $$PREFIX/share/icons/hicolor/32x32/apps
|
||||
icon48.files = $$PWD/packaging/linux/icons/48x48/org.olivevideoeditor.Olive.png
|
||||
icon48.path = $$PREFIX/share/icons/hicolor/48x48/apps
|
||||
icon64.files = $$PWD/packaging/linux/icons/64x64/org.olivevideoeditor.Olive.png
|
||||
icon64.path = $$PREFIX/share/icons/hicolor/64x64/apps
|
||||
icon128.files = $$PWD/packaging/linux/icons/128x128/org.olivevideoeditor.Olive.png
|
||||
icon128.path = $$PREFIX/share/icons/hicolor/128x128/apps
|
||||
icon256.files = $$PWD/packaging/linux/icons/256x256/org.olivevideoeditor.Olive.png
|
||||
icon256.path = $$PREFIX/share/icons/hicolor/256x256/apps
|
||||
icon512.files = $$PWD/packaging/linux/icons/512x512/org.olivevideoeditor.Olive.png
|
||||
icon512.path = $$PREFIX/share/icons/hicolor/512x512/apps
|
||||
icon1024.files = $$PWD/packaging/linux/icons/1024x1024/org.olivevideoeditor.Olive.png
|
||||
icon1024.path = $$PREFIX/share/icons/hicolor/1024x1024/apps
|
||||
INSTALLS += target effects metainfo desktop mime icon16 icon32 icon48 icon64 icon128 icon256 icon512 icon1024
|
||||
}
|
||||
|
||||
@@ -59,13 +59,13 @@ GraphEditor::GraphEditor(QWidget* parent) : QDockWidget(parent), row(nullptr) {
|
||||
left_tool_layout->addStretch();
|
||||
|
||||
linear_button = new QPushButton(tr("Linear"));
|
||||
linear_button->setProperty("type", KEYFRAME_TYPE_LINEAR);
|
||||
linear_button->setProperty("type", EFFECT_KEYFRAME_LINEAR);
|
||||
linear_button->setCheckable(true);
|
||||
bezier_button = new QPushButton(tr("Bezier"));
|
||||
bezier_button->setProperty("type", KEYFRAME_TYPE_BEZIER);
|
||||
bezier_button->setProperty("type", EFFECT_KEYFRAME_BEZIER);
|
||||
bezier_button->setCheckable(true);
|
||||
hold_button = new QPushButton(tr("Hold"));
|
||||
hold_button->setProperty("type", KEYFRAME_TYPE_HOLD);
|
||||
hold_button->setProperty("type", EFFECT_KEYFRAME_HOLD);
|
||||
hold_button->setCheckable(true);
|
||||
|
||||
center_tool_layout->addStretch();
|
||||
@@ -216,11 +216,11 @@ void GraphEditor::select_all() {
|
||||
|
||||
void GraphEditor::set_key_button_enabled(bool e, int type) {
|
||||
linear_button->setEnabled(e);
|
||||
linear_button->setChecked(type == KEYFRAME_TYPE_LINEAR);
|
||||
linear_button->setChecked(type == EFFECT_KEYFRAME_LINEAR);
|
||||
bezier_button->setEnabled(e);
|
||||
bezier_button->setChecked(type == KEYFRAME_TYPE_BEZIER);
|
||||
bezier_button->setChecked(type == EFFECT_KEYFRAME_BEZIER);
|
||||
hold_button->setEnabled(e);
|
||||
hold_button->setChecked(type == KEYFRAME_TYPE_HOLD);
|
||||
hold_button->setChecked(type == EFFECT_KEYFRAME_HOLD);
|
||||
}
|
||||
|
||||
void GraphEditor::passthrough_slider_value() {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "project/transition.h"
|
||||
#include "io/config.h"
|
||||
#include "grapheditor.h"
|
||||
#include "project/effectloaders.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
|
||||
+4
-4
@@ -33,7 +33,7 @@ bool audio_rendering = false;
|
||||
bool recording = false;
|
||||
|
||||
qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
int audio_ibuffer_read = 0;
|
||||
unsigned long audio_ibuffer_read = 0;
|
||||
long audio_ibuffer_frame = 0;
|
||||
double audio_ibuffer_timecode = 0;
|
||||
|
||||
@@ -114,9 +114,9 @@ int current_audio_freq() {
|
||||
return audio_rendering ? sequence->audio_frequency : audio_output->format().sampleRate();
|
||||
}
|
||||
|
||||
int get_buffer_offset_from_frame(double framerate, long frame) {
|
||||
unsigned long get_buffer_offset_from_frame(double framerate, long frame) {
|
||||
if (frame >= audio_ibuffer_frame) {
|
||||
return qFloor(((double) (frame - audio_ibuffer_frame)/framerate)*current_audio_freq())*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)*av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
|
||||
return static_cast<unsigned long>(((double(frame - audio_ibuffer_frame)/framerate)*current_audio_freq())*av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)*av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO));
|
||||
} else {
|
||||
qWarning() << "Invalid values passed to get_buffer_offset_from_frame";
|
||||
return 0;
|
||||
@@ -168,7 +168,7 @@ int AudioSenderThread::send_audio_to_output(int offset, int max) {
|
||||
// send audio to device
|
||||
int actual_write = audio_io_device->write((const char*) audio_ibuffer+offset, max);
|
||||
|
||||
int audio_ibuffer_limit = audio_ibuffer_read + actual_write;
|
||||
unsigned long audio_ibuffer_limit = audio_ibuffer_read + actual_write;
|
||||
|
||||
// send samples to audio monitor cache
|
||||
// TODO make this work for the footage viewer - currently, enabling it causes crash due to an ASSERT
|
||||
|
||||
+2
-2
@@ -37,7 +37,7 @@ extern QMutex audio_write_lock;
|
||||
|
||||
#define audio_ibuffer_size 192000
|
||||
extern qint8 audio_ibuffer[audio_ibuffer_size];
|
||||
extern int audio_ibuffer_read;
|
||||
extern unsigned long audio_ibuffer_read;
|
||||
extern long audio_ibuffer_frame;
|
||||
extern double audio_ibuffer_timecode;
|
||||
extern bool audio_scrub;
|
||||
@@ -51,7 +51,7 @@ bool is_audio_device_set();
|
||||
|
||||
void init_audio();
|
||||
void stop_audio();
|
||||
int get_buffer_offset_from_frame(double framerate, long frame);
|
||||
unsigned long get_buffer_offset_from_frame(double framerate, long frame);
|
||||
|
||||
bool start_recording();
|
||||
void stop_recording();
|
||||
|
||||
+3
-2
@@ -364,7 +364,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
if (frame->nb_samples == 0) {
|
||||
break;
|
||||
} else {
|
||||
long buffer_timeline_out = get_buffer_offset_from_frame(c->sequence->frame_rate, timeline_out);
|
||||
unsigned long buffer_timeline_out = get_buffer_offset_from_frame(c->sequence->frame_rate, timeline_out);
|
||||
|
||||
audio_write_lock.lock();
|
||||
|
||||
while (c->frame_sample_index < nb_bytes
|
||||
@@ -767,7 +768,7 @@ void open_clip_worker(Clip* clip) {
|
||||
}*/
|
||||
|
||||
enum AVPixelFormat valid_pix_fmts[] = {
|
||||
AV_PIX_FMT_RGB24,
|
||||
// AV_PIX_FMT_RGB24,
|
||||
AV_PIX_FMT_RGBA,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
+19
-10
@@ -255,26 +255,35 @@ void get_clip_frame(Clip* c, long playhead, bool& texture_failed) {
|
||||
int nb_components = av_pix_fmt_desc_get(static_cast<enum AVPixelFormat>(c->pix_fmt))->nb_components;
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, target_frame->linesize[0]/nb_components);
|
||||
|
||||
bool copied = false;
|
||||
uint8_t* data = target_frame->data[0];
|
||||
// 2 data buffers to ping-pong between
|
||||
bool using_db_1 = true;
|
||||
uint8_t* data_buffer_1 = target_frame->data[0];
|
||||
uint8_t* data_buffer_2 = nullptr;
|
||||
|
||||
int frame_size;
|
||||
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
Effect* e = c->effects.at(i);
|
||||
if (e->enable_image) {
|
||||
if (!copied) {
|
||||
if (e->enable_image && e->is_enabled()) {
|
||||
if (data_buffer_1 == target_frame->data[0]) {
|
||||
frame_size = target_frame->linesize[0]*target_frame->height;
|
||||
data = new uint8_t[frame_size];
|
||||
memcpy(data, target_frame->data[0], frame_size);
|
||||
copied = true;
|
||||
|
||||
data_buffer_1 = new uint8_t[frame_size];
|
||||
data_buffer_2 = new uint8_t[frame_size];
|
||||
|
||||
memcpy(data_buffer_1, target_frame->data[0], frame_size);
|
||||
}
|
||||
e->process_image(get_timecode(c, playhead), data, frame_size);
|
||||
e->process_image(get_timecode(c, playhead), using_db_1 ? data_buffer_1 : data_buffer_2, using_db_1 ? data_buffer_2 : data_buffer_1, frame_size);
|
||||
using_db_1 = !using_db_1;
|
||||
}
|
||||
}
|
||||
|
||||
c->texture->setData(0, get_gl_pix_fmt_from_av(c->pix_fmt), QOpenGLTexture::UInt8, data);
|
||||
c->texture->setData(0, get_gl_pix_fmt_from_av(c->pix_fmt), QOpenGLTexture::UInt8, using_db_1 ? data_buffer_1 : data_buffer_2);
|
||||
|
||||
if (copied) delete [] data;
|
||||
if (data_buffer_1 != target_frame->data[0]) {
|
||||
delete [] data_buffer_1;
|
||||
delete [] data_buffer_2;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
|
||||
+40
-40
@@ -33,17 +33,17 @@ class QOpenGLTexture;
|
||||
|
||||
struct Clip
|
||||
{
|
||||
Clip(Sequence* s);
|
||||
Clip(Sequence* s);
|
||||
~Clip();
|
||||
Clip* copy(Sequence* s);
|
||||
void reset_audio();
|
||||
Clip* copy(Sequence* s);
|
||||
void reset_audio();
|
||||
void reset();
|
||||
void refresh();
|
||||
long get_clip_in_with_transition();
|
||||
long get_clip_in_with_transition();
|
||||
long get_timeline_in_with_transition();
|
||||
long get_timeline_out_with_transition();
|
||||
long getLength();
|
||||
double getMediaFrameRate();
|
||||
double getMediaFrameRate();
|
||||
long getMaximumLength();
|
||||
void recalculateMaxLength();
|
||||
int getWidth();
|
||||
@@ -56,39 +56,39 @@ struct Clip
|
||||
void queue_remove_earliest();
|
||||
|
||||
// timeline variables (should be copied in copy())
|
||||
bool enabled;
|
||||
long clip_in;
|
||||
long timeline_in;
|
||||
long timeline_out;
|
||||
int track;
|
||||
bool enabled;
|
||||
long clip_in;
|
||||
long timeline_in;
|
||||
long timeline_out;
|
||||
int track;
|
||||
QString name;
|
||||
quint8 color_r;
|
||||
quint8 color_g;
|
||||
quint8 color_b;
|
||||
Media* media;
|
||||
int media_stream;
|
||||
quint8 color_r;
|
||||
quint8 color_g;
|
||||
quint8 color_b;
|
||||
Media* media;
|
||||
int media_stream;
|
||||
double speed;
|
||||
double cached_fr;
|
||||
double cached_fr;
|
||||
bool reverse;
|
||||
bool maintain_audio_pitch;
|
||||
bool autoscale;
|
||||
|
||||
// other variables (should be deep copied/duplicated in copy())
|
||||
QList<Effect*> effects;
|
||||
QVector<int> linked;
|
||||
int opening_transition;
|
||||
Transition* get_opening_transition();
|
||||
int closing_transition;
|
||||
Transition* get_closing_transition();
|
||||
QList<Effect*> effects;
|
||||
QVector<int> linked;
|
||||
int opening_transition;
|
||||
Transition* get_opening_transition();
|
||||
int closing_transition;
|
||||
Transition* get_closing_transition();
|
||||
|
||||
// media handling
|
||||
AVFormatContext* formatCtx;
|
||||
AVStream* stream;
|
||||
AVCodec* codec;
|
||||
AVCodecContext* codecCtx;
|
||||
AVPacket* pkt;
|
||||
AVFormatContext* formatCtx;
|
||||
AVStream* stream;
|
||||
AVCodec* codec;
|
||||
AVCodecContext* codecCtx;
|
||||
AVPacket* pkt;
|
||||
AVFrame* frame;
|
||||
AVDictionary* opts;
|
||||
AVDictionary* opts;
|
||||
long calculated_length;
|
||||
|
||||
// temporary variables
|
||||
@@ -96,23 +96,23 @@ struct Clip
|
||||
bool undeletable;
|
||||
bool reached_end;
|
||||
bool pkt_written;
|
||||
bool open;
|
||||
bool finished_opening;
|
||||
bool replaced;
|
||||
bool open;
|
||||
bool finished_opening;
|
||||
bool replaced;
|
||||
bool ignore_reverse;
|
||||
int pix_fmt;
|
||||
|
||||
// caching functions
|
||||
bool use_existing_frame;
|
||||
bool multithreaded;
|
||||
bool multithreaded;
|
||||
Cacher* cacher;
|
||||
QWaitCondition can_cache;
|
||||
QWaitCondition can_cache;
|
||||
int max_queue_size;
|
||||
QVector<AVFrame*> queue;
|
||||
QMutex queue_lock;
|
||||
QMutex lock;
|
||||
QMutex lock;
|
||||
QMutex open_lock;
|
||||
int64_t last_invalid_ts;
|
||||
int64_t last_invalid_ts;
|
||||
|
||||
// converters/filters
|
||||
AVFilterGraph* filter_graph;
|
||||
@@ -121,15 +121,15 @@ struct Clip
|
||||
|
||||
// video playback variables
|
||||
QOpenGLFramebufferObject** fbo;
|
||||
QOpenGLTexture* texture;
|
||||
QOpenGLTexture* texture;
|
||||
long texture_frame;
|
||||
|
||||
// audio playback variables
|
||||
int64_t reverse_target;
|
||||
int frame_sample_index;
|
||||
int audio_buffer_write;
|
||||
bool audio_reset;
|
||||
bool audio_just_reset;
|
||||
int frame_sample_index;
|
||||
unsigned long audio_buffer_write;
|
||||
bool audio_reset;
|
||||
bool audio_just_reset;
|
||||
long audio_target_frame;
|
||||
};
|
||||
|
||||
|
||||
+11
-181
@@ -32,6 +32,7 @@
|
||||
#include "effects/internal/vsthostwin.h"
|
||||
#endif
|
||||
#include "effects/internal/fillleftrighteffect.h"
|
||||
#include "effects/internal/frei0reffect.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QGridLayout>
|
||||
@@ -49,10 +50,7 @@ bool shaders_are_enabled = true;
|
||||
QVector<EffectMeta> effects;
|
||||
|
||||
Effect* create_effect(Clip* c, const EffectMeta* em) {
|
||||
if (!em->filename.isEmpty()) {
|
||||
// load effect from file
|
||||
return new Effect(c, em);
|
||||
} else if (em->internal >= 0 && em->internal < EFFECT_INTERNAL_COUNT) {
|
||||
if (em->internal >= 0 && em->internal < EFFECT_INTERNAL_COUNT) {
|
||||
// must be an internal effect
|
||||
switch (em->internal) {
|
||||
case EFFECT_INTERNAL_TRANSFORM: return new TransformEffect(c, em);
|
||||
@@ -68,8 +66,14 @@ Effect* create_effect(Clip* c, const EffectMeta* em) {
|
||||
case EFFECT_INTERNAL_FILLLEFTRIGHT: return new FillLeftRightEffect(c, em);
|
||||
#ifdef _WIN32
|
||||
case EFFECT_INTERNAL_VST: return new VSTHostWin(c, em);
|
||||
#endif
|
||||
#ifndef NOFREI0R
|
||||
case EFFECT_INTERNAL_FREI0R: return new Frei0rEffect(c, em);
|
||||
#endif
|
||||
}
|
||||
} else if (!em->filename.isEmpty()) {
|
||||
// load effect from file
|
||||
return new Effect(c, em);
|
||||
} else {
|
||||
qCritical() << "Invalid effect data";
|
||||
QMessageBox::critical(mainWindow,
|
||||
@@ -88,180 +92,6 @@ const EffectMeta* get_internal_meta(int internal_id, int type) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void load_internal_effects() {
|
||||
if (!shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional";
|
||||
|
||||
EffectMeta em;
|
||||
|
||||
// internal effects
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
em.subtype = EFFECT_TYPE_AUDIO;
|
||||
|
||||
em.name = "Volume";
|
||||
em.internal = EFFECT_INTERNAL_VOLUME;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Pan";
|
||||
em.internal = EFFECT_INTERNAL_PAN;
|
||||
effects.append(em);
|
||||
|
||||
#ifdef _WIN32
|
||||
em.name = "VST Plugin 2.x";
|
||||
em.internal = EFFECT_INTERNAL_VST;
|
||||
effects.append(em);
|
||||
#endif
|
||||
|
||||
em.name = "Tone";
|
||||
em.internal = EFFECT_INTERNAL_TONE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Noise";
|
||||
em.internal = EFFECT_INTERNAL_NOISE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Fill Left/Right";
|
||||
em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT;
|
||||
effects.append(em);
|
||||
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
|
||||
em.name = "Transform";
|
||||
em.category = "Distort";
|
||||
em.internal = EFFECT_INTERNAL_TRANSFORM;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Corner Pin";
|
||||
em.internal = EFFECT_INTERNAL_CORNERPIN;
|
||||
effects.append(em);
|
||||
|
||||
/*em.name = "Mask";
|
||||
em.internal = EFFECT_INTERNAL_MASK;
|
||||
effects.append(em);*/
|
||||
|
||||
em.name = "Shake";
|
||||
em.internal = EFFECT_INTERNAL_SHAKE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Text";
|
||||
em.category = "Render";
|
||||
em.internal = EFFECT_INTERNAL_TEXT;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Timecode";
|
||||
em.internal = EFFECT_INTERNAL_TIMECODE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Solid";
|
||||
em.internal = EFFECT_INTERNAL_SOLID;
|
||||
effects.append(em);
|
||||
|
||||
// internal transitions
|
||||
em.type = EFFECT_TYPE_TRANSITION;
|
||||
em.category = "";
|
||||
|
||||
em.name = "Cross Dissolve";
|
||||
em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE;
|
||||
effects.append(em);
|
||||
|
||||
em.subtype = EFFECT_TYPE_AUDIO;
|
||||
|
||||
em.name = "Linear Fade";
|
||||
em.internal = TRANSITION_INTERNAL_LINEARFADE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Exponential Fade";
|
||||
em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Logarithmic Fade";
|
||||
em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE;
|
||||
effects.append(em);
|
||||
}
|
||||
|
||||
QList<QString> get_effects_paths() {
|
||||
QList<QString> effects_paths;
|
||||
effects_paths.append(get_app_dir() + "/effects");
|
||||
effects_paths.append(get_app_dir() + "/../share/olive-editor/effects");
|
||||
QString env_path(qgetenv("OLIVE_EFFECTS_PATH"));
|
||||
if (!env_path.isEmpty()) effects_paths.append(env_path);
|
||||
return effects_paths;
|
||||
}
|
||||
|
||||
void load_shader_effects() {
|
||||
QList<QString> effects_paths = get_effects_paths();
|
||||
|
||||
for (int h=0;h<effects_paths.size();h++) {
|
||||
const QString& effects_path = effects_paths.at(h);
|
||||
QDir effects_dir(effects_path);
|
||||
if (effects_dir.exists()) {
|
||||
QList<QString> entries = effects_dir.entryList(QStringList("*.xml"), QDir::Files);
|
||||
for (int i=0;i<entries.size();i++) {
|
||||
QFile file(effects_path + "/" + entries.at(i));
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qCritical() << "Could not open" << entries.at(i);
|
||||
return;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(&file);
|
||||
while (!reader.atEnd()) {
|
||||
if (reader.name() == "effect") {
|
||||
QString effect_name = "";
|
||||
QString effect_cat = "";
|
||||
const QXmlStreamAttributes attr = reader.attributes();
|
||||
for (int j=0;j<attr.size();j++) {
|
||||
if (attr.at(j).name() == "name") {
|
||||
effect_name = attr.at(j).value().toString();
|
||||
} else if (attr.at(j).name() == "category") {
|
||||
effect_cat = attr.at(j).value().toString();
|
||||
}
|
||||
}
|
||||
if (!effect_name.isEmpty()) {
|
||||
EffectMeta em;
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
em.name = effect_name;
|
||||
em.category = effect_cat;
|
||||
em.filename = file.fileName();
|
||||
em.path = effects_path;
|
||||
em.internal = -1;
|
||||
effects.append(em);
|
||||
} else {
|
||||
qCritical() << "Invalid effect found in" << entries.at(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
reader.readNext();
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load_vst_effects() {
|
||||
|
||||
}
|
||||
|
||||
void init_effects() {
|
||||
EffectInit* init_thread = new EffectInit();
|
||||
QObject::connect(init_thread, SIGNAL(finished()), init_thread, SLOT(deleteLater()));
|
||||
init_thread->start();
|
||||
}
|
||||
|
||||
EffectInit::EffectInit() {
|
||||
panel_effect_controls->effects_loaded.lock();
|
||||
}
|
||||
|
||||
void EffectInit::run() {
|
||||
qInfo() << "Initializing effects...";
|
||||
load_internal_effects();
|
||||
load_shader_effects();
|
||||
load_vst_effects();
|
||||
panel_effect_controls->effects_loaded.unlock();
|
||||
qInfo() << "Finished initializing effects";
|
||||
}
|
||||
|
||||
Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
parent_clip(c),
|
||||
meta(em),
|
||||
@@ -290,7 +120,7 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
|
||||
// set up UI from effect file
|
||||
container->setText(em->name);
|
||||
|
||||
if (!em->filename.isEmpty()) {
|
||||
if (!em->filename.isEmpty() && em->internal == -1) {
|
||||
QFile effect_file(em->filename);
|
||||
if (effect_file.open(QFile::ReadOnly)) {
|
||||
QXmlStreamReader reader(&effect_file);
|
||||
@@ -735,7 +565,7 @@ void Effect::load(QXmlStreamReader& stream) {
|
||||
void Effect::custom_load(QXmlStreamReader &) {}
|
||||
|
||||
void Effect::save(QXmlStreamWriter& stream) {
|
||||
stream.writeAttribute("name", meta->name);
|
||||
stream.writeAttribute("name", meta->category + "/" + meta->name);
|
||||
stream.writeAttribute("enabled", QString::number(is_enabled()));
|
||||
|
||||
for (int i=0;i<rows.size();i++) {
|
||||
@@ -866,7 +696,7 @@ void Effect::endEffect() {
|
||||
bound = false;
|
||||
}
|
||||
|
||||
void Effect::process_image(double, uint8_t *, int) {}
|
||||
void Effect::process_image(double, uint8_t *input, uint8_t *output, int) {}
|
||||
|
||||
Effect* Effect::copy(Clip* c) {
|
||||
Effect* copy = create_effect(c, meta);
|
||||
|
||||
+30
-28
@@ -38,38 +38,40 @@ extern bool shaders_are_enabled;
|
||||
extern QVector<EffectMeta> effects;
|
||||
|
||||
double log_volume(double linear);
|
||||
void init_effects();
|
||||
Effect* create_effect(Clip* c, const EffectMeta *em);
|
||||
const EffectMeta* get_internal_meta(int internal_id, int type);
|
||||
|
||||
#define EFFECT_TYPE_INVALID 0
|
||||
#define EFFECT_TYPE_VIDEO 1
|
||||
#define EFFECT_TYPE_AUDIO 2
|
||||
#define EFFECT_TYPE_EFFECT 3
|
||||
#define EFFECT_TYPE_TRANSITION 4
|
||||
enum EffectType {
|
||||
EFFECT_TYPE_INVALID,
|
||||
EFFECT_TYPE_VIDEO,
|
||||
EFFECT_TYPE_AUDIO,
|
||||
EFFECT_TYPE_EFFECT,
|
||||
EFFECT_TYPE_TRANSITION
|
||||
};
|
||||
|
||||
#define EFFECT_KEYFRAME_LINEAR 0
|
||||
#define EFFECT_KEYFRAME_HOLD 1
|
||||
#define EFFECT_KEYFRAME_BEZIER 2
|
||||
enum EffectKeyframeType {
|
||||
EFFECT_KEYFRAME_LINEAR,
|
||||
EFFECT_KEYFRAME_BEZIER,
|
||||
EFFECT_KEYFRAME_HOLD
|
||||
};
|
||||
|
||||
#define EFFECT_INTERNAL_TRANSFORM 0
|
||||
#define EFFECT_INTERNAL_TEXT 1
|
||||
#define EFFECT_INTERNAL_SOLID 2
|
||||
#define EFFECT_INTERNAL_NOISE 3
|
||||
#define EFFECT_INTERNAL_VOLUME 4
|
||||
#define EFFECT_INTERNAL_PAN 5
|
||||
#define EFFECT_INTERNAL_TONE 6
|
||||
#define EFFECT_INTERNAL_SHAKE 7
|
||||
#define EFFECT_INTERNAL_TIMECODE 8
|
||||
#define EFFECT_INTERNAL_MASK 9
|
||||
#define EFFECT_INTERNAL_FILLLEFTRIGHT 10
|
||||
#define EFFECT_INTERNAL_VST 11
|
||||
#define EFFECT_INTERNAL_CORNERPIN 12
|
||||
#define EFFECT_INTERNAL_COUNT 13
|
||||
|
||||
#define KEYFRAME_TYPE_LINEAR 0
|
||||
#define KEYFRAME_TYPE_BEZIER 1
|
||||
#define KEYFRAME_TYPE_HOLD 2
|
||||
enum EffectInternal {
|
||||
EFFECT_INTERNAL_TRANSFORM,
|
||||
EFFECT_INTERNAL_TEXT,
|
||||
EFFECT_INTERNAL_SOLID,
|
||||
EFFECT_INTERNAL_NOISE,
|
||||
EFFECT_INTERNAL_VOLUME,
|
||||
EFFECT_INTERNAL_PAN,
|
||||
EFFECT_INTERNAL_TONE,
|
||||
EFFECT_INTERNAL_SHAKE,
|
||||
EFFECT_INTERNAL_TIMECODE,
|
||||
EFFECT_INTERNAL_MASK,
|
||||
EFFECT_INTERNAL_FILLLEFTRIGHT,
|
||||
EFFECT_INTERNAL_VST,
|
||||
EFFECT_INTERNAL_CORNERPIN,
|
||||
EFFECT_INTERNAL_FREI0R,
|
||||
EFFECT_INTERNAL_COUNT
|
||||
};
|
||||
|
||||
struct GLTextureCoords {
|
||||
int grid_size;
|
||||
@@ -156,7 +158,7 @@ public:
|
||||
|
||||
const char* ffmpeg_filter;
|
||||
|
||||
virtual void process_image(double timecode, uint8_t* data, int size);
|
||||
virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size);
|
||||
virtual void process_shader(double timecode, GLTextureCoords&);
|
||||
virtual void process_coords(double timecode, GLTextureCoords& coords, int data);
|
||||
virtual GLuint process_superimpose(double timecode);
|
||||
|
||||
+44
-44
@@ -86,53 +86,53 @@ EffectField::EffectField(EffectRow *parent, int t, const QString &i) :
|
||||
connect(efc, SIGNAL(changed()), this, SLOT(ui_element_change()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double EffectField::get_validated_keyframe_handle(int key, bool post) {
|
||||
int comp_key = -1;
|
||||
int comp_key = -1;
|
||||
|
||||
// find keyframe before or after this one
|
||||
for (int i=0;i<keyframes.size();i++) {
|
||||
if (i != key
|
||||
&& ((keyframes.at(i).time > keyframes.at(key).time) == post)
|
||||
&& (comp_key == -1
|
||||
|| ((keyframes.at(i).time < keyframes.at(comp_key).time) == post))) {
|
||||
// compare with next keyframe for post or previous frame for pre
|
||||
comp_key = i;
|
||||
}
|
||||
}
|
||||
// find keyframe before or after this one
|
||||
for (int i=0;i<keyframes.size();i++) {
|
||||
if (i != key
|
||||
&& ((keyframes.at(i).time > keyframes.at(key).time) == post)
|
||||
&& (comp_key == -1
|
||||
|| ((keyframes.at(i).time < keyframes.at(comp_key).time) == post))) {
|
||||
// compare with next keyframe for post or previous frame for pre
|
||||
comp_key = i;
|
||||
}
|
||||
}
|
||||
|
||||
double adjusted_key = post ? keyframes.at(key).post_handle_x : keyframes.at(key).pre_handle_x;
|
||||
double adjusted_key = post ? keyframes.at(key).post_handle_x : keyframes.at(key).pre_handle_x;
|
||||
|
||||
// if this is the earliest/latest keyframe, no validation is required
|
||||
if (comp_key == -1) {
|
||||
return adjusted_key;
|
||||
}
|
||||
// if this is the earliest/latest keyframe, no validation is required
|
||||
if (comp_key == -1) {
|
||||
return adjusted_key;
|
||||
}
|
||||
|
||||
double comp = keyframes.at(comp_key).time - keyframes.at(key).time;
|
||||
double comp = keyframes.at(comp_key).time - keyframes.at(key).time;
|
||||
|
||||
// if comp keyframe is bezier, validate with its accompanying handle
|
||||
if (keyframes.at(comp_key).type == KEYFRAME_TYPE_BEZIER) {
|
||||
double relative_comp_handle = comp + (post ? keyframes.at(comp_key).pre_handle_x : keyframes.at(comp_key).post_handle_x);
|
||||
// return an average
|
||||
if ((post && keyframes.at(key).post_handle_x > relative_comp_handle)
|
||||
|| (!post && keyframes.at(key).pre_handle_x < relative_comp_handle)) {
|
||||
adjusted_key = (adjusted_key + relative_comp_handle)*0.5;
|
||||
}
|
||||
}
|
||||
// if comp keyframe is bezier, validate with its accompanying handle
|
||||
if (keyframes.at(comp_key).type == EFFECT_KEYFRAME_BEZIER) {
|
||||
double relative_comp_handle = comp + (post ? keyframes.at(comp_key).pre_handle_x : keyframes.at(comp_key).post_handle_x);
|
||||
// return an average
|
||||
if ((post && keyframes.at(key).post_handle_x > relative_comp_handle)
|
||||
|| (!post && keyframes.at(key).pre_handle_x < relative_comp_handle)) {
|
||||
adjusted_key = (adjusted_key + relative_comp_handle)*0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// don't let handle go beyond the compare keyframe's time
|
||||
if (post == (adjusted_key > comp)) {
|
||||
return comp;
|
||||
}
|
||||
// don't let handle go beyond the compare keyframe's time
|
||||
if (post == (adjusted_key > comp)) {
|
||||
return comp;
|
||||
}
|
||||
|
||||
if (post == (adjusted_key < 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (post == (adjusted_key < 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// original value is valid
|
||||
return adjusted_key;
|
||||
// original value is valid
|
||||
return adjusted_key;
|
||||
}
|
||||
|
||||
QVariant EffectField::get_previous_data() {
|
||||
@@ -162,7 +162,7 @@ QVariant EffectField::get_current_data() {
|
||||
}
|
||||
|
||||
double EffectField::frameToTimecode(long frame) {
|
||||
return ((double) frame / parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
return (double(frame) / parent_row->parent_effect->parent_clip->sequence->frame_rate);
|
||||
}
|
||||
|
||||
long EffectField::timecodeToFrame(double timecode) {
|
||||
@@ -242,22 +242,22 @@ QVariant EffectField::validate_keyframe_data(double timecode, bool async) {
|
||||
double before_dbl = before_key.data.toDouble();
|
||||
double after_dbl = after_key.data.toDouble();
|
||||
|
||||
if (before_key.type == KEYFRAME_TYPE_HOLD) {
|
||||
if (before_key.type == EFFECT_KEYFRAME_HOLD) {
|
||||
// hold
|
||||
value = before_dbl;
|
||||
} else if (before_key.type == KEYFRAME_TYPE_BEZIER || after_key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
} else if (before_key.type == EFFECT_KEYFRAME_BEZIER || after_key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
// bezier interpolation
|
||||
if (before_key.type == KEYFRAME_TYPE_BEZIER && after_key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
if (before_key.type == EFFECT_KEYFRAME_BEZIER && after_key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
// cubic bezier
|
||||
double t = cubic_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+get_validated_keyframe_handle(before_keyframe, true), after_key.time+get_validated_keyframe_handle(after_keyframe, false), after_key.time);
|
||||
double t = cubic_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+get_validated_keyframe_handle(before_keyframe, true), after_key.time+get_validated_keyframe_handle(after_keyframe, false), after_key.time);
|
||||
value = cubic_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl+after_key.pre_handle_y, after_dbl, t);
|
||||
} else if (after_key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier
|
||||
} else if (after_key.type == EFFECT_KEYFRAME_LINEAR) { // quadratic bezier
|
||||
// last keyframe is the bezier one
|
||||
double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+get_validated_keyframe_handle(before_keyframe, true), after_key.time);
|
||||
double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, before_key.time+get_validated_keyframe_handle(before_keyframe, true), after_key.time);
|
||||
value = quad_from_t(before_dbl, before_dbl+before_key.post_handle_y, after_dbl, t);
|
||||
} else {
|
||||
// this keyframe is the bezier one
|
||||
double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, after_key.time+get_validated_keyframe_handle(after_keyframe, false), after_key.time);
|
||||
double t = quad_t_from_x(timecode*parent_row->parent_effect->parent_clip->sequence->frame_rate, before_key.time, after_key.time+get_validated_keyframe_handle(after_keyframe, false), after_key.time);
|
||||
value = quad_from_t(before_dbl, after_dbl+after_key.pre_handle_y, after_dbl, t);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
#include "effectloaders.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/transition.h"
|
||||
#include "io/path.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "io/crossplatformlib.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#ifndef NOFREI0R
|
||||
#include <frei0r.h>
|
||||
typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info);
|
||||
#endif
|
||||
|
||||
void load_internal_effects() {
|
||||
if (!shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional";
|
||||
|
||||
EffectMeta em;
|
||||
|
||||
// internal effects
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
em.subtype = EFFECT_TYPE_AUDIO;
|
||||
|
||||
em.name = "Volume";
|
||||
em.internal = EFFECT_INTERNAL_VOLUME;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Pan";
|
||||
em.internal = EFFECT_INTERNAL_PAN;
|
||||
effects.append(em);
|
||||
|
||||
#ifdef _WIN32
|
||||
em.name = "VST Plugin 2.x";
|
||||
em.internal = EFFECT_INTERNAL_VST;
|
||||
effects.append(em);
|
||||
#endif
|
||||
|
||||
em.name = "Tone";
|
||||
em.internal = EFFECT_INTERNAL_TONE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Noise";
|
||||
em.internal = EFFECT_INTERNAL_NOISE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Fill Left/Right";
|
||||
em.internal = EFFECT_INTERNAL_FILLLEFTRIGHT;
|
||||
effects.append(em);
|
||||
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
|
||||
em.name = "Transform";
|
||||
em.category = "Distort";
|
||||
em.internal = EFFECT_INTERNAL_TRANSFORM;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Corner Pin";
|
||||
em.internal = EFFECT_INTERNAL_CORNERPIN;
|
||||
effects.append(em);
|
||||
|
||||
/*em.name = "Mask";
|
||||
em.internal = EFFECT_INTERNAL_MASK;
|
||||
effects.append(em);*/
|
||||
|
||||
em.name = "Shake";
|
||||
em.internal = EFFECT_INTERNAL_SHAKE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Text";
|
||||
em.category = "Render";
|
||||
em.internal = EFFECT_INTERNAL_TEXT;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Timecode";
|
||||
em.internal = EFFECT_INTERNAL_TIMECODE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Solid";
|
||||
em.internal = EFFECT_INTERNAL_SOLID;
|
||||
effects.append(em);
|
||||
|
||||
// internal transitions
|
||||
em.type = EFFECT_TYPE_TRANSITION;
|
||||
em.category = "";
|
||||
|
||||
em.name = "Cross Dissolve";
|
||||
em.internal = TRANSITION_INTERNAL_CROSSDISSOLVE;
|
||||
effects.append(em);
|
||||
|
||||
em.subtype = EFFECT_TYPE_AUDIO;
|
||||
|
||||
em.name = "Linear Fade";
|
||||
em.internal = TRANSITION_INTERNAL_LINEARFADE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Exponential Fade";
|
||||
em.internal = TRANSITION_INTERNAL_EXPONENTIALFADE;
|
||||
effects.append(em);
|
||||
|
||||
em.name = "Logarithmic Fade";
|
||||
em.internal = TRANSITION_INTERNAL_LOGARITHMICFADE;
|
||||
effects.append(em);
|
||||
}
|
||||
|
||||
void load_shader_effects() {
|
||||
QList<QString> effects_paths = get_effects_paths();
|
||||
|
||||
for (int h=0;h<effects_paths.size();h++) {
|
||||
const QString& effects_path = effects_paths.at(h);
|
||||
QDir effects_dir(effects_path);
|
||||
if (effects_dir.exists()) {
|
||||
QList<QString> entries = effects_dir.entryList(QStringList("*.xml"), QDir::Files);
|
||||
for (int i=0;i<entries.size();i++) {
|
||||
QFile file(effects_path + "/" + entries.at(i));
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qCritical() << "Could not open" << entries.at(i);
|
||||
return;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(&file);
|
||||
while (!reader.atEnd()) {
|
||||
if (reader.name() == "effect") {
|
||||
QString effect_name = "";
|
||||
QString effect_cat = "";
|
||||
const QXmlStreamAttributes attr = reader.attributes();
|
||||
for (int j=0;j<attr.size();j++) {
|
||||
if (attr.at(j).name() == "name") {
|
||||
effect_name = attr.at(j).value().toString();
|
||||
} else if (attr.at(j).name() == "category") {
|
||||
effect_cat = attr.at(j).value().toString();
|
||||
}
|
||||
}
|
||||
if (!effect_name.isEmpty()) {
|
||||
EffectMeta em;
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
em.name = effect_name;
|
||||
em.category = effect_cat;
|
||||
em.filename = file.fileName();
|
||||
em.path = effects_path;
|
||||
em.internal = -1;
|
||||
effects.append(em);
|
||||
} else {
|
||||
qCritical() << "Invalid effect found in" << entries.at(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
reader.readNext();
|
||||
}
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_effects() {
|
||||
EffectInit* init_thread = new EffectInit();
|
||||
QObject::connect(init_thread, SIGNAL(finished()), init_thread, SLOT(deleteLater()));
|
||||
init_thread->start();
|
||||
}
|
||||
|
||||
#ifndef NOFREI0R
|
||||
void load_frei0r_effects_worker(const QString& dir, EffectMeta& em, QVector<QString>& loaded_names) {
|
||||
QDir search_dir(dir);
|
||||
if (search_dir.exists()) {
|
||||
QList<QString> entry_list = search_dir.entryList(LibFilter(), QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot);
|
||||
for (int j=0;j<entry_list.size();j++) {
|
||||
QString entry_path = search_dir.filePath(entry_list.at(j));
|
||||
if (QFileInfo(entry_path).isDir()) {
|
||||
load_frei0r_effects_worker(entry_path, em, loaded_names);
|
||||
} else {
|
||||
ModulePtr effect = LibLoad(entry_path);
|
||||
if (effect != nullptr) {
|
||||
f0rGetPluginInfo get_info_func = reinterpret_cast<f0rGetPluginInfo>(LibAddress(effect, "f0r_get_plugin_info"));
|
||||
if (get_info_func != nullptr) {
|
||||
f0r_plugin_info_t info;
|
||||
get_info_func(&info);
|
||||
|
||||
if (!loaded_names.contains(info.name)
|
||||
&& info.plugin_type == F0R_PLUGIN_TYPE_FILTER
|
||||
&& info.color_model == F0R_COLOR_MODEL_RGBA8888) {
|
||||
em.name = info.name;
|
||||
em.path = dir;
|
||||
em.filename = entry_list.at(j);
|
||||
|
||||
effects.append(em);
|
||||
}
|
||||
// qDebug() << "Found:" << info.name << "by" << info.author;
|
||||
}
|
||||
LibClose(effect);
|
||||
}
|
||||
// qDebug() << search_dir.filePath(entry_list.at(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load_frei0r_effects() {
|
||||
QList<QString> effect_dirs = get_effects_paths();
|
||||
int lim = effect_dirs.size();
|
||||
|
||||
// add extra search paths for frei0r effects
|
||||
for (int i=0;i<lim;i++) {
|
||||
effect_dirs.append(QDir(effect_dirs.at(i)).filePath("frei0r"));
|
||||
}
|
||||
|
||||
// add defined paths for frei0r plugins on unix
|
||||
#if defined(__APPLE__) || defined(__linux__)
|
||||
effect_dirs.append(QDir::homePath() + "/.frei0r-1/lib");
|
||||
effect_dirs.append("/usr/local/lib/frei0r-1");
|
||||
effect_dirs.append("/usr/lib/frei0r-1");
|
||||
#endif
|
||||
|
||||
QVector<QString> loaded_names;
|
||||
|
||||
// search for paths
|
||||
EffectMeta em;
|
||||
em.category = "Frei0r";
|
||||
em.type = EFFECT_TYPE_EFFECT;
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
em.internal = EFFECT_INTERNAL_FREI0R;
|
||||
|
||||
for (int i=0;i<effect_dirs.size();i++) {
|
||||
load_frei0r_effects_worker(effect_dirs.at(i), em, loaded_names);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
EffectInit::EffectInit() {
|
||||
panel_effect_controls->effects_loaded.lock();
|
||||
}
|
||||
|
||||
void EffectInit::run() {
|
||||
qInfo() << "Initializing effects...";
|
||||
load_internal_effects();
|
||||
load_shader_effects();
|
||||
#ifndef NOFREI0R
|
||||
load_frei0r_effects();
|
||||
#endif
|
||||
panel_effect_controls->effects_loaded.unlock();
|
||||
qInfo() << "Finished initializing effects";
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef EFFECTLOADERS_H
|
||||
#define EFFECTLOADERS_H
|
||||
|
||||
#include <QList>
|
||||
|
||||
void init_effects();
|
||||
|
||||
#endif // EFFECTLOADERS_H
|
||||
@@ -197,7 +197,7 @@ void EffectRow::set_keyframe_now(ComboAction* ca) {
|
||||
}
|
||||
}
|
||||
if (exist_key == -1) {
|
||||
key.type = (f->keyframes.size() == 0) ? KEYFRAME_TYPE_LINEAR : f->keyframes.at(closest_key).type;
|
||||
key.type = (f->keyframes.size() == 0) ? EFFECT_KEYFRAME_LINEAR : f->keyframes.at(closest_key).type;
|
||||
key.data = f->get_current_data();//f->keyframes.at(closest_key).data;
|
||||
unsafe_keys[i] = f->keyframes.size();
|
||||
f->keyframes.append(key);
|
||||
|
||||
@@ -33,6 +33,7 @@ parts:
|
||||
- qtmultimedia5-dev
|
||||
- libavformat-dev
|
||||
- libavfilter-dev
|
||||
- frei0r-plugins-dev
|
||||
stage-packages:
|
||||
- ffmpeg
|
||||
- libqt5multimedia5
|
||||
@@ -40,6 +41,7 @@ parts:
|
||||
- libpulse0
|
||||
- libslang2
|
||||
- libglu1-mesa
|
||||
- frei0r-plugins
|
||||
override-build: |
|
||||
qmake olive.pro
|
||||
make
|
||||
|
||||
+15
-15
@@ -238,33 +238,33 @@ void GraphView::paintEvent(QPaintEvent *) {
|
||||
} else {
|
||||
const EffectKeyframe& last_key = field->keyframes.at(sorted_keys.at(j-1));
|
||||
|
||||
double pre_handle = field->get_validated_keyframe_handle(sorted_keys.at(j), false);
|
||||
double last_post_handle = field->get_validated_keyframe_handle(sorted_keys.at(j-1), true);
|
||||
double pre_handle = field->get_validated_keyframe_handle(sorted_keys.at(j), false);
|
||||
double last_post_handle = field->get_validated_keyframe_handle(sorted_keys.at(j-1), true);
|
||||
|
||||
if (last_key.type == KEYFRAME_TYPE_HOLD) {
|
||||
if (last_key.type == EFFECT_KEYFRAME_HOLD) {
|
||||
// hold
|
||||
p.drawLine(last_key_x, last_key_y, key_x, last_key_y);
|
||||
p.drawLine(key_x, last_key_y, key_x, key_y);
|
||||
} else if (last_key.type == KEYFRAME_TYPE_BEZIER || key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
} else if (last_key.type == EFFECT_KEYFRAME_BEZIER || key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
QPainterPath bezier_path;
|
||||
bezier_path.moveTo(last_key_x, last_key_y);
|
||||
if (last_key.type == KEYFRAME_TYPE_BEZIER && key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
if (last_key.type == EFFECT_KEYFRAME_BEZIER && key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
// cubic bezier
|
||||
bezier_path.cubicTo(
|
||||
QPointF(last_key_x+last_post_handle*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
QPointF(key_x+pre_handle*zoom, key_y-key.pre_handle_y*zoom),
|
||||
QPointF(last_key_x+last_post_handle*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
QPointF(key_x+pre_handle*zoom, key_y-key.pre_handle_y*zoom),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
} else if (key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier
|
||||
} else if (key.type == EFFECT_KEYFRAME_LINEAR) { // quadratic bezier
|
||||
// last keyframe is the bezier one
|
||||
bezier_path.quadTo(
|
||||
QPointF(last_key_x+last_post_handle*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
QPointF(last_key_x+last_post_handle*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
} else {
|
||||
// this keyframe is the bezier one
|
||||
bezier_path.quadTo(
|
||||
QPointF(key_x+pre_handle*zoom, key_y-key.pre_handle_y*zoom),
|
||||
QPointF(key_x+pre_handle*zoom, key_y-key.pre_handle_y*zoom),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ void GraphView::paintEvent(QPaintEvent *) {
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
|
||||
if (key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
if (key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
p.setPen(Qt::gray);
|
||||
|
||||
// pre handle line
|
||||
@@ -612,24 +612,24 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
&& event->pos().x() <= key_x) {
|
||||
QRect mouse_rect(event->pos().x()-BEZIER_LINE_SIZE, event->pos().y()-BEZIER_LINE_SIZE, BEZIER_LINE_SIZE+BEZIER_LINE_SIZE, BEZIER_LINE_SIZE+BEZIER_LINE_SIZE);
|
||||
// NOTE: FILTHY copy/paste from paintEvent
|
||||
if (last_key.type == KEYFRAME_TYPE_HOLD) {
|
||||
if (last_key.type == EFFECT_KEYFRAME_HOLD) {
|
||||
// hold
|
||||
if (event->pos().y() >= last_key_y-BEZIER_LINE_SIZE
|
||||
&& event->pos().y() <= last_key_y+BEZIER_LINE_SIZE) {
|
||||
// dout << "make an HOLD key on field" << i << "after key" << j;
|
||||
click_add = true;
|
||||
}
|
||||
} else if (last_key.type == KEYFRAME_TYPE_BEZIER || key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
} else if (last_key.type == EFFECT_KEYFRAME_BEZIER || key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
QPainterPath bezier_path;
|
||||
bezier_path.moveTo(last_key_x, last_key_y);
|
||||
if (last_key.type == KEYFRAME_TYPE_BEZIER && key.type == KEYFRAME_TYPE_BEZIER) {
|
||||
if (last_key.type == EFFECT_KEYFRAME_BEZIER && key.type == EFFECT_KEYFRAME_BEZIER) {
|
||||
// cubic bezier
|
||||
bezier_path.cubicTo(
|
||||
QPointF(last_key_x+last_key.post_handle_x*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
QPointF(key_x+key.pre_handle_x*zoom, key_y-key.pre_handle_y*zoom),
|
||||
QPointF(key_x, key_y)
|
||||
);
|
||||
} else if (key.type == KEYFRAME_TYPE_LINEAR) { // quadratic bezier
|
||||
} else if (key.type == EFFECT_KEYFRAME_LINEAR) { // quadratic bezier
|
||||
// last keyframe is the bezier one
|
||||
bezier_path.quadTo(
|
||||
QPointF(last_key_x+last_key.post_handle_x*zoom, last_key_y-last_key.post_handle_y*zoom),
|
||||
|
||||
@@ -14,16 +14,16 @@ void draw_keyframe(QPainter &p, int type, int x, int y, bool darker, int r, int
|
||||
p.setBrush(QColor(r, g, b));
|
||||
|
||||
switch (type) {
|
||||
case KEYFRAME_TYPE_LINEAR:
|
||||
case EFFECT_KEYFRAME_LINEAR:
|
||||
{
|
||||
QPoint points[KEYFRAME_POINT_COUNT] = {QPoint(x-KEYFRAME_SIZE, y), QPoint(x, y-KEYFRAME_SIZE), QPoint(x+KEYFRAME_SIZE, y), QPoint(x, y+KEYFRAME_SIZE)};
|
||||
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
|
||||
}
|
||||
break;
|
||||
case KEYFRAME_TYPE_BEZIER:
|
||||
case EFFECT_KEYFRAME_BEZIER:
|
||||
p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE);
|
||||
break;
|
||||
case KEYFRAME_TYPE_HOLD:
|
||||
case EFFECT_KEYFRAME_HOLD:
|
||||
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
|
||||
break;
|
||||
}
|
||||
|
||||
+9
-9
@@ -50,12 +50,12 @@ void KeyframeView::show_context_menu(const QPoint& pos) {
|
||||
if (selected_fields.size() > 0) {
|
||||
QMenu menu(this);
|
||||
|
||||
QAction* linear = menu.addAction(tr("Linear"));
|
||||
linear->setData(KEYFRAME_TYPE_LINEAR);
|
||||
QAction* bezier = menu.addAction(tr("Bezier"));
|
||||
bezier->setData(KEYFRAME_TYPE_BEZIER);
|
||||
QAction* hold = menu.addAction(tr("Hold"));
|
||||
hold->setData(KEYFRAME_TYPE_HOLD);
|
||||
QAction* linear = menu.addAction(tr("Linear"));
|
||||
linear->setData(EFFECT_KEYFRAME_LINEAR);
|
||||
QAction* bezier = menu.addAction(tr("Bezier"));
|
||||
bezier->setData(EFFECT_KEYFRAME_BEZIER);
|
||||
QAction* hold = menu.addAction(tr("Hold"));
|
||||
hold->setData(EFFECT_KEYFRAME_HOLD);
|
||||
menu.addSeparator();
|
||||
menu.addAction("Graph Editor");
|
||||
|
||||
@@ -199,9 +199,9 @@ void KeyframeView::set_y_scroll(int s) {
|
||||
}
|
||||
|
||||
void KeyframeView::resize_move(double d) {
|
||||
panel_effect_controls->zoom *= d;
|
||||
header->update_zoom(panel_effect_controls->zoom);
|
||||
update();
|
||||
panel_effect_controls->zoom *= d;
|
||||
header->update_zoom(panel_effect_controls->zoom);
|
||||
update();
|
||||
}
|
||||
|
||||
void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
|
||||
Reference in New Issue
Block a user