13 #include <glib/gstdio.h>
15 #include "ardour/linux_vst_support.h"
16 #include "pbd/error.h"
18 /***********************************************************/
19 /* VSTFX - A set of modules for managing linux VST plugins */
20 /* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc */
21 /***********************************************************/
23 /*Simple error handler stuff for VSTFX*/
25 void vstfx_error (const char *fmt, ...)
31 vsnprintf (buffer, sizeof(buffer), fmt, ap);
32 vstfx_error_callback (buffer);
36 /*default error handler callback*/
38 void default_vstfx_error_callback (const char *desc)
40 PBD::error << desc << endmsg;
43 void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
47 /*Create and return a pointer to a new VSTFX handle*/
52 VSTHandle* vstfx = (VSTHandle *) calloc (1, sizeof (VSTHandle));
56 /*Create and return a pointer to a new vstfx instance*/
61 VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
65 pthread_mutex_init (&vstfx->lock, NULL);
66 pthread_cond_init (&vstfx->window_status_change, NULL);
67 pthread_cond_init (&vstfx->plugin_dispatcher_called, NULL);
68 pthread_cond_init (&vstfx->window_created, NULL);
72 vstfx->want_program = -1;
73 vstfx->want_chunk = 0;
74 vstfx->n_pending_keys = 0;
75 vstfx->has_editor = 0;
76 vstfx->program_set_without_editor = 0;
77 vstfx->linux_window = 0;
78 vstfx->linux_plugin_ui_window = 0;
79 vstfx->eventProc = NULL;
80 vstfx->extra_data = NULL;
81 vstfx->want_resize = 0;
86 /*This loads the plugin shared library*/
88 void* vstfx_load_vst_library(const char* path)
97 /*Try and load the shared library pointed to by the path -
98 NOTE: You have to give RTLD_LAZY or RTLD_NOW to dlopen or
99 you get some occasional failures to load - dlerror reports
102 if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
105 /*We didn't find the library so try and get the path specified in the
106 env variable LXVST_PATH*/
108 envdup = getenv ("LXVST_PATH");
110 /*Path not specified - not much more we can do*/
115 /*Copy the path into envdup*/
117 envdup = strdup (envdup);
124 /*Try all the possibilities in the path - deliminated by : */
126 lxvst_path = strtok (envdup, ":");
128 while (lxvst_path != NULL)
130 vstfx_error ("\"%s\"", lxvst_path);
131 len1 = strlen(lxvst_path);
133 full_path = (char*)malloc(len1 + 1 + len2 + 1);
134 memcpy(full_path, lxvst_path, len1);
135 full_path[len1] = '/';
136 memcpy(full_path + len1 + 1, path, len2);
137 full_path[len1 + 1 + len2] = '\0';
139 /*Try and load the library*/
141 if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
149 lxvst_path = strtok (NULL, ":");
159 /*This loads up a plugin, given the path to its .so file and
160 finds its main entry point etc*/
163 vstfx_load (const char *path)
169 /*Create a new handle we can use to reference the plugin*/
171 fhandle = vstfx_handle_new();
173 /*See if we have .so appended to the path - if not we need to make sure it is added*/
175 if (strstr (path, ".so") == NULL)
178 /*Append the .so to the path - Make sure the path has enough space*/
180 buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
182 sprintf (buf, "%s.so", path);
184 fhandle->nameptr = strdup (path);
189 /*We already have .so appened to the filename*/
193 fhandle->nameptr = strdup (path);
196 /*Use basename to shorten the path and then strip off the .so - the old VST problem,
197 we don't know anything about its name until we load and instantiate the plugin
198 which we don't want to do at this point*/
200 for(i=0; i < (int)strlen(fhandle->nameptr); i++)
202 if(fhandle->nameptr[i] == '.')
203 fhandle->nameptr[i] = 0;
207 fhandle->name = basename (fhandle->nameptr);
209 /*call load_vstfx_library to actually load the .so into memory*/
211 if ((fhandle->dll = vstfx_load_vst_library (buf)) == NULL)
213 vstfx_unload (fhandle);
220 /*Find the main entry point into the plugin*/
222 if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == NULL)
224 /*If it can't be found, unload the plugin and return a NULL handle*/
226 vstfx_unload (fhandle);
235 /*return the handle of the plugin*/
240 /*This unloads a plugin*/
243 vstfx_unload (VSTHandle* fhandle)
245 if (fhandle->plugincnt)
247 /*Still have plugin instances - can't unload the library
248 - actually dlclose keeps an instance count anyway*/
253 /*Valid plugin loaded?*/
257 dlclose(fhandle->dll);
261 if (fhandle->nameptr)
263 free (fhandle->nameptr);
264 fhandle->name = NULL;
267 /*Don't need the plugin handle any more*/
273 /*This instantiates a plugin*/
276 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
278 VSTState* vstfx = vstfx_new ();
282 vstfx_error( "** ERROR ** VSTFX : The handle was NULL\n" );
286 if ((vstfx->plugin = fhandle->main_entry (amc)) == NULL)
288 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
293 vstfx->handle = fhandle;
294 vstfx->plugin->user = userptr;
296 if (vstfx->plugin->magic != kEffectMagic)
298 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
303 vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
305 /*May or May not need to 'switch the plugin on' here - unlikely
306 since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
308 //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, NULL, 0);
310 vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
312 vstfx->handle->plugincnt++;
318 /*Close a vstfx instance*/
320 void vstfx_close (VSTState* vstfx)
322 vstfx_destroy_editor(vstfx);
326 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, NULL, 0);
328 /*Calling dispatcher with effClose will cause the plugin's destructor to
329 be called, which will also remove the editor if it exists*/
331 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
334 if (vstfx->handle->plugincnt)
335 vstfx->handle->plugincnt--;
337 /*vstfx_unload will unload the dll if the instance count allows -
338 we need to do this because some plugins keep their own instance count
339 and (JUCE) manages the plugin UI in its own thread. When the plugins
340 internal instance count reaches zero, JUCE stops the UI thread and won't
341 restart it until the next time the library is loaded. If we don't unload
342 the lib JUCE will never restart*/
345 if (vstfx->handle->plugincnt)
350 /*Valid plugin loaded - so we can unload it and NULL the pointer
351 to it. We can't free the handle here because we don't know what else
352 might need it. It should be / is freed when the plugin is deleted*/
354 if (vstfx->handle->dll)
356 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
357 vstfx->handle->dll = NULL;
363 vstfx_save_state (VSTState* vstfx, char * filename)
365 FILE* f = g_fopen (filename, "wb");
369 int numParams = vstfx->plugin->numParams;
371 char productString[64];
373 char vendorString[64];
378 fprintf(f, "<plugin_state>\n");
380 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
384 fprintf (f, " <check field=\"productString\" value=\"%s\"/>\n", productString);
388 printf ("No product string\n");
391 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
395 fprintf (f, " <check field=\"effectName\" value=\"%s\"/>\n", effectName);
396 printf ("Effect name: %s\n", effectName);
400 printf ("No effect name\n");
403 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
407 fprintf (f, " <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
408 printf ("Vendor string: %s\n", vendorString);
412 printf ("No vendor string\n");
416 if(vstfx->plugin->flags & 32 )
421 for(i=0; i < numParams; i++)
425 pthread_mutex_lock( &vstfx->lock );
426 val = vstfx->plugin->getParameter(vstfx->plugin, i );
427 pthread_mutex_unlock( &vstfx->lock );
428 fprintf( f, " <param index=\"%d\" value=\"%f\"/>\n", i, val );
431 if(vstfx->plugin->flags & 32 )
433 printf( "getting chunk...\n" );
435 bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
436 printf( "got tha chunk..\n" );
441 printf( "Chunke len < 0 !!! Not saving chunk.\n" );
445 //char *encoded = g_base64_encode( chunk, bytelen );
446 //fprintf( f, " <chunk size=\"%d\">\n %s\n </chunk>\n", bytelen, encoded );
452 fprintf( f, "</plugin_state>\n" );
457 printf ("Could not open state file\n");
463 /*Set up a call to the plugins 'dispatcher' function*/
465 int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt)
467 pthread_mutex_lock (&vstfx->lock);
469 /*Set up the opcode and parameters*/
471 vstfx->dispatcher_opcode = opcode;
472 vstfx->dispatcher_index = index;
473 vstfx->dispatcher_val = val;
474 vstfx->dispatcher_ptr = ptr;
475 vstfx->dispatcher_opt = opt;
477 /*Signal that we want the call to happen*/
479 vstfx->dispatcher_wantcall = 1;
481 /*Wait for the call to happen*/
483 pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
484 pthread_mutex_unlock (&vstfx->lock);
486 /*Return the result*/
488 return vstfx->dispatcher_retval;