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