use QLibrary to load external libs instead of direct OS calls
This commit is contained in:
@@ -25,12 +25,11 @@
|
||||
#include "global/path.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "global/crossplatformlib.h"
|
||||
#include "global/config.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
#include <QLibrary>
|
||||
#include <QDebug>
|
||||
|
||||
#ifndef NOFREI0R
|
||||
@@ -206,15 +205,19 @@ void EffectInit::StartLoading() {
|
||||
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);
|
||||
QList<QString> entry_list = search_dir.entryList(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"));
|
||||
|
||||
QString path_without_extension = search_dir.filePath(QFileInfo(entry_list.at(j)).baseName());
|
||||
|
||||
QLibrary effect;
|
||||
effect.setFileName(path_without_extension);
|
||||
if (effect.load()) {
|
||||
f0rGetPluginInfo get_info_func = reinterpret_cast<f0rGetPluginInfo>(effect.resolve("f0r_get_plugin_info"));
|
||||
if (get_info_func != nullptr) {
|
||||
f0r_plugin_info_t info;
|
||||
get_info_func(&info);
|
||||
@@ -231,11 +234,9 @@ void load_frei0r_effects_worker(const QString& dir, EffectMeta& em, QVector<QStr
|
||||
|
||||
effects.append(em);
|
||||
}
|
||||
// qDebug() << "Found:" << info.name << "by" << info.author;
|
||||
}
|
||||
LibClose(effect);
|
||||
effect.unload();
|
||||
}
|
||||
// qDebug() << search_dir.filePath(entry_list.at(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,10 @@ Frei0rEffect::Frei0rEffect(Clip* c, const EffectMeta *em) :
|
||||
// Windows DLL loading routine
|
||||
QString dll_fn = QDir(em->path).filePath(em->filename);
|
||||
|
||||
handle = LibLoad(dll_fn);
|
||||
if(handle == nullptr) {
|
||||
handle.setFileName(dll_fn);
|
||||
|
||||
|
||||
if (!handle.load()) {
|
||||
QString dll_error;
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -75,18 +77,18 @@ Frei0rEffect::Frei0rEffect(Clip* c, const EffectMeta *em) :
|
||||
return;
|
||||
}
|
||||
|
||||
f0rInitFunc init = reinterpret_cast<f0rInitFunc>(LibAddress(handle, "f0r_init"));
|
||||
f0rInitFunc init = reinterpret_cast<f0rInitFunc>(handle.resolve("f0r_init"));
|
||||
init();
|
||||
|
||||
construct_module();
|
||||
|
||||
f0r_plugin_info_t info;
|
||||
f0rGetPluginInfo info_func = reinterpret_cast<f0rGetPluginInfo>(LibAddress(handle, "f0r_get_plugin_info"));
|
||||
f0rGetPluginInfo info_func = reinterpret_cast<f0rGetPluginInfo>(handle.resolve("f0r_get_plugin_info"));
|
||||
info_func(&info);
|
||||
|
||||
param_count = info.num_params;
|
||||
|
||||
get_param_info = reinterpret_cast<f0rGetParamInfo>(LibAddress(handle, "f0r_get_param_info"));
|
||||
get_param_info = reinterpret_cast<f0rGetParamInfo>(handle.resolve("f0r_get_param_info"));
|
||||
for (int i=0;i<param_count;i++) {
|
||||
f0r_param_info_t param_info;
|
||||
get_param_info(¶m_info, i);
|
||||
@@ -126,16 +128,16 @@ Frei0rEffect::Frei0rEffect(Clip* c, const EffectMeta *em) :
|
||||
}
|
||||
|
||||
Frei0rEffect::~Frei0rEffect() {
|
||||
if (handle != nullptr) {
|
||||
f0rDeinitFunc deinit = reinterpret_cast<f0rDeinitFunc>(LibAddress(handle, "f0r_deinit"));
|
||||
if (handle.isLoaded()) {
|
||||
f0rDeinitFunc deinit = reinterpret_cast<f0rDeinitFunc>(handle.resolve("f0r_deinit"));
|
||||
deinit();
|
||||
|
||||
LibClose(handle);
|
||||
handle.unload();
|
||||
}
|
||||
}
|
||||
|
||||
void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *output, int) {
|
||||
f0rUpdateFunc update_func = reinterpret_cast<f0rUpdateFunc>(LibAddress(handle, "f0r_update"));
|
||||
f0rUpdateFunc update_func = reinterpret_cast<f0rUpdateFunc>(handle.resolve("f0r_update"));
|
||||
|
||||
for (int i=0;i<param_count;i++) {
|
||||
EffectRow* param_row = row(i);
|
||||
@@ -143,7 +145,7 @@ void Frei0rEffect::process_image(double timecode, uint8_t *input, uint8_t *outpu
|
||||
f0r_param_info_t param_info;
|
||||
get_param_info(¶m_info, i);
|
||||
|
||||
f0rSetParamValue set_param = reinterpret_cast<f0rSetParamValue>(LibAddress(handle, "f0r_set_param_value"));
|
||||
f0rSetParamValue set_param = reinterpret_cast<f0rSetParamValue>(handle.resolve("f0r_set_param_value"));
|
||||
switch (param_info.type) {
|
||||
case F0R_PARAM_BOOL:
|
||||
{
|
||||
@@ -197,7 +199,7 @@ void Frei0rEffect::refresh() {
|
||||
|
||||
void Frei0rEffect::destruct_module() {
|
||||
if (open) {
|
||||
f0rDestructFunc destruct = reinterpret_cast<f0rDestructFunc>(LibAddress(handle, "f0r_destruct"));
|
||||
f0rDestructFunc destruct = reinterpret_cast<f0rDestructFunc>(handle.resolve("f0r_destruct"));
|
||||
destruct(instance);
|
||||
|
||||
open = false;
|
||||
@@ -205,7 +207,7 @@ void Frei0rEffect::destruct_module() {
|
||||
}
|
||||
|
||||
void Frei0rEffect::construct_module() {
|
||||
f0rConstructFunc construct = reinterpret_cast<f0rConstructFunc>(LibAddress(handle, "f0r_construct"));
|
||||
f0rConstructFunc construct = reinterpret_cast<f0rConstructFunc>(handle.resolve("f0r_construct"));
|
||||
instance = construct(parent_clip->media_width(), parent_clip->media_height());
|
||||
|
||||
open = true;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#ifndef NOFREI0R
|
||||
|
||||
#include <QLibrary>
|
||||
#include <frei0r.h>
|
||||
|
||||
#include "effects/effect.h"
|
||||
@@ -41,7 +42,7 @@ public:
|
||||
|
||||
virtual void refresh();
|
||||
private:
|
||||
ModulePtr handle;
|
||||
QLibrary handle;
|
||||
f0r_instance_t instance;
|
||||
int param_count;
|
||||
f0rGetParamInfo get_param_info;
|
||||
|
||||
@@ -34,7 +34,14 @@
|
||||
#include "global/global.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
#ifdef __linux__
|
||||
// Load libraries for retrieving the native window handle. Used for VST plugins that have a separate window
|
||||
// dedicated to controls.
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
class NSWindow;
|
||||
#elif defined(__linux__)
|
||||
#include <X11/X.h>
|
||||
#endif
|
||||
|
||||
@@ -105,95 +112,53 @@ typedef int32_t (*processEventsFuncPtr)(VstEvents *events);
|
||||
typedef void (*processFuncPtr)(AEffect *effect, float **inputs, float **outputs, int32_t sampleFrames);
|
||||
|
||||
void VSTHost::loadPlugin() {
|
||||
|
||||
QString dll_fn = file_field->GetFileAt(0);
|
||||
|
||||
if (dll_fn.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
bundle = BundleLoad(dll_fn);
|
||||
// Try to load the plugin
|
||||
modulePtr.setFileName(dll_fn);
|
||||
if (!modulePtr.load()) {
|
||||
|
||||
if (bundle == NULL) {
|
||||
QMessageBox::critical(nullptr, tr("Error loading VST plugin"), tr("Failed to create VST reference"));
|
||||
// Show an error if the plugin fails to load
|
||||
|
||||
qCritical() << "Failed to load VST plugin" << dll_fn << "-" << modulePtr.errorString();
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Error loading VST plugin"),
|
||||
tr("Failed to load VST plugin \"%1\": %2").arg(dll_fn, modulePtr.errorString()));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
vstPluginFuncPtr mainEntryPoint = NULL;
|
||||
mainEntryPoint = (vstPluginFuncPtr)CFBundleGetFunctionPointerForName(bundle, CFSTR("VSTPluginMain"));
|
||||
// VST plugins previous to the 2.4 SDK used main_macho for the entry point name
|
||||
if(mainEntryPoint == NULL) {
|
||||
mainEntryPoint = (vstPluginFuncPtr)CFBundleGetFunctionPointerForName(bundle, CFSTR("main_macho"));
|
||||
// Try to find the VST entry point (first using VSTPluginMain() )
|
||||
vstPluginFuncPtr mainEntryPoint = reinterpret_cast<vstPluginFuncPtr>(modulePtr.resolve("VSTPluginMain"));
|
||||
|
||||
if (mainEntryPoint == nullptr) {
|
||||
// If there's no VSTPluginMain(), the plugin may use main() instead
|
||||
mainEntryPoint = reinterpret_cast<vstPluginFuncPtr>(modulePtr.resolve("main"));
|
||||
}
|
||||
if(mainEntryPoint == NULL) {
|
||||
qCritical() << "Couldn't get a pointer to VST plugin's main()";
|
||||
BundleClose(bundle);
|
||||
|
||||
if (mainEntryPoint == nullptr) {
|
||||
QMessageBox::critical(olive::MainWindow,
|
||||
tr("Error loading VST plugin"),
|
||||
tr("Failed to locate entry point for dynamic library."));
|
||||
modulePtr.unload();
|
||||
return;
|
||||
}
|
||||
|
||||
// Instantiate the plugin
|
||||
plugin = mainEntryPoint(hostCallback);
|
||||
if(plugin == NULL) {
|
||||
qCritical() << "Plugin's main() returns null";
|
||||
BundleClose(bundle);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
modulePtr = LibLoad(dll_fn);
|
||||
if(modulePtr == nullptr) {
|
||||
QString dll_error;
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD dll_err = GetLastError();
|
||||
dll_error = QString::number(dll_err);
|
||||
#elif defined(__linux__) || defined(__HAIKU__)
|
||||
dll_error = dlerror();
|
||||
#endif
|
||||
qCritical() << "Failed to load VST plugin" << dll_fn << "-" << dll_error;
|
||||
|
||||
QString msg_err = tr("Failed to load VST 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.");
|
||||
#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.");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
QMessageBox::critical(nullptr, tr("Error loading VST plugin"), msg_err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
vstPluginFuncPtr mainEntryPoint = reinterpret_cast<vstPluginFuncPtr>(LibAddress(modulePtr, "VSTPluginMain"));
|
||||
|
||||
if (mainEntryPoint == nullptr) {
|
||||
// if there's no VSTPluginMain(), fallback to main()
|
||||
mainEntryPoint = reinterpret_cast<vstPluginFuncPtr>(LibAddress(modulePtr, "main"));
|
||||
}
|
||||
|
||||
if (mainEntryPoint == nullptr) {
|
||||
QMessageBox::critical(nullptr, tr("Error loading VST plugin"), tr("Failed to locate entry point for dynamic library."));
|
||||
LibClose(modulePtr);
|
||||
} else {
|
||||
// Instantiate the plugin
|
||||
plugin = mainEntryPoint(hostCallback);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void VSTHost::freePlugin() {
|
||||
if (plugin != nullptr) {
|
||||
stopPlugin();
|
||||
data_cache.clear();
|
||||
#if defined(__APPLE__)
|
||||
CFBundleUnloadExecutable(bundle);
|
||||
CFRelease(bundle);
|
||||
#else
|
||||
LibClose(modulePtr);
|
||||
#endif
|
||||
modulePtr.unload();
|
||||
plugin = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -406,13 +371,10 @@ void VSTHost::change_plugin() {
|
||||
dialog->setFixedSize(eRect->right - eRect->left, eRect->bottom - eRect->top);
|
||||
|
||||
} else {
|
||||
#ifdef __APPLE__
|
||||
CFBundleUnloadExecutable(bundle);
|
||||
CFRelease(bundle);
|
||||
#else
|
||||
LibClose(modulePtr);
|
||||
#endif
|
||||
|
||||
modulePtr.unload();
|
||||
plugin = nullptr;
|
||||
|
||||
}
|
||||
}
|
||||
show_interface_btn->SetEnabled(plugin != nullptr);
|
||||
|
||||
@@ -21,17 +21,16 @@
|
||||
#ifndef VSTHOSTWIN_H
|
||||
#define VSTHOSTWIN_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLibrary>
|
||||
|
||||
#include "effects/effect.h"
|
||||
|
||||
#include "global/crossplatformlib.h"
|
||||
|
||||
#include "include/vestige.h"
|
||||
|
||||
// Plugin's dispatcher function
|
||||
typedef intptr_t (*dispatcherFuncPtr)(AEffect *effect, int32_t opCode, int32_t index, int32_t value, void *ptr, float opt);
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class VSTHost : public Effect {
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -68,11 +67,7 @@ private:
|
||||
|
||||
void send_data_cache_to_plugin();
|
||||
|
||||
#if defined(__APPLE__)
|
||||
CFBundleRef bundle;
|
||||
#else
|
||||
ModulePtr modulePtr;
|
||||
#endif
|
||||
QLibrary modulePtr;
|
||||
};
|
||||
|
||||
#endif // VSTHOSTWIN_H
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#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__) || defined(__HAIKU__)
|
||||
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__) || defined(__HAIKU__)
|
||||
return {"*.so", "*.dylib"};
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
CFBundleRef BundleLoad(const QString &filename) {
|
||||
CFStringRef bundle_str = CFStringCreateWithCString(NULL, filename.toUtf8(), kCFStringEncodingUTF8);
|
||||
CFURLRef bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundle_str, kCFURLPOSIXPathStyle, true);
|
||||
CFBundleRef bundle = NULL;
|
||||
if (bundle_url != NULL) {
|
||||
bundle = CFBundleCreate(kCFAllocatorDefault, bundle_url);
|
||||
} else {
|
||||
qCritical() << "Failed to create VST URL";
|
||||
}
|
||||
CFRelease(bundle_url);
|
||||
CFRelease(bundle_str);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
void BundleClose(CFBundleRef bundle) {
|
||||
CFBundleUnloadExecutable(bundle);
|
||||
CFRelease(bundle);
|
||||
}
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef 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__) || defined(__HAIKU__)
|
||||
#include <dlfcn.h>
|
||||
#define LibAddress dlsym
|
||||
#define LibClose dlclose
|
||||
#define ModulePtr void*
|
||||
#endif
|
||||
|
||||
ModulePtr LibLoad(const QString& filename);
|
||||
QStringList LibFilter();
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
class NSWindow;
|
||||
|
||||
CFBundleRef BundleLoad(const QString& filename);
|
||||
void BundleClose(CFBundleRef bundle);
|
||||
#endif
|
||||
|
||||
#endif // CROSSPLATFORMLIB_H
|
||||
@@ -135,7 +135,6 @@ SOURCES += \
|
||||
project/projectfilter.cpp \
|
||||
effects/internal/frei0reffect.cpp \
|
||||
effects/effectloaders.cpp \
|
||||
global/crossplatformlib.cpp \
|
||||
effects/internal/vsthost.cpp \
|
||||
ui/flowlayout.cpp \
|
||||
dialogs/proxydialog.cpp \
|
||||
@@ -262,7 +261,6 @@ HEADERS += \
|
||||
project/projectfilter.h \
|
||||
effects/internal/frei0reffect.h \
|
||||
effects/effectloaders.h \
|
||||
global/crossplatformlib.h \
|
||||
effects/internal/vsthost.h \
|
||||
ui/flowlayout.h \
|
||||
dialogs/proxydialog.h \
|
||||
@@ -338,9 +336,6 @@ unix:!mac {
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libavutil libavformat libavcodec libavfilter libswscale libswresample
|
||||
}
|
||||
unix:!mac:!haiku {
|
||||
LIBS += -ldl
|
||||
}
|
||||
|
||||
RESOURCES += \
|
||||
icons/icons.qrc \
|
||||
|
||||
Reference in New Issue
Block a user