if a request to reset the speed to zero as the default arrives when stopped, reset...
[ardour.git] / libs / ardour / linux_vst_support.cc
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <stdlib.h>
4 #include <libgen.h>
5 #include <pthread.h>
6 #include <signal.h>
7 #include <dlfcn.h>
8 #include <string.h>
9 #include <time.h>
10 #include <unistd.h>
11 #include <pthread.h>
12 #include <glib.h>
13 #include <glib/gstdio.h>
14
15 #include "ardour/linux_vst_support.h"
16 #include "pbd/error.h"
17
18 /***********************************************************/
19 /* VSTFX - A set of modules for managing linux VST plugins */
20 /* vstfx.cc, vstfxwin.cc and vstfxinfofile.cc              */
21 /***********************************************************/
22
23 /*Simple error handler stuff for VSTFX*/
24
25 void vstfx_error (const char *fmt, ...)
26 {
27         va_list ap;
28         char buffer[512];
29
30         va_start (ap, fmt);
31         vsnprintf (buffer, sizeof(buffer), fmt, ap);
32         vstfx_error_callback (buffer);
33         va_end (ap);
34 }
35
36 /*default error handler callback*/
37
38 void default_vstfx_error_callback (const char *desc)
39 {
40         PBD::error << desc << endmsg;
41 }
42
43 void (*vstfx_error_callback)(const char *desc) = &default_vstfx_error_callback;
44
45 /* --- */
46
47 /*Create and return a pointer to a new VSTFX handle*/
48
49 VSTHandle *
50 vstfx_handle_new ()
51 {
52         VSTHandle* vstfx = (VSTHandle *) calloc (1, sizeof (VSTHandle));
53         return vstfx;
54 }
55
56 /*Create and return a pointer to a new vstfx instance*/
57
58 VSTState *
59 vstfx_new ()
60 {
61         VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
62         
63         /*Mutexes*/
64         
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);
69
70         /*Safe values*/
71         
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;
82         
83         return vstfx;
84 }
85
86 /*This loads the plugin shared library*/
87
88 void* vstfx_load_vst_library(const char* path)
89 {
90         void* dll;
91         char* full_path;
92         char* envdup;
93         char* lxvst_path;
94         size_t len1;
95         size_t len2;
96
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
100         invalid arguments*/
101
102         if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
103                 return dll;
104                 
105         /*We didn't find the library so try and get the path specified in the
106         env variable LXVST_PATH*/
107
108         envdup = getenv ("LXVST_PATH");
109         
110         /*Path not specified - not much more we can do*/
111         
112         if (envdup == NULL)
113                 return NULL;
114         
115         /*Copy the path into envdup*/
116                 
117         envdup = strdup (envdup);
118         
119         if (envdup == NULL)
120                 return NULL;
121                 
122         len2 = strlen(path);
123
124         /*Try all the possibilities in the path - deliminated by : */
125
126         lxvst_path = strtok (envdup, ":");
127         
128         while (lxvst_path != NULL)
129         {
130                 vstfx_error ("\"%s\"", lxvst_path);
131                 len1 = strlen(lxvst_path);
132                 
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';
138
139                 /*Try and load the library*/
140
141                 if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != NULL)
142                 {
143                         /*Succeeded */
144                         break;
145                 }
146         
147                 /*Try again*/
148
149                 lxvst_path = strtok (NULL, ":");
150         }
151
152         /*Free the path*/
153
154         free(envdup);
155
156         return dll;
157 }
158
159 /*This loads up a plugin, given the path to its .so file and
160  finds its main entry point etc*/
161
162 VSTHandle *
163 vstfx_load (const char *path)
164 {
165         char* buf = NULL;
166         VSTHandle* fhandle;
167         int i;
168         
169         /*Create a new handle we can use to reference the plugin*/
170
171         fhandle = vstfx_handle_new();
172         
173         /*See if we have .so appended to the path - if not we need to make sure it is added*/
174         
175         if (strstr (path, ".so") == NULL)
176         {
177
178                 /*Append the .so to the path - Make sure the path has enough space*/
179                 
180                 buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
181
182                 sprintf (buf, "%s.so", path);
183                 
184                 fhandle->nameptr = strdup (path);
185
186         }
187         else
188         {
189                 /*We already have .so appened to the filename*/
190                 
191                 buf = strdup(path);
192                 
193                 fhandle->nameptr = strdup (path);
194         }
195         
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*/
199         
200         for(i=0; i < (int)strlen(fhandle->nameptr); i++)
201         {
202                 if(fhandle->nameptr[i] == '.')
203                         fhandle->nameptr[i] = 0;
204         }
205                         
206         
207         fhandle->name = basename (fhandle->nameptr);
208
209         /*call load_vstfx_library to actually load the .so into memory*/
210
211         if ((fhandle->dll = vstfx_load_vst_library (buf)) == NULL)
212         {
213                 vstfx_unload (fhandle);
214                 
215                 free(buf);
216                 
217                 return NULL;
218         }
219
220         /*Find the main entry point into the plugin*/
221
222         if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == NULL)
223         {
224                 /*If it can't be found, unload the plugin and return a NULL handle*/
225                 
226                 vstfx_unload (fhandle);
227                 
228                 free(buf);
229                 
230                 return NULL;
231         }
232
233         free(buf);
234
235         /*return the handle of the plugin*/
236
237         return fhandle;
238 }
239
240 /*This unloads a plugin*/
241
242 int
243 vstfx_unload (VSTHandle* fhandle)
244 {
245         if (fhandle->plugincnt)
246         {
247                 /*Still have plugin instances - can't unload the library
248                 - actually dlclose keeps an instance count anyway*/
249                 
250                 return -1;
251         }
252
253         /*Valid plugin loaded?*/
254
255         if (fhandle->dll)
256         {
257                 dlclose(fhandle->dll);
258                 fhandle->dll = NULL;
259         }
260
261         if (fhandle->nameptr)
262         {
263                 free (fhandle->nameptr);
264                 fhandle->name = NULL;
265         }
266         
267         /*Don't need the plugin handle any more*/
268         
269         free (fhandle);
270         return 0;
271 }
272
273 /*This instantiates a plugin*/
274
275 VSTState *
276 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
277 {
278         VSTState* vstfx = vstfx_new ();
279
280         if(fhandle == NULL)
281         {
282             vstfx_error( "** ERROR ** VSTFX : The handle was NULL\n" );
283             return NULL;
284         }
285
286         if ((vstfx->plugin = fhandle->main_entry (amc)) == NULL) 
287         {
288                 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
289                 free (vstfx);
290                 return NULL;
291         }
292         
293         vstfx->handle = fhandle;
294         vstfx->plugin->user = userptr;
295                 
296         if (vstfx->plugin->magic != kEffectMagic)
297         {
298                 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
299                 free (vstfx);
300                 return NULL;
301         }
302         
303         vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
304         
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*/
307         
308         //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, NULL, 0);
309         
310         vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
311         
312         vstfx->handle->plugincnt++;
313         vstfx->wantIdle = 0;
314         
315         return vstfx;
316 }
317
318 /*Close a vstfx instance*/
319
320 void vstfx_close (VSTState* vstfx)
321 {
322         vstfx_destroy_editor(vstfx);
323         
324         if(vstfx->plugin)
325         {
326                 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, NULL, 0);
327                 
328                 /*Calling dispatcher with effClose will cause the plugin's destructor to
329                 be called, which will also remove the editor if it exists*/
330                 
331                 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
332         }
333
334         if (vstfx->handle->plugincnt)
335                         vstfx->handle->plugincnt--;
336                 
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*/
343         
344         
345         if (vstfx->handle->plugincnt)
346         {
347                 return;
348         }
349         
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*/
353
354         if (vstfx->handle->dll)
355         {
356                 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
357                 vstfx->handle->dll = NULL;
358         }
359 }
360
361
362 bool 
363 vstfx_save_state (VSTState* vstfx, char * filename)
364 {
365         FILE* f = g_fopen (filename, "wb");
366         if (f)
367         {
368                 int bytelen;
369                 int numParams = vstfx->plugin->numParams;
370                 int i;
371                 char productString[64];
372                 char effectName[64];
373                 char vendorString[64];
374                 int success;
375
376                 /* write header */
377                 
378                 fprintf(f, "<plugin_state>\n");
379
380                 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
381                 
382                 if(success == 1)
383                 {
384                         fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
385                 }
386                 else
387                 {
388                         printf ("No product string\n");
389                 }
390
391                 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
392                 
393                 if(success == 1)
394                 {
395                         fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
396                         printf ("Effect name: %s\n", effectName);
397                 }
398                 else
399                 {
400                         printf ("No effect name\n");
401                 }
402
403                 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
404                 
405                 if( success == 1 )
406                 {
407                         fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
408                         printf ("Vendor string: %s\n", vendorString);
409                 }
410                 else
411                 {
412                         printf ("No vendor string\n");
413                 }
414
415
416                 if(vstfx->plugin->flags & 32 )
417                 {
418                         numParams = 0;
419                 }
420
421                 for(i=0; i < numParams; i++)
422                 {
423                         float val;
424                         
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 );
429                 }
430
431                 if(vstfx->plugin->flags & 32 )
432                 {
433                         printf( "getting chunk...\n" );
434                         void * chunk;
435                         bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
436                         printf( "got tha chunk..\n" );
437                         if( bytelen )
438                         {
439                                 if( bytelen < 0 )
440                                 {
441                                         printf( "Chunke len < 0 !!! Not saving chunk.\n" );
442                                 }
443                                 else
444                                 {
445                                         //char *encoded = g_base64_encode( chunk, bytelen );
446                                         //fprintf( f, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
447                                         //g_free( encoded );
448                                 }
449                         }
450                 } 
451
452                 fprintf( f, "</plugin_state>\n" );
453                 fclose( f );
454         }
455         else
456         {
457                 printf ("Could not open state file\n");
458                 return false;
459         }
460         return true;
461 }
462
463 /*Set up a call to the plugins 'dispatcher' function*/
464
465 int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
466 {
467         pthread_mutex_lock (&vstfx->lock);
468         
469         /*Set up the opcode and parameters*/
470         
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;
476         
477         /*Signal that we want the call to happen*/
478         
479         vstfx->dispatcher_wantcall = 1;
480
481         /*Wait for the call to happen*/
482
483         pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
484         pthread_mutex_unlock (&vstfx->lock);
485
486         /*Return the result*/
487         
488         return vstfx->dispatcher_retval;
489 }