065e8bd755b9e79674b7cc05d480642860c89eba
[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 "pbd/gstdio_compat.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 "pbd/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 static 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 static 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 static VSTState *
83 vstfx_new ()
84 {
85         VSTState* vstfx = (VSTState *) calloc (1, sizeof (VSTState));
86         vststate_init (vstfx);
87         return vstfx;
88 }
89
90 /*This loads the plugin shared library*/
91
92 static void* vstfx_load_vst_library(const char* path)
93 {
94         void* dll;
95         char* full_path = NULL;
96         char* envdup;
97         char* lxvst_path;
98         size_t len1;
99         size_t len2;
100
101         /*Try and load the shared library pointed to by the path -
102         NOTE: You have to give RTLD_LAZY or RTLD_NOW to dlopen or
103         you get some occasional failures to load - dlerror reports
104         invalid arguments*/
105
106         if ((dll = dlopen (path, RTLD_LOCAL | RTLD_LAZY)) != 0) {
107                 return dll;
108         }
109
110         if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
111                 PBD::error << string_compose (_("Could not open existing LXVST plugin: %1"), dlerror()) << endmsg;
112                 return 0;
113         }
114
115         /*We didn't find the library so try and get the path specified in the
116         env variable LXVST_PATH*/
117
118         envdup = getenv ("LXVST_PATH");
119
120         /*Path not specified - not much more we can do*/
121
122         if (envdup == 0)
123                 return 0;
124
125         /*Copy the path into envdup*/
126
127         envdup = strdup (envdup);
128
129         if (envdup == 0)
130                 return 0;
131
132         len2 = strlen(path);
133
134         /*Try all the possibilities in the path - deliminated by : */
135         char *saveptr;
136         lxvst_path = strtok_r (envdup, ":", &saveptr);
137
138         while (lxvst_path != 0)
139         {
140                 vstfx_error ("\"%s\"", lxvst_path);
141                 len1 = strlen(lxvst_path);
142
143                 if (full_path) free(full_path);
144                 full_path = (char*)malloc(len1 + 1 + len2 + 1);
145                 memcpy(full_path, lxvst_path, len1);
146                 full_path[len1] = '/';
147                 memcpy(full_path + len1 + 1, path, len2);
148                 full_path[len1 + 1 + len2] = '\0';
149
150                 /*Try and load the library*/
151
152                 if ((dll = dlopen(full_path, RTLD_LOCAL | RTLD_LAZY)) != 0)
153                 {
154                         /*Succeeded */
155                         break;
156                 }
157
158                 /*Try again*/
159
160                 lxvst_path = strtok_r (0, ":", &saveptr);
161         }
162
163         /*Free the path*/
164         if (full_path) free(full_path);
165         free(envdup);
166
167         return dll;
168 }
169
170 /*This loads up a plugin, given the path to its .so file and
171  finds its main entry point etc*/
172
173 VSTHandle *
174 vstfx_load (const char *path)
175 {
176         char* buf = 0;
177         VSTHandle* fhandle;
178
179         /*Create a new handle we can use to reference the plugin*/
180
181         fhandle = vstfx_handle_new();
182
183         /*See if we have .so appended to the path - if not we need to make sure it is added*/
184
185         if (strstr (path, ".so") == 0)
186         {
187
188                 /*Append the .so to the path - Make sure the path has enough space*/
189
190                 buf = (char *)malloc(strlen(path) + 4); //The .so and a terminating zero
191
192                 sprintf (buf, "%s.so", path);
193
194         }
195         else
196         {
197                 /*We already have .so appened to the filename*/
198
199                 buf = strdup(path);
200         }
201
202         /* get a name for the plugin based on the path: ye old VST problem where
203            we don't know anything about its name until we load and instantiate the plugin
204            which we don't want to do at this point
205         */
206
207         fhandle->name = strdup (PBD::basename_nosuffix (path).c_str());
208
209         /*call load_vstfx_library to actually load the .so into memory*/
210
211         if ((fhandle->dll = vstfx_load_vst_library (buf)) == 0)
212         {
213                 vstfx_unload (fhandle);
214
215                 free(buf);
216
217                 return 0;
218         }
219
220         /*Find the main entry point into the plugin*/
221
222         fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main");
223
224         if (fhandle->main_entry == 0) {
225                 if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "VSTPluginMain")) != 0) {
226                         PBD::warning << path << _(": is a VST >= 2.4 - this plugin may or may not function correctly with this version of Ardour.") << endmsg;
227                 }
228         }
229
230         if (fhandle->main_entry == 0)
231         {
232                 /*If it can't be found, unload the plugin and return a 0 handle*/
233
234                 vstfx_unload (fhandle);
235
236                 free(buf);
237
238                 return 0;
239         }
240
241         free(buf);
242
243         /*return the handle of the plugin*/
244
245         return fhandle;
246 }
247
248 /*This unloads a plugin*/
249
250 int
251 vstfx_unload (VSTHandle* fhandle)
252 {
253         if (fhandle->plugincnt)
254         {
255                 /*Still have plugin instances - can't unload the library
256                 - actually dlclose keeps an instance count anyway*/
257
258                 return -1;
259         }
260
261         /*Valid plugin loaded?*/
262
263         if (fhandle->dll)
264         {
265                 dlclose(fhandle->dll);
266                 fhandle->dll = 0;
267         }
268
269         if (fhandle->name)
270         {
271                 free (fhandle->name);
272         }
273
274         /*Don't need the plugin handle any more*/
275
276         free (fhandle);
277         return 0;
278 }
279
280 /*This instantiates a plugin*/
281
282 VSTState *
283 vstfx_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
284 {
285         VSTState* vstfx = vstfx_new ();
286
287         if(fhandle == 0)
288         {
289                 vstfx_error( "** ERROR ** VSTFX : The handle was 0\n" );
290                 free (vstfx);
291                 return 0;
292         }
293
294         if ((vstfx->plugin = fhandle->main_entry (amc)) == 0)
295         {
296                 vstfx_error ("** ERROR ** VSTFX : %s could not be instantiated :(\n", fhandle->name);
297                 free (vstfx);
298                 return 0;
299         }
300
301         vstfx->handle = fhandle;
302         vstfx->plugin->user = userptr;
303
304         if (vstfx->plugin->magic != kEffectMagic)
305         {
306                 vstfx_error ("** ERROR ** VSTFX : %s is not a VST plugin\n", fhandle->name);
307                 free (vstfx);
308                 return 0;
309         }
310
311         vstfx->plugin->dispatcher (vstfx->plugin, effOpen, 0, 0, 0, 0);
312
313         /*May or May not need to 'switch the plugin on' here - unlikely
314         since FST doesn't and most plugins start up 'On' by default - I think this is the least of our worries*/
315
316         //vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 1, 0, 0);
317
318         vstfx->vst_version = vstfx->plugin->dispatcher (vstfx->plugin, effGetVstVersion, 0, 0, 0, 0);
319
320         vstfx->handle->plugincnt++;
321         vstfx->wantIdle = 0;
322
323         return vstfx;
324 }
325
326 /*Close a vstfx instance*/
327
328 void vstfx_close (VSTState* vstfx)
329 {
330         vstfx_destroy_editor(vstfx);
331
332         if(vstfx->plugin)
333         {
334                 vstfx->plugin->dispatcher (vstfx->plugin, effMainsChanged, 0, 0, 0, 0);
335
336                 /*Calling dispatcher with effClose will cause the plugin's destructor to
337                 be called, which will also remove the editor if it exists*/
338
339                 vstfx->plugin->dispatcher (vstfx->plugin, effClose, 0, 0, 0, 0);
340         }
341
342         if (vstfx->handle->plugincnt)
343                         vstfx->handle->plugincnt--;
344
345         /*vstfx_unload will unload the dll if the instance count allows -
346         we need to do this because some plugins keep their own instance count
347         and (JUCE) manages the plugin UI in its own thread.  When the plugins
348         internal instance count reaches zero, JUCE stops the UI thread and won't
349         restart it until the next time the library is loaded.  If we don't unload
350         the lib JUCE will never restart*/
351
352
353         if (vstfx->handle->plugincnt)
354         {
355                 return;
356         }
357
358         /*Valid plugin loaded - so we can unload it and 0 the pointer
359         to it.  We can't free the handle here because we don't know what else
360         might need it.  It should be / is freed when the plugin is deleted*/
361
362         if (vstfx->handle->dll)
363         {
364                 dlclose(vstfx->handle->dll); //dlclose keeps its own reference count
365                 vstfx->handle->dll = 0;
366         }
367         free(vstfx);
368 }