99251f08e476234f7969f5d6c7489ad5dc558f2d
[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         {
247                 /*If it can't be found, unload the plugin and return a 0 handle*/
248                 
249                 vstfx_unload (fhandle);
250                 
251                 free(buf);
252                 
253                 return 0;
254         }
255
256         free(buf);
257
258         /*return the handle of the plugin*/
259
260         return fhandle;
261 }
262
263 /*This unloads a plugin*/
264
265 int
266 vstfx_unload (VSTHandle* fhandle)
267 {
268         if (fhandle->plugincnt)
269         {
270                 /*Still have plugin instances - can't unload the library
271                 - actually dlclose keeps an instance count anyway*/
272                 
273                 return -1;
274         }
275
276         /*Valid plugin loaded?*/
277
278         if (fhandle->dll)
279         {
280                 dlclose(fhandle->dll);
281                 fhandle->dll = 0;
282         }
283
284         if (fhandle->nameptr)
285         {
286                 free (fhandle->nameptr);
287                 free (fhandle->name);
288         }
289         
290         /*Don't need the plugin handle any more*/
291         
292         free (fhandle);
293         return 0;
294 }
295
296 /*This instantiates a plugin*/
297
298 VSTState *
299 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
300 {
301         VSTState* vstfx = vstfx_new ();
302
303         if(fhandle == 0)
304         {
305             vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
306             return 0;
307         }
308
309         if ((vstfx->plugin = fhandle->main_entry (amc)) == 0) 
310         {
311                 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
312                 free (vstfx);
313                 return 0;
314         }
315         
316         vstfx->handle = fhandle;
317         vstfx->plugin->user = userptr;
318                 
319         if (vstfx->plugin->magic != kEffectMagic)
320         {
321                 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
322                 free (vstfx);
323                 return 0;
324         }
325         
326         vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
327         
328         /*May or May not need to 'switch the plugin on' here - unlikely
329         since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
330         
331         //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, 0, 0);
332         
333         vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
334         
335         vstfx->handle->plugincnt++;
336         vstfx->wantIdle = 0;
337         
338         return vstfx;
339 }
340
341 /*Close a vstfx instance*/
342
343 void vstfx_close (VSTState* vstfx)
344 {
345         vstfx_destroy_editor(vstfx);
346         
347         if(vstfx->plugin)
348         {
349                 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, 0, 0);
350                 
351                 /*Calling dispatcher with effClose will cause the plugin's destructor to
352                 be called, which will also remove the editor if it exists*/
353                 
354                 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
355         }
356
357         if (vstfx->handle->plugincnt)
358                         vstfx->handle->plugincnt--;
359                 
360         /*vstfx_unload will unload the dll if the instance count allows - 
361         we need to do this because some plugins keep their own instance count
362         and (JUCE) manages the plugin UI in its own thread.  When the plugins
363         internal instance count reaches zero, JUCE stops the UI thread and won't
364         restart it until the next time the library is loaded.  If we don't unload
365         the lib JUCE will never restart*/
366         
367         
368         if (vstfx->handle->plugincnt)
369         {
370                 return;
371         }
372         
373         /*Valid plugin loaded - so we can unload it and 0 the pointer
374         to it.  We can't free the handle here because we don't know what else
375         might need it.  It should be / is freed when the plugin is deleted*/
376
377         if (vstfx->handle->dll)
378         {
379                 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
380                 vstfx->handle->dll = 0;
381         }
382 }
383
384
385 bool 
386 vstfx_save_state (VSTState* vstfx, char * filename)
387 {
388         FILE* f = g_fopen (filename, "wb");
389         if (f)
390         {
391                 int bytelen;
392                 int numParams = vstfx->plugin->numParams;
393                 int i;
394                 char productString[64];
395                 char effectName[64];
396                 char vendorString[64];
397                 int success;
398
399                 /* write header */
400                 
401                 fprintf(f, "<plugin_state>\n");
402
403                 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
404                 
405                 if(success == 1)
406                 {
407                         fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
408                 }
409                 else
410                 {
411                         printf ("No product string\n");
412                 }
413
414                 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
415                 
416                 if(success == 1)
417                 {
418                         fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
419                         printf ("Effect name: %s\n", effectName);
420                 }
421                 else
422                 {
423                         printf ("No effect name\n");
424                 }
425
426                 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
427                 
428                 if( success == 1 )
429                 {
430                         fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
431                         printf ("Vendor string: %s\n", vendorString);
432                 }
433                 else
434                 {
435                         printf ("No vendor string\n");
436                 }
437
438
439                 if(vstfx->plugin->flags & 32 )
440                 {
441                         numParams = 0;
442                 }
443
444                 for(i=0; i < numParams; i++)
445                 {
446                         float val;
447                         
448                         pthread_mutex_lock( &vstfx->lock );
449                         val = vstfx->plugin->getParameter(vstfx->plugin, i );
450                         pthread_mutex_unlock( &vstfx->lock );
451                         fprintf( f, "  <param index=\"%d\" value=\"%f\"/>\n", i, val );
452                 }
453
454                 if(vstfx->plugin->flags & 32 )
455                 {
456                         printf( "getting chunk...\n" );
457                         void * chunk;
458                         bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
459                         printf( "got tha chunk..\n" );
460                         if( bytelen )
461                         {
462                                 if( bytelen < 0 )
463                                 {
464                                         printf( "Chunke len < 0 !!! Not saving chunk.\n" );
465                                 }
466                                 else
467                                 {
468                                         //char *encoded = g_base64_encode( chunk, bytelen );
469                                         //fprintf( f, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
470                                         //g_free( encoded );
471                                 }
472                         }
473                 } 
474
475                 fprintf( f, "</plugin_state>\n" );
476                 fclose( f );
477         }
478         else
479         {
480                 printf ("Could not open state file\n");
481                 return false;
482         }
483         return true;
484 }
485
486 /*Set up a call to the plugins 'dispatcher' function*/
487
488 int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
489 {
490         pthread_mutex_lock (&vstfx->lock);
491         
492         /*Set up the opcode and parameters*/
493         
494         vstfx->dispatcher_opcode = opcode;
495         vstfx->dispatcher_index = index;
496         vstfx->dispatcher_val = val;
497         vstfx->dispatcher_ptr = ptr;
498         vstfx->dispatcher_opt = opt;
499         
500         /*Signal that we want the call to happen*/
501         
502         vstfx->dispatcher_wantcall = 1;
503
504         /*Wait for the call to happen*/
505
506         pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
507         pthread_mutex_unlock (&vstfx->lock);
508
509         /*Return the result*/
510         
511         return vstfx->dispatcher_retval;
512 }