13 #include "ardour/vstfx.h"
14 #include "pbd/error.h"
16 /***********************************************************/
17 /* VSTFX - A set of modules for managing linux VST plugins */
18 /* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc */
19 /***********************************************************/
21 /*Simple error handler stuff for VSTFX*/
23 void vstfx_error (const char *fmt, ...)
29 vsnprintf (buffer, sizeof(buffer), fmt, ap);
30 vstfx_error_callback (buffer);
34 /*default error handler callback*/
36 void default_vstfx_error_callback (const char *desc)
38 PBD::error << desc << endmsg;
41 void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
45 /*Create and return a pointer to a new VSTFX handle*/
47 VSTFXHandle* vstfx_handle_new()
49 VSTFXHandle* vstfx = (VSTFXHandle*)calloc(1, sizeof (VSTFXHandle));
53 /*Create and return a pointer to a new vstfx instance*/
57 VSTFX* vstfx = (VSTFX*) calloc (1, sizeof (VSTFX));
61 pthread_mutex_init (&vstfx->lock, NULL);
62 pthread_cond_init (&vstfx->window_status_change, NULL);
63 pthread_cond_init (&vstfx->plugin_dispatcher_called, NULL);
64 pthread_cond_init (&vstfx->window_created, NULL);
68 vstfx->want_program = -1;
69 vstfx->want_chunk = 0;
70 vstfx->current_program = -1;
71 vstfx->n_pending_keys = 0;
72 vstfx->has_editor = 0;
73 vstfx->program_set_without_editor = 0;
75 vstfx->plugin_ui_window = 0;
76 vstfx->eventProc = NULL;
77 vstfx->extra_data = NULL;
78 vstfx->want_resize = 0;
83 /*This loads the plugin shared library*/
85 void* vstfx_load_vst_library(const char* path)
94 /*Try and load the shared library pointed to by the path -
95 NOTE: You have to give RTLD_LAZY or RTLD_NOW to dlopen or
96 you get some occasional failures to load - dlerror reports
99 if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
102 /*We didn't find the library so try and get the path specified in the
103 env variable LXVST_PATH*/
105 envdup = getenv ("LXVST_PATH");
107 /*Path not specified - not much more we can do*/
112 /*Copy the path into envdup*/
114 envdup = strdup (envdup);
121 /*Try all the possibilities in the path - deliminated by : */
123 lxvst_path = strtok (envdup, ":");
125 while (lxvst_path != NULL)
127 vstfx_error ("\"%s\"", lxvst_path);
128 len1 = strlen(lxvst_path);
130 full_path = (char*)malloc(len1 + 1 + len2 + 1);
131 memcpy(full_path, lxvst_path, len1);
132 full_path[len1] = '/';
133 memcpy(full_path + len1 + 1, path, len2);
134 full_path[len1 + 1 + len2] = '\0';
136 /*Try and load the library*/
138 if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
146 lxvst_path = strtok (NULL, ":");
156 /*This loads up a plugin, given the path to its .so file and
157 finds its main entry point etc*/
159 VSTFXHandle* vstfx_load (const char *path)
162 VSTFXHandle* fhandle;
165 /*Create a new handle we can use to reference the plugin*/
167 fhandle = vstfx_handle_new();
169 /*See if we have .so appended to the path - if not we need to make sure it is added*/
171 if (strstr (path, ".so") == NULL)
174 /*Append the .so to the path - Make sure the path has enough space*/
176 buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
178 sprintf (buf, "%s.so", path);
180 fhandle->nameptr = strdup (path);
185 /*We already have .so appened to the filename*/
189 fhandle->nameptr = strdup (path);
192 /*Use basename to shorten the path and then strip off the .so - the old VST problem,
193 we don't know anything about its name until we load and instantiate the plugin
194 which we don't want to do at this point*/
196 for(i=0; i < (int)strlen(fhandle->nameptr); i++)
198 if(fhandle->nameptr[i] == '.')
199 fhandle->nameptr[i] = 0;
203 fhandle->name = basename (fhandle->nameptr);
205 /*call load_vstfx_library to actually load the .so into memory*/
207 if ((fhandle->dll = vstfx_load_vst_library (buf)) == NULL)
209 vstfx_unload (fhandle);
216 /*Find the main entry point into the plugin*/
218 if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == NULL)
220 /*If it can't be found, unload the plugin and return a NULL handle*/
222 vstfx_unload (fhandle);
231 /*return the handle of the plugin*/
236 /*This unloads a plugin*/
238 int vstfx_unload (VSTFXHandle* fhandle)
240 if (fhandle->plugincnt)
242 /*Still have plugin instances - can't unload the library
243 - actually dlclose keeps an instance count anyway*/
248 /*Valid plugin loaded?*/
252 dlclose(fhandle->dll);
256 if (fhandle->nameptr)
258 free (fhandle->nameptr);
259 fhandle->name = NULL;
262 /*Don't need the plugin handle any more*/
268 /*This instantiates a plugin*/
270 VSTFX* vstfx_instantiate (VSTFXHandle* fhandle, audioMasterCallback amc, void* userptr)
272 VSTFX* vstfx = vstfx_new ();
276 vstfx_error( "** ERROR ** VSTFX : The handle was NULL\n" );
280 if ((vstfx->plugin = fhandle->main_entry (amc)) == NULL)
282 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
287 vstfx->handle = fhandle;
288 vstfx->plugin->user = userptr;
290 if (vstfx->plugin->magic != kEffectMagic)
292 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
297 vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
299 /*May or May not need to 'switch the plugin on' here - unlikely
300 since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
302 //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, NULL, 0);
304 vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
306 vstfx->handle->plugincnt++;
312 /*Close a vstfx instance*/
314 void vstfx_close (VSTFX* vstfx)
316 vstfx_destroy_editor(vstfx);
320 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, NULL, 0);
322 /*Calling dispatcher with effClose will cause the plugin's destructor to
323 be called, which will also remove the editor if it exists*/
325 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
328 if (vstfx->handle->plugincnt)
329 vstfx->handle->plugincnt--;
331 /*vstfx_unload will unload the dll if the instance count allows -
332 we need to do this because some plugins keep their own instance count
333 and (JUCE) manages the plugin UI in its own thread. When the plugins
334 internal instance count reaches zero, JUCE stops the UI thread and won't
335 restart it until the next time the library is loaded. If we don't unload
336 the lib JUCE will never restart*/
339 if (vstfx->handle->plugincnt)
344 /*Valid plugin loaded - so we can unload it and NULL the pointer
345 to it. We can't free the handle here because we don't know what else
346 might need it. It should be / is freed when the plugin is deleted*/
348 if (vstfx->handle->dll)
350 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
351 vstfx->handle->dll = NULL;
357 vstfx_save_state (VSTFX* vstfx, char * filename)
359 FILE* f = fopen (filename, "wb");
363 int numParams = vstfx->plugin->numParams;
365 char productString[64];
367 char vendorString[64];
372 fprintf(f, "<plugin_state>\n");
374 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
378 fprintf (f, " <check field=\"productString\" value=\"%s\"/>\n", productString);
382 printf ("No product string\n");
385 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
389 fprintf (f, " <check field=\"effectName\" value=\"%s\"/>\n", effectName);
390 printf ("Effect name: %s\n", effectName);
394 printf ("No effect name\n");
397 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
401 fprintf (f, " <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
402 printf ("Vendor string: %s\n", vendorString);
406 printf ("No vendor string\n");
410 if(vstfx->plugin->flags & 32 )
415 for(i=0; i < numParams; i++)
419 pthread_mutex_lock( &vstfx->lock );
420 val = vstfx->plugin->getParameter(vstfx->plugin, i );
421 pthread_mutex_unlock( &vstfx->lock );
422 fprintf( f, " <param index=\"%d\" value=\"%f\"/>\n", i, val );
425 if(vstfx->plugin->flags & 32 )
427 printf( "getting chunk...\n" );
429 bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
430 printf( "got tha chunk..\n" );
435 printf( "Chunke len < 0 !!! Not saving chunk.\n" );
439 //char *encoded = g_base64_encode( chunk, bytelen );
440 //fprintf( f, " <chunk size=\"%d\">\n %s\n </chunk>\n", bytelen, encoded );
446 fprintf( f, "</plugin_state>\n" );
451 printf ("Could not open state file\n");
457 /*Set up a call to the plugins 'dispatcher' function*/
459 int vstfx_call_dispatcher (VSTFX *vstfx, int opcode, int index, int val, void *ptr, float opt)
461 pthread_mutex_lock (&vstfx->lock);
463 /*Set up the opcode and parameters*/
465 vstfx->dispatcher_opcode = opcode;
466 vstfx->dispatcher_index = index;
467 vstfx->dispatcher_val = val;
468 vstfx->dispatcher_ptr = ptr;
469 vstfx->dispatcher_opt = opt;
471 /*Signal that we want the call to happen*/
473 vstfx->dispatcher_wantcall = 1;
475 /*Wait for the call to happen*/
477 pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
478 pthread_mutex_unlock (&vstfx->lock);
480 /*Return the result*/
482 return vstfx->dispatcher_retval;