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