windows frei0r support done
This commit is contained in:
+6
-6
@@ -50,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);
|
||||
@@ -72,6 +69,9 @@ Effect* create_effect(Clip* c, const EffectMeta* em) {
|
||||
#endif
|
||||
case EFFECT_INTERNAL_FREI0R: return new Frei0rEffect(c, em);
|
||||
}
|
||||
} else if (!em->filename.isEmpty()) {
|
||||
// load effect from file
|
||||
return new Effect(c, em);
|
||||
} else {
|
||||
qCritical() << "Invalid effect data";
|
||||
QMessageBox::critical(mainWindow,
|
||||
@@ -118,7 +118,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);
|
||||
@@ -563,7 +563,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++) {
|
||||
|
||||
+29
-27
@@ -41,35 +41,37 @@ double log_volume(double linear);
|
||||
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_FREI0R 13
|
||||
#define EFFECT_INTERNAL_COUNT 14
|
||||
|
||||
#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;
|
||||
|
||||
+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 {
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <frei0r/frei0r.h>
|
||||
typedef void (*f0rGetPluginInfo)(f0r_plugin_info_t* info);
|
||||
|
||||
void load_internal_effects() {
|
||||
if (!shaders_are_enabled) qWarning() << "Shaders are disabled, some effects may be nonfunctional";
|
||||
|
||||
@@ -48,12 +51,6 @@ void load_internal_effects() {
|
||||
|
||||
em.subtype = EFFECT_TYPE_VIDEO;
|
||||
|
||||
// TEMPORARY begin
|
||||
em.name = "Frei0r Plugin";
|
||||
em.internal = EFFECT_INTERNAL_FREI0R;
|
||||
effects.append(em);
|
||||
// TEMPORARY end
|
||||
|
||||
em.name = "Transform";
|
||||
em.category = "Distort";
|
||||
em.internal = EFFECT_INTERNAL_TRANSFORM;
|
||||
@@ -165,6 +162,60 @@ void init_effects() {
|
||||
init_thread->start();
|
||||
}
|
||||
|
||||
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__)
|
||||
|
||||
#endif
|
||||
|
||||
// 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++) {
|
||||
QDir search_dir(effect_dirs.at(i));
|
||||
if (search_dir.exists()) {
|
||||
QList<QString> entry_list = search_dir.entryList(QStringList("*.dll"));
|
||||
for (int j=0;j<entry_list.size();j++) {
|
||||
|
||||
HMODULE effect = LoadLibrary(reinterpret_cast<const wchar_t*>(search_dir.filePath(entry_list.at(j)).utf16()));
|
||||
if (effect != nullptr) {
|
||||
f0rGetPluginInfo get_info_func = reinterpret_cast<f0rGetPluginInfo>(GetProcAddress(effect, "f0r_get_plugin_info"));
|
||||
if (get_info_func != nullptr) {
|
||||
f0r_plugin_info_t info;
|
||||
get_info_func(&info);
|
||||
|
||||
if (info.plugin_type == F0R_PLUGIN_TYPE_FILTER
|
||||
&& info.color_model == F0R_COLOR_MODEL_RGBA8888) {
|
||||
em.name = info.name;
|
||||
em.path = effect_dirs.at(i);
|
||||
em.filename = entry_list.at(j);
|
||||
|
||||
effects.append(em);
|
||||
}
|
||||
|
||||
// qDebug() << "Found:" << info.name << "by" << info.author;
|
||||
}
|
||||
FreeLibrary(effect);
|
||||
}
|
||||
|
||||
|
||||
// qDebug() << search_dir.filePath(entry_list.at(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EffectInit::EffectInit() {
|
||||
panel_effect_controls->effects_loaded.lock();
|
||||
}
|
||||
@@ -173,6 +224,7 @@ void EffectInit::run() {
|
||||
qInfo() << "Initializing effects...";
|
||||
load_internal_effects();
|
||||
load_shader_effects();
|
||||
load_frei0r_effects();
|
||||
panel_effect_controls->effects_loaded.unlock();
|
||||
qInfo() << "Finished initializing effects";
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user