1 /*
2  * Copyright (C) 2018-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 #include <inttypes.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 
27 #include "project.h"
28 #include "audio/channel.h"
29 #include "audio/clip.h"
30 #include "audio/control_port.h"
31 #include "audio/engine_jack.h"
32 #include "audio/graph.h"
33 #include "audio/hardware_processor.h"
34 #include "audio/master_track.h"
35 #include "audio/midi_event.h"
36 #include "audio/pan.h"
37 #include "audio/port.h"
38 #include "audio/router.h"
39 #include "audio/rtaudio_device.h"
40 #include "audio/rtmidi_device.h"
41 #include "audio/tempo_track.h"
42 #include "audio/windows_mme_device.h"
43 #include "gui/backend/event.h"
44 #include "gui/backend/event_manager.h"
45 #include "gui/widgets/channel.h"
46 #include "plugins/carla_native_plugin.h"
47 #include "plugins/plugin.h"
48 #include "plugins/lv2/lv2_ui.h"
49 #include "utils/arrays.h"
50 #include "utils/dsp.h"
51 #include "utils/error.h"
52 #include "utils/flags.h"
53 #include "utils/hash.h"
54 #include "utils/math.h"
55 #include "utils/mem.h"
56 #include "utils/object_utils.h"
57 #include "utils/objects.h"
58 #include "utils/string.h"
59 #include "zix/ring.h"
60 #include "zrythm_app.h"
61 
62 #include <gtk/gtk.h>
63 
64 #define SLEEPTIME_USEC 60
65 
66 #define AUDIO_RING_SIZE 65536
67 
68 /**
69  * Allocates buffers used during DSP.
70  *
71  * To be called only where necessary to save
72  * RAM.
73  */
74 NONNULL
75 void
port_allocate_bufs(Port * self)76 port_allocate_bufs (
77   Port * self)
78 {
79 #if 0
80   size_t sz = 600;
81   char str[sz];
82   port_identifier_print_to_str (
83     &self->id, str, sz);
84   g_message ("allocating bufs for %s", str);
85 #endif
86 
87   switch (self->id.type)
88     {
89     case TYPE_EVENT:
90       object_free_w_func_and_null (
91         midi_events_free, self->midi_events);
92       self->midi_events = midi_events_new ();
93       object_free_w_func_and_null (
94         zix_ring_free, self->midi_ring);
95       self->midi_ring =
96         zix_ring_new (
97           sizeof (MidiEvent) * (size_t) 11);
98       break;
99     case TYPE_AUDIO:
100     case TYPE_CV:
101       {
102         object_free_w_func_and_null (
103           zix_ring_free, self->audio_ring);
104         self->audio_ring =
105           zix_ring_new (
106             sizeof (float) * AUDIO_RING_SIZE);
107         object_zero_and_free (self->buf);
108         size_t max =
109           MAX (
110             AUDIO_ENGINE->block_length,
111             self->min_buf_size);
112         max = MAX (max, 1);
113         self->buf = object_new_n (max, float);
114         self->last_buf_sz = max;
115       }
116     default:
117       break;
118     }
119 }
120 
121 /**
122  * Frees buffers.
123  *
124  * To be used when removing ports from the
125  * project/graph.
126  */
127 void
port_free_bufs(Port * self)128 port_free_bufs (
129   Port * self)
130 {
131   object_free_w_func_and_null (
132     midi_events_free, self->midi_events);
133   object_free_w_func_and_null (
134     zix_ring_free, self->midi_ring);
135   object_free_w_func_and_null (
136     zix_ring_free, self->audio_ring);
137   object_zero_and_free (self->buf);
138 }
139 
140 /**
141  * This function finds the Ports corresponding to
142  * the PortIdentifiers for srcs and dests.
143  *
144  * Should be called after the ports are loaded from
145  * yml.
146  */
147 void
port_init_loaded(Port * self,void * owner)148 port_init_loaded (
149   Port *        self,
150   void *        owner)
151 {
152   self->magic = PORT_MAGIC;
153 
154   self->unsnapped_control = self->control;
155 
156   port_set_owner (self, self->id.owner_type, owner);
157 
158 #if 0
159   if (self->track
160       && self->id.flags & PORT_FLAG_AUTOMATABLE)
161     {
162       if (!self->at)
163         {
164           self->at =
165             automation_track_find_from_port (
166               self, NULL, false);
167         }
168       g_return_if_fail (self->at);
169     }
170 #endif
171 }
172 
173 /**
174  * Finds the Port corresponding to the identifier.
175  *
176  * @param id The PortIdentifier to use for
177  *   searching.
178  */
179 Port *
port_find_from_identifier(const PortIdentifier * const id)180 port_find_from_identifier (
181   const PortIdentifier * const id)
182 {
183   Track * tr = NULL;
184   Channel * ch = NULL;
185   Plugin * pl = NULL;
186   Fader * fader = NULL;
187   PortFlags flags = id->flags;
188   PortFlags2 flags2 = id->flags2;
189   switch (id->owner_type)
190     {
191     case PORT_OWNER_TYPE_AUDIO_ENGINE:
192       switch (id->type)
193         {
194         case TYPE_EVENT:
195           if (id->flow == FLOW_OUTPUT)
196             { /* TODO */ }
197           else if (id->flow == FLOW_INPUT)
198             {
199               if (flags & PORT_FLAG_MANUAL_PRESS)
200                 return
201                   AUDIO_ENGINE->
202                     midi_editor_manual_press;
203             }
204           break;
205         case TYPE_AUDIO:
206           if (id->flow == FLOW_OUTPUT)
207             {
208               if (flags & PORT_FLAG_STEREO_L)
209                 return
210                   AUDIO_ENGINE->monitor_out->l;
211               else if (flags &
212                          PORT_FLAG_STEREO_R)
213                 return
214                   AUDIO_ENGINE->monitor_out->r;
215             }
216           else if (id->flow == FLOW_INPUT)
217             {
218               /* none */
219             }
220           break;
221         default:
222           break;
223         }
224       break;
225     case PORT_OWNER_TYPE_PLUGIN:
226       tr =
227         tracklist_find_track_by_name_hash (
228           TRACKLIST, id->track_name_hash);
229       if (!tr)
230         tr =
231           tracklist_find_track_by_name_hash (
232             SAMPLE_PROCESSOR->tracklist,
233             id->track_name_hash);
234       g_return_val_if_fail (
235         IS_TRACK_AND_NONNULL (tr), NULL);
236       switch (id->plugin_id.slot_type)
237         {
238         case PLUGIN_SLOT_MIDI_FX:
239           pl =
240             tr->channel->midi_fx[
241               id->plugin_id.slot];
242           break;
243         case PLUGIN_SLOT_INSTRUMENT:
244           pl = tr->channel->instrument;
245           break;
246         case PLUGIN_SLOT_INSERT:
247           pl =
248             tr->channel->inserts[
249               id->plugin_id.slot];
250           break;
251         case PLUGIN_SLOT_MODULATOR:
252           pl =
253             tr->modulators[id->plugin_id.slot];
254           break;
255         default:
256           g_return_val_if_reached (NULL);
257           break;
258         }
259       if (!IS_PLUGIN_AND_NONNULL (pl))
260         {
261           g_critical (
262             "could not find plugin for port of "
263             "track %s", tr->name);
264           return NULL;
265         }
266 
267       switch (id->flow)
268         {
269         case FLOW_INPUT:
270           return
271             pl->in_ports[id->port_index];
272           break;
273         case FLOW_OUTPUT:
274           return
275             pl->out_ports[id->port_index];
276           break;
277         default:
278           g_return_val_if_reached (NULL);
279           break;
280         }
281       break;
282     case PORT_OWNER_TYPE_TRACK_PROCESSOR:
283       tr =
284         tracklist_find_track_by_name_hash (
285           TRACKLIST, id->track_name_hash);
286       if (!tr)
287         tr =
288           tracklist_find_track_by_name_hash (
289             SAMPLE_PROCESSOR->tracklist,
290             id->track_name_hash);
291       g_return_val_if_fail (
292         IS_TRACK_AND_NONNULL (tr), NULL);
293       switch (id->type)
294         {
295         case TYPE_EVENT:
296           if (id->flow == FLOW_OUTPUT)
297             {
298               return tr->processor->midi_out;
299             }
300           else if (id->flow == FLOW_INPUT)
301             {
302               if (flags & PORT_FLAG_PIANO_ROLL)
303                 return tr->processor->piano_roll;
304               else
305                 return tr->processor->midi_in;
306             }
307           break;
308         case TYPE_AUDIO:
309           if (id->flow == FLOW_OUTPUT)
310             {
311               if (flags & PORT_FLAG_STEREO_L)
312                 return tr->processor->stereo_out->l;
313               else if (flags &
314                          PORT_FLAG_STEREO_R)
315                 return tr->processor->stereo_out->r;
316             }
317           else if (id->flow == FLOW_INPUT)
318             {
319               g_return_val_if_fail (
320                 tr->processor->stereo_in, NULL);
321               if (flags & PORT_FLAG_STEREO_L)
322                 return tr->processor->stereo_in->l;
323               else if (flags & PORT_FLAG_STEREO_R)
324                 return tr->processor->stereo_in->r;
325             }
326           break;
327         case TYPE_CONTROL:
328           if (flags & PORT_FLAG_TP_MONO)
329             {
330               return tr->processor->mono;
331             }
332           else if (flags &
333                      PORT_FLAG_TP_INPUT_GAIN)
334             {
335               return tr->processor->input_gain;
336             }
337           else if (flags2 &
338                      PORT_FLAG2_TP_OUTPUT_GAIN)
339             {
340               return tr->processor->output_gain;
341             }
342           else if (flags2 &
343                      PORT_FLAG2_TP_MONITOR_AUDIO)
344             {
345               return tr->processor->monitor_audio;
346             }
347           else if (flags &
348                      PORT_FLAG_MIDI_AUTOMATABLE)
349             {
350               if (flags2 &
351                     PORT_FLAG2_MIDI_PITCH_BEND)
352                 {
353                   return
354                     tr->processor->pitch_bend[
355                       id->port_index];
356                 }
357               else if (flags2 &
358                     PORT_FLAG2_MIDI_POLY_KEY_PRESSURE)
359                 {
360                   return
361                     tr->processor->poly_key_pressure[
362                       id->port_index];
363                 }
364               else if (flags2 &
365                     PORT_FLAG2_MIDI_CHANNEL_PRESSURE)
366                 {
367                   return
368                     tr->processor->channel_pressure[
369                       id->port_index];
370                 }
371               else
372                 {
373                   return
374                     tr->processor->midi_cc[
375                       id->port_index];
376                 }
377             }
378           break;
379         default:
380           break;
381         }
382       break;
383     case PORT_OWNER_TYPE_TRACK:
384       tr =
385         tracklist_find_track_by_name_hash (
386           TRACKLIST, id->track_name_hash);
387       if (!tr)
388         tr =
389           tracklist_find_track_by_name_hash (
390             SAMPLE_PROCESSOR->tracklist,
391             id->track_name_hash);
392       g_return_val_if_fail (tr, NULL);
393       if (flags & PORT_FLAG_BPM)
394         {
395           return tr->bpm_port;
396         }
397       else if (flags2 & PORT_FLAG2_BEATS_PER_BAR)
398         {
399           return tr->beats_per_bar_port;
400         }
401       else if (flags2 & PORT_FLAG2_BEAT_UNIT)
402         {
403           return tr->beat_unit_port;
404         }
405       else if (flags2 & PORT_FLAG2_TRACK_RECORDING)
406         {
407           return tr->recording;
408         }
409       break;
410     case PORT_OWNER_TYPE_FADER:
411       fader =
412         fader_find_from_port_identifier (id);
413       g_return_val_if_fail (fader, NULL);
414       switch (id->type)
415         {
416         case TYPE_EVENT:
417           switch (id->flow)
418             {
419             case FLOW_INPUT:
420               if (fader)
421                 return fader->midi_in;
422               break;
423             case FLOW_OUTPUT:
424               if (fader)
425                 return fader->midi_out;
426               break;
427             default:
428               break;
429             }
430           break;
431         case TYPE_AUDIO:
432           if (id->flow == FLOW_OUTPUT)
433             {
434               if (flags & PORT_FLAG_STEREO_L
435                   && fader)
436                 return fader->stereo_out->l;
437               else if (
438                 flags & PORT_FLAG_STEREO_R
439                 && fader)
440                 return fader->stereo_out->r;
441             }
442           else if (id->flow == FLOW_INPUT)
443             {
444               if (flags & PORT_FLAG_STEREO_L
445                   && fader)
446                 return fader->stereo_in->l;
447               else if (
448                 flags & PORT_FLAG_STEREO_R
449                 && fader)
450                 return fader->stereo_in->r;
451             }
452           break;
453         case TYPE_CONTROL:
454           if (id->flow == FLOW_INPUT)
455             {
456               if (flags & PORT_FLAG_AMPLITUDE
457                   && fader)
458                 return fader->amp;
459               else if (
460                 flags & PORT_FLAG_STEREO_BALANCE
461                 && fader)
462                 return fader->balance;
463               else if (
464                 flags & PORT_FLAG_FADER_MUTE
465                 && fader)
466                 return fader->mute;
467               else if (
468                 flags2 & PORT_FLAG2_FADER_SOLO
469                 && fader)
470                 return fader->solo;
471               else if (
472                 flags2 & PORT_FLAG2_FADER_LISTEN
473                 && fader)
474                 return fader->listen;
475               else if (
476                 flags2 &
477                   PORT_FLAG2_FADER_MONO_COMPAT
478                 && fader)
479                 return fader->mono_compat_enabled;
480             }
481           break;
482         default:
483           break;
484         }
485       g_return_val_if_reached (NULL);
486       break;
487     case PORT_OWNER_TYPE_CHANNEL_SEND:
488       tr =
489         tracklist_find_track_by_name_hash (
490           TRACKLIST, id->track_name_hash);
491       if (!tr)
492         tr =
493           tracklist_find_track_by_name_hash (
494             SAMPLE_PROCESSOR->tracklist,
495             id->track_name_hash);
496       g_return_val_if_fail (tr, NULL);
497       ch = tr->channel;
498       g_return_val_if_fail (ch, NULL);
499       if (id->flags2 &
500             PORT_FLAG2_CHANNEL_SEND_ENABLED)
501         {
502           return ch->sends[id->port_index]->enabled;
503         }
504       else if (id->flags2 &
505                  PORT_FLAG2_CHANNEL_SEND_AMOUNT)
506         {
507           return ch->sends[id->port_index]->amount;
508         }
509       else if (id->flow == FLOW_INPUT)
510         {
511           if (id->type == TYPE_AUDIO)
512             {
513               if (id->flags &
514                     PORT_FLAG_STEREO_L)
515                 {
516                   return
517                     ch->sends[id->port_index]->
518                       stereo_in->l;
519                 }
520               else if (id->flags &
521                         PORT_FLAG_STEREO_R)
522                 {
523                   return
524                     ch->sends[id->port_index]->
525                       stereo_in->r;
526                 }
527             }
528           else if (id->type == TYPE_EVENT)
529             {
530               return
531                 ch->sends[id->port_index]->midi_in;
532             }
533         }
534       else if (id->flow == FLOW_OUTPUT)
535         {
536           if (id->type == TYPE_AUDIO)
537             {
538               if (id->flags &
539                     PORT_FLAG_STEREO_L)
540                 {
541                   return
542                     ch->sends[id->port_index]->
543                       stereo_out->l;
544                 }
545               else if (id->flags &
546                         PORT_FLAG_STEREO_R)
547                 {
548                   return
549                     ch->sends[id->port_index]->
550                       stereo_out->r;
551                 }
552             }
553           else if (id->type == TYPE_EVENT)
554             {
555               return
556                 ch->sends[id->port_index]->midi_out;
557             }
558         }
559       else
560         {
561           g_return_val_if_reached (NULL);
562         }
563       break;
564     case PORT_OWNER_TYPE_HW:
565       {
566         Port * port = NULL;
567 
568         /* note: flows are reversed */
569         if (id->flow == FLOW_OUTPUT)
570           {
571             port =
572               hardware_processor_find_port (
573                 HW_IN_PROCESSOR, id->ext_port_id);
574           }
575         else if (id->flow == FLOW_INPUT)
576           {
577             port =
578               hardware_processor_find_port (
579                 HW_OUT_PROCESSOR, id->ext_port_id);
580           }
581 
582         /* only warn when hardware is not
583          * connected anymore */
584         g_warn_if_fail (port);
585         /*g_return_val_if_fail (port, NULL);*/
586         return port;
587       }
588       break;
589     case PORT_OWNER_TYPE_TRANSPORT:
590       switch (id->type)
591         {
592         case TYPE_EVENT:
593           if (id->flow == FLOW_INPUT)
594             {
595               if (flags2 &
596                     PORT_FLAG2_TRANSPORT_ROLL)
597                 return TRANSPORT->roll;
598               if (flags2 &
599                     PORT_FLAG2_TRANSPORT_STOP)
600                 return TRANSPORT->stop;
601               if (flags2 &
602                     PORT_FLAG2_TRANSPORT_BACKWARD)
603                 return TRANSPORT->backward;
604               if (flags2 &
605                     PORT_FLAG2_TRANSPORT_FORWARD)
606                 return TRANSPORT->forward;
607               if (flags2 &
608                     PORT_FLAG2_TRANSPORT_LOOP_TOGGLE)
609                 return TRANSPORT->loop_toggle;
610               if (flags2 &
611                     PORT_FLAG2_TRANSPORT_REC_TOGGLE)
612                 return TRANSPORT->rec_toggle;
613             }
614           break;
615         default:
616           break;
617         }
618       break;
619     case PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR:
620       if (flags & PORT_FLAG_MODULATOR_MACRO)
621         {
622           tr =
623             tracklist_find_track_by_name_hash (
624               TRACKLIST, id->track_name_hash);
625           g_return_val_if_fail (
626             IS_TRACK_AND_NONNULL (tr), NULL);
627           ModulatorMacroProcessor * processor =
628             tr->modulator_macros[id->port_index];
629           if (id->flow == FLOW_INPUT)
630             {
631               if (id->type == TYPE_CV)
632                 {
633                   return processor->cv_in;
634                 }
635               else if (id->type == TYPE_CONTROL)
636                 {
637                   return processor->macro;
638                 }
639             }
640           else if (id->flow == FLOW_OUTPUT)
641             {
642               return processor->cv_out;
643             }
644         }
645       break;
646     case PORT_OWNER_TYPE_CHANNEL:
647       tr =
648         tracklist_find_track_by_name_hash (
649           TRACKLIST, id->track_name_hash);
650       if (!tr)
651         tr =
652           tracklist_find_track_by_name_hash (
653             SAMPLE_PROCESSOR->tracklist,
654             id->track_name_hash);
655       g_return_val_if_fail (tr, NULL);
656       ch = tr->channel;
657       g_return_val_if_fail (ch, NULL);
658       switch (id->type)
659         {
660         case TYPE_EVENT:
661           if (id->flow == FLOW_OUTPUT)
662             {
663               return ch->midi_out;
664             }
665           break;
666         case TYPE_AUDIO:
667           if (id->flow == FLOW_OUTPUT)
668             {
669               if (flags & PORT_FLAG_STEREO_L)
670                 return ch->stereo_out->l;
671               else if (flags &
672                          PORT_FLAG_STEREO_R)
673                 return ch->stereo_out->r;
674             }
675           break;
676         default:
677           break;
678         }
679       break;
680     default:
681       g_return_val_if_reached (NULL);
682     }
683 
684   g_return_val_if_reached (NULL);
685 }
686 
687 /**
688  * Creates port.
689  *
690  * Sets id and updates appropriate counters.
691  */
692 RETURNS_NONNULL
693 static Port *
_port_new(const char * label)694 _port_new (
695   const char * label)
696 {
697   Port * self = object_new (Port);
698 
699   self->schema_version = PORT_SCHEMA_VERSION;
700   port_identifier_init (&self->id);
701   self->magic = PORT_MAGIC;
702 
703   self->num_dests = 0;
704   self->id.flow = FLOW_UNKNOWN;
705   self->id.label = g_strdup (label);
706 
707   return self;
708 }
709 
710 /**
711  * Creates port.
712  */
713 Port *
port_new_with_type(PortType type,PortFlow flow,const char * label)714 port_new_with_type (
715   PortType     type,
716   PortFlow     flow,
717   const char * label)
718 {
719   Port * self = _port_new (label);
720 
721   self->id.type = type;
722   self->id.flow = flow;
723 
724   switch (type)
725     {
726     case TYPE_EVENT:
727       self->maxf = 1.f;
728 #ifdef _WOE32
729       if (AUDIO_ENGINE->midi_backend ==
730             MIDI_BACKEND_WINDOWS_MME)
731         {
732           zix_sem_init (
733             &self->mme_connections_sem, 1);
734         }
735 #endif
736       break;
737     case TYPE_CONTROL:
738       self->minf = 0.f;
739       self->maxf = 1.f;
740       self->zerof = 0.f;
741       break;
742     case TYPE_AUDIO:
743       self->minf = 0.f;
744       self->maxf = 2.f;
745       self->zerof = 0.f;
746       break;
747     case TYPE_CV:
748       self->minf = -1.f;
749       self->maxf = 1.f;
750       self->zerof = 0.f;
751     default:
752       break;
753     }
754 
755   g_return_val_if_fail (IS_PORT (self), NULL);
756 
757   g_return_val_if_fail (
758     self->magic == PORT_MAGIC, NULL);
759 
760   return self;
761 }
762 
763 Port *
port_new_with_type_and_owner(PortType type,PortFlow flow,const char * label,PortOwnerType owner_type,void * owner)764 port_new_with_type_and_owner (
765   PortType      type,
766   PortFlow      flow,
767   const char *  label,
768   PortOwnerType owner_type,
769   void *        owner)
770 {
771   Port * self =
772     port_new_with_type (type, flow, label);
773   port_set_owner (self, owner_type, owner);
774 
775   return self;
776 }
777 
778 /**
779  * Creates stereo ports.
780  */
781 StereoPorts *
stereo_ports_new_from_existing(Port * l,Port * r)782 stereo_ports_new_from_existing (
783   Port * l, Port * r)
784 {
785   StereoPorts * sp = object_new (StereoPorts);
786   sp->schema_version = STEREO_PORTS_SCHEMA_VERSION;
787   sp->l = l;
788   l->id.flags |= PORT_FLAG_STEREO_L;
789   r->id.flags |= PORT_FLAG_STEREO_R;
790   sp->r = r;
791 
792   return sp;
793 }
794 
795 void
stereo_ports_fill_from_clip(StereoPorts * self,AudioClip * clip,long g_start_frames,nframes_t start_frame,nframes_t nframes)796 stereo_ports_fill_from_clip (
797   StereoPorts * self,
798   AudioClip *   clip,
799   long          g_start_frames,
800   nframes_t     start_frame,
801   nframes_t     nframes)
802 {
803   channels_t max_channels = MAX (2, clip->channels);
804   for (nframes_t i = start_frame;
805        i < start_frame + nframes;
806        i++)
807     {
808       /* no more frames to read */
809       if (g_start_frames + i > clip->num_frames)
810         {
811           return;
812         }
813 
814       if (max_channels == 1)
815         {
816           self->l->buf[i] =
817             clip->frames[g_start_frames + i];
818           self->r->buf[i] =
819             clip->frames[g_start_frames + i];
820         }
821       else if (max_channels == 2)
822         {
823           self->l->buf[i] =
824             clip->frames[
825               (g_start_frames + i) * 2];
826           self->r->buf[i] =
827             clip->frames[
828               (g_start_frames + i) * 2 + 1];
829         }
830     }
831 }
832 
833 void
stereo_ports_disconnect(StereoPorts * self)834 stereo_ports_disconnect (
835   StereoPorts * self)
836 {
837   port_disconnect_all (self->l);
838   port_disconnect_all (self->r);
839 }
840 
841 StereoPorts *
stereo_ports_clone(const StereoPorts * src)842 stereo_ports_clone (
843   const StereoPorts * src)
844 {
845   StereoPorts * sp = object_new (StereoPorts);
846   sp->schema_version = STEREO_PORTS_SCHEMA_VERSION;
847 
848   sp->l = port_clone (src->l);
849   sp->r = port_clone (src->r);
850 
851   return sp;
852 }
853 
854 void
stereo_ports_free(StereoPorts * self)855 stereo_ports_free (
856   StereoPorts * self)
857 {
858   object_free_w_func_and_null (
859     port_free, self->l);
860   object_free_w_func_and_null (
861     port_free, self->r);
862 
863   object_zero_and_free (self);
864 }
865 
866 #ifdef HAVE_JACK
867 void
port_receive_midi_events_from_jack(Port * self,const nframes_t start_frame,const nframes_t nframes)868 port_receive_midi_events_from_jack (
869   Port *          self,
870   const nframes_t start_frame,
871   const nframes_t nframes)
872 {
873   if (self->internal_type !=
874         INTERNAL_JACK_PORT ||
875       self->id.type !=
876         TYPE_EVENT)
877     return;
878 
879   void * port_buf =
880     jack_port_get_buffer (
881       JACK_PORT_T (self->data), nframes);
882   uint32_t num_events =
883     jack_midi_get_event_count (port_buf);
884 
885   jack_midi_event_t jack_ev;
886   for(unsigned i = 0; i < num_events; i++)
887     {
888       jack_midi_event_get (
889         &jack_ev, port_buf, i);
890 
891       if (jack_ev.time >= start_frame &&
892           jack_ev.time < start_frame + nframes)
893         {
894           midi_byte_t channel =
895             jack_ev.buffer[0] & 0xf;
896           Track * track =
897             port_get_track (self, 0);
898           if (self->id.owner_type ==
899                 PORT_OWNER_TYPE_TRACK_PROCESSOR &&
900               !track)
901             {
902               g_return_if_reached ();
903             }
904 
905           if (self->id.owner_type ==
906                 PORT_OWNER_TYPE_TRACK_PROCESSOR &&
907               (track->type ==
908                    TRACK_TYPE_MIDI ||
909                  track->type ==
910                    TRACK_TYPE_INSTRUMENT) &&
911                 !track->channel->
912                   all_midi_channels &&
913                 !track->channel->
914                   midi_channels[channel])
915             {
916               /* different channel */
917             }
918           else if (jack_ev.size == 3)
919             {
920               midi_events_add_event_from_buf (
921                 self->midi_events,
922                 jack_ev.time, jack_ev.buffer,
923                 (int) jack_ev.size, F_NOT_QUEUED);
924             }
925         }
926     }
927 
928 #if 0
929   if (self->midi_events->num_events > 0)
930     {
931       MidiEvent * ev =
932         &self->midi_events->events[0];
933       char designation[600];
934       port_get_full_designation (
935         self, designation);
936       g_debug (
937         "JACK MIDI (%s): have %d events\n"
938         "first event is: [%u] %hhx %hhx %hhx",
939         designation, num_events,
940         ev->time, ev->raw_buffer[0],
941         ev->raw_buffer[1], ev->raw_buffer[2]);
942     }
943 #endif
944 }
945 
946 void
port_receive_audio_data_from_jack(Port * self,const nframes_t start_frames,const nframes_t nframes)947 port_receive_audio_data_from_jack (
948   Port *          self,
949   const nframes_t start_frames,
950   const nframes_t nframes)
951 {
952   if (self->internal_type !=
953         INTERNAL_JACK_PORT ||
954       self->id.type != TYPE_AUDIO)
955     return;
956 
957   float * in;
958   in =
959     (float *)
960     jack_port_get_buffer (
961       JACK_PORT_T (self->data),
962       AUDIO_ENGINE->nframes);
963 
964   dsp_add2 (
965     &self->buf[start_frames],
966     &in[start_frames], nframes);
967 }
968 
969 static void
send_midi_events_to_jack(Port * port,const nframes_t start_frames,const nframes_t nframes)970 send_midi_events_to_jack (
971   Port *      port,
972   const nframes_t         start_frames,
973   const nframes_t   nframes)
974 {
975   if (port->internal_type !=
976         INTERNAL_JACK_PORT ||
977       port->id.type != TYPE_EVENT)
978     return;
979 
980   jack_port_t * jport = JACK_PORT_T (port->data);
981 
982   if (jack_port_connected (jport) <= 0)
983     {
984       return;
985     }
986 
987   void * buf =
988     jack_port_get_buffer (
989       jport, AUDIO_ENGINE->nframes);
990   midi_events_copy_to_jack (
991     port->midi_events, buf);
992 }
993 
994 static void
send_audio_data_to_jack(Port * port,const nframes_t start_frames,const nframes_t nframes)995 send_audio_data_to_jack (
996   Port *      port,
997   const nframes_t         start_frames,
998   const nframes_t         nframes)
999 {
1000   if (port->internal_type !=
1001         INTERNAL_JACK_PORT ||
1002       port->id.type != TYPE_AUDIO)
1003     return;
1004 
1005   jack_port_t * jport = JACK_PORT_T (port->data);
1006 
1007   if (jack_port_connected (jport) <= 0)
1008     {
1009       return;
1010     }
1011 
1012   float * out =
1013     (float *)
1014     jack_port_get_buffer (
1015       jport, AUDIO_ENGINE->nframes);
1016 
1017 #ifdef TRIAL_VER
1018   if (AUDIO_ENGINE->limit_reached)
1019     {
1020       dsp_fill (&out[start_frames], 0.f, nframes);
1021     }
1022   else
1023     {
1024 #endif
1025       dsp_copy (
1026         &out[start_frames],
1027         &port->buf[start_frames], nframes);
1028 #ifdef TRIAL_VER
1029     }
1030 #endif
1031 }
1032 
1033 /**
1034  * Sums the inputs coming in from JACK, before the
1035  * port is processed.
1036  */
1037 static void
sum_data_from_jack(Port * self,const nframes_t start_frame,const nframes_t nframes)1038 sum_data_from_jack (
1039   Port * self,
1040   const nframes_t start_frame,
1041   const nframes_t nframes)
1042 {
1043   if (self->id.owner_type ==
1044         PORT_OWNER_TYPE_AUDIO_ENGINE ||
1045       self->internal_type != INTERNAL_JACK_PORT ||
1046       self->id.flow != FLOW_INPUT)
1047     return;
1048 
1049   /* append events from JACK if any */
1050   if (AUDIO_ENGINE->midi_backend ==
1051         MIDI_BACKEND_JACK)
1052     {
1053       port_receive_midi_events_from_jack (
1054         self, start_frame, nframes);
1055     }
1056 
1057   /* audio */
1058   if (AUDIO_ENGINE->audio_backend ==
1059         AUDIO_BACKEND_JACK)
1060     {
1061       port_receive_audio_data_from_jack (
1062         self, start_frame, nframes);
1063     }
1064 }
1065 
1066 /**
1067  * Sends the port data to JACK, after the port
1068  * is processed.
1069  */
1070 static void
send_data_to_jack(Port * self,const nframes_t start_frame,const nframes_t nframes)1071 send_data_to_jack (
1072   Port * self,
1073   const nframes_t start_frame,
1074   const nframes_t nframes)
1075 {
1076   if (self->internal_type != INTERNAL_JACK_PORT ||
1077       self->id.flow != FLOW_OUTPUT)
1078     return;
1079 
1080   /* send midi events */
1081   if (AUDIO_ENGINE->midi_backend ==
1082         MIDI_BACKEND_JACK)
1083     {
1084       send_midi_events_to_jack (
1085         self, start_frame, nframes);
1086     }
1087 
1088   /* send audio data */
1089   if (AUDIO_ENGINE->audio_backend ==
1090         AUDIO_BACKEND_JACK)
1091     {
1092       send_audio_data_to_jack (
1093         self, start_frame, nframes);
1094     }
1095 }
1096 
1097 /**
1098  * Sets whether to expose the port to JACk and
1099  * exposes it or removes it from JACK.
1100  */
1101 static void
expose_to_jack(Port * self,bool expose)1102 expose_to_jack (
1103   Port *   self,
1104   bool     expose)
1105 {
1106   enum JackPortFlags flags;
1107   if (self->id.owner_type == PORT_OWNER_TYPE_HW)
1108     {
1109       /* these are reversed */
1110       if (self->id.flow == FLOW_INPUT)
1111         flags = JackPortIsOutput;
1112       else if (self->id.flow == FLOW_OUTPUT)
1113         flags = JackPortIsInput;
1114       else
1115         {
1116           g_return_if_reached ();
1117         }
1118     }
1119   else
1120     {
1121       if (self->id.flow == FLOW_INPUT)
1122         flags = JackPortIsInput;
1123       else if (self->id.flow == FLOW_OUTPUT)
1124         flags = JackPortIsOutput;
1125       else
1126         {
1127           g_return_if_reached ();
1128         }
1129     }
1130 
1131   const char * type =
1132     engine_jack_get_jack_type (self->id.type);
1133   if (!type)
1134     g_return_if_reached ();
1135 
1136   char label[600];
1137   port_get_full_designation (self, label);
1138   if (expose)
1139     {
1140       g_message (
1141         "exposing port %s to JACK", label);
1142       if (!self->data)
1143         {
1144           self->data =
1145             (void *) jack_port_register (
1146               AUDIO_ENGINE->client,
1147               label, type, flags, 0);
1148         }
1149       g_return_if_fail (self->data);
1150       self->internal_type = INTERNAL_JACK_PORT;
1151     }
1152   else
1153     {
1154       g_message (
1155         "unexposing port %s from JACK", label);
1156       if (AUDIO_ENGINE->client)
1157         {
1158           g_warn_if_fail (self->data);
1159           int ret =
1160             jack_port_unregister (
1161               AUDIO_ENGINE->client,
1162               JACK_PORT_T (self->data));
1163           if (ret)
1164             {
1165               char jack_error[600];
1166               engine_jack_get_error_message (
1167                 (jack_status_t) ret, jack_error);
1168               g_warning (
1169                 "JACK port unregister error: %s",
1170                 jack_error);
1171             }
1172         }
1173       self->internal_type = INTERNAL_NONE;
1174       self->data = NULL;
1175     }
1176 
1177   self->exposed_to_backend = expose;
1178 }
1179 #endif /* HAVE_JACK */
1180 
1181 /**
1182  * Sums the inputs coming in from dummy, before the
1183  * port is processed.
1184  */
1185 static void
sum_data_from_dummy(Port * self,const nframes_t start_frame,const nframes_t nframes)1186 sum_data_from_dummy (
1187   Port * self,
1188   const nframes_t start_frame,
1189   const nframes_t nframes)
1190 {
1191   if (self->id.owner_type ==
1192         PORT_OWNER_TYPE_AUDIO_ENGINE ||
1193       self->id.flow !=
1194         FLOW_INPUT ||
1195       self->id.type != TYPE_AUDIO ||
1196       AUDIO_ENGINE->audio_backend !=
1197         AUDIO_BACKEND_DUMMY ||
1198       AUDIO_ENGINE->midi_backend !=
1199         MIDI_BACKEND_DUMMY)
1200     return;
1201 
1202   if (AUDIO_ENGINE->dummy_input)
1203     {
1204       Port * port = NULL;
1205       if (self->id.flags & PORT_FLAG_STEREO_L)
1206         {
1207           port = AUDIO_ENGINE->dummy_input->l;
1208         }
1209       else if (self->id.flags & PORT_FLAG_STEREO_R)
1210         {
1211           port = AUDIO_ENGINE->dummy_input->r;
1212         }
1213 
1214       if (port)
1215         {
1216           dsp_add2 (
1217             &self->buf[start_frame],
1218             &port->buf[start_frame], nframes);
1219         }
1220     }
1221 }
1222 
1223 /**
1224  * Connects the internal ports using
1225  * port_connect().
1226  *
1227  * @param locked Lock the connection.
1228  */
1229 void
stereo_ports_connect(StereoPorts * src,StereoPorts * dest,int locked)1230 stereo_ports_connect (
1231   StereoPorts * src,
1232   StereoPorts * dest,
1233   int           locked)
1234 {
1235   port_connect (
1236     src->l, dest->l, locked);
1237   port_connect (
1238     src->r, dest->r, locked);
1239 }
1240 
1241 static int
get_num_unlocked(const Port * self,bool sources)1242 get_num_unlocked (
1243   const Port * self,
1244   bool         sources)
1245 {
1246   g_return_val_if_fail (
1247     IS_PORT_AND_NONNULL (self)
1248     && port_is_in_active_project (self),
1249     0);
1250 
1251   GPtrArray * conns = g_ptr_array_new ();
1252   int num_conns =
1253     port_connections_manager_get_sources_or_dests (
1254       PORT_CONNECTIONS_MGR, conns, &self->id,
1255       sources);
1256   int ret = 0;
1257   for (int i = 0; i < num_conns; i++)
1258     {
1259       PortConnection * conn =
1260         (PortConnection *)
1261         g_ptr_array_index (conns, i);
1262       if (!conn->locked)
1263         ret++;
1264     }
1265   g_ptr_array_unref (conns);
1266 
1267   return ret;
1268 }
1269 
1270 /**
1271  * Returns the number of unlocked (user-editable)
1272  * destinations.
1273  */
1274 int
port_get_num_unlocked_dests(const Port * self)1275 port_get_num_unlocked_dests (
1276   const Port * self)
1277 {
1278   return get_num_unlocked (self, false);
1279 }
1280 
1281 /**
1282  * Returns the number of unlocked (user-editable)
1283  * sources.
1284  */
1285 int
port_get_num_unlocked_srcs(const Port * self)1286 port_get_num_unlocked_srcs (
1287   const Port * self)
1288 {
1289   return get_num_unlocked (self, true);
1290 }
1291 
1292 /**
1293  * Gathers all ports in the project and appends them
1294  * in the given array.
1295  */
1296 void
port_get_all(GPtrArray * ports)1297 port_get_all (
1298   GPtrArray * ports)
1299 {
1300 #define _ADD(port) \
1301   g_return_if_fail (port); \
1302   g_ptr_array_add (ports, port)
1303 
1304   engine_append_ports (AUDIO_ENGINE, ports);
1305 
1306   for (int i = 0; i < TRACKLIST->num_tracks; i++)
1307     {
1308       Track * tr = TRACKLIST->tracks[i];
1309       track_append_ports (
1310         tr, ports, F_INCLUDE_PLUGINS);
1311     }
1312 
1313 #undef _ADD
1314 }
1315 
1316 /**
1317  * Sets the owner plugin & its slot.
1318  */
1319 NONNULL
1320 static void
set_owner_plugin(Port * port,Plugin * pl)1321 set_owner_plugin (
1322   Port *   port,
1323   Plugin * pl)
1324 {
1325   plugin_identifier_copy (
1326     &port->id.plugin_id, &pl->id);
1327   port->id.track_name_hash = pl->id.track_name_hash;
1328   port->id.owner_type =
1329     PORT_OWNER_TYPE_PLUGIN;
1330 
1331   if (port->at)
1332     {
1333       port_identifier_copy (
1334         &port->at->port_id, &port->id);
1335     }
1336 }
1337 
1338 /**
1339  * Sets the owner track & its ID.
1340  */
1341 NONNULL
1342 static void
set_owner_track_processor(Port * port,TrackProcessor * track_processor)1343 set_owner_track_processor (
1344   Port *           port,
1345   TrackProcessor * track_processor)
1346 {
1347   Track * track = track_processor->track;
1348   g_return_if_fail (track && track->name);
1349   port->id.track_name_hash =
1350     track_get_name_hash (track);
1351   port->id.owner_type =
1352     PORT_OWNER_TYPE_TRACK_PROCESSOR;
1353 }
1354 
1355 /**
1356  * Sets the owner fader & its ID.
1357  */
1358 static void
set_owner_fader(Port * self,Fader * fader)1359 set_owner_fader (
1360   Port *    self,
1361   Fader *   fader)
1362 {
1363   PortIdentifier * id = &self->id;
1364   id->owner_type = PORT_OWNER_TYPE_FADER;
1365   self->fader = fader;
1366 
1367   if (fader->type == FADER_TYPE_AUDIO_CHANNEL ||
1368       fader->type == FADER_TYPE_MIDI_CHANNEL)
1369     {
1370       Track * track = fader->track;
1371       g_return_if_fail (track && track->name);
1372       self->id.track_name_hash =
1373         track_get_name_hash (track);
1374       if (fader->passthrough)
1375         {
1376           id->flags2 |= PORT_FLAG2_PREFADER;
1377         }
1378       else
1379         {
1380           id->flags2 |= PORT_FLAG2_POSTFADER;
1381         }
1382     }
1383   else if (fader->type ==
1384              FADER_TYPE_SAMPLE_PROCESSOR)
1385     {
1386       id->flags2 |=
1387         PORT_FLAG2_SAMPLE_PROCESSOR_FADER;
1388     }
1389   else
1390     {
1391       id->flags2 |= PORT_FLAG2_MONITOR_FADER;
1392     }
1393 
1394   if (id->flags & PORT_FLAG_AMPLITUDE)
1395     {
1396       self->minf = 0.f;
1397       self->maxf = 2.f;
1398       self->zerof = 0.f;
1399     }
1400   else if (id->flags & PORT_FLAG_STEREO_BALANCE)
1401     {
1402       self->minf = 0.f;
1403       self->maxf = 1.f;
1404       self->zerof = 0.5f;
1405     }
1406 }
1407 
1408 /**
1409  * Sets the owner track & its ID.
1410  */
1411 NONNULL
1412 static void
set_owner_track(Port * port,Track * track)1413 set_owner_track (
1414   Port *    port,
1415   Track *   track)
1416 {
1417   g_return_if_fail (track->name);
1418   port->id.track_name_hash =
1419     track_get_name_hash (track);
1420   port->id.owner_type =
1421     PORT_OWNER_TYPE_TRACK;
1422 }
1423 
1424 /**
1425  * Sets the channel send as the port's owner.
1426  */
1427 NONNULL
1428 static void
set_owner_channel_send(Port * self,ChannelSend * send)1429 set_owner_channel_send (
1430   Port *        self,
1431   ChannelSend * send)
1432 {
1433   self->id.track_name_hash =
1434     send->track_name_hash;
1435   self->id.port_index = send->slot;
1436   self->id.owner_type =
1437     PORT_OWNER_TYPE_CHANNEL_SEND;
1438   self->channel_send = send;
1439 
1440   if (self->id.flags2 &
1441         PORT_FLAG2_CHANNEL_SEND_ENABLED)
1442     {
1443       self->minf = 0.f;
1444       self->maxf = 1.f;
1445       self->zerof = 0.0f;
1446     }
1447   else if (self->id.flags2 &
1448              PORT_FLAG2_CHANNEL_SEND_AMOUNT)
1449     {
1450       self->minf = 0.f;
1451       self->maxf = 2.f;
1452       self->zerof = 0.f;
1453     }
1454 }
1455 
1456 NONNULL
1457 static void
set_owner_channel(Port * port,Channel * ch)1458 set_owner_channel (
1459   Port *    port,
1460   Channel * ch)
1461 {
1462   Track * track = ch->track;
1463   g_return_if_fail (track && track->name);
1464   port->id.track_name_hash =
1465     track_get_name_hash (track);
1466   port->id.owner_type = PORT_OWNER_TYPE_CHANNEL;
1467 }
1468 
1469 NONNULL
1470 static void
set_owner_transport(Port * self,Transport * transport)1471 set_owner_transport (
1472   Port *      self,
1473   Transport * transport)
1474 {
1475   self->transport = transport;
1476   self->id.owner_type = PORT_OWNER_TYPE_TRANSPORT;
1477 }
1478 
1479 NONNULL
1480 static void
set_owner_modulator_macro_processor(Port * self,ModulatorMacroProcessor * mmp)1481 set_owner_modulator_macro_processor (
1482   Port *                    self,
1483   ModulatorMacroProcessor * mmp)
1484 {
1485   self->modulator_macro_processor = mmp;
1486   self->id.owner_type =
1487     PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR;
1488   g_return_if_fail (
1489     IS_TRACK_AND_NONNULL (mmp->track));
1490   self->id.track_name_hash =
1491     track_get_name_hash (mmp->track);
1492   self->track = mmp->track;
1493 }
1494 
1495 NONNULL
1496 static void
set_owner_audio_engine(Port * self,AudioEngine * engine)1497 set_owner_audio_engine (
1498   Port *        self,
1499   AudioEngine * engine)
1500 {
1501   self->engine = engine;
1502   self->id.owner_type =
1503     PORT_OWNER_TYPE_AUDIO_ENGINE;
1504 }
1505 
1506 NONNULL
1507 static void
set_owner_ext_port(Port * self,ExtPort * ext_port)1508 set_owner_ext_port (
1509   Port *    self,
1510   ExtPort * ext_port)
1511 {
1512   self->ext_port = ext_port;
1513   self->id.owner_type = PORT_OWNER_TYPE_HW;
1514 }
1515 
1516 NONNULL
1517 void
port_set_owner(Port * self,PortOwnerType owner_type,void * owner)1518 port_set_owner (
1519   Port *        self,
1520   PortOwnerType owner_type,
1521   void *        owner)
1522 {
1523   switch (owner_type)
1524     {
1525     case PORT_OWNER_TYPE_CHANNEL_SEND:
1526       set_owner_channel_send (
1527         self, (ChannelSend *) owner);
1528       break;
1529     case PORT_OWNER_TYPE_FADER:
1530       set_owner_fader (self, (Fader *) owner);
1531       break;
1532     case PORT_OWNER_TYPE_TRACK:
1533       set_owner_track (self, (Track *) owner);
1534       break;
1535     case PORT_OWNER_TYPE_TRACK_PROCESSOR:
1536       set_owner_track_processor (
1537         self, (TrackProcessor *) owner);
1538       break;
1539     case PORT_OWNER_TYPE_CHANNEL:
1540       set_owner_channel (self, (Channel *) owner);
1541       break;
1542     case PORT_OWNER_TYPE_PLUGIN:
1543       set_owner_plugin (self, (Plugin *) owner);
1544       break;
1545     case PORT_OWNER_TYPE_TRANSPORT:
1546       set_owner_transport (
1547         self, (Transport *) owner);
1548       break;
1549     case PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR:
1550       set_owner_modulator_macro_processor (
1551         self, (ModulatorMacroProcessor *) owner);
1552       break;
1553     case PORT_OWNER_TYPE_AUDIO_ENGINE:
1554       set_owner_audio_engine (
1555         self, (AudioEngine *) owner);
1556       break;
1557     case PORT_OWNER_TYPE_HW:
1558       set_owner_ext_port (
1559         self, (ExtPort *) owner);
1560       break;
1561     default:
1562       g_return_if_reached ();
1563     }
1564 }
1565 
1566 /**
1567  * Returns whether the Port's can be connected (if
1568  * the connection will be valid and won't break the
1569  * acyclicity of the graph).
1570  */
1571 bool
ports_can_be_connected(const Port * src,const Port * dest)1572 ports_can_be_connected (
1573   const Port * src,
1574   const Port *dest)
1575 {
1576   Graph * graph = graph_new (ROUTER);
1577   bool valid =
1578     graph_validate_with_connection (
1579       graph, src, dest);
1580   graph_free (graph);
1581 
1582   return valid;
1583 }
1584 
1585 /**
1586  * Disconnects all the given ports.
1587  */
1588 void
ports_disconnect(Port ** ports,int num_ports,int deleting)1589 ports_disconnect (
1590   Port ** ports,
1591   int     num_ports,
1592   int     deleting)
1593 {
1594   if (!PORT_CONNECTIONS_MGR)
1595     return;
1596 
1597   /* can only be called from the gtk thread */
1598   g_return_if_fail (ZRYTHM_APP_IS_GTK_THREAD);
1599 
1600   /* go through each port */
1601   for (int i = 0; i < num_ports; i++)
1602     {
1603       Port * port = ports[i];
1604 
1605       port_connections_manager_ensure_disconnect_all (
1606         PORT_CONNECTIONS_MGR, &port->id);
1607 
1608       port->num_srcs = 0;
1609       port->num_dests = 0;
1610       port->deleting = deleting;
1611     }
1612 }
1613 
1614 /**
1615  * Disconnects all srcs and dests from port.
1616  */
1617 int
port_disconnect_all(Port * self)1618 port_disconnect_all (
1619   Port * self)
1620 {
1621   g_return_val_if_fail (IS_PORT (self), -1);
1622 
1623   self->num_srcs = 0;
1624   self->num_dests = 0;
1625 
1626   if (!PORT_CONNECTIONS_MGR)
1627     return 0;
1628 
1629   if (!port_is_in_active_project (self))
1630     {
1631 #if 0
1632       g_debug (
1633         "%s (%p) is not a project port, "
1634         "skipping",
1635         self->id.label, self);
1636 #endif
1637       return 0;
1638     }
1639 
1640   GPtrArray * srcs = g_ptr_array_new ();
1641   int num_srcs =
1642     port_connections_manager_get_sources_or_dests (
1643       PORT_CONNECTIONS_MGR, srcs, &self->id,
1644       true);
1645   for (int i = 0; i < num_srcs; i++)
1646     {
1647       PortConnection * conn =
1648         (PortConnection *)
1649         g_ptr_array_index (srcs, i);
1650       port_connections_manager_ensure_disconnect (
1651         PORT_CONNECTIONS_MGR,
1652         conn->src_id, conn->dest_id);
1653     }
1654   g_ptr_array_unref (srcs);
1655 
1656   GPtrArray * dests = g_ptr_array_new ();
1657   int num_dests =
1658     port_connections_manager_get_sources_or_dests (
1659       PORT_CONNECTIONS_MGR, dests, &self->id,
1660       false);
1661   for (int i = 0; i < num_dests; i++)
1662     {
1663       PortConnection * conn =
1664         (PortConnection *)
1665         g_ptr_array_index (dests, i);
1666       port_connections_manager_ensure_disconnect (
1667         PORT_CONNECTIONS_MGR,
1668         conn->src_id, conn->dest_id);
1669     }
1670   g_ptr_array_unref (dests);
1671 
1672 #ifdef HAVE_JACK
1673   if (self->internal_type == INTERNAL_JACK_PORT)
1674     {
1675       expose_to_jack (self, false);
1676     }
1677 #endif
1678 
1679 #ifdef HAVE_RTMIDI
1680   for (int i = self->num_rtmidi_ins - 1; i >= 0;
1681        i--)
1682     {
1683       rtmidi_device_close (
1684         self->rtmidi_ins[i], 1);
1685       self->num_rtmidi_ins--;
1686     }
1687 #endif
1688 
1689   return 0;
1690 }
1691 
1692 /**
1693  * To be called when the port's identifier changes
1694  * to update corresponding identifiers.
1695  *
1696  * @param prev_id Previous identifier to be used
1697  *   for searching.
1698  * @param track The track that owns this port.
1699  * @param update_automation_track Whether to update
1700  *   the identifier in the corresponding automation
1701  *   track as well. This should be false when
1702  *   moving a plugin.
1703  */
1704 void
port_update_identifier(Port * self,const PortIdentifier * prev_id,Track * track,bool update_automation_track)1705 port_update_identifier (
1706   Port *                 self,
1707   const PortIdentifier * prev_id,
1708   Track *                track,
1709   bool                   update_automation_track)
1710 {
1711   /*g_message (*/
1712     /*"updating identifier for %p %s (track pos %d)", */
1713     /*self, self->id.label, self->id.track_pos);*/
1714 
1715   if (port_is_in_active_project (self))
1716     {
1717       /* update in all sources */
1718       GPtrArray * srcs = g_ptr_array_new ();
1719       int num_srcs =
1720         port_connections_manager_get_sources_or_dests (
1721           PORT_CONNECTIONS_MGR, srcs, prev_id,
1722           true);
1723       for (int i = 0; i < num_srcs; i++)
1724         {
1725           PortConnection * conn =
1726             (PortConnection *)
1727             g_ptr_array_index (srcs, i);
1728           if (!port_identifier_is_equal (
1729                  conn->dest_id, &self->id))
1730             {
1731               port_identifier_copy (
1732                 conn->dest_id, &self->id);
1733               port_connections_manager_regenerate_hashtables (
1734                 PORT_CONNECTIONS_MGR);
1735             }
1736         }
1737       g_ptr_array_unref (srcs);
1738 
1739       /* update in all dests */
1740       GPtrArray * dests = g_ptr_array_new ();
1741       int num_dests =
1742         port_connections_manager_get_sources_or_dests (
1743           PORT_CONNECTIONS_MGR, dests, prev_id,
1744           false);
1745       for (int i = 0; i < num_dests; i++)
1746         {
1747           PortConnection * conn =
1748             (PortConnection *)
1749             g_ptr_array_index (dests, i);
1750           if (!port_identifier_is_equal (
1751                  conn->src_id, &self->id))
1752             {
1753               port_identifier_copy (
1754                 conn->src_id, &self->id);
1755               port_connections_manager_regenerate_hashtables (
1756                 PORT_CONNECTIONS_MGR);
1757             }
1758         }
1759       g_ptr_array_unref (dests);
1760 
1761       if (update_automation_track
1762           && self->id.track_name_hash
1763           && self->id.flags & PORT_FLAG_AUTOMATABLE)
1764         {
1765           /* update automation track's port id */
1766           self->at =
1767             automation_track_find_from_port (
1768               self, track, true);
1769           AutomationTrack * at = self->at;
1770           g_return_if_fail (at);
1771           port_identifier_copy (
1772             &at->port_id, &self->id);
1773         }
1774     }
1775 
1776 #if 0
1777   if (self->lv2_port)
1778     {
1779       Lv2Port * port = self->lv2_port;
1780       port_identifier_copy (
1781         &port->port_id, &self->id);
1782     }
1783 #endif
1784 }
1785 
1786 /**
1787  * Updates the track name hash on a track port and
1788  * all its source/destination identifiers.
1789  *
1790  * @param track Owner track.
1791  * @param hash The new hash.
1792  */
1793 void
port_update_track_name_hash(Port * self,Track * track,unsigned int new_hash)1794 port_update_track_name_hash (
1795   Port *       self,
1796   Track *      track,
1797   unsigned int new_hash)
1798 {
1799   PortIdentifier * copy =
1800     port_identifier_clone (&self->id);
1801 
1802   self->id.track_name_hash = new_hash;
1803   if (self->id.owner_type == PORT_OWNER_TYPE_PLUGIN)
1804     {
1805       self->id.plugin_id.track_name_hash = new_hash;
1806     }
1807   port_update_identifier (
1808     self, copy, track, F_UPDATE_AUTOMATION_TRACK);
1809   object_free_w_func_and_null (
1810     port_identifier_free, copy);
1811 }
1812 
1813 #ifdef HAVE_ALSA
1814 #if 0
1815 
1816 /**
1817  * Returns the Port matching the given ALSA
1818  * sequencer port ID.
1819  */
1820 Port *
1821 port_find_by_alsa_seq_id (
1822   const int id)
1823 {
1824   Port * ports[10000];
1825   int num_ports;
1826   Port * port;
1827   port_get_all (ports, &num_ports);
1828   for (int i = 0; i < num_ports; i++)
1829     {
1830       port = ports[i];
1831 
1832       if (port->internal_type ==
1833             INTERNAL_ALSA_SEQ_PORT &&
1834           snd_seq_port_info_get_port (
1835             (snd_seq_port_info_t *) port->data) ==
1836             id)
1837         return port;
1838     }
1839   g_return_val_if_reached (NULL);
1840 }
1841 
1842 static void
1843 expose_to_alsa (
1844   Port * self,
1845   int    expose)
1846 {
1847   if (self->id.type == TYPE_EVENT)
1848     {
1849       unsigned int flags = 0;
1850       if (self->id.flow == FLOW_INPUT)
1851         flags =
1852           SND_SEQ_PORT_CAP_WRITE |
1853           SND_SEQ_PORT_CAP_SUBS_WRITE;
1854       else if (self->id.flow == FLOW_OUTPUT)
1855         flags =
1856           SND_SEQ_PORT_CAP_READ |
1857           SND_SEQ_PORT_CAP_SUBS_READ;
1858       else
1859         g_return_if_reached ();
1860 
1861       if (expose)
1862         {
1863           char lbl[600];
1864           port_get_full_designation (self, lbl);
1865 
1866           g_return_if_fail (
1867             AUDIO_ENGINE->seq_handle);
1868 
1869           int id =
1870             snd_seq_create_simple_port (
1871               AUDIO_ENGINE->seq_handle,
1872               lbl, flags,
1873               SND_SEQ_PORT_TYPE_APPLICATION);
1874           g_return_if_fail (id >= 0);
1875           snd_seq_port_info_t * info;
1876           snd_seq_port_info_malloc (&info);
1877           snd_seq_get_port_info (
1878             AUDIO_ENGINE->seq_handle,
1879             id, info);
1880           self->data = (void *) info;
1881           self->internal_type =
1882             INTERNAL_ALSA_SEQ_PORT;
1883         }
1884       else
1885         {
1886           snd_seq_delete_port (
1887             AUDIO_ENGINE->seq_handle,
1888             snd_seq_port_info_get_port (
1889               (snd_seq_port_info_t *)
1890                 self->data));
1891           self->internal_type = INTERNAL_NONE;
1892           self->data = NULL;
1893         }
1894     }
1895   self->exposed_to_backend = expose;
1896 }
1897 #endif
1898 #endif // HAVE_ALSA
1899 
1900 #ifdef HAVE_RTMIDI
1901 static void
expose_to_rtmidi(Port * self,int expose)1902 expose_to_rtmidi (
1903   Port * self,
1904   int    expose)
1905 {
1906   char lbl[600];
1907   port_get_full_designation (self, lbl);
1908   if (expose)
1909     {
1910 #if 0
1911 
1912       if (self->id.flow == FLOW_INPUT)
1913         {
1914           self->rtmidi_in =
1915             rtmidi_in_create (
1916 #ifdef _WOE32
1917               RTMIDI_API_WINDOWS_MM,
1918 #elif defined(__APPLE__)
1919               RTMIDI_API_MACOSX_CORE,
1920 #else
1921               RTMIDI_API_LINUX_ALSA,
1922 #endif
1923               "Zrythm",
1924               AUDIO_ENGINE->midi_buf_size);
1925 
1926           /* don't ignore any messages */
1927           rtmidi_in_ignore_types (
1928             self->rtmidi_in, 0, 0, 0);
1929 
1930           rtmidi_open_port (
1931             self->rtmidi_in, 1, lbl);
1932         }
1933 #endif
1934       g_message ("exposing %s", lbl);
1935     }
1936   else
1937     {
1938 #if 0
1939       if (self->id.flow == FLOW_INPUT &&
1940           self->rtmidi_in)
1941         {
1942           rtmidi_close_port (self->rtmidi_in);
1943           self->rtmidi_in = NULL;
1944         }
1945 #endif
1946       g_message ("unexposing %s", lbl);
1947     }
1948   self->exposed_to_backend = expose;
1949 }
1950 
1951 /**
1952  * Sums the inputs coming in from RtMidi
1953  * before the port is processed.
1954  */
1955 void
port_sum_data_from_rtmidi(Port * self,const nframes_t start_frame,const nframes_t nframes)1956 port_sum_data_from_rtmidi (
1957   Port * self,
1958   const nframes_t start_frame,
1959   const nframes_t nframes)
1960 {
1961   g_return_if_fail (
1962     /*self->id.flow == FLOW_INPUT &&*/
1963     midi_backend_is_rtmidi (
1964       AUDIO_ENGINE->midi_backend));
1965 
1966   for (int i = 0; i < self->num_rtmidi_ins; i++)
1967     {
1968       RtMidiDevice * dev = self->rtmidi_ins[i];
1969       MidiEvent * ev;
1970       for (int j = 0; j < dev->events->num_events;
1971            j++)
1972         {
1973           ev = &dev->events->events[j];
1974 
1975           if (ev->time >= start_frame &&
1976               ev->time < start_frame + nframes)
1977             {
1978               midi_byte_t channel =
1979                 ev->raw_buffer[0] & 0xf;
1980               Track * track =
1981                 port_get_track (self, 0);
1982               if (self->id.owner_type ==
1983                     PORT_OWNER_TYPE_TRACK_PROCESSOR &&
1984                   !track)
1985                 {
1986                   g_return_if_reached ();
1987                 }
1988 
1989               if (self->id.owner_type ==
1990                     PORT_OWNER_TYPE_TRACK_PROCESSOR &&
1991                   (track->type ==
1992                        TRACK_TYPE_MIDI ||
1993                      track->type ==
1994                        TRACK_TYPE_INSTRUMENT) &&
1995                     !track->channel->
1996                       all_midi_channels &&
1997                     !track->channel->
1998                       midi_channels[channel])
1999                 {
2000                   /* different channel */
2001                 }
2002               else
2003                 {
2004                   midi_events_add_event_from_buf (
2005                     self->midi_events,
2006                     ev->time, ev->raw_buffer,
2007                     3, F_NOT_QUEUED);
2008                 }
2009             }
2010         }
2011     }
2012 
2013 #if 0
2014   if (DEBUGGING &&
2015       self->midi_events->num_events > 0)
2016     {
2017       MidiEvent * ev =
2018         &self->midi_events->events[0];
2019       char designation[600];
2020       port_get_full_designation (
2021         self, designation);
2022       g_message (
2023         "RtMidi (%s): have %d events\n"
2024         "first event is: [%u] %hhx %hhx %hhx",
2025         designation, self->midi_events->num_events,
2026         ev->time, ev->raw_buffer[0],
2027         ev->raw_buffer[1], ev->raw_buffer[2]);
2028     }
2029 #endif
2030 }
2031 
2032 /**
2033  * Dequeue the midi events from the ring
2034  * buffers into \ref RtMidiDevice.events.
2035  */
2036 void
port_prepare_rtmidi_events(Port * self)2037 port_prepare_rtmidi_events (
2038   Port * self)
2039 {
2040   g_return_if_fail (
2041     /*self->id.flow == FLOW_INPUT &&*/
2042     midi_backend_is_rtmidi (
2043       AUDIO_ENGINE->midi_backend));
2044 
2045   gint64 cur_time = g_get_monotonic_time ();
2046   for (int i = 0; i < self->num_rtmidi_ins; i++)
2047     {
2048       RtMidiDevice * dev = self->rtmidi_ins[i];
2049 
2050       /* clear the events */
2051       midi_events_clear (dev->events, 0);
2052 
2053       uint32_t read_space = 0;
2054       zix_sem_wait (&dev->midi_ring_sem);
2055       do
2056         {
2057           read_space =
2058             zix_ring_read_space (dev->midi_ring);
2059           if (read_space <= sizeof(MidiEventHeader))
2060             {
2061               /* no more events */
2062               break;
2063             }
2064 
2065           /* peek the next event header to check
2066            * the time */
2067           MidiEventHeader h = { 0, 0 };
2068           zix_ring_peek (
2069             dev->midi_ring, &h, sizeof (h));
2070           g_return_if_fail (h.size > 0);
2071 
2072           /* read event header */
2073           zix_ring_read (
2074             dev->midi_ring, &h, sizeof (h));
2075 
2076           /* read event body */
2077           midi_byte_t raw[h.size];
2078           zix_ring_read (
2079             dev->midi_ring, raw, sizeof (raw));
2080 
2081           /* calculate event timestamp */
2082           gint64 length =
2083             cur_time - self->last_midi_dequeue;
2084           midi_time_t ev_time =
2085             (midi_time_t)
2086             (((double) h.time / (double) length) *
2087             (double) AUDIO_ENGINE->block_length);
2088 
2089           if (ev_time >= AUDIO_ENGINE->block_length)
2090             {
2091               g_warning (
2092                 "event with invalid time %u "
2093                 "received. the maximum allowed time "
2094                 "is %" PRIu32 ". setting it to "
2095                 "%u...",
2096                 ev_time,
2097                 AUDIO_ENGINE->block_length - 1,
2098                 AUDIO_ENGINE->block_length - 1);
2099               ev_time =
2100                 (midi_byte_t)
2101                 (AUDIO_ENGINE->block_length - 1);
2102             }
2103 
2104           midi_events_add_event_from_buf (
2105             dev->events,
2106             ev_time, raw, (int) h.size,
2107             F_NOT_QUEUED);
2108         } while (
2109             read_space > sizeof (MidiEventHeader));
2110       zix_sem_post (&dev->midi_ring_sem);
2111     }
2112   self->last_midi_dequeue = cur_time;
2113 }
2114 #endif // HAVE_RTMIDI
2115 
2116 #ifdef HAVE_RTAUDIO
2117 static void
expose_to_rtaudio(Port * self,int expose)2118 expose_to_rtaudio (
2119   Port * self,
2120   int    expose)
2121 {
2122   Track * track = port_get_track (self, 0);
2123   if (!track)
2124     return;
2125 
2126   Channel * ch = track->channel;
2127   if (!ch)
2128     return;
2129 
2130   char lbl[600];
2131   port_get_full_designation (self, lbl);
2132   if (expose)
2133     {
2134       if (self->id.flow == FLOW_INPUT)
2135         {
2136           if (self->id.flags & PORT_FLAG_STEREO_L)
2137             {
2138               if (ch->all_stereo_l_ins)
2139                 {
2140                 }
2141               else
2142                 {
2143                   for (int i = 0;
2144                        i < ch->num_ext_stereo_l_ins; i++)
2145                     {
2146                       int idx =
2147                         self->num_rtaudio_ins;
2148                       ExtPort * ext_port =
2149                         ch->ext_stereo_l_ins[i];
2150                       ext_port_print (ext_port);
2151                       self->rtaudio_ins[idx] =
2152                         rtaudio_device_new (
2153                           ext_port->rtaudio_is_input,
2154                           NULL,
2155                           ext_port->rtaudio_id,
2156                           ext_port->rtaudio_channel_idx,
2157                           self);
2158                       rtaudio_device_open (
2159                         self->rtaudio_ins[idx], true);
2160                       self->num_rtaudio_ins++;
2161                     }
2162                 }
2163             }
2164           else if (self->id.flags & PORT_FLAG_STEREO_R)
2165             {
2166               if (ch->all_stereo_r_ins)
2167                 {
2168                 }
2169               else
2170                 {
2171                   for (int i = 0;
2172                        i < ch->num_ext_stereo_r_ins; i++)
2173                     {
2174                       int idx =
2175                         self->num_rtaudio_ins;
2176                       ExtPort * ext_port =
2177                         ch->ext_stereo_r_ins[i];
2178                       ext_port_print (ext_port);
2179                       self->rtaudio_ins[idx] =
2180                         rtaudio_device_new (
2181                           ext_port->rtaudio_is_input,
2182                           NULL,
2183                           ext_port->rtaudio_id,
2184                           ext_port->rtaudio_channel_idx,
2185                           self);
2186                       rtaudio_device_open (
2187                         self->rtaudio_ins[idx], true);
2188                       self->num_rtaudio_ins++;
2189                     }
2190                 }
2191             }
2192         }
2193       g_message ("exposing %s", lbl);
2194     }
2195   else
2196     {
2197       if (self->id.flow == FLOW_INPUT)
2198         {
2199           for (int i = 0; i < self->num_rtaudio_ins;
2200                i++)
2201             {
2202               rtaudio_device_close (
2203                 self->rtaudio_ins[i], true);
2204             }
2205           self->num_rtaudio_ins = 0;
2206         }
2207       g_message ("unexposing %s", lbl);
2208     }
2209   self->exposed_to_backend = expose;
2210 }
2211 
2212 /**
2213  * Dequeue the audio data from the ring buffer
2214  * into @ref RtAudioDevice.buf.
2215  */
2216 void
port_prepare_rtaudio_data(Port * self)2217 port_prepare_rtaudio_data (
2218   Port * self)
2219 {
2220   g_return_if_fail (
2221     /*self->id.flow == FLOW_INPUT &&*/
2222     audio_backend_is_rtaudio (
2223       AUDIO_ENGINE->audio_backend));
2224 
2225   for (int i = 0; i < self->num_rtaudio_ins; i++)
2226     {
2227       RtAudioDevice * dev = self->rtaudio_ins[i];
2228 
2229       /* clear the data */
2230       dsp_fill (
2231         dev->buf,
2232         DENORMAL_PREVENTION_VAL,
2233         AUDIO_ENGINE->nframes);
2234 
2235       zix_sem_wait (&dev->audio_ring_sem);
2236 
2237       uint32_t read_space =
2238         zix_ring_read_space (dev->audio_ring);
2239 
2240       /* only process if data exists */
2241       if (read_space >=
2242             AUDIO_ENGINE->nframes *
2243             sizeof (float))
2244         {
2245           /* read the buffer */
2246           zix_ring_read (
2247             dev->audio_ring,
2248             &dev->buf[0],
2249             AUDIO_ENGINE->nframes *
2250               sizeof (float));
2251         }
2252 
2253       zix_sem_post (&dev->audio_ring_sem);
2254     }
2255 }
2256 
2257 /**
2258  * Sums the inputs coming in from RtAudio
2259  * before the port is processed.
2260  */
2261 void
port_sum_data_from_rtaudio(Port * self,const nframes_t start_frame,const nframes_t nframes)2262 port_sum_data_from_rtaudio (
2263   Port * self,
2264   const nframes_t start_frame,
2265   const nframes_t nframes)
2266 {
2267   g_return_if_fail (
2268     /*self->id.flow == FLOW_INPUT &&*/
2269     audio_backend_is_rtaudio (
2270       AUDIO_ENGINE->audio_backend));
2271 
2272   for (int i = 0; i < self->num_rtaudio_ins; i++)
2273     {
2274       RtAudioDevice * dev = self->rtaudio_ins[i];
2275 
2276       dsp_add2 (
2277         &self->buf[start_frame],
2278         &dev->buf[start_frame], nframes);
2279     }
2280 }
2281 #endif // HAVE_RTAUDIO
2282 
2283 #ifdef _WOE32
2284 /**
2285  * Sums the inputs coming in from Windows MME,
2286  * before the port is processed.
2287  */
2288 static void
sum_data_from_windows_mme(Port * self,const nframes_t start_frame,const nframes_t nframes)2289 sum_data_from_windows_mme (
2290   Port * self,
2291   const nframes_t start_frame,
2292   const nframes_t nframes)
2293 {
2294   g_return_if_fail (
2295     self->id.flow == FLOW_INPUT &&
2296     AUDIO_ENGINE->midi_backend ==
2297       MIDI_BACKEND_WINDOWS_MME);
2298 
2299   if (self->id.owner_type ==
2300         PORT_OWNER_TYPE_AUDIO_ENGINE)
2301     return;
2302 
2303   /* append events from Windows MME if any */
2304   for (int i = 0; i < self->num_mme_connections;
2305        i++)
2306     {
2307       WindowsMmeDevice * dev =
2308         self->mme_connections[i];
2309       if (!dev)
2310         {
2311           g_warn_if_reached ();
2312           continue;
2313         }
2314 
2315       MidiEvent ev;
2316       gint64 cur_time = g_get_monotonic_time ();
2317       while (
2318         windows_mme_device_dequeue_midi_event_struct (
2319           dev, self->last_midi_dequeue,
2320           cur_time, &ev))
2321         {
2322           int is_valid =
2323             ev.time >= start_frame &&
2324             ev.time < start_frame + nframes;
2325           if (!is_valid)
2326             {
2327               g_warning (
2328                 "Invalid event time %u", ev.time);
2329               continue;
2330             }
2331 
2332           if (ev.time >= start_frame &&
2333               ev.time < start_frame + nframes)
2334             {
2335               midi_byte_t channel =
2336                 ev.raw_buffer[0] & 0xf;
2337               Track * track =
2338                 port_get_track (self, 0);
2339               if (self->id.owner_type ==
2340                     PORT_OWNER_TYPE_TRACK_PROCESSOR &&
2341                   (track->type ==
2342                      TRACK_TYPE_MIDI ||
2343                    track->type ==
2344                      TRACK_TYPE_INSTRUMENT) &&
2345                   !track->channel->
2346                     all_midi_channels &&
2347                   !track->channel->
2348                     midi_channels[channel])
2349                 {
2350                   /* different channel */
2351                 }
2352               else
2353                 {
2354                   midi_events_add_event_from_buf (
2355                     self->midi_events,
2356                     ev.time, ev.raw_buffer, 3, 0);
2357                 }
2358             }
2359         }
2360       self->last_midi_dequeue = cur_time;
2361 
2362       if (self->midi_events->num_events > 0)
2363         {
2364           MidiEvent * ev =
2365             &self->midi_events->events[0];
2366           char designation[600];
2367           port_get_full_designation (
2368             self, designation);
2369           g_message (
2370             "MME MIDI (%s): have %d events\n"
2371             "first event is: [%u] %hhx %hhx %hhx",
2372             designation,
2373             self->midi_events->num_events,
2374             ev->time, ev->raw_buffer[0],
2375             ev->raw_buffer[1], ev->raw_buffer[2]);
2376         }
2377     }
2378 }
2379 
2380 /**
2381  * Sends the port data to Windows MME, after the
2382  * port is processed.
2383  */
2384 static void
send_data_to_windows_mme(Port * self,const nframes_t start_frame,const nframes_t nframes)2385 send_data_to_windows_mme (
2386   Port * self,
2387   const nframes_t start_frame,
2388   const nframes_t nframes)
2389 {
2390   g_return_if_fail (
2391     self->id.flow == FLOW_OUTPUT &&
2392     AUDIO_ENGINE->midi_backend ==
2393       MIDI_BACKEND_WINDOWS_MME);
2394 
2395   /* TODO send midi events */
2396 }
2397 #endif
2398 
2399 /**
2400  * To be called when a control's value changes
2401  * so that a message can be sent to the UI.
2402  */
2403 static void
port_forward_control_change_event(Port * self)2404 port_forward_control_change_event (
2405   Port * self)
2406 {
2407   /* if lv2 port/parameter */
2408   if (self->value_type > 0)
2409     {
2410       Plugin * pl = port_get_plugin (self, 1);
2411       g_return_if_fail (
2412         IS_PLUGIN_AND_NONNULL (pl) && pl->lv2);
2413       lv2_ui_send_control_val_event_from_plugin_to_ui (
2414         pl->lv2, self);
2415     }
2416   else if (
2417     self->id.owner_type ==
2418       PORT_OWNER_TYPE_PLUGIN)
2419     {
2420       Plugin * pl = port_get_plugin (self, 1);
2421       if (pl)
2422         {
2423 #ifdef HAVE_CARLA
2424           if (pl->setting->open_with_carla &&
2425               self->carla_param_id >= 0)
2426             {
2427               g_return_if_fail (pl->carla);
2428               carla_native_plugin_set_param_value (
2429                 pl->carla,
2430                 (uint32_t) self->carla_param_id,
2431                 self->control);
2432             }
2433 #endif
2434           if (!g_atomic_int_get (
2435                  &pl->state_changed_event_sent))
2436             {
2437               EVENTS_PUSH (
2438                 ET_PLUGIN_STATE_CHANGED, pl);
2439               g_atomic_int_set (
2440                 &pl->state_changed_event_sent, 1);
2441             }
2442         }
2443     }
2444   else if (self->id.owner_type ==
2445              PORT_OWNER_TYPE_FADER)
2446     {
2447       Track * track = port_get_track (self, 1);
2448       g_return_if_fail (
2449         track && track->channel);
2450 
2451       if (self->id.flags & PORT_FLAG_FADER_MUTE ||
2452           self->id.flags2 & PORT_FLAG2_FADER_SOLO ||
2453           self->id.flags2 &
2454             PORT_FLAG2_FADER_LISTEN ||
2455           self->id.flags2 &
2456             PORT_FLAG2_FADER_MONO_COMPAT)
2457         {
2458           EVENTS_PUSH (
2459             ET_TRACK_FADER_BUTTON_CHANGED, track);
2460         }
2461       else if (self->id.flags & PORT_FLAG_AMPLITUDE)
2462         {
2463           if (ZRYTHM_HAVE_UI)
2464             g_return_if_fail (
2465               track->channel->widget);
2466           fader_update_volume_and_fader_val (
2467             track->channel->fader);
2468           EVENTS_PUSH (
2469             ET_CHANNEL_FADER_VAL_CHANGED,
2470             track->channel);
2471         }
2472     }
2473   else if (self->id.owner_type ==
2474              PORT_OWNER_TYPE_CHANNEL_SEND)
2475     {
2476       Track * track = port_get_track (self, 1);
2477       ChannelSend * send =
2478         track->channel->sends[self->id.port_index];
2479       EVENTS_PUSH (
2480         ET_CHANNEL_SEND_CHANGED, send);
2481     }
2482   else if (
2483     self->id.owner_type == PORT_OWNER_TYPE_TRACK)
2484     {
2485       Track * track = port_get_track (self, 1);
2486       EVENTS_PUSH (
2487         ET_TRACK_STATE_CHANGED, track);
2488     }
2489 }
2490 
2491 /**
2492  * Sets the given control value to the
2493  * corresponding underlying structure in the Port.
2494  *
2495  * Note: this is only for setting the base values
2496  * (eg when automating via an automation lane). For
2497  * CV automations this should not be used.
2498  *
2499  * @param is_normalized Whether the given value is
2500  *   normalized between 0 and 1.
2501  * @param forward_event Whether to forward a port
2502  *   control change event to the plugin UI. Only
2503  *   applicable for plugin control ports.
2504  *   If the control is being changed manually or
2505  *   from within Zrythm, this should be true to
2506  *   notify the plugin of the change.
2507  */
2508 void
port_set_control_value(Port * self,const float val,const bool is_normalized,const bool forward_event)2509 port_set_control_value (
2510   Port *      self,
2511   const float val,
2512   const bool  is_normalized,
2513   const bool  forward_event)
2514 {
2515   PortIdentifier * id = &self->id;
2516 
2517   /* set the base value */
2518   if (is_normalized)
2519     {
2520       float minf = self->minf;
2521       float maxf = self->maxf;
2522       self->base_value =
2523         minf + val * (maxf - minf);
2524     }
2525   else
2526     {
2527       self->base_value = val;
2528     }
2529 
2530   self->unsnapped_control = self->base_value;
2531   self->base_value =
2532     control_port_get_snapped_val_from_val (
2533       self, self->unsnapped_control);
2534 
2535   if (!math_floats_equal (
2536         self->control, self->base_value))
2537     {
2538       self->control = self->base_value;
2539 
2540       /* remember time */
2541       self->last_change = g_get_monotonic_time ();
2542       self->value_changed_from_reading = false;
2543 
2544       /* if bpm, update engine */
2545       if (id->flags & PORT_FLAG_BPM)
2546         {
2547           /* this must only be called during
2548            * processing kickoff or while the
2549            * engine is stopped */
2550           g_return_if_fail (
2551             !engine_get_run (AUDIO_ENGINE)
2552             ||
2553             router_is_processing_kickoff_thread (
2554               ROUTER));
2555 
2556           int beats_per_bar =
2557             tempo_track_get_beats_per_bar (
2558               P_TEMPO_TRACK);
2559           engine_update_frames_per_tick (
2560             AUDIO_ENGINE, beats_per_bar,
2561             self->control,
2562             AUDIO_ENGINE->sample_rate, false, true);
2563           EVENTS_PUSH (ET_BPM_CHANGED, NULL);
2564         }
2565 
2566       /* if time sig value, update transport
2567        * caches */
2568       if (id->flags2 & PORT_FLAG2_BEATS_PER_BAR ||
2569           id->flags2 & PORT_FLAG2_BEAT_UNIT)
2570         {
2571           /* this must only be called during
2572            * processing kickoff or while the
2573            * engine is stopped */
2574           g_return_if_fail (
2575             !engine_get_run (AUDIO_ENGINE)
2576             ||
2577             router_is_processing_kickoff_thread (
2578               ROUTER));
2579 
2580           int beats_per_bar =
2581             tempo_track_get_beats_per_bar (
2582               P_TEMPO_TRACK);
2583           int beat_unit =
2584             tempo_track_get_beat_unit (
2585               P_TEMPO_TRACK);
2586           bpm_t bpm =
2587             tempo_track_get_current_bpm (
2588               P_TEMPO_TRACK);
2589           transport_update_caches (
2590             TRANSPORT, beats_per_bar, beat_unit);
2591           bool update_from_ticks =
2592             id->flags2 & PORT_FLAG2_BEATS_PER_BAR;
2593           engine_update_frames_per_tick (
2594             AUDIO_ENGINE, beats_per_bar, bpm,
2595             AUDIO_ENGINE->sample_rate, false,
2596             update_from_ticks);
2597           EVENTS_PUSH (
2598             ET_TIME_SIGNATURE_CHANGED, NULL);
2599         }
2600 
2601       /* if plugin enabled port, also set
2602        * plugin's own enabled port value and
2603        * vice versa */
2604       if (port_is_in_active_project (self)
2605           &&
2606           self->id.flags & PORT_FLAG_PLUGIN_ENABLED)
2607         {
2608           Plugin * pl = port_get_plugin (self, 1);
2609           g_return_if_fail (pl);
2610 
2611           if (self->id.flags &
2612                 PORT_FLAG_GENERIC_PLUGIN_PORT)
2613             {
2614               if (
2615                 pl->own_enabled_port &&
2616                 !math_floats_equal (
2617                   pl->own_enabled_port->
2618                     control,
2619                   self->control))
2620                 {
2621                   g_debug (
2622                     "generic enabled "
2623                     "changed - changing "
2624                     "plugin's own enabled");
2625                   port_set_control_value (
2626                     pl->own_enabled_port,
2627                     self->control, false,
2628                     F_PUBLISH_EVENTS);
2629                 }
2630             }
2631           else if (!math_floats_equal (
2632                      pl->enabled->control,
2633                      self->control))
2634             {
2635               g_debug (
2636                 "plugin's own enabled "
2637                 "changed - changing "
2638                 "generic enabled");
2639               port_set_control_value (
2640                 pl->enabled,
2641                 self->control, false,
2642                 F_PUBLISH_EVENTS);
2643             }
2644         }
2645     }
2646 
2647   if (forward_event)
2648     {
2649       port_forward_control_change_event (self);
2650     }
2651 }
2652 
2653 /**
2654  * Gets the given control value from the
2655  * corresponding underlying structure in the Port.
2656  *
2657  * @param normalized Whether to get the value
2658  *   normalized or not.
2659  */
2660 float
port_get_control_value(Port * self,const bool normalize)2661 port_get_control_value (
2662   Port *      self,
2663   const bool  normalize)
2664 {
2665   g_return_val_if_fail (
2666     self->id.type == TYPE_CONTROL, 0.f);
2667 
2668   /* verify that plugin exists if plugin control */
2669   if (ZRYTHM_TESTING
2670       && port_is_in_active_project (self)
2671       && self->id.flags & PORT_FLAG_PLUGIN_CONTROL)
2672     {
2673       Plugin * pl = port_get_plugin (self, 1);
2674       g_return_val_if_fail (
2675         IS_PLUGIN_AND_NONNULL (pl), 0.f);
2676     }
2677 
2678   if (normalize)
2679     {
2680       return
2681         control_port_real_val_to_normalized (
2682           self, self->control);
2683     }
2684   else
2685     {
2686       return self->control;
2687     }
2688 }
2689 
2690 int
port_scale_point_cmp(const void * _a,const void * _b)2691 port_scale_point_cmp (
2692   const void * _a,
2693   const void * _b)
2694 {
2695   const PortScalePoint * a =
2696     *(PortScalePoint const **) _a;
2697   const PortScalePoint * b =
2698     *(PortScalePoint const **) _b;
2699   return a->val - b->val > 0.f;
2700 }
2701 
2702 PortScalePoint *
port_scale_point_new(const float val,const char * label)2703 port_scale_point_new (
2704   const float  val,
2705   const char * label)
2706 {
2707   PortScalePoint * self =
2708     object_new (PortScalePoint);
2709 
2710   self->val = val;
2711   self->label = g_strdup (label);
2712 
2713   return self;
2714 }
2715 
2716 void
port_scale_point_free(PortScalePoint * self)2717 port_scale_point_free (
2718   PortScalePoint * self)
2719 {
2720   g_free_and_null (self->label);
2721 
2722   object_zero_and_free (self);
2723 }
2724 
2725 /**
2726  * Copies the metadata from a project port to
2727  * the given port.
2728  *
2729  * Used when doing delete actions so that ports
2730  * can be restored on undo.
2731  */
2732 void
port_copy_metadata_from_project(Port * clone_port,Port * prj_port)2733 port_copy_metadata_from_project (
2734   Port * clone_port,
2735   Port * prj_port)
2736 {
2737   clone_port->control = prj_port->control;
2738 }
2739 
2740 /**
2741  * Copies the port values from @ref other to @ref
2742  * self.
2743  *
2744  * @param self
2745  * @param other
2746  */
2747 void
port_copy_values(Port * self,const Port * other)2748 port_copy_values (
2749   Port *       self,
2750   const Port * other)
2751 {
2752   /* set value */
2753   self->control = other->control;
2754 }
2755 
2756 /**
2757  * Reverts the data on the corresponding project
2758  * port for the given non-project port.
2759  *
2760  * This restores src/dest connections and the
2761  * control value.
2762  *
2763  * @param self Project port.
2764  * @param non_project Non-project port.
2765  */
2766 void
port_restore_from_non_project(Port * self,Port * non_project)2767 port_restore_from_non_project (
2768   Port * self,
2769   Port * non_project)
2770 {
2771   Port * prj_port = self;
2772 
2773   /* set value */
2774   prj_port->control = non_project->control;
2775 
2776   g_return_if_fail (
2777     non_project->num_srcs <=
2778       (int) non_project->srcs_size);
2779   g_return_if_fail (
2780     non_project->num_dests <=
2781       (int) non_project->dests_size);
2782 }
2783 
2784 /**
2785  * Creates stereo ports for generic use.
2786  *
2787  * @param in 1 for in, 0 for out.
2788  * @param owner Pointer to the owner. The type is
2789  *   determined by owner_type.
2790  */
2791 StereoPorts *
stereo_ports_new_generic(int in,const char * name,PortOwnerType owner_type,void * owner)2792 stereo_ports_new_generic (
2793   int           in,
2794   const char *  name,
2795   PortOwnerType owner_type,
2796   void *        owner)
2797 {
2798   char * pll =
2799     g_strdup_printf (
2800       "%s L", name);
2801   char * plr =
2802     g_strdup_printf (
2803       "%s R", name);
2804 
2805   StereoPorts * ports =
2806     stereo_ports_new_from_existing (
2807       port_new_with_type (
2808         TYPE_AUDIO,
2809         in ? FLOW_INPUT : FLOW_OUTPUT,
2810         pll),
2811       port_new_with_type (
2812         TYPE_AUDIO,
2813         in ? FLOW_INPUT : FLOW_OUTPUT,
2814         plr));
2815   ports->l->id.flags |=
2816     PORT_FLAG_STEREO_L;
2817   ports->r->id.flags |=
2818     PORT_FLAG_STEREO_R;
2819 
2820   port_set_owner (ports->l, owner_type, owner);
2821   port_set_owner (ports->r, owner_type, owner);
2822 
2823   g_free (pll);
2824   g_free (plr);
2825 
2826   return ports;
2827 }
2828 
2829 /**
2830  * First sets port buf to 0, then sums the given
2831  * port signal from its inputs.
2832  *
2833  * @param noroll Clear the port buffer in this
2834  *   range.
2835  */
2836 void
port_process(Port * port,const EngineProcessTimeInfo * const time_nfo,const bool noroll)2837 port_process (
2838   Port *                              port,
2839   const EngineProcessTimeInfo * const time_nfo,
2840   const bool                          noroll)
2841 {
2842 #define nframes (time_nfo->nframes)
2843 #define local_offset (time_nfo->local_offset)
2844 
2845   g_return_if_fail (IS_PORT (port));
2846 
2847   const PortIdentifier * id = &port->id;
2848 
2849   Track * track = NULL;
2850   if (id->owner_type ==
2851         PORT_OWNER_TYPE_TRACK_PROCESSOR
2852       ||
2853       id->owner_type == PORT_OWNER_TYPE_TRACK
2854       ||
2855       id->owner_type == PORT_OWNER_TYPE_CHANNEL
2856       ||
2857       /* if track/channel fader */
2858       (id->owner_type == PORT_OWNER_TYPE_FADER
2859        &&
2860        (id->flags2 & PORT_FLAG2_PREFADER
2861         || id->flags2 & PORT_FLAG2_POSTFADER))
2862       ||
2863       (id->owner_type == PORT_OWNER_TYPE_PLUGIN
2864        &&
2865        id->plugin_id.slot_type ==
2866          PLUGIN_SLOT_INSTRUMENT))
2867     {
2868       if (ZRYTHM_TESTING)
2869         track = port_get_track (port, true);
2870       else
2871         track = port->track;
2872       g_return_if_fail (
2873         IS_TRACK_AND_NONNULL (track));
2874     }
2875 
2876   bool is_stereo_port =
2877     id->flags & PORT_FLAG_STEREO_L ||
2878     id->flags & PORT_FLAG_STEREO_R;
2879 
2880   switch (id->type)
2881     {
2882     case TYPE_EVENT:
2883       if (noroll)
2884         break;
2885 
2886       if (G_UNLIKELY (
2887             id->owner_type ==
2888               PORT_OWNER_TYPE_TRACK_PROCESSOR &&
2889             !track))
2890         {
2891           g_return_if_reached ();
2892         }
2893 
2894       /* if piano roll keys, add the notes to the
2895        * piano roll "current notes" (to show
2896        * pressed keys in the UI) */
2897       if (G_UNLIKELY (
2898             id->owner_type ==
2899               PORT_OWNER_TYPE_TRACK_PROCESSOR
2900             && track
2901             && port == track->processor->midi_out
2902             && port->midi_events->num_events > 0
2903             && CLIP_EDITOR->has_region
2904             &&
2905             CLIP_EDITOR->region_id.
2906               track_name_hash ==
2907                 track_get_name_hash (track)))
2908         {
2909           MidiEvents * events = port->midi_events;
2910           bool events_processed = false;
2911           for (int i = 0;
2912                i < events->num_events; i++)
2913             {
2914               MidiEvent * ev = &events->events[i];
2915               switch (ev->type)
2916                 {
2917                 case MIDI_EVENT_TYPE_NOTE_ON:
2918                   piano_roll_add_current_note (
2919                     PIANO_ROLL, ev->note_pitch);
2920                   events_processed = true;
2921                   break;
2922                 case MIDI_EVENT_TYPE_NOTE_OFF:
2923                   piano_roll_remove_current_note (
2924                     PIANO_ROLL, ev->note_pitch);
2925                   events_processed = true;
2926                   break;
2927                 case MIDI_EVENT_TYPE_ALL_NOTES_OFF:
2928                   PIANO_ROLL->num_current_notes = 0;
2929                   events_processed = true;
2930                   break;
2931                 default:
2932                   break;
2933                 }
2934             }
2935           if (events_processed)
2936             {
2937               EVENTS_PUSH (
2938                 ET_PIANO_ROLL_KEY_ON_OFF, NULL);
2939             }
2940         }
2941 
2942       /* only consider incoming external data if
2943        * armed for recording (if the port is owner
2944        * by a track), otherwise always consider
2945        * incoming external data */
2946       if ((id->owner_type !=
2947              PORT_OWNER_TYPE_TRACK_PROCESSOR ||
2948            (id->owner_type ==
2949               PORT_OWNER_TYPE_TRACK_PROCESSOR &&
2950             track &&
2951             track_type_can_record (track->type) &&
2952             track_get_recording (track))) &&
2953            id->flow == FLOW_INPUT)
2954         {
2955           switch (AUDIO_ENGINE->midi_backend)
2956             {
2957 #ifdef HAVE_JACK
2958             case MIDI_BACKEND_JACK:
2959               sum_data_from_jack (
2960                 port, local_offset, nframes);
2961               break;
2962 #endif
2963 #ifdef _WOE32
2964             case MIDI_BACKEND_WINDOWS_MME:
2965               sum_data_from_windows_mme (
2966                 port, local_offset, nframes);
2967               break;
2968 #endif
2969 #ifdef HAVE_RTMIDI
2970             case MIDI_BACKEND_ALSA_RTMIDI:
2971             case MIDI_BACKEND_JACK_RTMIDI:
2972             case MIDI_BACKEND_WINDOWS_MME_RTMIDI:
2973             case MIDI_BACKEND_COREMIDI_RTMIDI:
2974               port_sum_data_from_rtmidi (
2975                 port, local_offset, nframes);
2976               break;
2977 #endif
2978             default:
2979               break;
2980             }
2981         }
2982 
2983       /* set midi capture if hardware */
2984       if (id->owner_type ==
2985             PORT_OWNER_TYPE_HW)
2986         {
2987           MidiEvents * events = port->midi_events;
2988           if (events->num_events > 0)
2989             {
2990               AUDIO_ENGINE->trigger_midi_activity =
2991                 1;
2992 
2993               /* capture cc if capturing */
2994               if (AUDIO_ENGINE->capture_cc)
2995                 {
2996                   memcpy (
2997                     AUDIO_ENGINE->last_cc,
2998                     events->events[
2999                       events->num_events - 1].
3000                         raw_buffer,
3001                     sizeof (midi_byte_t) * 3);
3002                 }
3003 
3004               /* send cc to mapped ports */
3005               for (int i = 0;
3006                    i < events->num_events; i++)
3007                 {
3008                   MidiEvent * ev =
3009                     &events->events[i];
3010                   midi_mappings_apply (
3011                     MIDI_MAPPINGS, ev->raw_buffer);
3012                 }
3013             }
3014         }
3015 
3016       for (int k = 0; k < port->num_srcs; k++)
3017         {
3018           Port * src_port = port->srcs[k];
3019           const PortConnection * conn =
3020             port->src_connections[k];
3021           if (!conn->enabled)
3022             continue;
3023 
3024           g_return_if_fail (
3025             src_port->id.type == TYPE_EVENT);
3026 
3027           /* if hardware device connected to
3028            * track processor input, only allow
3029            * signal to pass if armed and
3030            * MIDI channel is valid */
3031           if (src_port->id.owner_type ==
3032                 PORT_OWNER_TYPE_HW &&
3033               id->owner_type ==
3034                 PORT_OWNER_TYPE_TRACK_PROCESSOR)
3035             {
3036               g_return_if_fail (track);
3037 
3038               /* skip if not armed */
3039               if (!track_get_recording (track))
3040                 continue;
3041 
3042               /* if not set to "all channels",
3043                * filter-append */
3044               if ((track->type ==
3045                      TRACK_TYPE_MIDI ||
3046                    track->type ==
3047                      TRACK_TYPE_INSTRUMENT) &&
3048                    !track->channel->
3049                      all_midi_channels)
3050                 {
3051                   midi_events_append_w_filter (
3052                     src_port->midi_events,
3053                     port->midi_events,
3054                     track->channel->
3055                       midi_channels,
3056                     local_offset,
3057                     nframes, F_NOT_QUEUED);
3058                   continue;
3059                 }
3060 
3061               /* otherwise append normally */
3062             }
3063 
3064           midi_events_append (
3065             src_port->midi_events,
3066             port->midi_events, local_offset,
3067             nframes, F_NOT_QUEUED);
3068         } /* foreach source */
3069 
3070       if (id->flow == FLOW_OUTPUT)
3071         {
3072           switch (AUDIO_ENGINE->midi_backend)
3073             {
3074 #ifdef HAVE_JACK
3075             case MIDI_BACKEND_JACK:
3076               send_data_to_jack (
3077                 port, local_offset, nframes);
3078               break;
3079 #endif
3080 #ifdef _WOE32
3081             case MIDI_BACKEND_WINDOWS_MME:
3082               send_data_to_windows_mme (
3083                 port, local_offset, nframes);
3084               break;
3085 #endif
3086             default:
3087               break;
3088             }
3089         }
3090 
3091       /* send UI notification */
3092       if (port->midi_events->num_events > 0)
3093         {
3094 #if 0
3095           g_message (
3096             "port %s has %d events",
3097             id->label,
3098             port->midi_events->num_events);
3099 #endif
3100 
3101           if (id->owner_type ==
3102                 PORT_OWNER_TYPE_TRACK_PROCESSOR)
3103             {
3104               g_return_if_fail (
3105                 IS_TRACK_AND_NONNULL (track));
3106 
3107               track->trigger_midi_activity = 1;
3108             }
3109         }
3110 
3111       if (local_offset + nframes ==
3112             AUDIO_ENGINE->block_length)
3113         {
3114           MidiEvents * events = port->midi_events;
3115           if (port->write_ring_buffers)
3116             {
3117               for (int i = events->num_events - 1;
3118                    i >= 0; i--)
3119                 {
3120                   if (zix_ring_write_space (
3121                         port->midi_ring) <
3122                         sizeof (MidiEvent))
3123                     {
3124                       zix_ring_skip (
3125                         port->midi_ring,
3126                         sizeof (MidiEvent));
3127                     }
3128 
3129                   MidiEvent * ev =
3130                     &events->events[i];
3131                   ev->systime =
3132                     g_get_monotonic_time ();
3133                   zix_ring_write (
3134                     port->midi_ring, ev,
3135                     sizeof (MidiEvent));
3136                 }
3137             }
3138           else
3139             {
3140               if (events->num_events > 0)
3141                 {
3142                   port->last_midi_event_time =
3143                     g_get_monotonic_time ();
3144                   g_atomic_int_set (
3145                     &port->has_midi_events, 1);
3146                 }
3147             }
3148         }
3149       break;
3150     case TYPE_AUDIO:
3151     case TYPE_CV:
3152       if (noroll)
3153         {
3154           dsp_fill (
3155             &port->buf[local_offset],
3156             DENORMAL_PREVENTION_VAL, nframes);
3157           break;
3158         }
3159 
3160       g_return_if_fail (
3161         id->owner_type !=
3162           PORT_OWNER_TYPE_TRACK_PROCESSOR
3163         || IS_TRACK_AND_NONNULL (track));
3164 
3165       /* only consider incoming external data if
3166        * armed for recording (if the port is owner
3167        * by a track), otherwise always consider
3168        * incoming external data */
3169       if ((id->owner_type !=
3170              PORT_OWNER_TYPE_TRACK_PROCESSOR
3171            || (id->owner_type ==
3172                  PORT_OWNER_TYPE_TRACK_PROCESSOR
3173                && track_type_can_record (track->type)
3174                && track_get_recording (track)))
3175           && id->flow == FLOW_INPUT)
3176         {
3177           switch (AUDIO_ENGINE->audio_backend)
3178             {
3179 #ifdef HAVE_JACK
3180             case AUDIO_BACKEND_JACK:
3181               sum_data_from_jack (
3182                 port, local_offset, nframes);
3183               break;
3184 #endif
3185             case AUDIO_BACKEND_DUMMY:
3186               sum_data_from_dummy (
3187                 port, local_offset, nframes);
3188               break;
3189             default:
3190               break;
3191             }
3192         }
3193 
3194       for (int k = 0; k < port->num_srcs; k++)
3195         {
3196           Port * src_port = port->srcs[k];
3197           const PortConnection * conn =
3198             port->src_connections[k];
3199           if (!conn->enabled)
3200             continue;
3201 
3202           float minf = 0.f, maxf = 0.f,
3203                 depth_range, multiplier;
3204           if (G_LIKELY (
3205                 id->type == TYPE_AUDIO))
3206             {
3207               minf = -2.f;
3208               maxf = 2.f;
3209               depth_range = 1.f;
3210               multiplier = conn->multiplier;
3211             }
3212           else if (id->type == TYPE_CV)
3213             {
3214               maxf = port->maxf;
3215               minf = port->minf;
3216 
3217               /* (maxf - minf) / 2 */
3218               depth_range = (maxf - minf) * 0.5f;
3219 
3220               multiplier =
3221                 depth_range * conn->multiplier;
3222             }
3223           else
3224             g_return_if_reached ();
3225 
3226           /* sum the signals */
3227           if (G_LIKELY (
3228                 math_floats_equal_epsilon (
3229                   multiplier, 1.f, 0.00001f)))
3230             {
3231               dsp_add2 (
3232                 &port->buf[local_offset],
3233                 &src_port->buf[local_offset],
3234                 nframes);
3235             }
3236           else
3237             {
3238               dsp_mix2 (
3239                 &port->buf[local_offset],
3240                 &src_port->buf[local_offset],
3241                 1.f, multiplier, nframes);
3242             }
3243 
3244           if (G_UNLIKELY (id->type == TYPE_CV)
3245               ||
3246               id->owner_type ==
3247                 PORT_OWNER_TYPE_FADER)
3248             {
3249               float abs_peak = 0.f;
3250               dsp_abs_max (
3251                 &port->buf[local_offset],
3252                 &abs_peak, nframes);
3253               if (abs_peak > maxf)
3254                 {
3255                   /* this limiting wastes around
3256                    * 50% of port processing so only
3257                    * do it on CV connections and
3258                    * faders if they exceed maxf */
3259                   dsp_limit1 (
3260                     &port->buf[local_offset],
3261                     minf, maxf, nframes);
3262                 }
3263             }
3264         } /* foreach source */
3265 
3266       if (id->flow == FLOW_OUTPUT)
3267         {
3268           switch (AUDIO_ENGINE->audio_backend)
3269             {
3270 #ifdef HAVE_JACK
3271             case AUDIO_BACKEND_JACK:
3272               send_data_to_jack (
3273                 port, local_offset, nframes);
3274               break;
3275 #endif
3276             default:
3277               break;
3278             }
3279         }
3280 
3281       if (local_offset + nframes ==
3282             AUDIO_ENGINE->block_length)
3283         {
3284           size_t size =
3285             sizeof (float) *
3286             (size_t) AUDIO_ENGINE->block_length;
3287           size_t write_space_avail =
3288             zix_ring_write_space (
3289               port->audio_ring);
3290 
3291           /* move the read head 8 blocks to make
3292            * space if no space avail to write */
3293           if (write_space_avail / size < 1)
3294             {
3295               zix_ring_skip (
3296                 port->audio_ring, size * 8);
3297             }
3298 
3299           zix_ring_write (
3300             port->audio_ring, &port->buf[0],
3301             size);
3302         }
3303 
3304       /* if track output (to be shown on mixer) */
3305       if (id->owner_type ==
3306             PORT_OWNER_TYPE_CHANNEL &&
3307           is_stereo_port &&
3308           id->flow == FLOW_OUTPUT)
3309         {
3310           g_return_if_fail (
3311             IS_TRACK_AND_NONNULL (track));
3312           Channel * ch = track->channel;
3313           g_return_if_fail (ch);
3314 
3315           /* calculate meter values */
3316           if (port == ch->stereo_out->l ||
3317               port == ch->stereo_out->r)
3318             {
3319               /* reset peak if needed */
3320               gint64 time_now =
3321                 g_get_monotonic_time ();
3322               if (time_now -
3323                     port->peak_timestamp >
3324                   TIME_TO_RESET_PEAK)
3325                 port->peak = -1.f;
3326 
3327               bool changed =
3328                 dsp_abs_max (
3329                   &port->buf[local_offset],
3330                   &port->peak,
3331                   nframes);
3332               if (changed)
3333                 {
3334                   port->peak_timestamp =
3335                     g_get_monotonic_time ();
3336                 }
3337             }
3338         }
3339 
3340         /* if bouncing tracks directly to
3341          * master (e.g., when bouncing the
3342          * track on its own without parents),
3343          * clear master input */
3344         if (G_UNLIKELY (
3345               AUDIO_ENGINE->bounce_mode > BOUNCE_OFF
3346               && !AUDIO_ENGINE->bounce_with_parents
3347               &&
3348               (port ==
3349                  P_MASTER_TRACK->processor->
3350                    stereo_in->l
3351                ||
3352                port ==
3353                  P_MASTER_TRACK->processor->
3354                    stereo_in->r)))
3355           {
3356             dsp_fill (
3357               &port->buf[local_offset],
3358               AUDIO_ENGINE->denormal_prevention_val,
3359               nframes);
3360           }
3361 
3362         /* if bouncing track directly to
3363          * master (e.g., when bouncing the
3364          * track on its own without parents),
3365          * add the buffer to master output */
3366         if (G_UNLIKELY (
3367               AUDIO_ENGINE->bounce_mode >
3368                 BOUNCE_OFF &&
3369               (id->owner_type ==
3370                  PORT_OWNER_TYPE_CHANNEL ||
3371                id->owner_type ==
3372                  PORT_OWNER_TYPE_TRACK_PROCESSOR ||
3373                (id->owner_type ==
3374                  PORT_OWNER_TYPE_FADER
3375                 &&
3376                 id->flags2 &
3377                   PORT_FLAG2_PREFADER)
3378                ||
3379                (id->owner_type ==
3380                  PORT_OWNER_TYPE_PLUGIN &&
3381                 id->plugin_id.slot_type ==
3382                   PLUGIN_SLOT_INSTRUMENT)) &&
3383               is_stereo_port &&
3384               id->flow == FLOW_OUTPUT &&
3385               track && track->bounce_to_master))
3386           {
3387 
3388 #define _ADD(l_or_r) \
3389   dsp_add2 ( \
3390     &P_MASTER_TRACK->channel->stereo_out-> \
3391        l_or_r->buf[local_offset], \
3392     &port->buf[local_offset], nframes)
3393 
3394             Channel * ch;
3395             Fader * prefader;
3396             TrackProcessor * tp;
3397             switch (AUDIO_ENGINE->bounce_step)
3398               {
3399               case BOUNCE_STEP_BEFORE_INSERTS:
3400                 tp = track->processor;
3401                 g_return_if_fail (tp);
3402                 if (track->type ==
3403                       TRACK_TYPE_INSTRUMENT)
3404                   {
3405                     if (port == track->channel->instrument->l_out)
3406                       {
3407                         _ADD (l);
3408                       }
3409                     if (port == track->channel->instrument->r_out)
3410                       {
3411                         _ADD (r);
3412                       }
3413                   }
3414                 else if (tp->stereo_out &&
3415                            track->bounce)
3416                   {
3417                     if (port == tp->stereo_out->l)
3418                       {
3419                         _ADD (l);
3420                       }
3421                     else if (port ==
3422                                tp->stereo_out->r)
3423                       {
3424                         _ADD (r);
3425                       }
3426                   }
3427                 break;
3428               case BOUNCE_STEP_PRE_FADER:
3429                 ch = track->channel;
3430                 g_return_if_fail (ch);
3431                 prefader = ch->prefader;
3432                 if (port == prefader->stereo_out->l)
3433                   {
3434                     _ADD (l);
3435                   }
3436                 else if (port ==
3437                            prefader->stereo_out->r)
3438                   {
3439                     _ADD (r);
3440                   }
3441                 break;
3442               case BOUNCE_STEP_POST_FADER:
3443                 ch = track->channel;
3444                 g_return_if_fail (ch);
3445                 if (track->type !=
3446                       TRACK_TYPE_MASTER)
3447                   {
3448                     if (port == ch->stereo_out->l)
3449                       {
3450                         _ADD (l);
3451                       }
3452                     else if (port ==
3453                                ch->stereo_out->r)
3454                       {
3455                         _ADD (r);
3456                       }
3457                   }
3458                 break;
3459               }
3460 #undef _ADD
3461 
3462           }
3463       break;
3464     case TYPE_CONTROL:
3465       {
3466         if (id->flow != FLOW_INPUT
3467             ||
3468             (id->owner_type ==
3469                PORT_OWNER_TYPE_FADER
3470              &&
3471              (id->flags2 &
3472                 PORT_FLAG2_MONITOR_FADER
3473               ||
3474               id->flags2 & PORT_FLAG2_PREFADER))
3475             || id->flags & PORT_FLAG_TP_MONO
3476             || id->flags &
3477               PORT_FLAG_TP_INPUT_GAIN
3478             || !(id->flags & PORT_FLAG_AUTOMATABLE))
3479           {
3480             break;
3481           }
3482 
3483         /* calculate value from automation track */
3484         g_return_if_fail (
3485           id->flags & PORT_FLAG_AUTOMATABLE);
3486         AutomationTrack * at = port->at;
3487         if (G_UNLIKELY (!at))
3488           {
3489             g_critical (
3490               "No automation track found for port "
3491               "%s", id->label);
3492           }
3493         if (ZRYTHM_TESTING && at)
3494           {
3495             AutomationTrack * found_at =
3496               automation_track_find_from_port (
3497                 port, NULL, true);
3498             g_return_if_fail (
3499               at == found_at);
3500           }
3501 
3502         if (at &&
3503             id->flags &
3504               PORT_FLAG_AUTOMATABLE &&
3505             automation_track_should_read_automation (
3506               at, AUDIO_ENGINE->timestamp_start))
3507           {
3508             Position pos;
3509             position_from_frames (
3510               &pos, time_nfo->g_start_frames);
3511 
3512             /* if playhead pos changed manually
3513              * recently or transport is rolling,
3514              * we will force the last known
3515              * automation point value regardless
3516              * of whether there is a region at
3517              * current pos */
3518             bool can_read_previous_automation =
3519               TRANSPORT_IS_ROLLING
3520               ||
3521               (TRANSPORT->last_manual_playhead_change
3522                - AUDIO_ENGINE->last_timestamp_start > 0);
3523 
3524             /* if there was an automation event
3525              * at the playhead position, set val
3526              * and flag */
3527             AutomationPoint * ap =
3528               automation_track_get_ap_before_pos (
3529                 at, &pos,
3530                 !can_read_previous_automation);
3531             if (ap)
3532               {
3533                 float val =
3534                   automation_track_get_val_at_pos (
3535                     at, &pos, true,
3536                     !can_read_previous_automation);
3537                 control_port_set_val_from_normalized (
3538                   port, val, true);
3539                 port->value_changed_from_reading =
3540                   true;
3541               }
3542           }
3543 
3544         float maxf, minf, depth_range, val_to_use;
3545         /* whether this is the first CV processed
3546          * on this control port */
3547         bool first_cv = true;
3548         for (int k = 0; k < port->num_srcs; k++)
3549           {
3550             Port * src_port = port->srcs[k];
3551             const PortConnection * conn =
3552               port->src_connections[k];
3553             if (!conn->enabled)
3554               continue;
3555 
3556             if (src_port->id.type == TYPE_CV)
3557               {
3558                 maxf = port->maxf;
3559                 minf = port->minf;
3560 
3561                 /*float deff =*/
3562                   /*port->lv2_port->lv2_control->deff;*/
3563                 /*port->lv2_port->control =*/
3564                   /*deff + (maxf - deff) **/
3565                     /*src_port->buf[0];*/
3566                 depth_range =
3567                   (maxf - minf) / 2.f;
3568 
3569                 /* figure out whether to use base
3570                  * value or the current value */
3571                 if (first_cv)
3572                   {
3573                     val_to_use = port->base_value;
3574                     first_cv = false;
3575                   }
3576                 else
3577                   {
3578                     val_to_use = port->control;
3579                   }
3580 
3581                 float result =
3582                   CLAMP (
3583                     val_to_use
3584                     + depth_range
3585                       * src_port->buf[0]
3586                       *  conn->multiplier,
3587                     minf, maxf);
3588                 port->control = result;
3589                 port_forward_control_change_event (
3590                   port);
3591               }
3592           }
3593       }
3594       break;
3595     default:
3596       break;
3597     }
3598 
3599 #undef nframes
3600 #undef local_offset
3601 }
3602 
3603 /**
3604  * Disconnects all hardware inputs from the port.
3605  */
3606 void
port_disconnect_hw_inputs(Port * self)3607 port_disconnect_hw_inputs (
3608   Port * self)
3609 {
3610   GPtrArray * srcs = g_ptr_array_new ();
3611   int num_srcs =
3612     port_connections_manager_get_sources_or_dests (
3613       PORT_CONNECTIONS_MGR, srcs, &self->id,
3614       true);
3615   for (int i = 0; i < num_srcs; i++)
3616     {
3617       PortConnection * conn =
3618         (PortConnection *)
3619         g_ptr_array_index (srcs, i);
3620       if (conn->src_id->owner_type == PORT_OWNER_TYPE_HW)
3621         port_connections_manager_ensure_disconnect (
3622           PORT_CONNECTIONS_MGR,
3623           conn->src_id, &self->id);
3624     }
3625   g_ptr_array_unref (srcs);
3626 }
3627 
3628 /**
3629  * Sets whether to expose the port to the backend
3630  * and exposes it or removes it.
3631  *
3632  * It checks what the backend is using the engine's
3633  * audio backend or midi backend settings.
3634  */
3635 void
port_set_expose_to_backend(Port * self,int expose)3636 port_set_expose_to_backend (
3637   Port * self,
3638   int    expose)
3639 {
3640   g_return_if_fail (
3641     AUDIO_ENGINE && AUDIO_ENGINE->setup);
3642 
3643   if (self->id.type == TYPE_AUDIO)
3644     {
3645       switch (AUDIO_ENGINE->audio_backend)
3646         {
3647 #ifdef HAVE_JACK
3648         case AUDIO_BACKEND_JACK:
3649           expose_to_jack (self, expose);
3650           break;
3651 #endif
3652 #ifdef HAVE_RTAUDIO
3653         case AUDIO_BACKEND_ALSA_RTAUDIO:
3654         case AUDIO_BACKEND_JACK_RTAUDIO:
3655         case AUDIO_BACKEND_PULSEAUDIO_RTAUDIO:
3656         case AUDIO_BACKEND_COREAUDIO_RTAUDIO:
3657         case AUDIO_BACKEND_WASAPI_RTAUDIO:
3658         case AUDIO_BACKEND_ASIO_RTAUDIO:
3659           expose_to_rtaudio (self, expose);
3660           break;
3661 #endif
3662         default:
3663           break;
3664         }
3665     }
3666   else if (self->id.type == TYPE_EVENT)
3667     {
3668       switch (AUDIO_ENGINE->midi_backend)
3669         {
3670 #ifdef HAVE_JACK
3671         case MIDI_BACKEND_JACK:
3672           expose_to_jack (self, expose);
3673           break;
3674 #endif
3675 #ifdef HAVE_ALSA
3676         case MIDI_BACKEND_ALSA:
3677 #if 0
3678           expose_to_alsa (self, expose);
3679 #endif
3680           break;
3681 #endif
3682 #ifdef HAVE_RTMIDI
3683         case MIDI_BACKEND_ALSA_RTMIDI:
3684         case MIDI_BACKEND_JACK_RTMIDI:
3685         case MIDI_BACKEND_WINDOWS_MME_RTMIDI:
3686         case MIDI_BACKEND_COREMIDI_RTMIDI:
3687           expose_to_rtmidi (self, expose);
3688           break;
3689 #endif
3690         default:
3691           break;
3692         }
3693     }
3694   else
3695     g_return_if_reached ();
3696 }
3697 
3698 /**
3699  * Returns if the port is exposed to the backend.
3700  */
3701 int
port_is_exposed_to_backend(const Port * self)3702 port_is_exposed_to_backend (
3703   const Port * self)
3704 {
3705   return
3706     self->internal_type == INTERNAL_JACK_PORT ||
3707     self->internal_type ==
3708       INTERNAL_ALSA_SEQ_PORT ||
3709     self->id.owner_type ==
3710       PORT_OWNER_TYPE_AUDIO_ENGINE ||
3711     self->exposed_to_backend;
3712 }
3713 
3714 /**
3715  * Renames the port on the backend side.
3716  */
3717 void
port_rename_backend(Port * self)3718 port_rename_backend (
3719   Port * self)
3720 {
3721   if ((!port_is_exposed_to_backend (self)))
3722     return;
3723 
3724   switch (self->internal_type)
3725     {
3726 #ifdef HAVE_JACK
3727     case INTERNAL_JACK_PORT:
3728       {
3729         char str[600];
3730         port_get_full_designation (self, str);
3731         jack_port_rename (
3732           AUDIO_ENGINE->client,
3733           (jack_port_t *) self->data,
3734           str);
3735       }
3736       break;
3737 #endif
3738     case INTERNAL_ALSA_SEQ_PORT:
3739       break;
3740     default:
3741       break;
3742     }
3743 }
3744 
3745 /**
3746  * If MIDI port, returns if there are any events,
3747  * if audio port, returns if there is sound in the
3748  * buffer.
3749  */
3750 bool
port_has_sound(Port * self)3751 port_has_sound (
3752   Port * self)
3753 {
3754   switch (self->id.type)
3755     {
3756     case TYPE_AUDIO:
3757       g_return_val_if_fail (self->buf, false);
3758       for (nframes_t i = 0;
3759            i < AUDIO_ENGINE->block_length; i++)
3760         {
3761           if (fabsf (self->buf[i]) > 0.0000001f)
3762             {
3763               return true;
3764             }
3765         }
3766       break;
3767     case TYPE_EVENT:
3768       /* TODO */
3769       break;
3770     default:
3771       break;
3772     }
3773 
3774   return false;
3775 }
3776 
3777 /**
3778  * Copies a full designation of \p self in the
3779  * format "Track/Port" or "Track/Plugin/Port" in
3780  * \p buf.
3781  */
3782 void
port_get_full_designation(Port * const self,char * buf)3783 port_get_full_designation (
3784   Port * const self,
3785   char *       buf)
3786 {
3787   const PortIdentifier * id = &self->id;
3788 
3789   switch (id->owner_type)
3790     {
3791     case PORT_OWNER_TYPE_AUDIO_ENGINE:
3792       strcpy (buf, id->label);
3793       return;
3794     case PORT_OWNER_TYPE_PLUGIN:
3795       {
3796         Plugin * pl = port_get_plugin (self, 1);
3797         g_return_if_fail (pl);
3798         Track * track =
3799           plugin_get_track (pl);
3800         g_return_if_fail (track);
3801         sprintf (
3802           buf, "%s/%s/%s",
3803           track->name, pl->setting->descr->name,
3804           id->label);
3805       }
3806       return;
3807     case PORT_OWNER_TYPE_CHANNEL:
3808     case PORT_OWNER_TYPE_TRACK:
3809     case PORT_OWNER_TYPE_TRACK_PROCESSOR:
3810     case PORT_OWNER_TYPE_CHANNEL_SEND:
3811       {
3812         Track * tr = port_get_track (self, 1);
3813         g_return_if_fail (
3814           IS_TRACK_AND_NONNULL (tr));
3815         sprintf (
3816           buf, "%s/%s", tr->name, id->label);
3817       }
3818       return;
3819     case PORT_OWNER_TYPE_FADER:
3820       if (id->flags2 & PORT_FLAG2_PREFADER
3821           || id->flags2 & PORT_FLAG2_POSTFADER)
3822         {
3823           Track * tr = port_get_track (self, 1);
3824           g_return_if_fail (
3825             IS_TRACK_AND_NONNULL (tr));
3826           sprintf (
3827             buf, "%s/%s", tr->name, id->label);
3828           return;
3829         }
3830       else if (id->flags2 & PORT_FLAG2_MONITOR_FADER)
3831 
3832         {
3833           sprintf (buf, "Engine/%s", id->label);
3834           return;
3835         }
3836       else if (id->flags2 &
3837                  PORT_FLAG2_SAMPLE_PROCESSOR_FADER)
3838         {
3839           strcpy (buf, id->label);
3840           return;
3841         }
3842       break;
3843     case PORT_OWNER_TYPE_HW:
3844       sprintf (buf, "HW/%s", id->label);
3845       return;
3846     case PORT_OWNER_TYPE_TRANSPORT:
3847       sprintf (buf, "Transport/%s", id->label);
3848       return;
3849     case PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR:
3850       sprintf (
3851         buf, "Modulator Macro Processor/%s",
3852         id->label);
3853       return;
3854     default:
3855       break;
3856     }
3857 
3858   g_return_if_reached ();
3859 }
3860 
3861 void
port_print_full_designation(Port * const self)3862 port_print_full_designation (
3863   Port * const self)
3864 {
3865   char buf[1200];
3866   port_get_full_designation (self, buf);
3867   g_message ("%s", buf);
3868 }
3869 
3870 /**
3871  * Clears the port buffer.
3872  */
3873 void
port_clear_buffer(Port * port)3874 port_clear_buffer (Port * port)
3875 {
3876   PortIdentifier * pi = &port->id;
3877   if ((pi->type == TYPE_AUDIO ||
3878        pi->type == TYPE_CV) && port->buf)
3879     {
3880       dsp_fill (
3881         port->buf, DENORMAL_PREVENTION_VAL,
3882         AUDIO_ENGINE->block_length);
3883 
3884       return;
3885     }
3886   else if (
3887     port->id.type == TYPE_EVENT
3888     && port->midi_events)
3889     {
3890       port->midi_events->num_events = 0;
3891     }
3892 }
3893 
3894 Track *
port_get_track(const Port * const self,int warn_if_fail)3895 port_get_track (
3896   const Port * const self,
3897   int                warn_if_fail)
3898 {
3899   g_return_val_if_fail (IS_PORT (self), NULL);
3900 
3901   /* return the pointer if dsp thread */
3902   if (G_LIKELY (
3903         self->track && PROJECT && PROJECT->loaded
3904         && ROUTER
3905         && router_is_processing_thread (ROUTER)))
3906     {
3907       g_return_val_if_fail (
3908         IS_TRACK (self->track), NULL);
3909       return self->track;
3910     }
3911 
3912   Track * track = NULL;
3913   if (self->id.track_name_hash != 0)
3914     {
3915       g_return_val_if_fail (
3916         ZRYTHM && TRACKLIST, NULL);
3917 
3918       track =
3919         tracklist_find_track_by_name_hash (
3920           TRACKLIST, self->id.track_name_hash);
3921       if (!track)
3922         track =
3923           tracklist_find_track_by_name_hash (
3924             SAMPLE_PROCESSOR->tracklist,
3925             self->id.track_name_hash);
3926     }
3927 
3928   if (!track && warn_if_fail)
3929     {
3930       g_warning (
3931         "track with name hash %d not found for "
3932         "port %s",
3933         self->id.track_name_hash, self->id.label);
3934     }
3935 
3936   return track;
3937 }
3938 
3939 Plugin *
port_get_plugin(Port * const self,const bool warn_if_fail)3940 port_get_plugin (
3941   Port * const self,
3942   const bool   warn_if_fail)
3943 {
3944   g_return_val_if_fail (IS_PORT (self), NULL);
3945 
3946   /* if DSP thread, return the pointer */
3947   if (G_LIKELY (
3948         self->plugin && PROJECT && PROJECT->loaded
3949         && ROUTER
3950         && router_is_processing_thread (ROUTER)))
3951     {
3952       g_return_val_if_fail (
3953         IS_PLUGIN (self->plugin), NULL);
3954       return self->plugin;
3955     }
3956 
3957   Track * track = port_get_track (self, 0);
3958   if (!track && self->tmp_plugin)
3959     {
3960       return self->tmp_plugin;
3961     }
3962   if (!track ||
3963       (track->type != TRACK_TYPE_MODULATOR &&
3964          !track->channel))
3965     {
3966       if (warn_if_fail)
3967         {
3968           g_warning (
3969             "No track found for port");
3970         }
3971       return NULL;
3972     }
3973 
3974   Plugin * pl = NULL;
3975   const PluginIdentifier * const pl_id =
3976     &self->id.plugin_id;
3977   switch (pl_id->slot_type)
3978     {
3979     case PLUGIN_SLOT_MIDI_FX:
3980       pl = track->channel->midi_fx[pl_id->slot];
3981       break;
3982     case PLUGIN_SLOT_INSTRUMENT:
3983       pl = track->channel->instrument;
3984       break;
3985     case PLUGIN_SLOT_INSERT:
3986       pl = track->channel->inserts[pl_id->slot];
3987       break;
3988     case PLUGIN_SLOT_MODULATOR:
3989       pl = track->modulators[pl_id->slot];
3990       break;
3991     default:
3992       g_return_val_if_reached (NULL);
3993       break;
3994     }
3995   if (!pl && self->tmp_plugin)
3996     return self->tmp_plugin;
3997 
3998   if (!pl && warn_if_fail)
3999     {
4000       g_critical (
4001         "plugin at slot type %s (slot %d) not "
4002         "found for port %s",
4003         plugin_slot_type_to_string (
4004           pl_id->slot_type),
4005         pl_id->slot,
4006         self->id.label);
4007       return NULL;
4008     }
4009 
4010   /* unset \ref Port.tmp_plugin if a Plugin was
4011    * found */
4012   self->tmp_plugin = NULL;
4013 
4014   return pl;
4015 }
4016 
4017 /**
4018  * Applies the pan to the given L/R ports.
4019  */
4020 void
port_apply_pan_stereo(Port * l,Port * r,float pan,PanLaw pan_law,PanAlgorithm pan_algo)4021 port_apply_pan_stereo (
4022   Port *       l,
4023   Port *       r,
4024   float        pan,
4025   PanLaw       pan_law,
4026   PanAlgorithm pan_algo)
4027 {
4028   /* FIXME not used */
4029   g_warn_if_reached ();
4030   /*int nframes = AUDIO_ENGINE->block_length;*/
4031   /*int i;*/
4032   /*switch (pan_algo)*/
4033     /*{*/
4034     /*case PAN_ALGORITHM_SINE_LAW:*/
4035       /*for (i = 0; i < nframes; i++)*/
4036         /*{*/
4037           /*if (r->buf[i] != 0.f)*/
4038             /*r->buf[i] *= sinf (pan * (M_PIF / 2.f));*/
4039           /*if (l->buf[i] != 0.f)*/
4040             /*l->buf[i] *= sinf ((1.f - pan) * (M_PIF / 2.f));*/
4041         /*}*/
4042       /*break;*/
4043     /*case PAN_ALGORITHM_SQUARE_ROOT:*/
4044       /*break;*/
4045     /*case PAN_ALGORITHM_LINEAR:*/
4046       /*for (i = 0; i < nframes; i++)*/
4047         /*{*/
4048           /*if (r->buf[i] != 0.f)*/
4049             /*r->buf[i] *= pan;*/
4050           /*if (l->buf[i] != 0.f)*/
4051             /*l->buf[i] *= (1.f - pan);*/
4052         /*}*/
4053       /*break;*/
4054     /*}*/
4055 }
4056 
4057 /**
4058  * Applies the pan to the given port.
4059  *
4060  * @param start_frame The start frame offset from
4061  *   0 in this cycle.
4062  * @param nframes The number of frames to process.
4063  */
4064 void
port_apply_pan(Port * port,float pan,PanLaw pan_law,PanAlgorithm pan_algo,nframes_t start_frame,const nframes_t nframes)4065 port_apply_pan (
4066   Port *       port,
4067   float        pan,
4068   PanLaw       pan_law,
4069   PanAlgorithm pan_algo,
4070   nframes_t    start_frame,
4071   const nframes_t    nframes)
4072 {
4073   float calc_r, calc_l;
4074   pan_get_calc_lr (
4075     pan_law, pan_algo, pan, &calc_l, &calc_r);
4076 
4077   /* if stereo R */
4078   if (port->id.flags & PORT_FLAG_STEREO_R)
4079     {
4080       dsp_mul_k2 (
4081         &port->buf[start_frame], calc_r, nframes);
4082     }
4083   /* else if stereo L */
4084   else
4085     {
4086       dsp_mul_k2 (
4087         &port->buf[start_frame], calc_l, nframes);
4088     }
4089 }
4090 
4091 /**
4092  * Generates a hash for a given port.
4093  */
4094 unsigned int
port_get_hash(const void * ptr)4095 port_get_hash (
4096   const void * ptr)
4097 {
4098   Port * self = (Port *) ptr;
4099   return
4100     hash_get_for_struct (self, sizeof (Port));
4101 }
4102 
4103 /**
4104  * To be used during serialization.
4105  */
4106 Port *
port_clone(const Port * src)4107 port_clone (
4108   const Port * src)
4109 {
4110   g_return_val_if_fail (IS_PORT (src), NULL);
4111 
4112   Port * self = object_new (Port);
4113   self->schema_version = PORT_SCHEMA_VERSION;
4114   self->magic = PORT_MAGIC;
4115 
4116   port_identifier_copy (&self->id, &src->id);
4117 
4118 #define COPY_MEMBER(x) self->x = src->x
4119 
4120   COPY_MEMBER (exposed_to_backend);
4121   COPY_MEMBER (control);
4122   COPY_MEMBER (minf);
4123   COPY_MEMBER (maxf);
4124   COPY_MEMBER (zerof);
4125   COPY_MEMBER (deff);
4126   COPY_MEMBER (carla_param_id);
4127 
4128 #undef COPY_MEMBER
4129 
4130   return self;
4131 }
4132 
4133 /**
4134  * Deletes port, doing required cleanup and
4135  * updating counters.
4136  */
4137 void
port_free(Port * self)4138 port_free (Port * self)
4139 {
4140   port_free_bufs (self);
4141 
4142 #ifdef HAVE_RTMIDI
4143   for (int i = 0; i < self->num_rtmidi_ins; i++)
4144     {
4145       rtmidi_device_close (
4146         self->rtmidi_ins[i], 1);
4147     }
4148 #endif
4149 
4150   object_zero_and_free (self->srcs);
4151   object_zero_and_free (self->dests);
4152   object_zero_and_free (self->src_connections);
4153   object_zero_and_free (self->dest_connections);
4154 
4155   for (int i = 0; i < self->num_scale_points; i++)
4156     {
4157       object_free_w_func_and_null (
4158         port_scale_point_free,
4159         self->scale_points[i]);
4160     }
4161   object_zero_and_free (self->scale_points);
4162 
4163   object_free_w_func_and_null (
4164     lv2_evbuf_free, self->evbuf);
4165 
4166   port_identifier_free_members (&self->id);
4167 
4168   object_zero_and_free (self);
4169 }
4170