1 /*
2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #include "zrythm-config.h"
21
22 #ifdef HAVE_CARLA
23
24 #include <math.h>
25 #include <stdlib.h>
26
27 #include "audio/engine.h"
28 #include "audio/midi_event.h"
29 #include "audio/tempo_track.h"
30 #include "audio/transport.h"
31 #include "gui/backend/event.h"
32 #include "gui/backend/event_manager.h"
33 #include "gui/widgets/main_window.h"
34 #include "plugins/cached_plugin_descriptors.h"
35 #include "plugins/lv2_plugin.h"
36 #include "plugins/plugin.h"
37 #include "plugins/plugin_manager.h"
38 #include "plugins/carla/carla_discovery.h"
39 #include "plugins/carla_native_plugin.h"
40 #include "project.h"
41 #include "settings/settings.h"
42 #include "utils/error.h"
43 #include "utils/file.h"
44 #include "utils/flags.h"
45 #include "utils/gtk.h"
46 #include "utils/io.h"
47 #include "utils/math.h"
48 #include "utils/objects.h"
49 #include "utils/string.h"
50 #include "zrythm.h"
51 #include "zrythm_app.h"
52
53 #include <gtk/gtk.h>
54 #ifdef HAVE_X11
55 #include <gtk/gtkx.h>
56 #endif
57 #include <glib/gi18n.h>
58
59 #include <CarlaHost.h>
60
61 typedef enum
62 {
63 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR_INSTANTIATION_FAILED,
64 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR_FAILED,
65 } ZPluginsCarlaNativePluginError;
66
67 #define Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR \
68 z_plugins_carla_native_plugin_error_quark ()
69 GQuark z_plugins_carla_native_plugin_error_quark (void);
70 G_DEFINE_QUARK (
71 z-plugins-carla-native-plugin-error-quark, z_plugins_carla_native_plugin_error)
72
73 static PluginType
get_plugin_type_from_protocol(PluginProtocol protocol)74 get_plugin_type_from_protocol (
75 PluginProtocol protocol)
76 {
77 switch (protocol)
78 {
79 case PROT_LV2:
80 return PLUGIN_LV2;
81 case PROT_AU:
82 return PLUGIN_AU;
83 case PROT_VST:
84 return PLUGIN_VST2;
85 case PROT_VST3:
86 return PLUGIN_VST3;
87 case PROT_SFZ:
88 return PLUGIN_SFZ;
89 case PROT_SF2:
90 return PLUGIN_SF2;
91 case PROT_DSSI:
92 return PLUGIN_DSSI;
93 case PROT_LADSPA:
94 return PLUGIN_LADSPA;
95 default:
96 g_return_val_if_reached (0);
97 }
98
99 g_return_val_if_reached (0);
100 }
101
102 void
carla_native_plugin_init_loaded(CarlaNativePlugin * self)103 carla_native_plugin_init_loaded (
104 CarlaNativePlugin * self)
105 {
106 }
107
108 /**
109 * Tick callback for the plugin UI.
110 */
111 static int
carla_plugin_tick_cb(GtkWidget * widget,GdkFrameClock * frame_clock,CarlaNativePlugin * self)112 carla_plugin_tick_cb (
113 GtkWidget * widget,
114 GdkFrameClock * frame_clock,
115 CarlaNativePlugin * self)
116 {
117 if (self->plugin->visible &&
118 MAIN_WINDOW)
119 {
120 self->native_plugin_descriptor->ui_idle (
121 self->native_plugin_handle);
122
123 return G_SOURCE_CONTINUE;
124 }
125 else
126 return G_SOURCE_REMOVE;
127 }
128
129 static uint32_t
host_get_buffer_size(NativeHostHandle handle)130 host_get_buffer_size (
131 NativeHostHandle handle)
132 {
133 uint32_t buffer_size = 512;
134 if (PROJECT && AUDIO_ENGINE &&
135 AUDIO_ENGINE->block_length > 0)
136 buffer_size =
137 (uint32_t) AUDIO_ENGINE->block_length;
138
139 return buffer_size;
140 }
141
142 static double
host_get_sample_rate(NativeHostHandle handle)143 host_get_sample_rate (
144 NativeHostHandle handle)
145 {
146 double sample_rate = 44000.0;
147 if (PROJECT && AUDIO_ENGINE &&
148 AUDIO_ENGINE->sample_rate > 0)
149 sample_rate =
150 (double) AUDIO_ENGINE->sample_rate;
151
152 return sample_rate;
153 }
154
155 static bool
host_is_offline(NativeHostHandle handle)156 host_is_offline (
157 NativeHostHandle handle)
158 {
159 if (!PROJECT || !AUDIO_ENGINE)
160 {
161 return true;
162 }
163
164 return !AUDIO_ENGINE->run;
165 }
166
167 static const NativeTimeInfo*
host_get_time_info(NativeHostHandle handle)168 host_get_time_info (
169 NativeHostHandle handle)
170 {
171 CarlaNativePlugin * plugin =
172 (CarlaNativePlugin *) handle;
173 return &plugin->time_info;
174 }
175
176 static bool
host_write_midi_event(NativeHostHandle handle,const NativeMidiEvent * event)177 host_write_midi_event (
178 NativeHostHandle handle,
179 const NativeMidiEvent * event)
180 {
181 /*g_message ("write midi event");*/
182
183 CarlaNativePlugin * self =
184 (CarlaNativePlugin *) handle;
185
186 Port * midi_out_port =
187 carla_native_plugin_get_midi_out_port (self);
188 g_return_val_if_fail (
189 IS_PORT_AND_NONNULL (midi_out_port), 0);
190
191 midi_byte_t buf[event->size];
192 for (int i = 0; i < event->size; i++)
193 {
194 buf[i] = event->data[i];
195 }
196 midi_events_add_event_from_buf (
197 midi_out_port->midi_events, event->time,
198 buf, event->size, false);
199
200 return 0;
201 }
202
203 static void
host_ui_parameter_changed(NativeHostHandle handle,uint32_t index,float value)204 host_ui_parameter_changed (
205 NativeHostHandle handle,
206 uint32_t index,
207 float value)
208 {
209 g_message ("handle ui param changed");
210 CarlaNativePlugin * self =
211 (CarlaNativePlugin *) handle;
212 Port * port =
213 carla_native_plugin_get_port_from_param_id (
214 self, index);
215 if (!port)
216 {
217 g_message (
218 "%s: no port found for param %u",
219 __func__, index);
220 return;
221 }
222
223 port_set_control_value (
224 port, value, false, false);
225 }
226
227 static void
host_ui_custom_data_changed(NativeHostHandle handle,const char * key,const char * value)228 host_ui_custom_data_changed (
229 NativeHostHandle handle,
230 const char* key,
231 const char* value)
232 {
233 }
234
235 static void
host_ui_closed(NativeHostHandle handle)236 host_ui_closed (
237 NativeHostHandle handle)
238 {
239 g_message ("ui closed");
240 }
241
242 static intptr_t
host_dispatcher(NativeHostHandle handle,NativeHostDispatcherOpcode opcode,int32_t index,intptr_t value,void * ptr,float opt)243 host_dispatcher (
244 NativeHostHandle handle,
245 NativeHostDispatcherOpcode opcode,
246 int32_t index,
247 intptr_t value,
248 void* ptr,
249 float opt)
250 {
251 /* TODO */
252 /*g_debug ("host dispatcher (opcode %d)", opcode);*/
253 switch (opcode)
254 {
255 case NATIVE_HOST_OPCODE_HOST_IDLE:
256 /*g_debug ("host idle");*/
257 /* some expensive computation is happening.
258 * this is used so that the GTK ui does not
259 * block */
260 /* note: disabled because some logic depends
261 * on this plugin being activated */
262 #if 0
263 while (gtk_events_pending ())
264 {
265 gtk_main_iteration ();
266 }
267 #endif
268 break;
269 #if 0
270 case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN:
271 /* falktx: you will need to call the new
272 * juce functions, then return 1 on the
273 * INTERNAL_PLUGIN host opcode.
274 * when that opcode returns 1, carla-plugin
275 * will let the host do the juce idling
276 * which is for the best here, since you want
277 * to show UIs without carla itself */
278 return 1;
279 break;
280 #endif
281 case NATIVE_HOST_OPCODE_GET_FILE_PATH:
282 g_debug ("get file path");
283 g_return_val_if_fail (ptr, 0);
284 if (string_is_equal ((char *) ptr, "carla"))
285 {
286 g_debug ("ptr is carla");
287 return (intptr_t) PROJECT->dir;
288 }
289 break;
290 case NATIVE_HOST_OPCODE_UI_RESIZE:
291 g_debug ("ui resize");
292 /* TODO handle UI resize */
293 break;
294 case NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER:
295 g_debug ("ui touch");
296 break;
297 case NATIVE_HOST_OPCODE_UI_UNAVAILABLE:
298 /* TODO handle UI close */
299 g_debug ("UI unavailable");
300 break;
301 default:
302 break;
303 }
304
305 return 0;
306 }
307
308 static void
engine_callback(void * ptr,EngineCallbackOpcode action,uint plugin_id,int val1,int val2,int val3,float valf,const char * val_str)309 engine_callback (
310 void * ptr,
311 EngineCallbackOpcode action,
312 uint plugin_id,
313 int val1,
314 int val2,
315 int val3,
316 float valf,
317 const char * val_str)
318 {
319 CarlaNativePlugin * self =
320 (CarlaNativePlugin *) ptr;
321
322 switch (action)
323 {
324 case ENGINE_CALLBACK_UI_STATE_CHANGED:
325 switch (val1)
326 {
327 case 0:
328 case -1:
329 self->plugin->visible = false;
330 self->plugin->visible = false;
331 break;
332 case 1:
333 self->plugin->visible = true;
334 break;
335 }
336 EVENTS_PUSH (
337 ET_PLUGIN_VISIBILITY_CHANGED,
338 self->plugin);
339 break;
340 case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
341 /* if plugin was deactivated and we didn't
342 * explicitly tell it to deactivate */
343 if (val1 == PARAMETER_ACTIVE
344 && val2 == 0 && val3 == 0
345 && self->plugin->activated
346 && !self->plugin->deactivating
347 && !self->loading_state)
348 {
349 /* send crash signal */
350 EVENTS_PUSH (
351 ET_PLUGIN_CRASHED, self->plugin);
352 }
353 break;
354 default:
355 break;
356 }
357 }
358
359 void
carla_native_plugin_populate_banks(CarlaNativePlugin * self)360 carla_native_plugin_populate_banks (
361 CarlaNativePlugin * self)
362 {
363 /* add default bank and preset */
364 PluginBank * pl_def_bank =
365 plugin_add_bank_if_not_exists (
366 self->plugin,
367 LV2_ZRYTHM__defaultBank,
368 _("Default bank"));
369 PluginPreset * pl_def_preset =
370 plugin_preset_new ();
371 pl_def_preset->uri =
372 g_strdup (LV2_ZRYTHM__initPreset);
373 pl_def_preset->name = g_strdup (_("Init"));
374 plugin_add_preset_to_bank (
375 self->plugin, pl_def_bank, pl_def_preset);
376
377 /*GString * presets_gstr = g_string_new (NULL);*/
378
379 uint32_t count =
380 carla_get_program_count (
381 self->host_handle, 0);
382 for (uint32_t i = 0; i < count; i++)
383 {
384 PluginPreset * pl_preset =
385 plugin_preset_new ();
386 pl_preset->carla_program = (int) i;
387 pl_preset->name =
388 g_strdup (
389 carla_get_program_name (
390 self->host_handle, 0, i));
391 plugin_add_preset_to_bank (
392 self->plugin, pl_def_bank, pl_preset);
393
394 #if 0
395 g_string_append_printf (
396 presets_gstr,
397 "found preset %s (%d)\n",
398 pl_preset->name, pl_preset->carla_program);
399 #endif
400 }
401
402 g_message ("found %d presets", count);
403
404 #if 0
405 char * str = g_string_free (presets_gstr, false);
406 g_message ("%s", str);
407 g_free (str);
408 #endif
409 }
410
411 bool
carla_native_plugin_has_custom_ui(const PluginDescriptor * descr)412 carla_native_plugin_has_custom_ui (
413 const PluginDescriptor * descr)
414 {
415 #if 0
416 CarlaNativePlugin * native_pl = _create (NULL);
417
418 /* instantiate the plugin to get its info */
419 native_pl->native_plugin_descriptor =
420 carla_get_native_rack_plugin ();
421 native_pl->native_plugin_handle =
422 native_pl->native_plugin_descriptor->instantiate (
423 &native_pl->native_host_descriptor);
424 native_pl->host_handle =
425 carla_create_native_plugin_host_handle (
426 native_pl->native_plugin_descriptor,
427 native_pl->native_plugin_handle);
428 PluginType type =
429 get_plugin_type_from_protocol (descr->protocol);
430 carla_add_plugin (
431 native_pl->host_handle,
432 descr->arch == ARCH_64 ?
433 BINARY_NATIVE : BINARY_WIN32,
434 type, descr->path, descr->name,
435 descr->uri, descr->unique_id, NULL, 0);
436 const CarlaPluginInfo * info =
437 carla_get_plugin_info (
438 native_pl->host_handle, 0);
439 g_return_val_if_fail (info, false);
440 bool has_custom_ui =
441 info->hints & PLUGIN_HAS_CUSTOM_UI;
442
443 carla_native_plugin_free (native_pl);
444
445 return has_custom_ui;
446 #endif
447 g_return_val_if_reached (false);
448 }
449
450 /**
451 * Processes the plugin for this cycle.
452 */
453 void
carla_native_plugin_process(CarlaNativePlugin * self,const long g_start_frames,const nframes_t local_offset,const nframes_t nframes)454 carla_native_plugin_process (
455 CarlaNativePlugin * self,
456 const long g_start_frames,
457 const nframes_t local_offset,
458 const nframes_t nframes)
459 {
460
461 self->time_info.playing =
462 TRANSPORT_IS_ROLLING;
463 self->time_info.frame =
464 (uint64_t) g_start_frames;
465 self->time_info.bbt.bar =
466 position_get_bars (PLAYHEAD, true);
467 self->time_info.bbt.beat =
468 position_get_beats (PLAYHEAD, true);
469 self->time_info.bbt.tick =
470 position_get_sixteenths (PLAYHEAD, true) *
471 TICKS_PER_SIXTEENTH_NOTE +
472 (int) floor (position_get_ticks (PLAYHEAD));
473 Position bar_start;
474 position_set_to_bar (
475 &bar_start,
476 position_get_bars (PLAYHEAD, true));
477 self->time_info.bbt.barStartTick =
478 (double)
479 (PLAYHEAD->ticks - bar_start.ticks);
480 int beats_per_bar =
481 tempo_track_get_beats_per_bar (P_TEMPO_TRACK);
482 int beat_unit =
483 tempo_track_get_beat_unit (P_TEMPO_TRACK);
484 self->time_info.bbt.beatsPerBar =
485 (float) beats_per_bar;
486 self->time_info.bbt.beatType = (float) beat_unit;
487 self->time_info.bbt.ticksPerBeat =
488 TRANSPORT->ticks_per_beat;
489 self->time_info.bbt.beatsPerMinute =
490 tempo_track_get_current_bpm (P_TEMPO_TRACK);
491
492 const PluginDescriptor * descr =
493 self->plugin->setting->descr;
494 switch (descr->protocol)
495 {
496 case PROT_LV2:
497 case PROT_VST:
498 case PROT_VST3:
499 case PROT_DSSI:
500 case PROT_LADSPA:
501 case PROT_AU:
502 case PROT_SFZ:
503 case PROT_SF2:
504 {
505 float * inbuf[2];
506 float dummy_inbuf1[nframes];
507 memset (
508 dummy_inbuf1, 0, nframes * sizeof (float));
509 float dummy_inbuf2[nframes];
510 memset (
511 dummy_inbuf2, 0, nframes * sizeof (float));
512 float * outbuf[2];
513 float dummy_outbuf1[nframes];
514 memset (
515 dummy_outbuf1, 0, nframes * sizeof (float));
516 float dummy_outbuf2[nframes];
517 memset (
518 dummy_outbuf2, 0, nframes * sizeof (float));
519 int i = 0;
520 int audio_ports = 0;
521 while (i < self->plugin->num_in_ports)
522 {
523 Port * port = self->plugin->in_ports[i];
524 if (port->id.type == TYPE_AUDIO)
525 {
526 inbuf[audio_ports++] =
527 &self->plugin->in_ports[i]->buf[
528 local_offset];
529 }
530 if (audio_ports == 2)
531 break;
532 i++;
533 }
534 switch (audio_ports)
535 {
536 case 0:
537 inbuf[0] = dummy_inbuf1;
538 inbuf[1] = dummy_inbuf2;
539 break;
540 case 1:
541 inbuf[1] = dummy_inbuf2;
542 break;
543 default:
544 break;
545 }
546
547 i = 0;
548 audio_ports = 0;
549 while (i < self->plugin->num_out_ports)
550 {
551 Port * port = self->plugin->out_ports[i];
552 if (port->id.type == TYPE_AUDIO)
553 {
554 outbuf[audio_ports++] =
555 &self->plugin->out_ports[i]->buf[
556 local_offset];
557 }
558 if (audio_ports == 2)
559 break;
560 i++;
561 }
562 switch (audio_ports)
563 {
564 case 0:
565 outbuf[0] = dummy_outbuf1;
566 outbuf[1] = dummy_outbuf2;
567 break;
568 case 1:
569 outbuf[1] = dummy_outbuf2;
570 break;
571 default:
572 break;
573 }
574
575 /* get main midi port */
576 Port * port = NULL;
577 for (i = 0;
578 i < self->plugin->num_in_ports; i++)
579 {
580 port = self->plugin->in_ports[i];
581 if (port->id.type == TYPE_EVENT &&
582 port->id.flags2 &
583 PORT_FLAG2_SUPPORTS_MIDI)
584 {
585 break;
586 }
587 else
588 port = NULL;
589 }
590
591 int num_events =
592 port ? port->midi_events->num_events : 0;
593 #define MAX_EVENTS 4000
594 NativeMidiEvent events[MAX_EVENTS];
595 int num_events_written = 0;
596 for (i = 0; i < num_events; i++)
597 {
598 MidiEvent * ev =
599 &port->midi_events->events[i];
600 if (ev->time < local_offset ||
601 ev->time >= local_offset + nframes)
602 {
603 /* skip events scheduled
604 * for another split within
605 * the processing cycle */
606 continue;
607 }
608
609 #if 0
610 g_message (
611 "writing plugin input event %d "
612 "at time %u - "
613 "local frames %u nframes %u",
614 num_events_written,
615 ev->time - local_offset,
616 local_offset, nframes);
617 midi_event_print (ev);
618 #endif
619
620 /* event time is relative to the current
621 * zrythm full cycle (not split). it
622 * needs to be made relative to the
623 * current split */
624 events[num_events_written].time =
625 ev->time - local_offset;
626 events[num_events_written].size = 3;
627 events[num_events_written].data[0] =
628 ev->raw_buffer[0];
629 events[num_events_written].data[1] =
630 ev->raw_buffer[1];
631 events[num_events_written].data[2] =
632 ev->raw_buffer[2];
633 num_events_written++;
634
635 if (num_events_written == MAX_EVENTS)
636 {
637 g_warning (
638 "written %d events", MAX_EVENTS);
639 break;
640 }
641 }
642 if (num_events_written > 0)
643 {
644 #if 0
645 g_message (
646 "Carla plugin %s has %d MIDI events",
647 self->plugin->descr->name,
648 num_events_written);
649 #endif
650 }
651
652 /*g_warn_if_reached ();*/
653 self->native_plugin_descriptor->process (
654 self->native_plugin_handle, inbuf, outbuf,
655 nframes, events,
656 (uint32_t) num_events_written);
657 }
658 break;
659 default:
660 break;
661 }
662 }
663
664 static ZPluginCategory
carla_category_to_zrythm_category(int category)665 carla_category_to_zrythm_category (
666 int category)
667 {
668 switch (category)
669 {
670 case PLUGIN_CATEGORY_NONE:
671 return ZPLUGIN_CATEGORY_NONE;
672 break;
673 case PLUGIN_CATEGORY_SYNTH:
674 return PC_INSTRUMENT;
675 break;
676 case PLUGIN_CATEGORY_DELAY:
677 return PC_DELAY;
678 break;
679 case PLUGIN_CATEGORY_EQ:
680 return PC_EQ;
681 break;
682 case PLUGIN_CATEGORY_FILTER:
683 return PC_FILTER;
684 break;
685 case PLUGIN_CATEGORY_DISTORTION:
686 return PC_DISTORTION;
687 break;
688 case PLUGIN_CATEGORY_DYNAMICS:
689 return PC_DYNAMICS;
690 break;
691 case PLUGIN_CATEGORY_MODULATOR:
692 return PC_MODULATOR;
693 break;
694 case PLUGIN_CATEGORY_UTILITY:
695 return PC_UTILITY;
696 break;
697 case PLUGIN_CATEGORY_OTHER:
698 return ZPLUGIN_CATEGORY_NONE;
699 break;
700 }
701 g_return_val_if_reached (ZPLUGIN_CATEGORY_NONE);
702 }
703
704 static char *
carla_category_to_zrythm_category_str(int category)705 carla_category_to_zrythm_category_str (
706 int category)
707 {
708 switch (category)
709 {
710 case PLUGIN_CATEGORY_SYNTH:
711 return g_strdup ("Instrument");
712 break;
713 case PLUGIN_CATEGORY_DELAY:
714 return g_strdup ("Delay");
715 break;
716 case PLUGIN_CATEGORY_EQ:
717 return g_strdup ("Equalizer");
718 break;
719 case PLUGIN_CATEGORY_FILTER:
720 return g_strdup ("Filter");
721 break;
722 case PLUGIN_CATEGORY_DISTORTION:
723 return g_strdup ("Distortion");
724 break;
725 case PLUGIN_CATEGORY_DYNAMICS:
726 return g_strdup ("Dynamics");
727 break;
728 case PLUGIN_CATEGORY_MODULATOR:
729 return g_strdup ("Modulator");
730 break;
731 case PLUGIN_CATEGORY_UTILITY:
732 return g_strdup ("Utility");
733 break;
734 case PLUGIN_CATEGORY_OTHER:
735 case PLUGIN_CATEGORY_NONE:
736 default:
737 return g_strdup ("Plugin");
738 break;
739 }
740 g_return_val_if_reached (NULL);
741 }
742
743 /**
744 * Returns a filled in descriptor from the
745 * CarlaCachedPluginInfo.
746 */
747 PluginDescriptor *
carla_native_plugin_get_descriptor_from_cached(const CarlaCachedPluginInfo * info,PluginType type)748 carla_native_plugin_get_descriptor_from_cached (
749 const CarlaCachedPluginInfo * info,
750 PluginType type)
751 {
752 PluginDescriptor * descr =
753 plugin_descriptor_new ();
754
755 switch (type)
756 {
757 #if 0
758 case PLUGIN_INTERNAL:
759 descr->protocol = PROT_CARLA_INTERNAL;
760 break;
761 case PLUGIN_LADSPA:
762 descr->protocol = PROT_LADSPA;
763 break;
764 case PLUGIN_DSSI:
765 descr->protocol = PROT_DSSI;
766 break;
767 #endif
768 case PLUGIN_LV2:
769 descr->protocol = PROT_LV2;
770 break;
771 case PLUGIN_VST2:
772 descr->protocol = PROT_VST;
773 break;
774 #if 0
775 case PLUGIN_SF2:
776 descr->protocol = PROT_SF2;
777 break;
778 case PLUGIN_SFZ:
779 descr->protocol = PROT_SFZ;
780 break;
781 case PLUGIN_JACK:
782 descr->protocol = PROT_JACK;
783 break;
784 #endif
785 default:
786 g_warn_if_reached ();
787 break;
788 }
789 descr->name =
790 g_strdup (info->name);
791 descr->author =
792 g_strdup (info->maker);
793 descr->num_audio_ins = (int) info->audioIns;
794 descr->num_audio_outs = (int) info->audioOuts;
795 descr->num_midi_ins = (int) info->midiIns;
796 descr->num_midi_outs = (int) info->midiOuts;
797 descr->num_ctrl_ins = (int) info->parameterIns;
798 descr->num_ctrl_outs = (int) info->parameterOuts;
799
800 descr->category =
801 carla_category_to_zrythm_category (
802 info->category);
803 descr->category_str =
804 carla_category_to_zrythm_category_str (
805 info->category);
806 descr->min_bridge_mode =
807 plugin_descriptor_get_min_bridge_mode (descr);
808 descr->has_custom_ui =
809 info->hints & PLUGIN_HAS_CUSTOM_UI;
810
811 return descr;
812 }
813
814 /**
815 * Creates an instance of a CarlaNativePlugin inside
816 * the given Plugin.
817 *
818 * The given Plugin must have its descriptor
819 * filled in.
820 *
821 * @return Non-zero if fail.
822 */
823 int
carla_native_plugin_new_from_setting(Plugin * plugin,GError ** error)824 carla_native_plugin_new_from_setting (
825 Plugin * plugin,
826 GError ** error)
827 {
828 g_return_val_if_fail (
829 plugin->setting->open_with_carla, -1);
830
831 CarlaNativePlugin * self =
832 object_new (CarlaNativePlugin);
833
834 plugin->carla = self;
835 self->plugin = plugin;
836
837 return 0;
838 }
839
840 static void
create_ports(CarlaNativePlugin * self,bool loading)841 create_ports (
842 CarlaNativePlugin * self,
843 bool loading)
844 {
845 g_debug ("%s: loading: %d", __func__, loading);
846
847 char tmp[500];
848 char name[4000];
849
850 const PluginDescriptor * descr =
851 self->plugin->setting->descr;
852 if (!loading)
853 {
854 for (int i = 0; i < descr->num_audio_ins; i++)
855 {
856 strcpy (tmp, _("Audio in"));
857 sprintf (name, "%s %d", tmp, i);
858 Port * port =
859 port_new_with_type (
860 TYPE_AUDIO, FLOW_INPUT, name);
861 plugin_add_in_port (
862 self->plugin, port);
863 }
864 for (int i = 0; i < descr->num_audio_outs; i++)
865 {
866 strcpy (tmp, _("Audio out"));
867 sprintf (name, "%s %d", tmp, i);
868 Port * port =
869 port_new_with_type (
870 TYPE_AUDIO, FLOW_OUTPUT, name);
871 plugin_add_out_port (
872 self->plugin, port);
873 }
874 for (int i = 0; i < descr->num_midi_ins; i++)
875 {
876 strcpy (tmp, _("MIDI in"));
877 sprintf (name, "%s %d", tmp, i);
878 Port * port =
879 port_new_with_type (
880 TYPE_EVENT, FLOW_INPUT, name);
881 port->id.flags2 |=
882 PORT_FLAG2_SUPPORTS_MIDI;
883 plugin_add_in_port (
884 self->plugin, port);
885 }
886 for (int i = 0; i < descr->num_midi_outs; i++)
887 {
888 strcpy (tmp, _("MIDI out"));
889 sprintf (name, "%s %d", tmp, i);
890 Port * port =
891 port_new_with_type (
892 TYPE_EVENT, FLOW_OUTPUT, name);
893 port->id.flags2 |=
894 PORT_FLAG2_SUPPORTS_MIDI;
895 plugin_add_out_port (
896 self->plugin, port);
897 }
898 for (int i = 0; i < descr->num_cv_ins; i++)
899 {
900 strcpy (tmp, _("CV in"));
901 sprintf (name, "%s %d", tmp, i);
902 Port * port =
903 port_new_with_type (
904 TYPE_CV, FLOW_INPUT, name);
905 plugin_add_in_port (
906 self->plugin, port);
907 }
908 for (int i = 0; i < descr->num_cv_outs; i++)
909 {
910 strcpy (tmp, _("CV out"));
911 sprintf (name, "%s %d", tmp, i);
912 Port * port =
913 port_new_with_type (
914 TYPE_CV, FLOW_OUTPUT, name);
915 plugin_add_out_port (
916 self->plugin, port);
917 }
918 }
919
920 /* create controls */
921 const CarlaPortCountInfo * param_counts =
922 carla_get_parameter_count_info (
923 self->host_handle, 0);
924 #if 0
925 /* FIXME eventually remove this line. this is added
926 * because carla discovery reports 0 params for
927 * AU plugins, so we update the descriptor here */
928 descr->num_ctrl_ins = (int) param_counts->ins;
929 g_message (
930 "params: %d ins and %d outs",
931 descr->num_ctrl_ins, (int) param_counts->outs);
932 #endif
933 for (uint32_t i = 0; i < param_counts->ins; i++)
934 {
935 Port * port = NULL;
936 if (loading)
937 {
938 port =
939 carla_native_plugin_get_port_from_param_id (
940 self, i);
941 g_return_if_fail (
942 IS_PORT_AND_NONNULL (port));
943 }
944 /* else if not loading (create new ports) */
945 else
946 {
947 const CarlaParameterInfo * param_info =
948 carla_get_parameter_info (
949 self->host_handle, 0, i);
950 port =
951 port_new_with_type (
952 TYPE_CONTROL, FLOW_INPUT,
953 param_info->name);
954 g_return_if_fail (
955 IS_PORT_AND_NONNULL (port));
956 if (param_info->symbol &&
957 strlen (param_info->symbol) > 0)
958 {
959 port->id.sym =
960 g_strdup (param_info->symbol);
961 }
962 port->id.flags |=
963 PORT_FLAG_PLUGIN_CONTROL;
964 if (param_info->comment &&
965 strlen (param_info->comment) > 0)
966 {
967 port->id.comment =
968 g_strdup (param_info->comment);
969 }
970 if (param_info->groupName &&
971 strlen (param_info->groupName) > 0)
972 {
973 port->id.port_group =
974 string_get_substr_before_suffix (
975 param_info->groupName, ":");
976 g_return_if_fail (
977 port->id.port_group);
978 }
979 port->carla_param_id = (int) i;
980
981 const NativeParameter * native_param =
982 self->native_plugin_descriptor->
983 get_parameter_info (
984 self->native_plugin_handle, i);
985 g_return_if_fail (native_param);
986 if (native_param->hints &
987 NATIVE_PARAMETER_IS_LOGARITHMIC)
988 {
989 port->id.flags |=
990 PORT_FLAG_LOGARITHMIC;
991 }
992 if (native_param->hints &
993 NATIVE_PARAMETER_IS_AUTOMABLE)
994 {
995 port->id.flags |=
996 PORT_FLAG_AUTOMATABLE;
997 }
998 if (native_param->hints &
999 NATIVE_PARAMETER_IS_BOOLEAN)
1000 {
1001 port->id.flags |= PORT_FLAG_TOGGLE;
1002 }
1003 else if (native_param->hints &
1004 NATIVE_PARAMETER_IS_INTEGER)
1005 {
1006 port->id.flags |= PORT_FLAG_INTEGER;
1007 }
1008
1009 /* get scale points */
1010 if (param_info->scalePointCount > 0)
1011 {
1012 port->scale_points =
1013 object_new_n (
1014 param_info->scalePointCount,
1015 PortScalePoint);
1016 port->num_scale_points =
1017 (int) param_info->scalePointCount;
1018 }
1019 for (uint32_t j = 0;
1020 j < param_info->scalePointCount; j++)
1021 {
1022 const CarlaScalePointInfo *
1023 scale_point_info =
1024 carla_get_parameter_scalepoint_info (
1025 self->host_handle, 0, i, j);
1026
1027 port->scale_points[j] =
1028 port_scale_point_new (
1029 scale_point_info->value,
1030 scale_point_info->label);
1031 }
1032 qsort (
1033 port->scale_points,
1034 (size_t) port->num_scale_points,
1035 sizeof (PortScalePoint *),
1036 port_scale_point_cmp);
1037
1038 plugin_add_in_port (
1039 self->plugin, port);
1040
1041 for (uint32_t j = 0;
1042 j < param_info->scalePointCount; j++)
1043 {
1044 const CarlaScalePointInfo * sp_info =
1045 carla_get_parameter_scalepoint_info (
1046 self->host_handle, 0, i, j);
1047 g_debug (
1048 "scale point: %s", sp_info->label);
1049 }
1050
1051 const ParameterRanges * ranges =
1052 carla_get_parameter_ranges (
1053 self->host_handle, 0, i);
1054 port->deff = ranges->def;
1055 port->minf = ranges->min;
1056 port->maxf = ranges->max;
1057 #if 0
1058 g_debug (
1059 "ranges: min %f max %f default %f",
1060 (double) port->minf,
1061 (double) port->maxf,
1062 (double) port->deff);
1063 #endif
1064 }
1065 float cur_val =
1066 carla_native_plugin_get_param_value (
1067 self, i);
1068 g_debug (
1069 "%d: %s=%f%s", i, port->id.label,
1070 (double) cur_val,
1071 loading ? " (loading)" : "");
1072 port_set_control_value (
1073 port, cur_val, F_NOT_NORMALIZED,
1074 F_NO_PUBLISH_EVENTS);
1075 }
1076
1077 self->ports_created = true;
1078 }
1079
1080 /**
1081 * Instantiates the plugin.
1082 *
1083 * @param loading Whether loading an existing plugin
1084 * or not.
1085 * @param use_state_file Whether to use the plugin's
1086 * state file to instantiate the plugin.
1087 *
1088 * @return 0 if no errors, non-zero if errors.
1089 */
1090 int
carla_native_plugin_instantiate(CarlaNativePlugin * self,bool loading,bool use_state_file,GError ** error)1091 carla_native_plugin_instantiate (
1092 CarlaNativePlugin * self,
1093 bool loading,
1094 bool use_state_file,
1095 GError ** error)
1096 {
1097 g_debug (
1098 "loading: %i, use state file: %d, "
1099 "ports_created: %d",
1100 loading, use_state_file, self->ports_created);
1101
1102 self->native_host_descriptor.handle = self;
1103 self->native_host_descriptor.uiName =
1104 g_strdup ("Zrythm");
1105
1106 self->native_host_descriptor.uiParentId = 0;
1107
1108 /* set resources dir */
1109 const char * carla_filename =
1110 carla_get_library_filename ();
1111 char * tmp = io_get_dir (carla_filename);
1112 char * dir = io_get_dir (tmp);
1113 g_free (tmp);
1114 tmp = io_get_dir (dir);
1115 g_free (dir);
1116 dir = tmp;
1117 self->native_host_descriptor.resourceDir =
1118 g_build_filename (
1119 dir, "share", "carla", "resources", NULL);
1120 g_free (dir);
1121
1122 self->native_host_descriptor.get_buffer_size =
1123 host_get_buffer_size;
1124 self->native_host_descriptor.get_sample_rate =
1125 host_get_sample_rate;
1126 self->native_host_descriptor.is_offline =
1127 host_is_offline;
1128 self->native_host_descriptor.get_time_info =
1129 host_get_time_info;
1130 self->native_host_descriptor.write_midi_event =
1131 host_write_midi_event;
1132 self->native_host_descriptor.
1133 ui_parameter_changed =
1134 host_ui_parameter_changed;
1135 self->native_host_descriptor.
1136 ui_custom_data_changed =
1137 host_ui_custom_data_changed;
1138 self->native_host_descriptor.ui_closed =
1139 host_ui_closed;
1140 self->native_host_descriptor.ui_open_file =
1141 NULL;
1142 self->native_host_descriptor.ui_save_file =
1143 NULL;
1144 self->native_host_descriptor.dispatcher = host_dispatcher;
1145
1146 self->time_info.bbt.valid = 1;
1147
1148 /* instantiate the plugin to get its info */
1149 self->native_plugin_descriptor =
1150 carla_get_native_rack_plugin ();
1151 self->native_plugin_handle =
1152 self->native_plugin_descriptor->instantiate (
1153 &self->native_host_descriptor);
1154 self->host_handle =
1155 carla_create_native_plugin_host_handle (
1156 self->native_plugin_descriptor,
1157 self->native_plugin_handle);
1158 self->carla_plugin_id = 0;
1159
1160 /* set binary paths */
1161 char * zrythm_libdir =
1162 zrythm_get_dir (
1163 ZRYTHM_DIR_SYSTEM_ZRYTHM_LIBDIR);
1164 char * carla_binaries_dir =
1165 g_build_filename (
1166 zrythm_libdir, "carla", NULL);
1167 g_message (
1168 "setting carla engine option "
1169 "[ENGINE_OPTION_PATH_BINARIES] to '%s'",
1170 carla_binaries_dir);
1171 carla_set_engine_option (
1172 self->host_handle,
1173 ENGINE_OPTION_PATH_BINARIES, 0,
1174 carla_binaries_dir);
1175 g_free (zrythm_libdir);
1176 g_free (carla_binaries_dir);
1177
1178 /* set lv2 path */
1179 carla_set_engine_option (
1180 self->host_handle,
1181 ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2,
1182 PLUGIN_MANAGER->lv2_path);
1183
1184 /* set UI scale factor */
1185 carla_set_engine_option (
1186 self->host_handle,
1187 ENGINE_OPTION_FRONTEND_UI_SCALE,
1188 (int)
1189 ((float) self->plugin->ui_scale_factor *
1190 1000.f),
1191 NULL);
1192
1193 /* set whether UI should stay on top */
1194 carla_set_engine_option (
1195 self->host_handle,
1196 ENGINE_OPTION_FRONTEND_UI_SCALE,
1197 (int)
1198 ((float) self->plugin->ui_scale_factor *
1199 1000.f),
1200 NULL);
1201
1202 if (!ZRYTHM_TESTING &&
1203 g_settings_get_boolean (
1204 S_P_PLUGINS_UIS, "stay-on-top"))
1205 {
1206 carla_set_engine_option (
1207 self->host_handle,
1208 ENGINE_OPTION_UIS_ALWAYS_ON_TOP, true,
1209 NULL);
1210 }
1211
1212 const PluginSetting * setting =
1213 self->plugin->setting;
1214 g_return_val_if_fail (
1215 setting->open_with_carla, -1);
1216 const PluginDescriptor * descr = setting->descr;
1217 g_message (
1218 "%s: using bridge mode %s", __func__,
1219 carla_bridge_mode_strings[
1220 setting->bridge_mode].str);
1221
1222 /* set bridging on if needed */
1223 switch (setting->bridge_mode)
1224 {
1225 case CARLA_BRIDGE_FULL:
1226 g_message (
1227 "plugin must be bridged whole, "
1228 "using plugin bridge");
1229 carla_set_engine_option (
1230 self->host_handle,
1231 ENGINE_OPTION_PREFER_PLUGIN_BRIDGES,
1232 true, NULL);
1233 break;
1234 case CARLA_BRIDGE_UI:
1235 g_message ("using UI bridge only");
1236 carla_set_engine_option (
1237 self->host_handle,
1238 ENGINE_OPTION_PREFER_UI_BRIDGES,
1239 true, NULL);
1240 break;
1241 default:
1242 break;
1243 }
1244
1245 /* raise bridge timeout to 8 sec */
1246 if (setting->bridge_mode == CARLA_BRIDGE_FULL ||
1247 setting->bridge_mode == CARLA_BRIDGE_UI)
1248 {
1249 carla_set_engine_option (
1250 self->host_handle,
1251 ENGINE_OPTION_UI_BRIDGES_TIMEOUT,
1252 8000, NULL);
1253 }
1254
1255 const PluginType type =
1256 get_plugin_type_from_protocol (descr->protocol);
1257 int ret = 0;
1258 switch (descr->protocol)
1259 {
1260 case PROT_LV2:
1261 case PROT_AU:
1262 g_message ("uri %s", descr->uri);
1263 ret =
1264 carla_add_plugin (
1265 self->host_handle,
1266 descr->arch == ARCH_64 ?
1267 BINARY_NATIVE : BINARY_WIN32,
1268 type, NULL, descr->name,
1269 descr->uri, 0, NULL, 0);
1270 break;
1271 case PROT_VST:
1272 case PROT_VST3:
1273 ret =
1274 carla_add_plugin (
1275 self->host_handle,
1276 descr->arch == ARCH_64 ?
1277 BINARY_NATIVE : BINARY_WIN32,
1278 type, descr->path, descr->name,
1279 descr->name, descr->unique_id, NULL, 0);
1280 break;
1281 case PROT_DSSI:
1282 case PROT_LADSPA:
1283 ret =
1284 carla_add_plugin (
1285 self->host_handle, BINARY_NATIVE,
1286 type, descr->path, descr->name,
1287 descr->uri, 0, NULL, 0);
1288 break;
1289 case PROT_SFZ:
1290 case PROT_SF2:
1291 ret =
1292 carla_add_plugin (
1293 self->host_handle,
1294 BINARY_NATIVE,
1295 type, descr->path, descr->name,
1296 descr->name, 0, NULL, 0);
1297 break;
1298 default:
1299 g_warn_if_reached ();
1300 break;
1301 }
1302
1303 if (ret != 1)
1304 {
1305 g_set_error (
1306 error,
1307 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR,
1308 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR_INSTANTIATION_FAILED,
1309 _("Error adding carla plugin: %s"),
1310 carla_get_last_error (self->host_handle));
1311 return -1;
1312 }
1313
1314 /* enable various messages */
1315 #define ENABLE_OPTION(x) \
1316 carla_set_option ( \
1317 self->host_handle, 0, \
1318 PLUGIN_OPTION_##x, true)
1319
1320 ENABLE_OPTION (FORCE_STEREO);
1321 ENABLE_OPTION (SEND_CONTROL_CHANGES);
1322 ENABLE_OPTION (SEND_CHANNEL_PRESSURE);
1323 ENABLE_OPTION (SEND_NOTE_AFTERTOUCH);
1324 ENABLE_OPTION (SEND_PITCHBEND);
1325 ENABLE_OPTION (SEND_ALL_SOUND_OFF);
1326 ENABLE_OPTION (SEND_PROGRAM_CHANGES);
1327
1328 #undef ENABLE_OPTION
1329
1330 /* add engine callback */
1331 carla_set_engine_callback (
1332 self->host_handle, engine_callback, self);
1333
1334 if (use_state_file)
1335 {
1336 /* load the state */
1337 GError * err = NULL;
1338 bool state_loaded =
1339 carla_native_plugin_load_state (
1340 self->plugin->carla, NULL, &err);
1341 if (!state_loaded)
1342 {
1343 PROPAGATE_PREFIXED_ERROR (
1344 error, err, "%s",
1345 _("Failed to load Carla state"));
1346 self->plugin->instantiation_failed =
1347 true;
1348 return -1;
1349 }
1350 }
1351
1352 if (!self->native_plugin_handle
1353 || !self->native_plugin_descriptor->activate
1354 || !self->native_plugin_descriptor->ui_show)
1355 {
1356 g_set_error (
1357 error, Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR,
1358 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR_INSTANTIATION_FAILED,
1359 "%s",
1360 _("Failed to instantiate Carla plugin: "
1361 "handle/descriptor not initialized "
1362 "properly"));
1363 self->plugin->instantiation_failed =
1364 true;
1365 return -1;
1366 }
1367
1368 /* create ports */
1369 if (!loading && !use_state_file &&
1370 !self->ports_created)
1371 {
1372 create_ports (self, false);
1373 }
1374
1375 g_message ("activating carla plugin...");
1376 self->native_plugin_descriptor->activate (
1377 self->native_plugin_handle);
1378 g_message ("carla plugin activated");
1379
1380 /* load data into existing ports */
1381 if (loading || use_state_file)
1382 {
1383 create_ports (self, true);
1384 }
1385
1386 return 0;
1387 }
1388
1389 static void
carla_plugin_tick_cb_destroy(void * data)1390 carla_plugin_tick_cb_destroy (
1391 void * data)
1392 {
1393 g_return_if_fail (data);
1394 CarlaNativePlugin * self =
1395 (CarlaNativePlugin *) data;
1396
1397 self->tick_cb = 0;
1398 }
1399
1400 /**
1401 * Shows or hides the UI.
1402 */
1403 void
carla_native_plugin_open_ui(CarlaNativePlugin * self,bool show)1404 carla_native_plugin_open_ui (
1405 CarlaNativePlugin * self,
1406 bool show)
1407 {
1408 Plugin * pl = self->plugin;
1409 g_return_if_fail (IS_PLUGIN_AND_NONNULL (pl));
1410 g_return_if_fail (
1411 plugin_is_in_active_project (pl));
1412 g_return_if_fail (pl->setting->descr);
1413
1414 g_message (
1415 "%s: show/hide '%s (%p)' UI: %d",
1416 __func__, pl->setting->descr->name, pl, show);
1417
1418 if ((self->tick_cb == 0 && !show)
1419 || (self->tick_cb != 0 && show))
1420 {
1421 g_message (
1422 "plugin already has visibility status %d, "
1423 "doing nothing",
1424 show);
1425 return;
1426 }
1427
1428 switch (pl->setting->descr->protocol)
1429 {
1430 case PROT_VST:
1431 case PROT_VST3:
1432 case PROT_DSSI:
1433 case PROT_LV2:
1434 case PROT_AU:
1435 if (show)
1436 {
1437 char * title =
1438 plugin_generate_window_title (pl);
1439 g_debug ("plugin window title '%s'", title);
1440 carla_set_custom_ui_title (
1441 self->host_handle, 0, title);
1442 g_free (title);
1443
1444 /* set whether to keep window on top */
1445 if (ZRYTHM_HAVE_UI &&
1446 g_settings_get_boolean (
1447 S_P_PLUGINS_UIS, "stay-on-top"))
1448 {
1449 #ifdef HAVE_X11
1450 char xid[400];
1451 sprintf (
1452 xid, "%lx",
1453 gdk_x11_window_get_xid (
1454 gtk_widget_get_window (
1455 GTK_WIDGET (MAIN_WINDOW))));
1456 carla_set_engine_option (
1457 self->host_handle,
1458 ENGINE_OPTION_FRONTEND_WIN_ID, 0,
1459 xid);
1460 #endif
1461 }
1462 }
1463
1464 carla_show_custom_ui (
1465 self->host_handle, 0, show);
1466 pl->visible = show;
1467
1468 if (self->tick_cb)
1469 {
1470 g_debug (
1471 "removing tick callback for %s",
1472 pl->setting->descr->name);
1473 gtk_widget_remove_tick_callback (
1474 GTK_WIDGET (MAIN_WINDOW),
1475 self->tick_cb);
1476 self->tick_cb = 0;
1477 }
1478
1479 if (show)
1480 {
1481 g_return_if_fail (MAIN_WINDOW);
1482 g_debug (
1483 "setting tick callback for %s",
1484 pl->setting->descr->name);
1485 self->tick_cb =
1486 gtk_widget_add_tick_callback (
1487 GTK_WIDGET (MAIN_WINDOW),
1488 (GtkTickCallback)
1489 carla_plugin_tick_cb,
1490 self,
1491 carla_plugin_tick_cb_destroy);
1492 }
1493
1494 if (!ZRYTHM_TESTING)
1495 {
1496 EVENTS_PUSH (
1497 ET_PLUGIN_WINDOW_VISIBILITY_CHANGED,
1498 pl);
1499 }
1500 break;
1501 default:
1502 break;
1503 }
1504 }
1505
1506 int
carla_native_plugin_activate(CarlaNativePlugin * self,bool activate)1507 carla_native_plugin_activate (
1508 CarlaNativePlugin * self,
1509 bool activate)
1510 {
1511 g_message ("setting plugin %s active %d",
1512 self->plugin->setting->descr->name, activate);
1513 carla_set_active (
1514 self->host_handle, 0, activate);
1515
1516 return 0;
1517 }
1518
1519 float
carla_native_plugin_get_param_value(CarlaNativePlugin * self,const uint32_t id)1520 carla_native_plugin_get_param_value (
1521 CarlaNativePlugin * self,
1522 const uint32_t id)
1523 {
1524 return
1525 carla_get_current_parameter_value (
1526 self->host_handle, 0, id);
1527 }
1528
1529 /**
1530 * Called from port_set_control_value() to send
1531 * the value to carla.
1532 *
1533 * @param val Real value (ie, not normalized).
1534 */
1535 void
carla_native_plugin_set_param_value(CarlaNativePlugin * self,const uint32_t id,float val)1536 carla_native_plugin_set_param_value (
1537 CarlaNativePlugin * self,
1538 const uint32_t id,
1539 float val)
1540 {
1541 if (self->plugin->instantiation_failed)
1542 {
1543 return;
1544 }
1545
1546 float cur_val =
1547 carla_get_current_parameter_value (
1548 self->host_handle, 0, id);
1549 if (!math_floats_equal (cur_val, val))
1550 {
1551 g_debug (
1552 "setting param %d value to %f",
1553 id, (double) val);
1554 }
1555 carla_set_parameter_value (
1556 self->host_handle, 0, id, val);
1557 }
1558
1559 /**
1560 * Returns the MIDI out port.
1561 */
1562 Port *
carla_native_plugin_get_midi_out_port(CarlaNativePlugin * self)1563 carla_native_plugin_get_midi_out_port (
1564 CarlaNativePlugin * self)
1565 {
1566 Plugin * pl = self->plugin;
1567 Port * port;
1568 for (int i = 0; i < pl->num_in_ports; i++)
1569 {
1570 port = pl->out_ports[i];
1571 if (port->id.type == TYPE_EVENT &&
1572 port->id.flags2 &
1573 PORT_FLAG2_SUPPORTS_MIDI)
1574 return port;
1575 }
1576
1577 g_return_val_if_reached (NULL);
1578 }
1579
1580 /**
1581 * Returns the plugin Port corresponding to the
1582 * given parameter.
1583 */
1584 Port *
carla_native_plugin_get_port_from_param_id(CarlaNativePlugin * self,const uint32_t id)1585 carla_native_plugin_get_port_from_param_id (
1586 CarlaNativePlugin * self,
1587 const uint32_t id)
1588 {
1589 Plugin * pl = self->plugin;
1590 Port * port;
1591 int j = 0;
1592 for (int i = 0; i < pl->num_in_ports; i++)
1593 {
1594 port = pl->in_ports[i];
1595 if (port->id.type != TYPE_CONTROL)
1596 continue;
1597
1598 j = port->carla_param_id;
1599 if ((int) id == port->carla_param_id)
1600 return port;
1601 }
1602
1603 if ((int) id > j)
1604 {
1605 g_message (
1606 "%s: index %u not found in input ports. "
1607 "this is likely an output param. ignoring",
1608 __func__, id);
1609 return NULL;
1610 }
1611
1612 g_return_val_if_reached (NULL);
1613 }
1614
1615 /**
1616 * Saves the state inside the standard state
1617 * directory.
1618 *
1619 * @param is_backup Whether this is a backup
1620 * project. Used for calculating the absolute
1621 * path to the state dir.
1622 * @param abs_state_dir If passed, the state will
1623 * be saved inside this directory instead of the
1624 * plugin's state directory. Used when saving
1625 * presets.
1626 */
1627 int
carla_native_plugin_save_state(CarlaNativePlugin * self,bool is_backup,const char * abs_state_dir)1628 carla_native_plugin_save_state (
1629 CarlaNativePlugin * self,
1630 bool is_backup,
1631 const char * abs_state_dir)
1632 {
1633 if (!self->plugin->instantiated)
1634 {
1635 g_debug (
1636 "plugin %s not instantiated, skipping %s",
1637 self->plugin->setting->descr->name,
1638 __func__);
1639 return 0;
1640 }
1641
1642 char * dir_to_use = NULL;
1643 if (abs_state_dir)
1644 {
1645 dir_to_use = g_strdup (abs_state_dir);
1646 }
1647 else
1648 {
1649 dir_to_use =
1650 plugin_get_abs_state_dir (
1651 self->plugin, is_backup);
1652 }
1653 io_mkdir (dir_to_use);
1654 char * state_file_abs_path =
1655 g_build_filename (
1656 dir_to_use, CARLA_STATE_FILENAME, NULL);
1657 carla_save_plugin_state (
1658 self->host_handle, 0, state_file_abs_path);
1659 g_free (state_file_abs_path);
1660
1661 g_warn_if_fail (self->plugin->state_dir);
1662
1663 return 0;
1664 }
1665
1666 char *
carla_native_plugin_get_abs_state_file_path(const CarlaNativePlugin * self,const bool is_backup)1667 carla_native_plugin_get_abs_state_file_path (
1668 const CarlaNativePlugin * self,
1669 const bool is_backup)
1670 {
1671 char * abs_state_dir =
1672 plugin_get_abs_state_dir (
1673 self->plugin, is_backup);
1674 char * state_file_abs_path =
1675 g_build_filename (
1676 abs_state_dir, CARLA_STATE_FILENAME, NULL);
1677
1678 g_free (abs_state_dir);
1679
1680 return state_file_abs_path;
1681 }
1682
1683 /**
1684 * Loads the state from the given file or from
1685 * its state file.
1686 *
1687 * @return True on success.
1688 */
1689 bool
carla_native_plugin_load_state(CarlaNativePlugin * self,const char * abs_path,GError ** error)1690 carla_native_plugin_load_state (
1691 CarlaNativePlugin * self,
1692 const char * abs_path,
1693 GError ** error)
1694 {
1695 Plugin * pl = self->plugin;
1696 g_return_val_if_fail (
1697 IS_PLUGIN_AND_NONNULL (pl), false);
1698
1699 g_debug (
1700 "%s: loading state from %s...",
1701 __func__, abs_path);
1702 char * state_file;
1703 if (abs_path)
1704 {
1705 state_file = g_strdup (abs_path);
1706 }
1707 else
1708 {
1709 char * state_dir_abs_path =
1710 plugin_get_abs_state_dir (
1711 pl,
1712 PROJECT->loading_from_backup);
1713 state_file =
1714 g_build_filename (
1715 state_dir_abs_path, CARLA_STATE_FILENAME,
1716 NULL);
1717 g_free (state_dir_abs_path);
1718 }
1719
1720 if (!file_exists (state_file))
1721 {
1722 g_set_error (
1723 error, Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR,
1724 Z_PLUGINS_CARLA_NATIVE_PLUGIN_ERROR_FAILED,
1725 _("State file %s doesn't exist"),
1726 state_file);
1727 return false;
1728 }
1729
1730 self->loading_state = true;
1731 carla_load_plugin_state (
1732 self->host_handle, 0, state_file);
1733 self->loading_state = false;
1734 if (pl->visible
1735 && plugin_is_in_active_project (pl))
1736 {
1737 EVENTS_PUSH (
1738 ET_PLUGIN_VISIBILITY_CHANGED, pl);
1739 }
1740 g_message (
1741 "%s: successfully loaded carla plugin state "
1742 "from %s",
1743 __func__, state_file);
1744
1745 g_free (state_file);
1746
1747 return true;
1748 }
1749
1750 void
carla_native_plugin_close(CarlaNativePlugin * self)1751 carla_native_plugin_close (
1752 CarlaNativePlugin * self)
1753 {
1754 if (self->native_plugin_descriptor)
1755 {
1756 self->native_plugin_descriptor->deactivate (
1757 self->native_plugin_handle);
1758 self->native_plugin_descriptor->cleanup (
1759 self->native_plugin_handle);
1760 self->native_plugin_descriptor = NULL;
1761 }
1762 if (self->host_handle)
1763 {
1764 carla_host_handle_free (self->host_handle);
1765 self->host_handle = NULL;
1766 }
1767 }
1768
1769 /**
1770 * Deactivates, cleanups and frees the instance.
1771 */
1772 void
carla_native_plugin_free(CarlaNativePlugin * self)1773 carla_native_plugin_free (
1774 CarlaNativePlugin * self)
1775 {
1776 carla_native_plugin_close (self);
1777
1778 object_zero_and_free (self);
1779 }
1780 #endif
1781