/*** Olive - Non-Linear Video Editor Copyright (C) 2019 Olive Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #include "frei0reffect.h" #ifndef NOFREI0R #include #include #include "timeline/clip.h" 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), open(false) { SetFlags(ImageFlag); // Windows DLL loading routine QString dll_fn = QDir(em->path).filePath(em->filename); handle.setFileName(dll_fn); if (!handle.load()) { QString dll_error = handle.errorString(); QMessageBox::critical(nullptr, tr("Error loading Frei0r plugin"), tr("Failed to load Frei0r plugin \"%1\": %2").arg(dll_fn, dll_error)); return; } f0rInitFunc init = reinterpret_cast(handle.resolve("f0r_init")); init(); construct_module(); f0r_plugin_info_t info; f0rGetPluginInfo info_func = reinterpret_cast(handle.resolve("f0r_get_plugin_info")); info_func(&info); param_count = info.num_params; get_param_info = reinterpret_cast(handle.resolve("f0r_get_param_info")); for (int i=0;i= 0 && param_info.type <= F0R_PARAM_STRING) { EffectRow* row = new EffectRow(this, param_info.name); switch (param_info.type) { case F0R_PARAM_BOOL: new BoolField(row, QString::number(i)); break; case F0R_PARAM_DOUBLE: { DoubleField* f = new DoubleField(row, QString::number(i)); f->SetMinimum(0); f->SetMaximum(100); } break; case F0R_PARAM_COLOR: new ColorField(row, QString::number(i)); break; case F0R_PARAM_POSITION: { DoubleField* fx = new DoubleField(row, QString("%1X").arg(QString::number(i))); fx->SetMinimum(0); fx->SetMaximum(100); DoubleField* fy = new DoubleField(row, QString("%1Y").arg(QString::number(i))); fy->SetMinimum(0); fy->SetMaximum(100); } break; case F0R_PARAM_STRING: new StringField(row, QString::number(i), false); break; } } } } Frei0rEffect::~Frei0rEffect() { if (handle.isLoaded()) { f0rDeinitFunc deinit = reinterpret_cast(handle.resolve("f0r_deinit")); deinit(); handle.unload(); } } void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *output, int) { f0rUpdateFunc update_func = reinterpret_cast(handle.resolve("f0r_update")); for (int i=0;i(handle.resolve("f0r_set_param_value")); switch (param_info.type) { case F0R_PARAM_BOOL: { double b = param_row->Field(0)->GetValueAt(timecode).toBool(); set_param(instance, &b, i); } break; case F0R_PARAM_DOUBLE: { double d = param_row->Field(0)->GetValueAt(timecode).toDouble()*0.01; set_param(instance, &d, i); } break; case F0R_PARAM_COLOR: { QColor qcolor = param_row->Field(0)->GetValueAt(timecode).value(); 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)->GetValueAt(timecode).toDouble(); pos.y = param_row->Field(1)->GetValueAt(timecode).toDouble(); set_param(instance, &pos, i); } break; case F0R_PARAM_STRING: { QByteArray bytes = param_row->Field(0)->GetValueAt(timecode).toString().toUtf8(); char* byte_data = bytes.data(); set_param(instance, &byte_data, i); } break; } } update_func(instance, timecode, reinterpret_cast(input), reinterpret_cast(output)); } void Frei0rEffect::refresh() { destruct_module(); construct_module(); } void Frei0rEffect::destruct_module() { if (open) { f0rDestructFunc destruct = reinterpret_cast(handle.resolve("f0r_destruct")); destruct(instance); open = false; } } void Frei0rEffect::construct_module() { f0rConstructFunc construct = reinterpret_cast(handle.resolve("f0r_construct")); instance = construct(parent_clip->media_width(), parent_clip->media_height()); open = true; } #endif