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