Merge windows+cc branch into cairocanvas branch. Not finished, need to now merge...
[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         fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main");
246
247         if (fhandle->main_entry == 0) {
248                 if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "VSTPluginMain")) != 0) {
249                         PBD::warning << path << _(": is a VST >= 2.4 - this plugin may or may not function correctly with this version of Ardour.") << endmsg;
250                 }
251         }
252
253         if (fhandle->main_entry == 0)
254         {
255                 /*If it can't be found, unload the plugin and return a 0 handle*/
256                 
257                 vstfx_unload (fhandle);
258                 
259                 free(buf);
260                 
261                 return 0;
262         }
263
264         free(buf);
265
266         /*return the handle of the plugin*/
267
268         return fhandle;
269 }
270
271 /*This unloads a plugin*/
272
273 int
274 vstfx_unload (VSTHandle* fhandle)
275 {
276         if (fhandle->plugincnt)
277         {
278                 /*Still have plugin instances - can't unload the library
279                 - actually dlclose keeps an instance count anyway*/
280                 
281                 return -1;
282         }
283
284         /*Valid plugin loaded?*/
285
286         if (fhandle->dll)
287         {
288                 dlclose(fhandle->dll);
289                 fhandle->dll = 0;
290         }
291
292         if (fhandle->nameptr)
293         {
294                 free (fhandle->nameptr);
295                 free (fhandle->name);
296         }
297         
298         /*Don't need the plugin handle any more*/
299         
300         free (fhandle);
301         return 0;
302 }
303
304 /*This instantiates a plugin*/
305
306 VSTState *
307 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
308 {
309         VSTState* vstfx = vstfx_new ();
310
311         if(fhandle == 0)
312         {
313             vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
314             return 0;
315         }
316
317         if ((vstfx->plugin = fhandle->main_entry (amc)) == 0) 
318         {
319                 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
320                 free (vstfx);
321                 return 0;
322         }
323         
324         vstfx->handle = fhandle;
325         vstfx->plugin->user = userptr;
326                 
327         if (vstfx->plugin->magic != kEffectMagic)
328         {
329                 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
330                 free (vstfx);
331                 return 0;
332         }
333         
334         vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
335         
336         /*May or May not need to 'switch the plugin on' here - unlikely
337         since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
338         
339         //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, 0, 0);
340         
341         vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
342         
343         vstfx->handle->plugincnt++;
344         vstfx->wantIdle = 0;
345         
346         return vstfx;
347 }
348
349 /*Close a vstfx instance*/
350
351 void vstfx_close (VSTState* vstfx)
352 {
353         vstfx_destroy_editor(vstfx);
354         
355         if(vstfx->plugin)
356         {
357                 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, 0, 0);
358                 
359                 /*Calling dispatcher with effClose will cause the plugin's destructor to
360                 be called, which will also remove the editor if it exists*/
361                 
362                 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
363         }
364
365         if (vstfx->handle->plugincnt)
366                         vstfx->handle->plugincnt--;
367                 
368         /*vstfx_unload will unload the dll if the instance count allows - 
369         we need to do this because some plugins keep their own instance count
370         and (JUCE) manages the plugin UI in its own thread.  When the plugins
371         internal instance count reaches zero, JUCE stops the UI thread and won't
372         restart it until the next time the library is loaded.  If we don't unload
373         the lib JUCE will never restart*/
374         
375         
376         if (vstfx->handle->plugincnt)
377         {
378                 return;
379         }
380         
381         /*Valid plugin loaded - so we can unload it and 0 the pointer
382         to it.  We can't free the handle here because we don't know what else
383         might need it.  It should be / is freed when the plugin is deleted*/
384
385         if (vstfx->handle->dll)
386         {
387                 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
388                 vstfx->handle->dll = 0;
389         }
390         free(vstfx);
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 }