Remove non-portable and unnused header includes
[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         free(vstfx);
383 }
384
385
386 bool 
387 vstfx_save_state (VSTState* vstfx, char * filename)
388 {
389         FILE* f = g_fopen (filename, "wb");
390         if (f)
391         {
392                 int bytelen;
393                 int numParams = vstfx->plugin->numParams;
394                 int i;
395                 char productString[64];
396                 char effectName[64];
397                 char vendorString[64];
398                 int success;
399
400                 /* write header */
401                 
402                 fprintf(f, "<plugin_state>\n");
403
404                 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
405                 
406                 if(success == 1)
407                 {
408                         fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
409                 }
410                 else
411                 {
412                         printf ("No product string\n");
413                 }
414
415                 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
416                 
417                 if(success == 1)
418                 {
419                         fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
420                         printf ("Effect name: %s\n", effectName);
421                 }
422                 else
423                 {
424                         printf ("No effect name\n");
425                 }
426
427                 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
428                 
429                 if( success == 1 )
430                 {
431                         fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
432                         printf ("Vendor string: %s\n", vendorString);
433                 }
434                 else
435                 {
436                         printf ("No vendor string\n");
437                 }
438
439
440                 if(vstfx->plugin->flags & 32 )
441                 {
442                         numParams = 0;
443                 }
444
445                 for(i=0; i < numParams; i++)
446                 {
447                         float val;
448                         
449                         pthread_mutex_lock( &vstfx->lock );
450                         val = vstfx->plugin->getParameter(vstfx->plugin, i );
451                         pthread_mutex_unlock( &vstfx->lock );
452                         fprintf( f, "  <param index=\"%d\" value=\"%f\"/>\n", i, val );
453                 }
454
455                 if(vstfx->plugin->flags & 32 )
456                 {
457                         printf( "getting chunk...\n" );
458                         void * chunk;
459                         bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
460                         printf( "got tha chunk..\n" );
461                         if( bytelen )
462                         {
463                                 if( bytelen < 0 )
464                                 {
465                                         printf( "Chunke len < 0 !!! Not saving chunk.\n" );
466                                 }
467                                 else
468                                 {
469                                         //char *encoded = g_base64_encode( chunk, bytelen );
470                                         //fprintf( f, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
471                                         //g_free( encoded );
472                                 }
473                         }
474                 } 
475
476                 fprintf( f, "</plugin_state>\n" );
477                 fclose( f );
478         }
479         else
480         {
481                 printf ("Could not open state file\n");
482                 return false;
483         }
484         return true;
485 }
486
487 /*Set up a call to the plugins 'dispatcher' function*/
488
489 int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
490 {
491         pthread_mutex_lock (&vstfx->lock);
492         
493         /*Set up the opcode and parameters*/
494         
495         vstfx->dispatcher_opcode = opcode;
496         vstfx->dispatcher_index = index;
497         vstfx->dispatcher_val = val;
498         vstfx->dispatcher_ptr = ptr;
499         vstfx->dispatcher_opt = opt;
500         
501         /*Signal that we want the call to happen*/
502         
503         vstfx->dispatcher_wantcall = 1;
504
505         /*Wait for the call to happen*/
506
507         pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
508         pthread_mutex_unlock (&vstfx->lock);
509
510         /*Return the result*/
511         
512         return vstfx->dispatcher_retval;
513 }