diff --git a/effects/internal/frei0reffect.cpp b/effects/internal/frei0reffect.cpp index 46d5e5cf0..fef9c937b 100644 --- a/effects/internal/frei0reffect.cpp +++ b/effects/internal/frei0reffect.cpp @@ -3,8 +3,6 @@ #include #include -#include - typedef f0r_instance_t (*f0rConstructFunc)(unsigned int width, unsigned int height); typedef int (*f0rInitFunc) (); typedef void (*f0rDeinitFunc) (); @@ -20,32 +18,45 @@ Frei0rEffect::Frei0rEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { // Windows DLL loading routine QString dll_fn = QDir(em->path).filePath(em->filename); - LPCWSTR dll_fn_w = reinterpret_cast(dll_fn.utf16()); - modulePtr = LoadLibrary(dll_fn_w); - if(modulePtr == nullptr) { + handle = LibLoad(dll_fn); + if(handle == nullptr) { + QString dll_error; + +#ifdef _WIN32 DWORD dll_err = GetLastError(); - qCritical() << "Failed to load VST" << dll_fn_w << "-" << dll_err; - QString msg_err = tr("Failed to load VST plugin \"%1\": %2").arg(dll_fn, QString::number(dll_err)); + dll_error = QString::number(dll_err); + qCritical() << "Failed to load Frei0r plugin" << dll_fn_w << "-" << dll_err; +#elif __linux__ + dll_error = dlerror(); + qCritical() << "Failed to load Frei0r plugin" << dll_fn << "-" << dll_error; +#endif + + 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 VST 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."); + 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 VST 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."); + 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 } - QMessageBox::critical(nullptr, tr("Error loading VST plugin"), msg_err); - return; - } +#endif - f0rInitFunc init = reinterpret_cast(GetProcAddress(modulePtr, "f0r_init")); + QMessageBox::critical(nullptr, tr("Error loading Frei0r plugin"), msg_err); + + return; + } + + f0rInitFunc init = reinterpret_cast(LibAddress(handle, "f0r_init")); init(); - f0rConstructFunc construct = reinterpret_cast(GetProcAddress(modulePtr, "f0r_construct")); + f0rConstructFunc construct = reinterpret_cast(LibAddress(handle, "f0r_construct")); instance = construct(1920, 1080); f0r_plugin_info_t info; - f0rGetPluginInfo info_func = reinterpret_cast(GetProcAddress(modulePtr, "f0r_get_plugin_info")); + f0rGetPluginInfo info_func = reinterpret_cast(LibAddress(handle, "f0r_get_plugin_info")); info_func(&info); param_count = info.num_params; @@ -54,7 +65,7 @@ Frei0rEffect::Frei0rEffect(Clip *c, const EffectMeta *em) : Effect(c, em) { qDebug() << "Frei0r Param Count:" << info.num_params; qDebug() << "Frei0r Explanation:" << info.explanation; - get_param_info = reinterpret_cast(GetProcAddress(modulePtr, "f0r_get_param_info")); + get_param_info = reinterpret_cast(LibAddress(handle, "f0r_get_param_info")); for (int i=0;i(GetProcAddress(modulePtr, "f0r_destruct")); + if (handle != nullptr) { + f0rDestructFunc destruct = reinterpret_cast(LibAddress(handle, "f0r_destruct")); destruct(instance); - f0rDeinitFunc deinit = reinterpret_cast(GetProcAddress(modulePtr, "f0r_deinit")); + f0rDeinitFunc deinit = reinterpret_cast(LibAddress(handle, "f0r_deinit")); deinit(); - FreeModule(modulePtr); + LibClose(handle); } } void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *output, int) { - f0rUpdateFunc update_func = reinterpret_cast(GetProcAddress(modulePtr, "f0r_update")); + f0rUpdateFunc update_func = reinterpret_cast(LibAddress(handle, "f0r_update")); for (int i=0;i(GetProcAddress(modulePtr, "f0r_set_param_value")); + f0rSetParamValue set_param = reinterpret_cast(LibAddress(handle, "f0r_set_param_value")); switch (param_info.type) { case F0R_PARAM_BOOL: { diff --git a/effects/internal/frei0reffect.h b/effects/internal/frei0reffect.h index 1992cbda3..8f528499f 100644 --- a/effects/internal/frei0reffect.h +++ b/effects/internal/frei0reffect.h @@ -3,7 +3,9 @@ #include "project/effect.h" -#include +#include + +#include "io/crossplatformlib.h" typedef void (*f0rGetParamInfo)(f0r_param_info_t * info, int param_index ); @@ -16,7 +18,7 @@ public: virtual void process_image(double timecode, uint8_t* input, uint8_t* output, int size); private: - HMODULE modulePtr; + ModulePtr handle; f0r_instance_t instance; int param_count; f0rGetParamInfo get_param_info; diff --git a/io/crossplatformlib.cpp b/io/crossplatformlib.cpp new file mode 100644 index 000000000..d05558dc3 --- /dev/null +++ b/io/crossplatformlib.cpp @@ -0,0 +1,25 @@ +#include "crossplatformlib.h" + +#include + +void *LibLoad(const QString &filename) { +#ifdef _WIN32 + LPCWSTR dll_fn_w = reinterpret_cast(filename.utf16()); + return LoadLibrary(dll_fn_w); +#elif __linux__ + 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 __linux__ + return QStringList("*.so"); +#elif __APPLE__ + return QStringList("*.dylib"); +#endif +} diff --git a/io/crossplatformlib.h b/io/crossplatformlib.h new file mode 100644 index 000000000..1b3eb266b --- /dev/null +++ b/io/crossplatformlib.h @@ -0,0 +1,21 @@ +#ifndef CROSSPLATFORMLIB_H +#define CROSSPLATFORMLIB_H + +#include + +#ifdef _WIN32 + #include + #define LibAddress GetProcAddress + #define CloseLib FreeModule + #define ModulePtr HMODULE +#elif __linux__ + #include + #define LibAddress dlsym + #define LibClose dlclose + #define ModulePtr void* +#endif + +ModulePtr LibLoad(const QString& filename); +QStringList LibFilter(); + +#endif // CROSSPLATFORMLIB_H diff --git a/io/loadthread.cpp b/io/loadthread.cpp index c7cd80f40..3c8ba1c63 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -43,10 +43,7 @@ const EffectMeta* get_meta_from_name(const QString& input) { if (split_index > -1) { category = input.left(split_index); } - QString name = input.mid(split_index + 1); - - qDebug() << "CAT:" << category; - qDebug() << "NAM:" << name; + QString name = input.mid(split_index + 1); for (int j=0;j #include #include -#include +#ifndef NOFREI0R +#include 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"; @@ -162,6 +165,40 @@ void init_effects() { init_thread->start(); } +void load_frei0r_effects_worker(const QString& dir, EffectMeta& em) { + QDir search_dir(dir); + if (search_dir.exists()) { + QList entry_list = search_dir.entryList(LibFilter(), QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); + for (int j=0;j(LibAddress(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 = 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 effect_dirs = get_effects_paths(); int lim = effect_dirs.size(); @@ -173,46 +210,20 @@ void load_frei0r_effects() { // 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 - // search for paths - EffectMeta em; - em.category = "Frei0r"; - em.type = EFFECT_TYPE_EFFECT; - em.subtype = EFFECT_TYPE_VIDEO; - em.internal = EFFECT_INTERNAL_FREI0R; + // 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 entry_list = search_dir.entryList(QStringList("*.dll")); - for (int j=0;j(search_dir.filePath(entry_list.at(j)).utf16())); - if (effect != nullptr) { - f0rGetPluginInfo get_info_func = reinterpret_cast(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)); - } - } + load_frei0r_effects_worker(effect_dirs.at(i), em); } }