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