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 /**
21 * \file
22 *
23 * Port identifier.
24 */
25
26 #ifndef __AUDIO_PORT_IDENTIFIER_H__
27 #define __AUDIO_PORT_IDENTIFIER_H__
28
29 #include "zrythm-config.h"
30
31 #include <stdbool.h>
32
33 #include "plugins/plugin_identifier.h"
34 #include "utils/yaml.h"
35
36 /**
37 * @addtogroup audio
38 *
39 * @{
40 */
41
42 #define PORT_IDENTIFIER_SCHEMA_VERSION 1
43
44 #define PORT_IDENTIFIER_MAGIC 3411841
45 #define IS_PORT_IDENTIFIER(tr) \
46 (tr && \
47 ((PortIdentifier *) tr)->magic == \
48 PORT_IDENTIFIER_MAGIC)
49
50 /**
51 * Direction of the signal.
52 */
53 typedef enum PortFlow {
54 FLOW_UNKNOWN,
55 FLOW_INPUT,
56 FLOW_OUTPUT
57 } PortFlow;
58
59 static const cyaml_strval_t
60 port_flow_strings[] =
61 {
62 { "unknown", FLOW_UNKNOWN },
63 { "input", FLOW_INPUT },
64 { "output", FLOW_OUTPUT },
65 };
66
67 /**
68 * Type of signals the Port handles.
69 */
70 typedef enum PortType {
71 TYPE_UNKNOWN,
72 TYPE_CONTROL,
73 TYPE_AUDIO,
74 TYPE_EVENT,
75 TYPE_CV
76 } PortType;
77
78 static const cyaml_strval_t
79 port_type_strings[] =
80 {
81 { "unknown", TYPE_UNKNOWN },
82 { "control", TYPE_CONTROL },
83 { "audio", TYPE_AUDIO },
84 { "event", TYPE_EVENT },
85 { "cv", TYPE_CV },
86 };
87
88 /**
89 * Port unit to be displayed in the UI.
90 */
91 typedef enum PortUnit
92 {
93 PORT_UNIT_NONE,
94 PORT_UNIT_HZ,
95 PORT_UNIT_MHZ,
96 PORT_UNIT_DB,
97 PORT_UNIT_DEGREES,
98 PORT_UNIT_SECONDS,
99
100 /** Milliseconds. */
101 PORT_UNIT_MS,
102 } PortUnit;
103
104 static const cyaml_strval_t
105 port_unit_strings[] =
106 {
107 { "none", PORT_UNIT_NONE },
108 { "Hz", PORT_UNIT_HZ },
109 { "MHz", PORT_UNIT_MHZ },
110 { "dB", PORT_UNIT_DB },
111 { "°", PORT_UNIT_DEGREES },
112 { "s", PORT_UNIT_SECONDS },
113 { "ms", PORT_UNIT_MS },
114 };
115
116 /**
117 * Type of owner.
118 */
119 typedef enum PortOwnerType
120 {
121 /* PORT_OWNER_TYPE_NONE, */
122 PORT_OWNER_TYPE_AUDIO_ENGINE,
123
124 /** Plugin owner. */
125 PORT_OWNER_TYPE_PLUGIN,
126
127 /** Track owner. */
128 PORT_OWNER_TYPE_TRACK,
129
130 /** Channel owner. */
131 PORT_OWNER_TYPE_CHANNEL,
132
133 /** Fader. */
134 PORT_OWNER_TYPE_FADER,
135
136 /**
137 * Channel send.
138 *
139 * PortIdentifier.port_index will contain the
140 * send index on the port's track's channel.
141 */
142 PORT_OWNER_TYPE_CHANNEL_SEND,
143
144 /* TrackProcessor. */
145 PORT_OWNER_TYPE_TRACK_PROCESSOR,
146
147 /** Port is part of a HardwareProcessor. */
148 PORT_OWNER_TYPE_HW,
149
150 /** Port is owned by engine transport. */
151 PORT_OWNER_TYPE_TRANSPORT,
152
153 /** Modulator macro processor owner. */
154 PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR,
155 } PortOwnerType;
156
157 static const cyaml_strval_t
158 port_owner_type_strings[] =
159 {
160 { "audio engine", PORT_OWNER_TYPE_AUDIO_ENGINE },
161 { "plugin", PORT_OWNER_TYPE_PLUGIN },
162 { "track", PORT_OWNER_TYPE_TRACK },
163 { "channel", PORT_OWNER_TYPE_CHANNEL },
164 { "fader", PORT_OWNER_TYPE_FADER },
165 { "channel send", PORT_OWNER_TYPE_CHANNEL_SEND },
166 { "track processor",
167 PORT_OWNER_TYPE_TRACK_PROCESSOR },
168 { "hw", PORT_OWNER_TYPE_HW },
169 { "transport", PORT_OWNER_TYPE_TRANSPORT },
170 { "modulator macro processor", PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR },
171 };
172
173 /**
174 * Port flags.
175 */
176 typedef enum PortFlags
177 {
178 PORT_FLAG_STEREO_L = 1 << 0,
179 PORT_FLAG_STEREO_R = 1 << 1,
180 PORT_FLAG_PIANO_ROLL = 1 << 2,
181 /** See http://lv2plug.in/ns/ext/port-groups/port-groups.html#sideChainOf. */
182 PORT_FLAG_SIDECHAIN = 1 << 3,
183 /** See http://lv2plug.in/ns/ext/port-groups/port-groups.html#mainInput
184 * and http://lv2plug.in/ns/ext/port-groups/port-groups.html#mainOutput. */
185 PORT_FLAG_MAIN_PORT = 1 << 4,
186 PORT_FLAG_MANUAL_PRESS = 1 << 5,
187
188 /** Amplitude port. */
189 PORT_FLAG_AMPLITUDE = 1 << 6,
190
191 /**
192 * Port controls the stereo balance.
193 *
194 * This is used in channels for the balance
195 * control.
196 */
197 PORT_FLAG_STEREO_BALANCE = 1 << 7,
198
199 /**
200 * Whether the port wants to receive position
201 * events.
202 *
203 * This is only applicable for LV2 Atom ports.
204 */
205 PORT_FLAG_WANT_POSITION = 1 << 8,
206
207 /**
208 * Trigger ports will be set to 0 at the end of
209 * each cycle.
210 *
211 * This mostly applies to LV2 Control Input
212 * ports.
213 */
214 PORT_FLAG_TRIGGER = 1 << 9,
215
216 /** Whether the port is a toggle (on/off). */
217 PORT_FLAG_TOGGLE = 1 << 10,
218
219 /** Whether the port is an integer. */
220 PORT_FLAG_INTEGER = 1 << 11,
221
222 /** Whether port is for letting the plugin know
223 * that we are in freewheeling (export) mode. */
224 PORT_FLAG_FREEWHEEL = 1 << 12,
225
226 /** Used for plugin ports. */
227 PORT_FLAG_REPORTS_LATENCY = 1 << 13,
228
229 /** Port should not be visible to users. */
230 PORT_FLAG_NOT_ON_GUI = 1 << 14,
231
232 /** Port is a switch for plugin enabled. */
233 PORT_FLAG_PLUGIN_ENABLED = 1 << 15,
234
235 /** Port is a plugin control. */
236 PORT_FLAG_PLUGIN_CONTROL = 1 << 16,
237
238 /** Port is for fader mute. */
239 PORT_FLAG_FADER_MUTE = 1 << 17,
240
241 /** Port is for channel fader. */
242 PORT_FLAG_CHANNEL_FADER = 1 << 18,
243
244 /**
245 * Port has an automation track.
246 *
247 * If this is set, it is assumed that the
248 * automation track at
249 * \ref PortIdentifier.port_index is for this
250 * port.
251 */
252 PORT_FLAG_AUTOMATABLE = 1 << 19,
253
254 /** MIDI automatable control, such as modwheel or
255 * pitch bend. */
256 PORT_FLAG_MIDI_AUTOMATABLE = 1 << 20,
257
258 /** Channels can send to this port (ie, this port
259 * is a track procesor midi/stereo in or a plugin
260 * sidechain in). */
261 PORT_FLAG_SEND_RECEIVABLE = 1 << 21,
262
263 /** This is a BPM port. */
264 PORT_FLAG_BPM = 1 << 22,
265
266 /**
267 * Generic plugin port not belonging to the
268 * underlying plugin.
269 *
270 * This is for ports that are added by Zrythm
271 * such as Enabled and Gain.
272 */
273 PORT_FLAG_GENERIC_PLUGIN_PORT = 1 << 23,
274
275 /** This is the plugin gain. */
276 PORT_FLAG_PLUGIN_GAIN = 1 << 24,
277
278 /** Track processor input mono switch. */
279 PORT_FLAG_TP_MONO = 1 << 25,
280
281 /** Track processor input gain. */
282 PORT_FLAG_TP_INPUT_GAIN = 1 << 26,
283
284 /** Port is a hardware port. */
285 PORT_FLAG_HW = 1 << 27,
286
287 /**
288 * Port is part of a modulator macro processor.
289 *
290 * Which of the ports it is can be determined
291 * by checking flow/type.
292 */
293 PORT_FLAG_MODULATOR_MACRO = 1 << 28,
294
295 /** Logarithmic. */
296 PORT_FLAG_LOGARITHMIC = 1 << 29,
297
298 /**
299 * Plugin control is a property (changes are set
300 * via atom message on the plugin's control port),
301 * as opposed to conventional float control ports.
302 *
303 * An input Port is created for each parameter
304 * declared as either writable or readable (or
305 * both).
306 *
307 * @seealso http://lv2plug.in/ns/lv2core#Parameter. */
308 PORT_FLAG_IS_PROPERTY = 1 << 30,
309 } PortFlags;
310
311 static const cyaml_bitdef_t
312 port_flags_bitvals[] =
313 {
314 { .name = "stereo_l", .offset = 0, .bits = 1 },
315 { .name = "stereo_r", .offset = 1, .bits = 1 },
316 { .name = "piano_roll", .offset = 2, .bits = 1 },
317 { .name = "sidechain", .offset = 3, .bits = 1 },
318 { .name = "main_port", .offset = 4, .bits = 1 },
319 { .name = "manual_press", .offset = 5, .bits = 1 },
320 { .name = "amplitude", .offset = 6, .bits = 1 },
321 { .name = "stereo_balance", .offset = 7, .bits = 1 },
322 { .name = "want_position", .offset = 8, .bits = 1 },
323 { .name = "trigger", .offset = 9, .bits = 1 },
324 { .name = "toggle", .offset = 10, .bits = 1 },
325 { .name = "integer", .offset = 11, .bits = 1 },
326 { .name = "freewheel", .offset = 12, .bits = 1 },
327 { .name = "reports_latency", .offset = 13, .bits = 1 },
328 { .name = "not_on_gui", .offset = 14, .bits = 1 },
329 { .name = "plugin_enabled", .offset = 15, .bits = 1 },
330 { .name = "plugin_control", .offset = 16, .bits = 1 },
331 { .name = "fader_mute", .offset = 17, .bits = 1 },
332 { .name = "channel_fader", .offset = 18, .bits = 1 },
333 { .name = "automatable", .offset = 19, .bits = 1 },
334 { .name = "midi_automatable", .offset = 20, .bits = 1 },
335 { .name = "send_receivable", .offset = 21, .bits = 1 },
336 { .name = "bpm", .offset = 22, .bits = 1 },
337 { .name = "generic_plugin_port", .offset = 23, .bits = 1 },
338 { .name = "plugin_gain", .offset = 24, .bits = 1 },
339 { .name = "tp_mono", .offset = 25, .bits = 1 },
340 { .name = "tp_input_gain", .offset = 26, .bits = 1 },
341 { .name = "hw", .offset = 27, .bits = 1 },
342 { .name = "modulator_macro", .offset = 28, .bits = 1 },
343 { .name = "logarithmic", .offset = 29, .bits = 1 },
344 { .name = "is_property", .offset = 30, .bits = 1 },
345 };
346
347 typedef enum PortFlags2
348 {
349 /** Transport ports. */
350 PORT_FLAG2_TRANSPORT_ROLL = 1 << 0,
351 PORT_FLAG2_TRANSPORT_STOP = 1 << 1,
352 PORT_FLAG2_TRANSPORT_BACKWARD = 1 << 2,
353 PORT_FLAG2_TRANSPORT_FORWARD = 1 << 3,
354 PORT_FLAG2_TRANSPORT_LOOP_TOGGLE = 1 << 4,
355 PORT_FLAG2_TRANSPORT_REC_TOGGLE = 1 << 5,
356
357 /** LV2 control atom port supports patch
358 * messages. */
359 PORT_FLAG2_SUPPORTS_PATCH_MESSAGE = 1 << 6,
360
361 /** Port's only reasonable values are its scale
362 * points. */
363 PORT_FLAG2_ENUMERATION = 1 << 7,
364
365 /** Parameter port's value type is URI. */
366 PORT_FLAG2_URI_PARAM = 1 << 8,
367
368 /** Atom port buffer type is sequence. */
369 PORT_FLAG2_SEQUENCE = 1 << 9,
370
371 /** Atom or event port supports MIDI. */
372 PORT_FLAG2_SUPPORTS_MIDI = 1 << 10,
373
374 /** Track processor output gain. */
375 PORT_FLAG2_TP_OUTPUT_GAIN = 1 << 11,
376
377 /** MIDI pitch bend. */
378 PORT_FLAG2_MIDI_PITCH_BEND = 1 << 12,
379
380 /** MIDI poly key pressure. */
381 PORT_FLAG2_MIDI_POLY_KEY_PRESSURE = 1 << 13,
382
383 /** MIDI channel pressure. */
384 PORT_FLAG2_MIDI_CHANNEL_PRESSURE = 1 << 14,
385
386 /** Channel send enabled. */
387 PORT_FLAG2_CHANNEL_SEND_ENABLED = 1 << 15,
388
389 /** Channel send amount. */
390 PORT_FLAG2_CHANNEL_SEND_AMOUNT = 1 << 16,
391
392 /** Beats per bar. */
393 PORT_FLAG2_BEATS_PER_BAR = 1 << 17,
394
395 /** Beat unit. */
396 PORT_FLAG2_BEAT_UNIT = 1 << 18,
397
398 /** Fader solo. */
399 PORT_FLAG2_FADER_SOLO = 1 << 19,
400
401 /** Fader listen. */
402 PORT_FLAG2_FADER_LISTEN = 1 << 20,
403
404 /** Fader mono compat. */
405 PORT_FLAG2_FADER_MONO_COMPAT = 1 << 21,
406
407 /** Track recording. */
408 PORT_FLAG2_TRACK_RECORDING = 1 << 22,
409
410 /** Track processor monitor audio. */
411 PORT_FLAG2_TP_MONITOR_AUDIO = 1 << 23,
412
413 /** Port is owned by prefader. */
414 PORT_FLAG2_PREFADER = 1 << 24,
415
416 /** Port is owned by postfader. */
417 PORT_FLAG2_POSTFADER = 1 << 25,
418
419 /** Port is owned by monitor fader. */
420 PORT_FLAG2_MONITOR_FADER = 1 << 26,
421
422 /** Port is owned by the sample processor fader. */
423 PORT_FLAG2_SAMPLE_PROCESSOR_FADER = 1 << 27,
424
425 /** Port is owned by sample processor
426 * track/channel (including faders owned by those
427 * tracks/channels). */
428 PORT_FLAG2_SAMPLE_PROCESSOR_TRACK = 1 << 28,
429 } PortFlags2;
430
431 static const cyaml_bitdef_t
432 port_flags2_bitvals[] =
433 {
434 YAML_BITVAL ("transport_roll", 0),
435 YAML_BITVAL ("transport_stop", 1),
436 YAML_BITVAL ("transport_backward", 2),
437 YAML_BITVAL ("transport_forward", 3),
438 YAML_BITVAL ("transport_loop_toggle", 4),
439 YAML_BITVAL ("transport_rec_toggle", 5),
440 YAML_BITVAL ("patch_message", 6),
441 YAML_BITVAL ("enumeration", 7),
442 YAML_BITVAL ("uri_param", 8),
443 YAML_BITVAL ("sequence", 9),
444 YAML_BITVAL ("supports_midi", 10),
445 YAML_BITVAL ("output_gain", 11),
446 YAML_BITVAL ("pitch_bend", 12),
447 YAML_BITVAL ("poly_key_pressure", 13),
448 YAML_BITVAL ("channel_pressure", 14),
449 YAML_BITVAL ("ch_send_enabled", 15),
450 YAML_BITVAL ("ch_send_amount", 16),
451 YAML_BITVAL ("beats_per_bar", 17),
452 YAML_BITVAL ("beat_unit", 18),
453 YAML_BITVAL ("fader_solo", 19),
454 YAML_BITVAL ("fader_listen", 20),
455 YAML_BITVAL ("fader_mono_compat", 21),
456 YAML_BITVAL ("track_recording", 22),
457 YAML_BITVAL ("tp_monitor_audio", 23),
458 YAML_BITVAL ("prefader", 24),
459 YAML_BITVAL ("postfader", 25),
460 YAML_BITVAL ("monitor_fader", 26),
461 YAML_BITVAL ("sample_processor_fader", 27),
462 YAML_BITVAL ("sample_processor_track", 28),
463 };
464
465 /**
466 * Struct used to identify Ports in the project.
467 *
468 * This should include some members of the original
469 * struct enough to identify the port. To be used
470 * for sources and dests.
471 *
472 * This must be filled in before saving and read from
473 * while loading to fill in the srcs/dests.
474 */
475 typedef struct PortIdentifier
476 {
477 int schema_version;
478
479 /** Human readable label. */
480 char * label;
481
482 /** Symbol, if LV2. */
483 char * sym;
484
485 /** URI, if LV2 property. */
486 char * uri;
487
488 /** Comment, if any. */
489 char * comment;
490
491 /** Owner type. */
492 PortOwnerType owner_type;
493 /** Data type (e.g. AUDIO). */
494 PortType type;
495 /** Flow (IN/OUT). */
496 PortFlow flow;
497 /** Flags (e.g. is side chain). */
498 PortFlags flags;
499 PortFlags2 flags2;
500
501 /** Port unit. */
502 PortUnit unit;
503
504 /** Identifier of plugin. */
505 PluginIdentifier plugin_id;
506
507 /** Port group this port is part of (only
508 * applicable for LV2 plugin ports). */
509 char * port_group;
510
511 /** ExtPort ID (type + full name), if hw port. */
512 char * ext_port_id;
513
514 /** Track name hash (0 for non-track ports). */
515 unsigned int track_name_hash;
516
517 /** Index (e.g. in plugin's output ports). */
518 int port_index;
519 } PortIdentifier;
520
521 static const cyaml_schema_field_t
522 port_identifier_fields_schema[] =
523 {
524 YAML_FIELD_INT (
525 PortIdentifier, schema_version),
526 YAML_FIELD_STRING_PTR_OPTIONAL (
527 PortIdentifier, label),
528 YAML_FIELD_STRING_PTR_OPTIONAL (
529 PortIdentifier, sym),
530 YAML_FIELD_STRING_PTR_OPTIONAL (
531 PortIdentifier, uri),
532 YAML_FIELD_STRING_PTR_OPTIONAL (
533 PortIdentifier, comment),
534 YAML_FIELD_ENUM (
535 PortIdentifier, owner_type,
536 port_owner_type_strings),
537 YAML_FIELD_ENUM (
538 PortIdentifier, type, port_type_strings),
539 YAML_FIELD_ENUM (
540 PortIdentifier, flow, port_flow_strings),
541 YAML_FIELD_ENUM (
542 PortIdentifier, unit, port_unit_strings),
543 YAML_FIELD_BITFIELD (
544 PortIdentifier, flags, port_flags_bitvals),
545 YAML_FIELD_BITFIELD (
546 PortIdentifier, flags2, port_flags2_bitvals),
547 YAML_FIELD_UINT (
548 PortIdentifier, track_name_hash),
549 YAML_FIELD_MAPPING_EMBEDDED (
550 PortIdentifier, plugin_id,
551 plugin_identifier_fields_schema),
552 YAML_FIELD_STRING_PTR_OPTIONAL (
553 PortIdentifier, port_group),
554 YAML_FIELD_STRING_PTR_OPTIONAL (
555 PortIdentifier, ext_port_id),
556 YAML_FIELD_INT (
557 PortIdentifier, port_index),
558
559 CYAML_FIELD_END,
560 };
561
562 static const cyaml_schema_value_t
563 port_identifier_schema = {
564 YAML_VALUE_PTR (
565 PortIdentifier, port_identifier_fields_schema),
566 };
567
568 static const cyaml_schema_value_t
569 port_identifier_schema_default = {
570 YAML_VALUE_DEFAULT (
571 PortIdentifier, port_identifier_fields_schema),
572 };
573
574 void
575 port_identifier_init (
576 PortIdentifier * self);
577
578 static inline const char *
port_identifier_get_label(PortIdentifier * self)579 port_identifier_get_label (
580 PortIdentifier * self)
581 {
582 return self->label;
583 }
584
585 /**
586 * Port group comparator function where @ref p1 and
587 * @ref p2 are pointers to Port.
588 */
589 int
590 port_identifier_port_group_cmp (
591 const void* p1, const void* p2);
592
593 /**
594 * Copy the identifier content from \ref src to
595 * \ref dest.
596 *
597 * @note This frees/allocates memory on \ref dest.
598 */
599 NONNULL
600 void
601 port_identifier_copy (
602 PortIdentifier * dest,
603 const PortIdentifier * src);
604
605 /**
606 * Returns if the 2 PortIdentifier's are equal.
607 */
608 WARN_UNUSED_RESULT
609 HOT
610 NONNULL
611 bool
612 port_identifier_is_equal (
613 const PortIdentifier * src,
614 const PortIdentifier * dest);
615
616 /**
617 * To be used as GEqualFunc.
618 */
619 int
620 port_identifier_is_equal_func (
621 const void * a,
622 const void * b);
623
624 NONNULL
625 void
626 port_identifier_print_to_str (
627 const PortIdentifier * self,
628 char * buf,
629 size_t buf_sz);
630
631 NONNULL
632 void
633 port_identifier_print (
634 const PortIdentifier * self);
635
636 NONNULL
637 bool
638 port_identifier_validate (
639 PortIdentifier * self);
640
641 NONNULL
642 unsigned int
643 port_identifier_get_hash (
644 const void * self);
645
646 NONNULL
647 PortIdentifier *
648 port_identifier_clone (
649 const PortIdentifier * src);
650
651 NONNULL
652 void
653 port_identifier_free_members (
654 PortIdentifier * self);
655
656 NONNULL
657 void
658 port_identifier_free (
659 PortIdentifier * self);
660
661 /**
662 * Compatible with GDestroyNotify.
663 */
664 void
665 port_identifier_free_func (
666 void * self);
667
668 /**
669 * @}
670 */
671
672 #endif
673