Mac VST-2.x support

This commit is contained in:
Robin Gareus 2016-11-13 16:31:15 +01:00
parent 43bd7f5db1
commit 8b93fb02f3
20 changed files with 865 additions and 15 deletions

View File

@ -30,7 +30,7 @@
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
#include "evoral/MIDIEvent.hpp"
struct _VstEvents;
typedef struct _VstEvents VstEvents;
@ -130,7 +130,7 @@ public:
void forward_lv2_midi(LV2_Evbuf*, size_t, bool purge_ardour_buffer = true);
#endif
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
VstEvents* get_vst_midi (size_t);
#endif
@ -189,7 +189,7 @@ private:
LV2Buffers _lv2_buffers;
#endif
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
class VSTBuffer {
public:
VSTBuffer (size_t);

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2016 Robin Gareus <robin@gareus.org>
* Copyright (C) 2004 Paul Davis
*
* 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, 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_mac_vst_plugin_h__
#define __ardour_mac_vst_plugin_h__
#include "ardour/vst_plugin.h"
struct LIBARDOUR_API _VSTHandle;
typedef struct _VSTHandle VSTHandle;
namespace ARDOUR {
class AudioEngine;
class Session;
class LIBARDOUR_API MacVSTPlugin : public VSTPlugin
{
public:
MacVSTPlugin (AudioEngine &, Session &, VSTHandle *, int unique_id);
MacVSTPlugin (const MacVSTPlugin &);
~MacVSTPlugin ();
std::string state_node_name () const { return "mac-vst"; }
};
class LIBARDOUR_API MacVSTPluginInfo : public PluginInfo
{
public:
MacVSTPluginInfo ();
~MacVSTPluginInfo () {}
PluginPtr load (Session& session);
std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
};
} // namespace ARDOUR
#endif /* __ardour_mac_vst_plugin_h__ */

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2016 Robin Gareus <robin@gareus.org>
* Copyright (C) 2012 Paul Davis
*
* 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, 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 __mac_vst_support_h__
#define __mac_vst_support_h__
#include <setjmp.h>
#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#include "ardour/libardour_visibility.h"
#include "ardour/vst_types.h"
LIBARDOUR_API extern void (*mac_vst_error_callback)(const char *msg);
LIBARDOUR_API void mac_vst_error (const char *fmt, ...);
LIBARDOUR_API extern VSTHandle * mac_vst_load (const char*);
LIBARDOUR_API extern int mac_vst_unload (VSTHandle *);
LIBARDOUR_API extern VSTState * mac_vst_instantiate (VSTHandle *, audioMasterCallback, void *);
LIBARDOUR_API extern void mac_vst_close (VSTState*);
#endif /* ____mac_vst_support_h__ */

View File

@ -47,6 +47,7 @@ class LIBARDOUR_API PluginManager : public boost::noncopyable {
ARDOUR::PluginInfoList &windows_vst_plugin_info ();
ARDOUR::PluginInfoList &lxvst_plugin_info ();
ARDOUR::PluginInfoList &mac_vst_plugin_info ();
ARDOUR::PluginInfoList &ladspa_plugin_info ();
ARDOUR::PluginInfoList &lv2_plugin_info ();
ARDOUR::PluginInfoList &au_plugin_info ();
@ -110,6 +111,7 @@ class LIBARDOUR_API PluginManager : public boost::noncopyable {
ARDOUR::PluginInfoList _empty_plugin_info;
ARDOUR::PluginInfoList* _windows_vst_plugin_info;
ARDOUR::PluginInfoList* _lxvst_plugin_info;
ARDOUR::PluginInfoList* _mac_vst_plugin_info;
ARDOUR::PluginInfoList* _ladspa_plugin_info;
ARDOUR::PluginInfoList* _lv2_plugin_info;
ARDOUR::PluginInfoList* _au_plugin_info;
@ -127,11 +129,13 @@ class LIBARDOUR_API PluginManager : public boost::noncopyable {
void lua_refresh ();
void lua_refresh_cb ();
void windows_vst_refresh (bool cache_only = false);
void mac_vst_refresh (bool cache_only = false);
void lxvst_refresh (bool cache_only = false);
void add_lrdf_data (const std::string &path);
void add_ladspa_presets ();
void add_windows_vst_presets ();
void add_mac_vst_presets ();
void add_lxvst_presets ();
void add_presets (std::string domain);
@ -142,6 +146,9 @@ class LIBARDOUR_API PluginManager : public boost::noncopyable {
int windows_vst_discover_from_path (std::string path, bool cache_only = false);
int windows_vst_discover (std::string path, bool cache_only = false);
int mac_vst_discover_from_path (std::string path, bool cache_only = false);
int mac_vst_discover (std::string path, bool cache_only = false);
int lxvst_discover_from_path (std::string path, bool cache_only = false);
int lxvst_discover (std::string path, bool cache_only = false);

View File

@ -28,6 +28,7 @@ namespace ARDOUR {
LV2,
Windows_VST,
LXVST,
MacVST,
Lua,
};

View File

@ -237,6 +237,7 @@ CONFIG_VARIABLE (bool, new_plugins_active, "new-plugins-active", true)
CONFIG_VARIABLE (bool, use_plugin_own_gui, "use-plugin-own-gui", true)
CONFIG_VARIABLE (bool, use_windows_vst, "use-windows-vst", true)
CONFIG_VARIABLE (bool, use_lxvst, "use-lxvst", true)
CONFIG_VARIABLE (bool, use_macvst, "use-macvst", true)
CONFIG_VARIABLE (bool, discover_vst_on_start, "discover-vst-on-start", false)
CONFIG_VARIABLE (bool, verbose_plugin_scan, "verbose-plugin-scan", true)
CONFIG_VARIABLE (int, vst_scan_timeout, "vst-scan-timeout", 600) /* deciseconds, per plugin, <= 0 no timeout */

View File

@ -60,6 +60,10 @@ LIBARDOUR_API extern std::vector<VSTInfo*> * vstfx_get_info_lx (char *, enum VST
LIBARDOUR_API extern std::vector<VSTInfo*> * vstfx_get_info_fst (char *, enum VSTScanMode mode = VST_SCAN_USE_APP);
#endif
#ifdef MACVST_SUPPORT
LIBARDOUR_API extern std::vector<VSTInfo*> * vstfx_get_info_mac (char *, enum VSTScanMode mode = VST_SCAN_USE_APP);
#endif
#ifndef VST_SCANNER_APP
} // namespace
#endif

View File

@ -68,6 +68,9 @@ struct LIBARDOUR_API _VSTHandle
main_entry_t main_entry;
int plugincnt;
#ifdef MACVST_SUPPORT
int32_t res_file_id;
#endif
};
typedef struct _VSTHandle VSTHandle;

View File

@ -39,7 +39,7 @@
#include "ardour/lv2_plugin.h"
#include "lv2_evbuf.h"
#endif
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
#include "ardour/vestige/aeffectx.h"
#endif
@ -79,7 +79,7 @@ BufferSet::clear()
_count.reset();
_available.reset();
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
for (VSTBuffers::iterator i = _vst_buffers.begin(); i != _vst_buffers.end(); ++i) {
delete *i;
}
@ -206,7 +206,7 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
}
#endif
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
// As above but for VST
if (type == DataType::MIDI) {
while (_vst_buffers.size() < _buffers[type].size()) {
@ -343,7 +343,7 @@ BufferSet::flush_lv2_midi(bool input, size_t i)
#endif /* LV2_SUPPORT */
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
VstEvents*
BufferSet::get_vst_midi (size_t b)

View File

@ -0,0 +1,168 @@
/*
* Copyright (C) 2016 Robin Gareus <robin@gareus.org>
* Copyright (C) 2004 Paul Davis
*
* 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, 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.
*/
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
#include "ardour/filesystem_paths.h"
#include "ardour/mac_vst_plugin.h"
#include "ardour/mac_vst_support.h"
#include "ardour/session.h"
#include "pbd/i18n.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
MacVSTPlugin::MacVSTPlugin (AudioEngine& e, Session& session, VSTHandle* h, int unique_id)
: VSTPlugin (e, session, h)
{
/* Instantiate the plugin and return a VSTState* */
Session::vst_current_loading_id = unique_id;
if ((_state = mac_vst_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor ();
}
Session::vst_current_loading_id = 0;
set_plugin (_state->plugin);
}
MacVSTPlugin::MacVSTPlugin (const MacVSTPlugin &other)
: VSTPlugin (other)
{
_handle = other._handle;
Session::vst_current_loading_id = PBD::atoi (other.unique_id ());
if ((_state = mac_vst_instantiate (_handle, Session::vst_callback, this)) == 0) {
throw failed_constructor ();
}
Session::vst_current_loading_id = 0;
_plugin = _state->plugin;
// Plugin::setup_controls ();
}
MacVSTPlugin::~MacVSTPlugin ()
{
mac_vst_close (_state);
}
PluginPtr
MacVSTPluginInfo::load (Session& session)
{
try {
PluginPtr plugin;
if (Config->get_use_macvst ()) {
VSTHandle* handle;
handle = mac_vst_load (path.c_str ());
if (handle == NULL) {
error << string_compose (_("MacVST: cannot load module from \"%1\""), path) << endmsg;
}
else {
plugin.reset (new MacVSTPlugin (session.engine (), session, handle, PBD::atoi (unique_id)));
}
}
else {
error << _("You asked ardour to not use any MacVST plugins") << endmsg;
return PluginPtr ((Plugin*) 0);
}
plugin->set_info (PluginInfoPtr (new MacVSTPluginInfo (*this)));
return plugin;
}
catch (failed_constructor &err) {
return PluginPtr ((Plugin*) 0);
}
}
std::vector<Plugin::PresetRecord>
MacVSTPluginInfo::get_presets (bool user_only) const
{
std::vector<Plugin::PresetRecord> p;
#ifndef NO_PLUGIN_STATE
if (!Config->get_use_macvst ()) {
return p;
}
if (!user_only) {
// TODO - cache, instantiating the plugin can be heavy
/* Built-in presets */
VSTHandle* handle = mac_vst_load (path.c_str ());
Session::vst_current_loading_id = atoi (unique_id);
AEffect* plugin = handle->main_entry (Session::vst_callback);
Session::vst_current_loading_id = 0;
plugin->dispatcher (plugin, effOpen, 0, 0, 0, 0); // :(
int const vst_version = plugin->dispatcher (plugin, effGetVstVersion, 0, 0, NULL, 0);
for (int i = 0; i < plugin->numPrograms; ++i) {
Plugin::PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id, i), "", false);
if (vst_version >= 2) {
char buf[256];
if (plugin->dispatcher (plugin, 29, i, 0, buf, 0) == 1) {
r.label = buf;
} else {
r.label = string_compose (_("Preset %1"), i);
}
} else {
r.label = string_compose (_("Preset %1"), i);
}
p.push_back (r);
}
plugin->dispatcher (plugin, effMainsChanged, 0, 0, 0, 0);
plugin->dispatcher (plugin, effClose, 0, 0, 0, 0); // :(
if (handle->plugincnt) {
handle->plugincnt--;
}
mac_vst_unload (handle);
}
/* user presets */
XMLTree* t = new XMLTree;
std::string pf = Glib::build_filename (ARDOUR::user_config_directory (), "presets", string_compose ("vst-%1", unique_id));
if (Glib::file_test (pf, Glib::FILE_TEST_EXISTS)) {
t->set_filename (pf);
if (t->read ()) { // TODO read names only. skip parsing the actual data
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children ().begin (); i != root->children ().end (); ++i) {
XMLProperty const * uri = (*i)->property (X_("uri"));
XMLProperty const * label = (*i)->property (X_("label"));
p.push_back (Plugin::PresetRecord (uri->value (), label->value (), true));
}
}
}
delete t;
#endif
return p;
}
MacVSTPluginInfo::MacVSTPluginInfo ()
{
type = ARDOUR::MacVST;
}

View File

@ -0,0 +1,303 @@
/*
* Copyright (C) 2016 Robin Gareus <robin@gareus.org>
* Copyright (C) 2012 Paul Davis
*
* 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, 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.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <dlfcn.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <glib.h>
#include "pbd/gstdio_compat.h"
#include <glibmm/miscutils.h>
#include <glibmm/fileutils.h>
#include "ardour/mac_vst_support.h"
#include "pbd/basename.h"
#include "pbd/error.h"
#include "pbd/i18n.h"
#include <Carbon/Carbon.h>
/*Simple error handler stuff for VSTFX*/
void mac_vst_error (const char *fmt, ...)
{
va_list ap;
char buffer[512];
va_start (ap, fmt);
vsnprintf (buffer, sizeof (buffer), fmt, ap);
mac_vst_error_callback (buffer);
va_end (ap);
}
/*default error handler callback*/
static void default_mac_vst_error_callback (const char *desc)
{
PBD::error << desc << endmsg;
}
void (*mac_vst_error_callback)(const char *desc) = &default_mac_vst_error_callback;
/* --- */
/*Create and return a pointer to a new VSTFX handle*/
static VSTHandle *
mac_vst_handle_new ()
{
VSTHandle* mac_vst = (VSTHandle *) calloc (1, sizeof (VSTHandle));
return mac_vst;
}
/*Create and return a pointer to a new mac_vst instance*/
static VSTState *
mac_vst_new ()
{
VSTState* mac_vst = (VSTState *) calloc (1, sizeof (VSTState));
/*Mutexes*/
pthread_mutex_init (&mac_vst->lock, 0);
pthread_cond_init (&mac_vst->window_status_change, 0); // XXX unused
pthread_cond_init (&mac_vst->plugin_dispatcher_called, 0); // XXX unused
pthread_cond_init (&mac_vst->window_created, 0); // XXX unused
/*Safe values*/
mac_vst->want_program = -1;
mac_vst->want_chunk = 0;
mac_vst->n_pending_keys = 0;
mac_vst->has_editor = 0;
mac_vst->program_set_without_editor = 0;
mac_vst->linux_window = 0;
mac_vst->linux_plugin_ui_window = 0;
mac_vst->eventProc = 0;
mac_vst->extra_data = 0;
mac_vst->want_resize = 0;
return mac_vst;
}
/*This loads up a plugin, given the path to its .vst bundle and
* finds its main entry point etc */
VSTHandle *
mac_vst_load (const char *path)
{
VSTHandle* fhandle;
/*Create a new handle we can use to reference the plugin*/
fhandle = mac_vst_handle_new ();
fhandle->dll = NULL;
CFURLRef url;
if (!(url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)path, (CFIndex) strlen (path), true))) {
return 0;
}
CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
CFRelease (url);
if (bundleRef == 0) {
return 0;
}
if (!CFBundleLoadExecutable (bundleRef)) {
CFRelease (bundleRef);
return 0;
}
fhandle->name = strdup (path);
fhandle->dll = (void*) &bundleRef;
fhandle->main_entry = (main_entry_t)
CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho"));
if (!fhandle->main_entry) {
fhandle->main_entry = (main_entry_t)
CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain"));
}
if (fhandle->main_entry == 0) {
mac_vst_unload (fhandle);
return 0;
}
fhandle->res_file_id = CFBundleOpenBundleResourceMap (bundleRef);
/*return the handle of the plugin*/
return fhandle;
}
/*This unloads a plugin*/
int
mac_vst_unload (VSTHandle* fhandle)
{
if (fhandle->plugincnt)
{
/*Still have plugin instances - can't unload the library
- actually dlclose keeps an instance count anyway*/
return -1;
}
/*Valid plugin loaded?*/
if (fhandle->dll)
{
CFBundleRef* bundleRefPtr = (CFBundleRef*) fhandle->dll;
CFBundleCloseBundleResourceMap (*bundleRefPtr, (CFBundleRefNum)fhandle->res_file_id);
CFRelease (*bundleRefPtr);
fhandle->dll = 0;
}
if (fhandle->name)
{
free (fhandle->name);
}
/*Don't need the plugin handle any more*/
free (fhandle);
return 0;
}
/*This instantiates a plugin*/
VSTState *
mac_vst_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
{
VSTState* mac_vst = mac_vst_new ();
if (fhandle == 0)
{
mac_vst_error ( "** ERROR ** VSTFX : The handle was 0\n" );
free (mac_vst);
return 0;
}
if ((mac_vst->plugin = fhandle->main_entry (amc)) == 0)
{
mac_vst_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
free (mac_vst);
return 0;
}
mac_vst->handle = fhandle;
mac_vst->plugin->user = userptr;
if (mac_vst->plugin->magic != kEffectMagic)
{
mac_vst_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
free (mac_vst);
return 0;
}
mac_vst->plugin->dispatcher (mac_vst->plugin, effOpen, 0, 0, 0, 0);
/*May or May not need to 'switch the plugin on' here - unlikely
since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
//mac_vst->plugin->dispatcher (mac_vst->plugin, effMainsChanged, 0, 1, 0, 0);
/* configure plugin to use Cocoa View */
mac_vst->plugin->dispatcher (mac_vst->plugin, effCanDo, 0, 0, const_cast<char*> ("hasCockosViewAsConfig"), 0.0f);
mac_vst->vst_version = mac_vst->plugin->dispatcher (mac_vst->plugin, effGetVstVersion, 0, 0, 0, 0);
mac_vst->handle->plugincnt++;
mac_vst->wantIdle = 0;
return mac_vst;
}
/*Close a mac_vst instance*/
void mac_vst_close (VSTState* mac_vst)
{
// assert that the GUI object is destoyed
if (mac_vst->plugin)
{
mac_vst->plugin->dispatcher (mac_vst->plugin, effMainsChanged, 0, 0, 0, 0);
/*Calling dispatcher with effClose will cause the plugin's destructor to
be called, which will also remove the editor if it exists*/
mac_vst->plugin->dispatcher (mac_vst->plugin, effClose, 0, 0, 0, 0);
}
if (mac_vst->handle->plugincnt)
mac_vst->handle->plugincnt--;
/*mac_vst_unload will unload the dll if the instance count allows -
we need to do this because some plugins keep their own instance count
and (JUCE) manages the plugin UI in its own thread. When the plugins
internal instance count reaches zero, JUCE stops the UI thread and won't
restart it until the next time the library is loaded. If we don't unload
the lib JUCE will never restart*/
if (mac_vst->handle->plugincnt)
{
return;
}
/*Valid plugin loaded - so we can unload it and 0 the pointer
to it. We can't free the handle here because we don't know what else
might need it. It should be / is freed when the plugin is deleted*/
if (mac_vst->handle->dll)
{
dlclose (mac_vst->handle->dll); //dlclose keeps its own reference count
mac_vst->handle->dll = 0;
}
free (mac_vst);
}
#if 0 // TODO wrap dispatch
intptr_t
mac_vst_dispatch (VSTState* mac_vst, int op, int idx, intptr_t val, void* ptr, float opt)
{
const ResFileRefNum old_resources = CurResFile();
if (mac_vst->handle->res_file_id) {
UseResFile (mac_vst->handle->res_file_id);
}
mac_vst->plugin->dispatcher (mac_vst->plugin, op, idx, val, prt, opt);
const ResFileRefNum current_res = CurResFile();
if (current_res != old_resources) {
mac_vst->handle->res_file_id = current_res;
UseResFile (old_resources);
}
}
#endif

View File

@ -195,6 +195,12 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
break;
#endif
#ifdef MACVST_SUPPORT
case ARDOUR::MacVST:
plugs = mgr.mac_vst_plugin_info();
break;
#endif
#ifdef AUDIOUNIT_SUPPORT
case ARDOUR::AudioUnit:
plugs = mgr.au_plugin_info();

View File

@ -50,6 +50,10 @@
#include "ardour/lxvst_plugin.h"
#endif
#ifdef MACVST_SUPPORT
#include "ardour/mac_vst_plugin.h"
#endif
#ifdef AUDIOUNIT_SUPPORT
#include "ardour/audio_unit.h"
#endif
@ -1242,6 +1246,9 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
#ifdef LXVST_SUPPORT
boost::shared_ptr<LXVSTPlugin> lxvp;
#endif
#ifdef MACVST_SUPPORT
boost::shared_ptr<MacVSTPlugin> mvp;
#endif
#ifdef AUDIOUNIT_SUPPORT
boost::shared_ptr<AUPlugin> ap;
#endif
@ -1262,6 +1269,10 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
} else if ((lxvp = boost::dynamic_pointer_cast<LXVSTPlugin> (other)) != 0) {
return boost::shared_ptr<Plugin> (new LXVSTPlugin (*lxvp));
#endif
#ifdef MACVST_SUPPORT
} else if ((mvp = boost::dynamic_pointer_cast<MacVSTPlugin> (other)) != 0) {
return boost::shared_ptr<Plugin> (new MacVSTPlugin (*mvp));
#endif
#ifdef AUDIOUNIT_SUPPORT
} else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
@ -2373,6 +2384,8 @@ PluginInsert::set_state(const XMLNode& node, int version)
type = ARDOUR::Windows_VST;
} else if (prop->value() == X_("lxvst")) {
type = ARDOUR::LXVST;
} else if (prop->value() == X_("mac-vst")) {
type = ARDOUR::MacVST;
} else if (prop->value() == X_("audiounit")) {
type = ARDOUR::AudioUnit;
} else if (prop->value() == X_("luaproc")) {
@ -2403,6 +2416,7 @@ PluginInsert::set_state(const XMLNode& node, int version)
prop = node.property ("id");
}
#endif
/* recheck */
if (prop == 0) {
@ -2429,6 +2443,13 @@ PluginInsert::set_state(const XMLNode& node, int version)
}
#endif
#ifdef MACVST_SUPPORT
if (plugin == 0 && type == ARDOUR::MacVST) {
type = ARDOUR::MacVST;
plugin = find_plugin (_session, prop->value(), type);
}
#endif
if (plugin == 0 && type == ARDOUR::Lua) {
/* unique ID (sha1 of script) was not found,
* load the plugin from the serialized version in the
@ -2937,7 +2958,7 @@ PluginInsert::add_plugin (boost::shared_ptr<Plugin> plugin)
}
}
}
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
boost::shared_ptr<VSTPlugin> vst = boost::dynamic_pointer_cast<VSTPlugin> (plugin);
if (vst) {
vst->set_insert (this, _plugins.size ());

View File

@ -55,6 +55,14 @@
#include <cstring>
#endif //LXVST_SUPPORT
#ifdef MACVST_SUPPORT
#include "ardour/vst_info_file.h"
#include "ardour/mac_vst_support.h"
#include "ardour/mac_vst_plugin.h"
#include "pbd/basename.h"
#include <cstring>
#endif //MACVST_SUPPORT
#include <glibmm/miscutils.h>
#include <glibmm/pattern.h>
#include <glibmm/fileutils.h>
@ -118,6 +126,7 @@ PluginManager::instance()
PluginManager::PluginManager ()
: _windows_vst_plugin_info(0)
, _lxvst_plugin_info(0)
, _mac_vst_plugin_info(0)
, _ladspa_plugin_info(0)
, _lv2_plugin_info(0)
, _au_plugin_info(0)
@ -128,7 +137,7 @@ PluginManager::PluginManager ()
char* s;
string lrdf_path;
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT
#if defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT
// source-tree (ardev, etc)
PBD::Searchpath vstsp(Glib::build_filename(ARDOUR::ardour_dll_directory(), "fst"));
@ -183,6 +192,12 @@ PluginManager::PluginManager ()
}
#endif /* Native LinuxVST support*/
#ifdef MACVST_SUPPORT
if (Config->get_use_macvst ()) {
add_mac_vst_presets ();
}
#endif
if ((s = getenv ("VST_PATH"))) {
windows_vst_path = s;
} else if ((s = getenv ("VST_PLUGINS"))) {
@ -229,6 +244,7 @@ PluginManager::~PluginManager()
// don't bother, just exit quickly.
delete _windows_vst_plugin_info;
delete _lxvst_plugin_info;
delete _mac_vst_plugin_info;
delete _ladspa_plugin_info;
delete _lv2_plugin_info;
delete _au_plugin_info;
@ -278,7 +294,18 @@ PluginManager::refresh (bool cache_only)
}
#endif //Native linuxVST SUPPORT
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
#ifdef MACVST_SUPPORT
if(Config->get_use_macvst ()) {
if (cache_only) {
BootMessage (_("Scanning Mac VST Plugins"));
} else {
BootMessage (_("Discovering Mac VST Plugins"));
}
mac_vst_refresh (cache_only);
}
#endif //Native Mac VST SUPPORT
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
if (!cache_only) {
string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
@ -383,7 +410,7 @@ PluginManager::clear_vst_cache ()
#endif
#endif // old cache cleanup
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
{
string dn = Glib::build_filename (ARDOUR::user_cache_directory(), "vst");
vector<string> fsi_files;
@ -430,7 +457,7 @@ PluginManager::clear_vst_blacklist ()
#endif // old blacklist cleanup
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT)
{
string fn = Glib::build_filename (ARDOUR::user_cache_directory(), VST_BLACKLIST);
if (Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
@ -538,6 +565,12 @@ PluginManager::add_windows_vst_presets()
add_presets ("windows-vst");
}
void
PluginManager::add_mac_vst_presets()
{
add_presets ("mac-vst");
}
void
PluginManager::add_lxvst_presets()
{
@ -813,7 +846,7 @@ PluginManager::windows_vst_discover_from_path (string path, bool cache_only)
info << string_compose (_("--- Windows VST plugins Scan: %1"), path) << endmsg;
}
find_files_matching_filter (plugin_objects, Config->get_plugin_path_vst(), windows_vst_filter, 0, false, true, true);
find_files_matching_filter (plugin_objects, path, windows_vst_filter, 0, false, true, true);
for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
ARDOUR::PluginScanMessage(_("VST"), *x, !cache_only && !cancelled());
@ -979,6 +1012,112 @@ PluginManager::windows_vst_discover (string path, bool cache_only)
#endif // WINDOWS_VST_SUPPORT
#ifdef MACVST_SUPPORT
void
PluginManager::mac_vst_refresh (bool cache_only)
{
if (_mac_vst_plugin_info) {
_mac_vst_plugin_info->clear ();
} else {
_mac_vst_plugin_info = new ARDOUR::PluginInfoList();
}
mac_vst_discover_from_path ("~/Library/Audio/Plug-Ins/VST:/Library/Audio/Plug-Ins/VST", cache_only);
}
static bool mac_vst_filter (const string& str, void *)
{
if (!Glib::file_test (str, Glib::FILE_TEST_IS_DIR)) {
return false;
}
string plist = Glib::build_filename (str, "Contents", "Info.plist");
if (!Glib::file_test (plist, Glib::FILE_TEST_IS_REGULAR)) {
return false;
}
return str[0] != '.' && str.length() > 4 && strings_equal_ignore_case (".vst", str.substr(str.length() - 4));
}
int
PluginManager::mac_vst_discover_from_path (string path, bool cache_only)
{
vector<string> plugin_objects;
vector<string>::iterator x;
find_paths_matching_filter (plugin_objects, path, mac_vst_filter, 0, true, true, false);
for (x = plugin_objects.begin(); x != plugin_objects.end (); ++x) {
ARDOUR::PluginScanMessage(_("MacVST"), *x, !cache_only && !cancelled());
mac_vst_discover (*x, cache_only || cancelled());
}
return 0;
}
int
PluginManager::mac_vst_discover (string path, bool cache_only)
{
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("checking apparent MacVST plugin at %1\n", path));
_cancel_timeout = false;
vector<VSTInfo*>* finfos = vstfx_get_info_mac (const_cast<char *> (path.c_str()),
cache_only ? VST_SCAN_CACHE_ONLY : VST_SCAN_USE_APP);
if (finfos->empty()) {
DEBUG_TRACE (DEBUG::PluginManager, string_compose ("Cannot get Mac VST information from '%1'\n", path));
return -1;
}
uint32_t discovered = 0;
for (vector<VSTInfo *>::iterator x = finfos->begin(); x != finfos->end(); ++x) {
VSTInfo* finfo = *x;
char buf[32];
if (!finfo->canProcessReplacing) {
warning << string_compose (_("Mac VST plugin %1 does not support processReplacing, and so cannot be used in %2 at this time"),
finfo->name, PROGRAM_NAME)
<< endl;
continue;
}
PluginInfoPtr info (new MacVSTPluginInfo);
info->name = finfo->name;
snprintf (buf, sizeof (buf), "%d", finfo->UniqueID);
info->unique_id = buf;
info->category = "MacVST";
info->path = path;
info->creator = finfo->creator;
info->index = 0;
info->n_inputs.set_audio (finfo->numInputs);
info->n_outputs.set_audio (finfo->numOutputs);
info->n_inputs.set_midi ((finfo->wantMidi&1) ? 1 : 0);
info->n_outputs.set_midi ((finfo->wantMidi&2) ? 1 : 0);
info->type = ARDOUR::MacVST;
bool duplicate = false;
if (!_mac_vst_plugin_info->empty()) {
for (PluginInfoList::iterator i =_mac_vst_plugin_info->begin(); i != _mac_vst_plugin_info->end(); ++i) {
if ((info->type == (*i)->type)&&(info->unique_id == (*i)->unique_id)) {
warning << "Ignoring duplicate Mac VST plugin " << info->name << "\n";
duplicate = true;
break;
}
}
}
if (!duplicate) {
_mac_vst_plugin_info->push_back (info);
discovered++;
}
}
vstfx_free_info_list (finfos);
return discovered > 0 ? 0 : -1;
}
#endif // MAC_VST_SUPPORT
#ifdef LXVST_SUPPORT
void
@ -1137,6 +1276,9 @@ PluginManager::save_statuses ()
case LXVST:
ofs << "LXVST";
break;
case MacVST:
ofs << "MacVST";
break;
case Lua:
ofs << "Lua";
break;
@ -1266,6 +1408,17 @@ PluginManager::windows_vst_plugin_info ()
#endif
}
ARDOUR::PluginInfoList&
PluginManager::mac_vst_plugin_info ()
{
#ifdef MACVST_SUPPORT
assert(_mac_vst_plugin_info);
return *_mac_vst_plugin_info;
#else
return _empty_plugin_info;
#endif
}
ARDOUR::PluginInfoList&
PluginManager::lxvst_plugin_info ()
{

View File

@ -836,6 +836,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
prop->value() == "lv2" ||
prop->value() == "windows-vst" ||
prop->value() == "mac-vst" ||
prop->value() == "lxvst" ||
prop->value() == "audiounit") {
@ -2759,6 +2760,7 @@ Route::set_processor_state (const XMLNode& node)
} else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
prop->value() == "lv2" ||
prop->value() == "windows-vst" ||
prop->value() == "mac-vst" ||
prop->value() == "lxvst" ||
prop->value() == "luaproc" ||
prop->value() == "audiounit") {

View File

@ -49,6 +49,7 @@
#include "ardour/filesystem_paths.h"
#include "ardour/linux_vst_support.h"
#include "ardour/mac_vst_support.h"
#include "ardour/plugin_types.h"
#include "ardour/vst_info_file.h"
@ -74,6 +75,10 @@ vstfx_instantiate_and_get_info_fst (const char* dllpath, vector<VSTInfo*> *infos
static bool vstfx_instantiate_and_get_info_lx (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
#endif
#ifdef MACVST_SUPPORT
static bool vstfx_instantiate_and_get_info_mac (const char* dllpath, vector<VSTInfo*> *infos, int uniqueID);
#endif
/* ID for shell plugins */
static int vstfx_current_loading_id = 0;
@ -442,6 +447,8 @@ vstfx_infofile_for_read (const char* dllpath)
if (
(slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so"))
&&
(slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".vst"))
&&
(slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll"))
) {
return 0;
@ -477,6 +484,8 @@ vstfx_infofile_for_write (const char* dllpath)
if (
(slen <= 3 || g_ascii_strcasecmp (&dllpath[slen-3], ".so"))
&&
(slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".vst"))
&&
(slen <= 4 || g_ascii_strcasecmp (&dllpath[slen-4], ".dll"))
) {
return NULL;
@ -665,6 +674,13 @@ vstfx_parse_vst_state (VSTState* vstfx)
info->ParamNames = (char **) malloc (sizeof (char*)*info->numParams);
info->ParamLabels = (char **) malloc (sizeof (char*)*info->numParams);
#ifdef __APPLE__
if (info->hasEditor) {
/* we only support Cocoa UIs (just like Reaper) */
info->hasEditor = (plugin->dispatcher (plugin, effCanDo, 0, 0, const_cast<char*> ("hasCockosViewAsConfig"), 0.0f) & 0xffff0000) == 0xbeef0000;
}
#endif
for (int i = 0; i < info->numParams; ++i) {
char name[64];
char label[64];
@ -724,6 +740,11 @@ vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector<VSTInfo *>
case ARDOUR::LXVST:
vstfx_close (vstfx);
break;
#endif
#ifdef MACVST_SUPPORT
case ARDOUR::MacVST:
mac_vst_close (vstfx);
break;
#endif
default:
assert (0);
@ -746,6 +767,11 @@ vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector<VSTInfo *>
case ARDOUR::LXVST:
ok = vstfx_instantiate_and_get_info_lx (dllpath, infos, id);
break;
#endif
#ifdef MACVST_SUPPORT
case ARDOUR::MacVST:
ok = vstfx_instantiate_and_get_info_mac (dllpath, infos, id);
break;
#endif
default:
ok = false;
@ -777,6 +803,11 @@ vstfx_info_from_plugin (const char *dllpath, VSTState* vstfx, vector<VSTInfo *>
case ARDOUR::LXVST:
vstfx_close (vstfx);
break;
#endif
#ifdef MACVST_SUPPORT
case ARDOUR::MacVST:
mac_vst_close (vstfx);
break;
#endif
default:
assert (0);
@ -847,7 +878,35 @@ vstfx_instantiate_and_get_info_fst (
}
#endif
#ifdef MACVST_SUPPORT
static bool
vstfx_instantiate_and_get_info_mac (
const char* dllpath, vector<VSTInfo*> *infos, int uniqueID)
{
printf("vstfx_instantiate_and_get_info_mac %s\n", dllpath);
VSTHandle* h;
VSTState* vstfx;
if (!(h = mac_vst_load (dllpath))) {
PBD::warning << string_compose (_("Cannot get MacVST information from '%1': load failed."), dllpath) << endmsg;
return false;
}
vstfx_current_loading_id = uniqueID;
if (!(vstfx = mac_vst_instantiate (h, simple_master_callback, 0))) {
mac_vst_unload (h);
PBD::warning << string_compose (_("Cannot get MacVST information from '%1': instantiation failed."), dllpath) << endmsg;
return false;
}
vstfx_current_loading_id = 0;
vstfx_info_from_plugin (dllpath, vstfx, infos, ARDOUR::MacVST);
mac_vst_unload (h);
return true;
}
#endif
/* *** ERROR LOGGING *** */
#ifndef VST_SCANNER_APP
@ -993,6 +1052,11 @@ vstfx_get_info (const char* dllpath, enum ARDOUR::PluginType type, enum VSTScanM
case ARDOUR::LXVST:
ok = vstfx_instantiate_and_get_info_lx (dllpath, infos, 0);
break;
#endif
#ifdef MACVST_SUPPORT
case ARDOUR::MacVST:
ok = vstfx_instantiate_and_get_info_mac (dllpath, infos, 0);
break;
#endif
default:
ok = false;
@ -1038,6 +1102,14 @@ vstfx_get_info_lx (char* dllpath, enum VSTScanMode mode)
}
#endif
#ifdef MACVST_SUPPORT
vector<VSTInfo *> *
vstfx_get_info_mac (char* dllpath, enum VSTScanMode mode)
{
return vstfx_get_info (dllpath, ARDOUR::MacVST, mode);
}
#endif
#ifdef WINDOWS_VST_SUPPORT
vector<VSTInfo *> *
vstfx_get_info_fst (char* dllpath, enum VSTScanMode mode)

View File

@ -435,9 +435,13 @@ def build(bld):
obj.source += [ 'lxvst_plugin.cc', 'linux_vst_support.cc' ]
obj.defines += [ 'LXVST_SUPPORT' ]
if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT'):
if bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT') or bld.is_defined('MACVST_SUPPORT'):
obj.source += [ 'session_vst.cc', 'vst_plugin.cc', 'vst_info_file.cc' ]
if bld.is_defined('MACVST_SUPPORT'):
obj.source += [ 'mac_vst_plugin.cc', 'mac_vst_support.cc' ]
obj.defines += [ 'MACVST_SUPPORT' ]
if bld.is_defined('HAVE_COREAUDIO'):
obj.source += [ 'coreaudiosource.cc', 'caimportable.cc' ]
obj.use += ['libappleutility']

View File

@ -31,6 +31,9 @@
#ifdef LXVST_SUPPORT
#include "../ardour/linux_vst_support.cc"
#endif
#ifdef MACVST_SUPPORT
#include "../ardour/mac_vst_support.cc"
#endif
#include "../ardour/filesystem_paths.cc"
#include "../ardour/directory_names.cc"
@ -117,6 +120,12 @@ int main (int argc, char **argv) {
infos = vstfx_get_info_fst(dllpath);
}
#endif
#ifdef MACVST_SUPPORT
else if (slen > 4 && 0 == g_ascii_strcasecmp (&dllpath[slen-4], ".vst")) {
infos = vstfx_get_info_mac(dllpath);
}
#endif
else {
fprintf(stderr, "'%s' is not a supported VST plugin.\n", dllpath);
}

View File

@ -42,7 +42,7 @@ def set_winegcc(self):
def build(bld):
VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR'])
if not (bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT')):
if not (bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT') or bld.is_defined ('MACVST_SUPPORT')):
return
if bld.is_defined('WINDOWS_VST_SUPPORT') and bld.env['build_target'] != 'mingw':

View File

@ -880,6 +880,7 @@ def configure(conf):
conf.define ('HAVE_COREAUDIO', 1)
conf.define ('AUDIOUNIT_SUPPORT', 1)
conf.define('MACVST_SUPPORT', 1)
conf.define ('TOP_MENUBAR',1)
@ -1229,6 +1230,7 @@ const char* const ardour_config_info = "\\n\\
write_config_text('Unit tests', conf.env['BUILD_TESTS'])
write_config_text('Mac i386 Architecture', opts.generic)
write_config_text('Mac ppc Architecture', opts.ppc)
write_config_text('Mac VST support', conf.is_defined('MACVST_SUPPORT'))
write_config_text('Windows VST support', opts.windows_vst)
write_config_text('Wiimote support', conf.is_defined('BUILD_WIIMOTE'))
write_config_text('Windows key', opts.windows_key)