1 /*
2 * JACK Rack
3 *
4 * Original:
5 * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
6 *
7 * Modification for MLT:
8 * Copyright (C) 2004-2021 Meltytech, LLC
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <ladspa.h>
28 #include <dlfcn.h>
29 #include <ctype.h>
30
31 #include <glib.h>
32
33 #include "plugin.h"
34 #include "jack_rack.h"
35 #include "process.h"
36 #include "framework/mlt_log.h"
37
38 #define CONTROL_FIFO_SIZE 128
39
40 #ifdef WITH_JACK
41 /* swap over the jack ports in two plugins */
42 static void
plugin_swap_aux_ports(plugin_t * plugin,plugin_t * other)43 plugin_swap_aux_ports (plugin_t * plugin, plugin_t * other)
44 {
45 guint copy;
46 jack_port_t ** aux_ports_tmp;
47
48 for (copy = 0; copy < plugin->copies; copy++)
49 {
50 aux_ports_tmp = other->holders[copy].aux_ports;
51 other->holders[copy].aux_ports = plugin->holders[copy].aux_ports;
52 plugin->holders[copy].aux_ports = aux_ports_tmp;
53 }
54 }
55 #endif
56
57 /** connect up the ladspa instance's input buffers to the previous
58 plugin's audio memory. make sure to check that plugin->prev
59 exists. */
60 void
plugin_connect_input_ports(plugin_t * plugin,LADSPA_Data ** inputs)61 plugin_connect_input_ports (plugin_t * plugin, LADSPA_Data ** inputs)
62 {
63 gint copy;
64 unsigned long channel;
65 unsigned long rack_channel;
66
67 if (!plugin || !inputs)
68 return;
69
70 rack_channel = 0;
71 for (copy = 0; copy < plugin->copies; copy++)
72 {
73 for (channel = 0; channel < plugin->desc->channels; channel++)
74 {
75 plugin->descriptor->
76 connect_port (plugin->holders[copy].instance,
77 plugin->desc->audio_input_port_indicies[channel],
78 inputs[rack_channel]);
79 rack_channel++;
80 }
81 }
82
83 plugin->audio_input_memory = inputs;
84 }
85
86 /** connect up a plugin's output ports to its own audio_output_memory output memory */
87 void
plugin_connect_output_ports(plugin_t * plugin)88 plugin_connect_output_ports (plugin_t * plugin)
89 {
90 gint copy;
91 unsigned long channel;
92 unsigned long rack_channel = 0;
93
94 if (!plugin)
95 return;
96
97
98 for (copy = 0; copy < plugin->copies; copy++)
99 {
100 for (channel = 0; channel < plugin->desc->channels; channel++)
101 {
102 plugin->descriptor->
103 connect_port (plugin->holders[copy].instance,
104 plugin->desc->audio_output_port_indicies[channel],
105 plugin->audio_output_memory[rack_channel]);
106 rack_channel++;
107 }
108 }
109 }
110
111 void
process_add_plugin(process_info_t * procinfo,plugin_t * plugin)112 process_add_plugin (process_info_t * procinfo, plugin_t * plugin)
113 {
114
115 /* sort out list pointers */
116 plugin->next = NULL;
117 plugin->prev = procinfo->chain_end;
118
119 if (procinfo->chain_end)
120 procinfo->chain_end->next = plugin;
121 else
122 procinfo->chain = plugin;
123
124 procinfo->chain_end = plugin;
125
126 }
127
128
129 /** remove a plugin from the chain */
130 plugin_t *
process_remove_plugin(process_info_t * procinfo,plugin_t * plugin)131 process_remove_plugin (process_info_t * procinfo, plugin_t *plugin)
132 {
133 /* sort out chain pointers */
134 if (plugin->prev)
135 plugin->prev->next = plugin->next;
136 else
137 procinfo->chain = plugin->next;
138
139 if (plugin->next)
140 plugin->next->prev = plugin->prev;
141 else
142 procinfo->chain_end = plugin->prev;
143
144 #ifdef WITH_JACK
145 /* sort out the aux ports */
146 if (procinfo->jack_client && plugin->desc->aux_channels > 0)
147 {
148 plugin_t * other;
149
150 for (other = plugin->next; other; other = other->next)
151 if (other->desc->id == plugin->desc->id)
152 plugin_swap_aux_ports (plugin, other);
153 }
154 #endif
155
156 return plugin;
157 }
158
159 /** enable/disable a plugin */
160 void
process_ablise_plugin(process_info_t * procinfo,plugin_t * plugin,gboolean enable)161 process_ablise_plugin (process_info_t * procinfo, plugin_t *plugin, gboolean enable)
162 {
163 plugin->enabled = enable;
164 }
165
166 /** enable/disable a plugin */
167 void
process_ablise_plugin_wet_dry(process_info_t * procinfo,plugin_t * plugin,gboolean enable)168 process_ablise_plugin_wet_dry (process_info_t * procinfo, plugin_t *plugin, gboolean enable)
169 {
170 plugin->wet_dry_enabled = enable;
171 }
172
173 /** move a plugin up or down one place in the chain */
174 void
process_move_plugin(process_info_t * procinfo,plugin_t * plugin,gint up)175 process_move_plugin (process_info_t * procinfo, plugin_t *plugin, gint up)
176 {
177 /* other plugins in the chain */
178 plugin_t *pp = NULL, *p, *n, *nn = NULL;
179
180 /* note that we should never receive an illogical move request
181 ie, there will always be at least 1 plugin before for an up
182 request or 1 plugin after for a down request */
183
184 /* these are pointers to the plugins surrounding the specified one:
185 { pp, p, plugin, n, nn } which makes things much clearer than
186 tptr, tptr2 etc */
187 p = plugin->prev;
188 if (p) pp = p->prev;
189 n = plugin->next;
190 if (n) nn = n->next;
191
192 if (up)
193 {
194 if (!p)
195 return;
196
197 if (pp)
198 pp->next = plugin;
199 else
200 procinfo->chain = plugin;
201
202 p->next = n;
203 p->prev = plugin;
204
205 plugin->prev = pp;
206 plugin->next = p;
207
208 if (n)
209 n->prev = p;
210 else
211 procinfo->chain_end = p;
212
213 }
214 else
215 {
216 if (!n)
217 return;
218
219 if (p)
220 p->next = n;
221 else
222 procinfo->chain = n;
223
224 n->prev = p;
225 n->next = plugin;
226
227 plugin->prev = n;
228 plugin->next = nn;
229
230 if (nn)
231 nn->prev = plugin;
232 else
233 procinfo->chain_end = plugin;
234 }
235
236 #ifdef WITH_JACK
237 if (procinfo->jack_client && plugin->desc->aux_channels > 0)
238 {
239 plugin_t * other;
240 other = up ? plugin->next : plugin->prev;
241
242 /* swap around the jack ports */
243 if (other->desc->id == plugin->desc->id)
244 plugin_swap_aux_ports (plugin, other);
245 }
246 #endif
247 }
248
249 /** exchange an existing plugin for a newly created one */
250 plugin_t *
process_change_plugin(process_info_t * procinfo,plugin_t * plugin,plugin_t * new_plugin)251 process_change_plugin (process_info_t * procinfo,
252 plugin_t *plugin, plugin_t * new_plugin)
253 {
254 new_plugin->next = plugin->next;
255 new_plugin->prev = plugin->prev;
256
257 if (plugin->prev)
258 plugin->prev->next = new_plugin;
259 else
260 procinfo->chain = new_plugin;
261
262 if (plugin->next)
263 plugin->next->prev = new_plugin;
264 else
265 procinfo->chain_end = new_plugin;
266
267 #ifdef WITH_JACK
268 /* sort out the aux ports */
269 if (procinfo->jack_client && plugin->desc->aux_channels > 0)
270 {
271 plugin_t * other;
272
273 for (other = plugin->next; other; other = other->next)
274 if (other->desc->id == plugin->desc->id)
275 plugin_swap_aux_ports (plugin, other);
276 }
277 #endif
278
279 return plugin;
280 }
281
282
283 /******************************************
284 ************* non RT stuff ***************
285 ******************************************/
286
287
288 static int
plugin_open_plugin(plugin_desc_t * desc,void ** dl_handle_ptr,const LADSPA_Descriptor ** descriptor_ptr)289 plugin_open_plugin (plugin_desc_t * desc,
290 void ** dl_handle_ptr,
291 const LADSPA_Descriptor ** descriptor_ptr)
292 {
293 void * dl_handle;
294 const char * dlerr;
295 LADSPA_Descriptor_Function get_descriptor;
296
297 /* clear the error report */
298 dlerror ();
299
300 /* open the object file */
301 dl_handle = dlopen (desc->object_file, RTLD_NOW);
302 dlerr = dlerror ();
303 if (!dl_handle || dlerr)
304 {
305 if (!dlerr)
306 dlerr = "unknown error";
307 mlt_log_warning( NULL, "%s: error opening shared object file '%s': %s\n",
308 __FUNCTION__, desc->object_file, dlerr);
309 return 1;
310 }
311
312
313 /* get the get_descriptor function */
314 get_descriptor = (LADSPA_Descriptor_Function)
315 dlsym (dl_handle, "ladspa_descriptor");
316 dlerr = dlerror();
317 if (dlerr)
318 {
319 if (!dlerr)
320 dlerr = "unknown error";
321 mlt_log_warning( NULL, "%s: error finding descriptor symbol in object file '%s': %s\n",
322 __FUNCTION__, desc->object_file, dlerr);
323 dlclose (dl_handle);
324 return 1;
325 }
326
327 #ifdef __APPLE__
328 if (!get_descriptor (desc->index)) {
329 void (*constructor)(void) = dlsym (dl_handle, "_init");
330 if (constructor) constructor();
331 }
332 #endif
333
334 *descriptor_ptr = get_descriptor (desc->index);
335 if (!*descriptor_ptr)
336 {
337 mlt_log_warning( NULL, "%s: error finding index %lu in object file '%s'\n",
338 __FUNCTION__, desc->index, desc->object_file);
339 dlclose (dl_handle);
340 return 1;
341 }
342 *dl_handle_ptr = dl_handle;
343
344 return 0;
345 }
346
347 static int
plugin_instantiate(const LADSPA_Descriptor * descriptor,unsigned long plugin_index,gint copies,LADSPA_Handle * instances)348 plugin_instantiate (const LADSPA_Descriptor * descriptor,
349 unsigned long plugin_index,
350 gint copies,
351 LADSPA_Handle * instances)
352 {
353 gint i;
354
355 for (i = 0; i < copies; i++)
356 {
357 instances[i] = descriptor->instantiate (descriptor, sample_rate);
358
359 if (!instances[i])
360 {
361 unsigned long d;
362
363 for (d = 0; d < i; d++)
364 descriptor->cleanup (instances[d]);
365
366 return 1;
367 }
368 }
369
370 return 0;
371 }
372
373 #ifdef WITH_JACK
374
375 static void
plugin_create_aux_ports(plugin_t * plugin,guint copy,jack_rack_t * jack_rack)376 plugin_create_aux_ports (plugin_t * plugin, guint copy, jack_rack_t * jack_rack)
377 {
378 plugin_desc_t * desc;
379 // plugin_slot_t * slot;
380 unsigned long aux_channel = 1;
381 unsigned long plugin_index = 1;
382 unsigned long i;
383 char port_name[64];
384 char * plugin_name;
385 char * ptr;
386 // GList * list;
387 ladspa_holder_t * holder;
388
389 desc = plugin->desc;
390 holder = plugin->holders + copy;
391
392 holder->aux_ports = g_malloc (sizeof (jack_port_t *) * desc->aux_channels);
393
394 /* make the plugin name jack worthy */
395 ptr = plugin_name = g_strndup (plugin->desc->name, 7);
396 while (*ptr != '\0')
397 {
398 if (*ptr == ' ')
399 *ptr = '_';
400 else
401 *ptr = tolower (*ptr);
402
403 ptr++;
404 }
405
406 /*
407 for (list = jack_rack->slots; list; list = g_list_next (list))
408 {
409 slot = (plugin_slot_t *) list->data;
410
411 if (slot->plugin->desc->id == plugin->desc->id)
412 plugin_index++;
413 }
414 */
415
416 for (i = 0; i < desc->aux_channels; i++, aux_channel++)
417 {
418 sprintf (port_name, "%s_%ld-%d_%c%ld",
419 plugin_name,
420 plugin_index,
421 copy + 1,
422 desc->aux_are_input ? 'i' : 'o',
423 aux_channel);
424
425 holder->aux_ports[i] =
426 jack_port_register (jack_rack->procinfo->jack_client,
427 port_name,
428 JACK_DEFAULT_AUDIO_TYPE,
429 desc->aux_are_input ? JackPortIsInput : JackPortIsOutput,
430 0);
431
432 if (!holder->aux_ports[i])
433 {
434 mlt_log_panic( NULL, "Could not register jack port '%s'; aborting\n", port_name);
435 }
436 }
437
438 g_free (plugin_name);
439 }
440
441 #endif
442
443 static void
plugin_init_holder(plugin_t * plugin,guint copy,LADSPA_Handle instance,jack_rack_t * jack_rack)444 plugin_init_holder (plugin_t * plugin,
445 guint copy,
446 LADSPA_Handle instance,
447 jack_rack_t * jack_rack)
448 {
449 unsigned long i;
450 plugin_desc_t * desc;
451 ladspa_holder_t * holder;
452
453 desc = plugin->desc;
454 holder = plugin->holders + copy;
455
456 holder->instance = instance;
457
458 if (desc->control_port_count > 0)
459 {
460 holder->ui_control_fifos = g_malloc (sizeof (lff_t) * desc->control_port_count);
461 holder->control_memory = g_malloc (sizeof (LADSPA_Data) * desc->control_port_count);
462 }
463 else
464 {
465 holder->ui_control_fifos = NULL;
466 holder->control_memory = NULL;
467 }
468
469 for (i = 0; i < desc->control_port_count; i++)
470 {
471 lff_init (holder->ui_control_fifos + i, CONTROL_FIFO_SIZE, sizeof (LADSPA_Data));
472 holder->control_memory[i] =
473 plugin_desc_get_default_control_value (desc, desc->control_port_indicies[i], sample_rate);
474
475 plugin->descriptor->
476 connect_port (instance, desc->control_port_indicies[i], holder->control_memory + i);
477 }
478
479 if (desc->status_port_count > 0)
480 {
481 holder->status_memory = g_malloc (sizeof (LADSPA_Data) * desc->status_port_count);
482 }
483 else
484 {
485 holder->status_memory = NULL;
486 }
487
488 for (i = 0; i < desc->status_port_count; i++)
489 {
490 plugin->descriptor->
491 connect_port (instance, desc->status_port_indicies[i], holder->status_memory + i);
492 }
493
494 #ifdef WITH_JACK
495 if (jack_rack->procinfo->jack_client && plugin->desc->aux_channels > 0)
496 plugin_create_aux_ports (plugin, copy, jack_rack);
497 #endif
498
499 if (plugin->descriptor->activate)
500 plugin->descriptor->activate (instance);
501 }
502
503
504 plugin_t *
plugin_new(plugin_desc_t * desc,jack_rack_t * jack_rack)505 plugin_new (plugin_desc_t * desc, jack_rack_t * jack_rack)
506 {
507 void * dl_handle;
508 const LADSPA_Descriptor * descriptor;
509 LADSPA_Handle * instances;
510 gint copies;
511 unsigned long i;
512 int err;
513 plugin_t * plugin;
514
515 /* open the plugin */
516 err = plugin_open_plugin (desc, &dl_handle, &descriptor);
517 if (err)
518 return NULL;
519
520 /* create the instances */
521 copies = plugin_desc_get_copies (desc, jack_rack->channels);
522 instances = g_malloc (sizeof (LADSPA_Handle) * copies);
523
524 err = plugin_instantiate (descriptor, desc->index, copies, instances);
525 if (err)
526 {
527 g_free (instances);
528 dlclose (dl_handle);
529 return NULL;
530 }
531
532
533 plugin = g_malloc (sizeof (plugin_t));
534
535 plugin->descriptor = descriptor;
536 plugin->dl_handle = dl_handle;
537 plugin->desc = desc;
538 plugin->copies = copies;
539 plugin->enabled = FALSE;
540 plugin->next = NULL;
541 plugin->prev = NULL;
542 plugin->wet_dry_enabled = FALSE;
543 plugin->jack_rack = jack_rack;
544
545 /* create audio memory and wet/dry stuff */
546 plugin->audio_output_memory = g_malloc (sizeof (LADSPA_Data *) * jack_rack->channels);
547 plugin->wet_dry_fifos = g_malloc (sizeof (lff_t) * jack_rack->channels);
548 plugin->wet_dry_values = g_malloc (sizeof (LADSPA_Data) * jack_rack->channels);
549
550 for (i = 0; i < jack_rack->channels; i++)
551 {
552 plugin->audio_output_memory[i] = g_malloc (sizeof (LADSPA_Data) * buffer_size);
553 lff_init (plugin->wet_dry_fifos + i, CONTROL_FIFO_SIZE, sizeof (LADSPA_Data));
554 plugin->wet_dry_values[i] = 1.0;
555 }
556
557 /* create holders and fill them out */
558 plugin->holders = g_malloc (sizeof (ladspa_holder_t) * copies);
559 for (i = 0; i < copies; i++)
560 plugin_init_holder (plugin, i, instances[i], jack_rack);
561
562 return plugin;
563 }
564
565
566 void
plugin_destroy(plugin_t * plugin)567 plugin_destroy (plugin_t * plugin)
568 {
569 unsigned long i, j;
570 int err;
571
572 /* destroy holders */
573 for (i = 0; i < plugin->copies; i++)
574 {
575 if (plugin->descriptor->deactivate)
576 plugin->descriptor->deactivate (plugin->holders[i].instance);
577
578 /* if (plugin->descriptor->cleanup)
579 plugin->descriptor->cleanup (plugin->holders[i].instance); */
580
581 if (plugin->desc->control_port_count > 0)
582 {
583 for (j = 0; j < plugin->desc->control_port_count; j++)
584 {
585 lff_free (plugin->holders[i].ui_control_fifos + j);
586 }
587 g_free (plugin->holders[i].ui_control_fifos);
588 g_free (plugin->holders[i].control_memory);
589 }
590
591 if (plugin->desc->status_port_count > 0)
592 {
593 g_free (plugin->holders[i].status_memory);
594 }
595
596 #ifdef WITH_JACK
597 /* aux ports */
598 if (plugin->jack_rack->procinfo->jack_client && plugin->desc->aux_channels > 0)
599 {
600 for (j = 0; j < plugin->desc->aux_channels; j++)
601 {
602 err = jack_port_unregister (plugin->jack_rack->procinfo->jack_client,
603 plugin->holders[i].aux_ports[j]);
604
605 if (err)
606 mlt_log_warning( NULL, "%s: could not unregister jack port\n", __FUNCTION__);
607 }
608
609 g_free (plugin->holders[i].aux_ports);
610 }
611 #endif
612 }
613
614 g_free (plugin->holders);
615
616 for (i = 0; i < plugin->jack_rack->channels; i++)
617 {
618 g_free (plugin->audio_output_memory[i]);
619 lff_free (plugin->wet_dry_fifos + i);
620 }
621
622 g_free (plugin->audio_output_memory);
623 g_free (plugin->wet_dry_fifos);
624 g_free (plugin->wet_dry_values);
625
626 err = dlclose (plugin->dl_handle);
627 if (err)
628 {
629 mlt_log_warning( NULL, "%s: error closing shared object '%s': %s\n",
630 __FUNCTION__, plugin->desc->object_file, dlerror ());
631 }
632
633 g_free (plugin);
634 }
635
636
637 /* EOF */
638