2 * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2012 Paul Davis
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include "pbd/gstdio_compat.h"
33 #include <glibmm/miscutils.h>
34 #include <glibmm/fileutils.h>
36 #include "ardour/mac_vst_support.h"
37 #include "pbd/basename.h"
38 #include "pbd/error.h"
42 #include <Carbon/Carbon.h>
44 /*Simple error handler stuff for VSTFX*/
46 void mac_vst_error (const char *fmt, ...)
52 vsnprintf (buffer, sizeof (buffer), fmt, ap);
53 mac_vst_error_callback (buffer);
57 /*default error handler callback*/
59 static void default_mac_vst_error_callback (const char *desc)
61 PBD::error << desc << endmsg;
64 void (*mac_vst_error_callback)(const char *desc) = &default_mac_vst_error_callback;
68 /*Create and return a pointer to a new VSTFX handle*/
73 VSTHandle* mac_vst = (VSTHandle *) calloc (1, sizeof (VSTHandle));
77 /*Create and return a pointer to a new mac_vst instance*/
82 VSTState* mac_vst = (VSTState *) calloc (1, sizeof (VSTState));
85 pthread_mutex_init (&mac_vst->lock, 0);
86 pthread_cond_init (&mac_vst->window_status_change, 0); // XXX unused
87 pthread_cond_init (&mac_vst->plugin_dispatcher_called, 0); // XXX unused
88 pthread_cond_init (&mac_vst->window_created, 0); // XXX unused
91 mac_vst->want_program = -1;
92 mac_vst->want_chunk = 0;
93 mac_vst->n_pending_keys = 0;
94 mac_vst->has_editor = 0;
95 mac_vst->program_set_without_editor = 0;
96 mac_vst->linux_window = 0;
97 mac_vst->linux_plugin_ui_window = 0;
98 mac_vst->eventProc = 0;
99 mac_vst->extra_data = 0;
100 mac_vst->want_resize = 0;
105 /*This loads up a plugin, given the path to its .vst bundle and
106 * finds its main entry point etc */
109 mac_vst_load (const char *path)
113 /*Create a new handle we can use to reference the plugin*/
115 fhandle = mac_vst_handle_new ();
120 if (!(url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)path, (CFIndex) strlen (path), true))) {
124 CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url);
127 if (bundleRef == 0) {
131 if (!CFBundleLoadExecutable (bundleRef)) {
132 CFRelease (bundleRef);
136 fhandle->name = strdup (path);
137 fhandle->dll = (void*) &bundleRef;
139 fhandle->main_entry = (main_entry_t)
140 CFBundleGetFunctionPointerForName (bundleRef, CFSTR("main_macho"));
142 if (!fhandle->main_entry) {
143 fhandle->main_entry = (main_entry_t)
144 CFBundleGetFunctionPointerForName (bundleRef, CFSTR("VSTPluginMain"));
147 if (fhandle->main_entry == 0) {
148 mac_vst_unload (fhandle);
152 fhandle->res_file_id = CFBundleOpenBundleResourceMap (bundleRef);
154 /*return the handle of the plugin*/
158 /*This unloads a plugin*/
161 mac_vst_unload (VSTHandle* fhandle)
163 if (fhandle->plugincnt)
165 /*Still have plugin instances - can't unload the library
166 - actually dlclose keeps an instance count anyway*/
171 /*Valid plugin loaded?*/
175 CFBundleRef* bundleRefPtr = (CFBundleRef*) fhandle->dll;
176 CFBundleCloseBundleResourceMap (*bundleRefPtr, (CFBundleRefNum)fhandle->res_file_id);
177 CFRelease (*bundleRefPtr);
183 free (fhandle->name);
186 /*Don't need the plugin handle any more*/
192 /*This instantiates a plugin*/
195 mac_vst_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
197 VSTState* mac_vst = mac_vst_new ();
201 mac_vst_error ( "** ERROR ** VSTFX : The handle was 0\n" );
206 if ((mac_vst->plugin = fhandle->main_entry (amc)) == 0)
208 mac_vst_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
213 mac_vst->handle = fhandle;
214 mac_vst->plugin->user = userptr;
216 if (mac_vst->plugin->magic != kEffectMagic)
218 mac_vst_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
223 mac_vst->plugin->dispatcher (mac_vst->plugin, effOpen, 0, 0, 0, 0);
225 /*May or May not need to 'switch the plugin on' here - unlikely
226 since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
228 //mac_vst->plugin->dispatcher (mac_vst->plugin, effMainsChanged, 0, 1, 0, 0);
230 /* configure plugin to use Cocoa View */
231 mac_vst->plugin->dispatcher (mac_vst->plugin, effCanDo, 0, 0, const_cast<char*> ("hasCockosViewAsConfig"), 0.0f);
233 mac_vst->vst_version = mac_vst->plugin->dispatcher (mac_vst->plugin, effGetVstVersion, 0, 0, 0, 0);
235 mac_vst->handle->plugincnt++;
236 mac_vst->wantIdle = 0;
241 /*Close a mac_vst instance*/
243 void mac_vst_close (VSTState* mac_vst)
245 // assert that the GUI object is destoyed
249 mac_vst->plugin->dispatcher (mac_vst->plugin, effMainsChanged, 0, 0, 0, 0);
251 /*Calling dispatcher with effClose will cause the plugin's destructor to
252 be called, which will also remove the editor if it exists*/
254 mac_vst->plugin->dispatcher (mac_vst->plugin, effClose, 0, 0, 0, 0);
257 if (mac_vst->handle->plugincnt)
258 mac_vst->handle->plugincnt--;
260 /*mac_vst_unload will unload the dll if the instance count allows -
261 we need to do this because some plugins keep their own instance count
262 and (JUCE) manages the plugin UI in its own thread. When the plugins
263 internal instance count reaches zero, JUCE stops the UI thread and won't
264 restart it until the next time the library is loaded. If we don't unload
265 the lib JUCE will never restart*/
268 if (mac_vst->handle->plugincnt)
273 /*Valid plugin loaded - so we can unload it and 0 the pointer
274 to it. We can't free the handle here because we don't know what else
275 might need it. It should be / is freed when the plugin is deleted*/
277 if (mac_vst->handle->dll)
279 dlclose (mac_vst->handle->dll); //dlclose keeps its own reference count
280 mac_vst->handle->dll = 0;
285 #if 0 // TODO wrap dispatch
287 mac_vst_dispatch (VSTState* mac_vst, int op, int idx, intptr_t val, void* ptr, float opt)
289 const ResFileRefNum old_resources = CurResFile();
291 if (mac_vst->handle->res_file_id) {
292 UseResFile (mac_vst->handle->res_file_id);
295 mac_vst->plugin->dispatcher (mac_vst->plugin, op, idx, val, prt, opt);
297 const ResFileRefNum current_res = CurResFile();
298 if (current_res != old_resources) {
299 mac_vst->handle->res_file_id = current_res;
300 UseResFile (old_resources);