VST3: Load and instantiate
This commit is contained in:
parent
3f16f60221
commit
9bd8c43693
46
libs/ardour/ardour/vst3_module.h
Normal file
46
libs/ardour/ardour/vst3_module.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _ardour_vst3_module_h_
|
||||
#define _ardour_vst3_module_h_
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "ardour/libardour_visibility.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class LIBARDOUR_API VST3PluginModule
|
||||
{
|
||||
public:
|
||||
static boost::shared_ptr<VST3PluginModule> load (std::string const& path);
|
||||
VST3PluginModule () {}
|
||||
virtual ~VST3PluginModule () {}
|
||||
|
||||
virtual void* fn_ptr (const char* name) const = 0;
|
||||
|
||||
protected:
|
||||
virtual bool init () = 0;
|
||||
virtual bool exit () = 0;
|
||||
|
||||
/* prevent copy construction */
|
||||
VST3PluginModule (VST3PluginModule const&);
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
#endif
|
@ -115,6 +115,8 @@
|
||||
#endif
|
||||
|
||||
#ifdef VST3_SUPPORT
|
||||
#include "pbd/basename.h"
|
||||
#include "ardour/vst3_module.h"
|
||||
#include "ardour/vst3_plugin.h"
|
||||
#endif
|
||||
|
||||
@ -1532,7 +1534,7 @@ PluginManager::vst3_discover (string const& path, bool cache_only)
|
||||
module_path = path;
|
||||
} else {
|
||||
module_path = Glib::build_filename (path, "Contents",
|
||||
vst3_bindir (), basename_nosuffix (path) + vst3_suffix ());
|
||||
vst3_bindir (), PBD::basename_nosuffix (path) + vst3_suffix ());
|
||||
}
|
||||
if (!Glib::file_test (module_path, Glib::FILE_TEST_IS_REGULAR)) {
|
||||
cerr << "VST3 not a valid bundle: '" << module_path << "'\n";
|
||||
@ -1541,6 +1543,13 @@ PluginManager::vst3_discover (string const& path, bool cache_only)
|
||||
ARDOUR::PluginScanMessage(_("VST3"), module_path, !(cache_only || cancelled()));
|
||||
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("VST3: discover %1 (%2)\n", path, module_path));
|
||||
|
||||
try {
|
||||
boost::shared_ptr<VST3PluginModule> m = VST3PluginModule::load (module_path);
|
||||
} catch (...) {
|
||||
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot load VST3 at '%1'\n", path));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
230
libs/ardour/vst3_module.cc
Normal file
230
libs/ardour/vst3_module.cc
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Carbon/Carbon.h>
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
#include <glibmm.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/error.h"
|
||||
#include "pbd/failed_constructor.h"
|
||||
|
||||
#include "ardour/vst3_module.h"
|
||||
|
||||
#include "pbd/i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
class VST3MacModule : public VST3PluginModule
|
||||
{
|
||||
public:
|
||||
VST3MacModule (std::string const& module_path)
|
||||
{
|
||||
std::string path = Glib::path_get_dirname (module_path); // MacOS
|
||||
path = Glib::path_get_dirname (path); // Contents
|
||||
path = Glib::path_get_dirname (path); // theVST.vst3
|
||||
CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)path.c_str (), (CFIndex)path.length (), true);
|
||||
if (url) {
|
||||
_bundle = CFBundleCreate (kCFAllocatorDefault, url);
|
||||
CFRelease (url);
|
||||
}
|
||||
|
||||
if (!_bundle) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (!CFBundleLoadExecutable (_bundle)) {
|
||||
CFRelease (_bundle);
|
||||
_bundle = 0;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (!init ()) {
|
||||
CFRelease (_bundle);
|
||||
_bundle = 0;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
~VST3MacModule ()
|
||||
{
|
||||
if (_bundle) {
|
||||
exit ();
|
||||
CFRelease (_bundle);
|
||||
}
|
||||
}
|
||||
|
||||
void* fn_ptr (const char* name) const
|
||||
{
|
||||
CFStringRef str = CFStringCreateWithCString (NULL, name, kCFStringEncodingUTF8);
|
||||
void* fn = CFBundleGetFunctionPointerForName (_bundle, str);
|
||||
if (str) {
|
||||
CFRelease (str);
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
|
||||
private:
|
||||
bool init ()
|
||||
{
|
||||
typedef bool (*init_fn_t) (CFBundleRef);
|
||||
init_fn_t fn = (init_fn_t)fn_ptr ("bundleEntry");
|
||||
return (fn && fn (_bundle));
|
||||
}
|
||||
|
||||
bool exit ()
|
||||
{
|
||||
typedef bool (*exit_fn_t) ();
|
||||
exit_fn_t fn = (exit_fn_t)fn_ptr ("bundleExit");
|
||||
return (fn && fn ());
|
||||
}
|
||||
|
||||
CFBundleRef _bundle;
|
||||
};
|
||||
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
|
||||
class VST3WindowsModule : public VST3PluginModule
|
||||
{
|
||||
public:
|
||||
VST3WindowsModule (const std::string& path)
|
||||
{
|
||||
if ((_handle = LoadLibraryA (Glib::locale_from_utf8 (path).c_str ())) == 0) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (!init ()) {
|
||||
FreeLibrary (_handle);
|
||||
_handle = 0;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
~VST3WindowsModule ()
|
||||
{
|
||||
if (_handle) {
|
||||
exit ();
|
||||
FreeLibrary (_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void* fn_ptr (const char* name) const
|
||||
{
|
||||
return (void*)GetProcAddress (_handle, name);
|
||||
}
|
||||
|
||||
private:
|
||||
bool init ()
|
||||
{
|
||||
typedef bool(__stdcall * init_fn_t) ();
|
||||
init_fn_t fn = (init_fn_t)fn_ptr ("InitDll");
|
||||
return (!fn || fn ()); // init is optional
|
||||
}
|
||||
|
||||
bool exit ()
|
||||
{
|
||||
typedef bool(__stdcall * exit_fn_t) ();
|
||||
exit_fn_t fn = (exit_fn_t)fn_ptr ("ExitDll");
|
||||
return (!fn || fn ()); // exit is optional
|
||||
}
|
||||
|
||||
HMODULE _handle;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class VST3LinuxModule : public VST3PluginModule
|
||||
{
|
||||
public:
|
||||
VST3LinuxModule (std::string const& path)
|
||||
{
|
||||
if ((_dll = dlopen (path.c_str (), RTLD_LOCAL | RTLD_LAZY)) == 0) {
|
||||
PBD::error << string_compose (_("Could not load VST3 plugin '%1': %2"), path, dlerror ()) << endmsg;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
void* m_entry = dlsym (_dll, "ModuleEntry");
|
||||
void* m_exit = dlsym (_dll, "ModuleExit");
|
||||
|
||||
if (!m_entry || !m_exit) {
|
||||
PBD::error << string_compose (_("Invalid VST3 plugin: '%1'"), path) << endmsg;
|
||||
dlclose (_dll);
|
||||
_dll = 0;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
if (!init ()) {
|
||||
dlclose (_dll);
|
||||
_dll = 0;
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
~VST3LinuxModule ()
|
||||
{
|
||||
if (_dll) {
|
||||
exit ();
|
||||
dlclose (_dll);
|
||||
}
|
||||
}
|
||||
|
||||
void* fn_ptr (const char* name) const
|
||||
{
|
||||
return dlsym (_dll, name);
|
||||
}
|
||||
|
||||
private:
|
||||
bool init ()
|
||||
{
|
||||
typedef bool (*init_fn_t) (void*);
|
||||
init_fn_t fn = (init_fn_t)fn_ptr ("ModuleEntry");
|
||||
return (fn && fn (_dll));
|
||||
}
|
||||
|
||||
bool exit ()
|
||||
{
|
||||
typedef bool (*exit_fn_t) ();
|
||||
exit_fn_t fn = (exit_fn_t)fn_ptr ("ModuleExit");
|
||||
return (fn && fn ());
|
||||
}
|
||||
|
||||
void* _dll;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<VST3PluginModule>
|
||||
VST3PluginModule::load (std::string const& path)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return boost::shared_ptr<VST3PluginModule> (new VST3MacModule (path));
|
||||
#elif defined PLATFORM_WINDOWS
|
||||
return boost::shared_ptr<VST3PluginModule> (new VST3WindowsModule (path));
|
||||
#else
|
||||
return boost::shared_ptr<VST3PluginModule> (new VST3LinuxModule (path));
|
||||
#endif
|
||||
}
|
@ -460,7 +460,7 @@ def build(bld):
|
||||
obj.defines += [ 'MACVST_SUPPORT' ]
|
||||
|
||||
if bld.is_defined('VST3_SUPPORT'):
|
||||
obj.source += [ 'vst3_plugin.cc' ]
|
||||
obj.source += [ 'vst3_plugin.cc', 'vst3_module.cc' ]
|
||||
obj.defines += [ 'VST3_SUPPORT' ]
|
||||
|
||||
if bld.is_defined('HAVE_COREAUDIO'):
|
||||
|
Loading…
Reference in New Issue
Block a user