more debugging output for failed LXVST opens, and drop use of NULL
[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 <libgen.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <dlfcn.h>
27 #include <string.h>
28 #include <time.h>
29 #include <unistd.h>
30 #include <pthread.h>
31
32 #include <glib.h>
33 #include <glib/gstdio.h>
34 #include <glibmm/miscutils.h>
35 #include <glibmm/fileutils.h>
36
37 #include "ardour/linux_vst_support.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         int i;
198         
199         /*Create a new handle we can use to reference the plugin*/
200
201         fhandle = vstfx_handle_new();
202         
203         /*See if we have .so appended to the path - if not we need to make sure it is added*/
204         
205         if (strstr (path, ".so") == 0)
206         {
207
208                 /*Append the .so to the path - Make sure the path has enough space*/
209                 
210                 buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
211
212                 sprintf (buf, "%s.so", path);
213                 
214                 fhandle->nameptr = strdup (path);
215
216         }
217         else
218         {
219                 /*We already have .so appened to the filename*/
220                 
221                 buf = strdup(path);
222                 
223                 fhandle->nameptr = strdup (path);
224         }
225         
226         /*Use basename to shorten the path and then strip off the .so - the old VST problem,
227         we don't know anything about its name until we load and instantiate the plugin
228         which we don't want to do at this point*/
229         
230         for(i=0; i < (int)strlen(fhandle->nameptr); i++)
231         {
232                 if(fhandle->nameptr[i] == '.')
233                         fhandle->nameptr[i] = 0;
234         }
235                         
236         
237         fhandle->name = basename (fhandle->nameptr);
238
239         /*call load_vstfx_library to actually load the .so into memory*/
240
241         if ((fhandle->dll = vstfx_load_vst_library (buf)) == 0)
242         {
243                 vstfx_unload (fhandle);
244                 
245                 free(buf);
246                 
247                 return 0;
248         }
249
250         /*Find the main entry point into the plugin*/
251
252         if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == 0)
253         {
254                 /*If it can't be found, unload the plugin and return a 0 handle*/
255                 
256                 vstfx_unload (fhandle);
257                 
258                 free(buf);
259                 
260                 return 0;
261         }
262
263         free(buf);
264
265         /*return the handle of the plugin*/
266
267         return fhandle;
268 }
269
270 /*This unloads a plugin*/
271
272 int
273 vstfx_unload (VSTHandle* fhandle)
274 {
275         if (fhandle->plugincnt)
276         {
277                 /*Still have plugin instances - can't unload the library
278                 - actually dlclose keeps an instance count anyway*/
279                 
280                 return -1;
281         }
282
283         /*Valid plugin loaded?*/
284
285         if (fhandle->dll)
286         {
287                 dlclose(fhandle->dll);
288                 fhandle->dll = 0;
289         }
290
291         if (fhandle->nameptr)
292         {
293                 free (fhandle->nameptr);
294                 fhandle->name = 0;
295         }
296         
297         /*Don't need the plugin handle any more*/
298         
299         free (fhandle);
300         return 0;
301 }
302
303 /*This instantiates a plugin*/
304
305 VSTState *
306 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
307 {
308         VSTState* vstfx = vstfx_new ();
309
310         if(fhandle == 0)
311         {
312             vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
313             return 0;
314         }
315
316         if ((vstfx->plugin = fhandle->main_entry (amc)) == 0) 
317         {
318                 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
319                 free (vstfx);
320                 return 0;
321         }
322         
323         vstfx->handle = fhandle;
324         vstfx->plugin->user = userptr;
325                 
326         if (vstfx->plugin->magic != kEffectMagic)
327         {
328                 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
329                 free (vstfx);
330                 return 0;
331         }
332         
333         vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
334         
335         /*May or May not need to 'switch the plugin on' here - unlikely
336         since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
337         
338         //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, 0, 0);
339         
340         vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
341         
342         vstfx->handle->plugincnt++;
343         vstfx->wantIdle = 0;
344         
345         return vstfx;
346 }
347
348 /*Close a vstfx instance*/
349
350 void vstfx_close (VSTState* vstfx)
351 {
352         vstfx_destroy_editor(vstfx);
353         
354         if(vstfx->plugin)
355         {
356                 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, 0, 0);
357                 
358                 /*Calling dispatcher with effClose will cause the plugin's destructor to
359                 be called, which will also remove the editor if it exists*/
360                 
361                 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
362         }
363
364         if (vstfx->handle->plugincnt)
365                         vstfx->handle->plugincnt--;
366                 
367         /*vstfx_unload will unload the dll if the instance count allows - 
368         we need to do this because some plugins keep their own instance count
369         and (JUCE) manages the plugin UI in its own thread.  When the plugins
370         internal instance count reaches zero, JUCE stops the UI thread and won't
371         restart it until the next time the library is loaded.  If we don't unload
372         the lib JUCE will never restart*/
373         
374         
375         if (vstfx->handle->plugincnt)
376         {
377                 return;
378         }
379         
380         /*Valid plugin loaded - so we can unload it and 0 the pointer
381         to it.  We can't free the handle here because we don't know what else
382         might need it.  It should be / is freed when the plugin is deleted*/
383
384         if (vstfx->handle->dll)
385         {
386                 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
387                 vstfx->handle->dll = 0;
388         }
389 }
390
391
392 bool 
393 vstfx_save_state (VSTState* vstfx, char * filename)
394 {
395         FILE* f = g_fopen (filename, "wb");
396         if (f)
397         {
398                 int bytelen;
399                 int numParams = vstfx->plugin->numParams;
400                 int i;
401                 char productString[64];
402                 char effectName[64];
403                 char vendorString[64];
404                 int success;
405
406                 /* write header */
407                 
408                 fprintf(f, "<plugin_state>\n");
409
410                 success = vstfx_call_dispatcher(vstfx, effGetProductString, 0, 0, productString, 0);
411                 
412                 if(success == 1)
413                 {
414                         fprintf (f, "  <check field=\"productString\" value=\"%s\"/>\n", productString);
415                 }
416                 else
417                 {
418                         printf ("No product string\n");
419                 }
420
421                 success = vstfx_call_dispatcher(vstfx, effGetEffectName, 0, 0, effectName, 0);
422                 
423                 if(success == 1)
424                 {
425                         fprintf (f, "  <check field=\"effectName\" value=\"%s\"/>\n", effectName);
426                         printf ("Effect name: %s\n", effectName);
427                 }
428                 else
429                 {
430                         printf ("No effect name\n");
431                 }
432
433                 success = vstfx_call_dispatcher(vstfx, effGetVendorString, 0, 0, vendorString, 0);
434                 
435                 if( success == 1 )
436                 {
437                         fprintf (f, "  <check field=\"vendorString\" value=\"%s\"/>\n", vendorString);
438                         printf ("Vendor string: %s\n", vendorString);
439                 }
440                 else
441                 {
442                         printf ("No vendor string\n");
443                 }
444
445
446                 if(vstfx->plugin->flags & 32 )
447                 {
448                         numParams = 0;
449                 }
450
451                 for(i=0; i < numParams; i++)
452                 {
453                         float val;
454                         
455                         pthread_mutex_lock( &vstfx->lock );
456                         val = vstfx->plugin->getParameter(vstfx->plugin, i );
457                         pthread_mutex_unlock( &vstfx->lock );
458                         fprintf( f, "  <param index=\"%d\" value=\"%f\"/>\n", i, val );
459                 }
460
461                 if(vstfx->plugin->flags & 32 )
462                 {
463                         printf( "getting chunk...\n" );
464                         void * chunk;
465                         bytelen = vstfx_call_dispatcher(vstfx, 23, 0, 0, &chunk, 0 );
466                         printf( "got tha chunk..\n" );
467                         if( bytelen )
468                         {
469                                 if( bytelen < 0 )
470                                 {
471                                         printf( "Chunke len < 0 !!! Not saving chunk.\n" );
472                                 }
473                                 else
474                                 {
475                                         //char *encoded = g_base64_encode( chunk, bytelen );
476                                         //fprintf( f, "  <chunk size=\"%d\">\n    %s\n  </chunk>\n", bytelen, encoded );
477                                         //g_free( encoded );
478                                 }
479                         }
480                 } 
481
482                 fprintf( f, "</plugin_state>\n" );
483                 fclose( f );
484         }
485         else
486         {
487                 printf ("Could not open state file\n");
488                 return false;
489         }
490         return true;
491 }
492
493 /*Set up a call to the plugins 'dispatcher' function*/
494
495 int vstfx_call_dispatcher (VSTState* vstfx, int opcode, int index, int val, void *ptr, float opt) 
496 {
497         pthread_mutex_lock (&vstfx->lock);
498         
499         /*Set up the opcode and parameters*/
500         
501         vstfx->dispatcher_opcode = opcode;
502         vstfx->dispatcher_index = index;
503         vstfx->dispatcher_val = val;
504         vstfx->dispatcher_ptr = ptr;
505         vstfx->dispatcher_opt = opt;
506         
507         /*Signal that we want the call to happen*/
508         
509         vstfx->dispatcher_wantcall = 1;
510
511         /*Wait for the call to happen*/
512
513         pthread_cond_wait (&vstfx->plugin_dispatcher_called, &vstfx->lock);
514         pthread_mutex_unlock (&vstfx->lock);
515
516         /*Return the result*/
517         
518         return vstfx->dispatcher_retval;
519 }