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