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