Zrythm
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
port.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: © 2018-2023 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
11#ifndef __AUDIO_PORTS_H__
12#define __AUDIO_PORTS_H__
13
14#include "zrythm-config.h"
15
16#include <stdbool.h>
17
18#include "dsp/port_identifier.h"
19#include "utils/types.h"
20
21#include "zix/sem.h"
22
23#ifdef HAVE_JACK
24# include "weak_libjack.h"
25#endif
26
27#ifdef HAVE_RTMIDI
28# include <rtmidi_c.h>
29#endif
30
31#ifdef HAVE_RTAUDIO
32# include <rtaudio_c.h>
33#endif
34
35typedef struct Plugin Plugin;
36typedef struct MidiEvents MidiEvents;
37typedef struct Fader Fader;
38typedef struct ZixRingImpl ZixRing;
39typedef struct WindowsMmeDevice WindowsMmeDevice;
40typedef struct Channel Channel;
41typedef struct AudioEngine AudioEngine;
42typedef struct Track Track;
43typedef struct PortConnection PortConnection;
44typedef struct TrackProcessor TrackProcessor;
46typedef struct RtMidiDevice RtMidiDevice;
47typedef struct RtAudioDevice RtAudioDevice;
48typedef struct AutomationTrack AutomationTrack;
49typedef struct TruePeakDsp TruePeakDsp;
50typedef struct ExtPort ExtPort;
51typedef struct AudioClip AudioClip;
52typedef struct ChannelSend ChannelSend;
53typedef struct Transport Transport;
56typedef enum PanAlgorithm PanAlgorithm;
57typedef enum PanLaw PanLaw;
58
65#define PORT_SCHEMA_VERSION 1
66#define STEREO_PORTS_SCHEMA_VERSION 1
67
68#define PORT_MAGIC 456861194
69#define IS_PORT(_p) (((Port *) (_p))->magic == PORT_MAGIC)
70#define IS_PORT_AND_NONNULL(x) ((x) && IS_PORT (x))
71
72#define TIME_TO_RESET_PEAK 4800000
73
78#define PORT_NOT_OWNED -1
79
80#define port_is_owner_active(self, _owner_type, owner) \
81 ((self->id.owner_type == _owner_type) && (self->owner != NULL) \
82 && owner##_is_in_active_project (self->owner))
83
84#define port_is_in_active_project(self) \
85 (port_is_owner_active (self, PORT_OWNER_TYPE_AUDIO_ENGINE, engine) \
86 || port_is_owner_active (self, PORT_OWNER_TYPE_PLUGIN, plugin) \
87 || port_is_owner_active (self, PORT_OWNER_TYPE_TRACK, track) \
88 || port_is_owner_active (self, PORT_OWNER_TYPE_CHANNEL, track) \
89 || port_is_owner_active (self, PORT_OWNER_TYPE_FADER, fader) \
90 || port_is_owner_active (self, PORT_OWNER_TYPE_CHANNEL_SEND, channel_send) \
91 || port_is_owner_active (self, PORT_OWNER_TYPE_TRACK_PROCESSOR, track) \
92 || port_is_owner_active ( \
93 self, PORT_OWNER_TYPE_MODULATOR_MACRO_PROCESSOR, modulator_macro_processor) \
94 || port_is_owner_active (self, PORT_OWNER_TYPE_HW, ext_port))
95
115
119typedef struct PortScalePoint
120{
121 float val;
122 char * label;
124
125PURE int
126port_scale_point_cmp (const void * _a, const void * _b);
127
128NONNULL PortScalePoint *
129port_scale_point_new (const float val, const char * label);
130
131NONNULL void
132port_scale_point_free (PortScalePoint * self);
133
137typedef struct Port
138{
139 int schema_version;
140
142
148
155 float * buf;
156
161
164 struct Port ** srcs;
165 int num_srcs;
166 size_t srcs_size;
167
170 struct Port ** dests;
171 int num_dests;
172 size_t dests_size;
173
177 int num_src_connections;
178 size_t src_connections_size;
179
183 int num_dest_connections;
184 size_t dest_connections_size;
185
191
199 float minf;
200 float maxf;
201
209 float zerof;
210
212 float deff;
213
217
226 void * data;
227
228#ifdef _WOE32
237 WindowsMmeDevice * mme_connections[40];
238 int num_mme_connections;
239#else
240 void * mme_connections[40];
241 int num_mme_connections;
242#endif
243
247
255
256#ifdef HAVE_RTMIDI
263 RtMidiDevice * rtmidi_ins[128];
264 int num_rtmidi_ins;
265
267 RtMidiDevice * rtmidi_outs[128];
268 int num_rtmidi_outs;
269#else
270 void * rtmidi_ins[128];
271 int num_rtmidi_ins;
272 void * rtmidi_outs[128];
273 int num_rtmidi_outs;
274#endif
275
276#ifdef HAVE_RTAUDIO
282 RtAudioDevice * rtaudio_ins[128];
283 int num_rtaudio_ins;
284#else
285 void * rtaudio_ins[128];
286 int num_rtaudio_ins;
287#endif
288
291 int num_scale_points;
292
304 float control;
305
308
312
319
322
325
328
331
334
342
346
347 /* ====== flags to indicate port owner ====== */
348
355
358
366
374
382
385
395
398
402
413 ZixRing * audio_ring;
414
428 ZixRing * midi_ring;
429
432 float peak;
433
436
446
453
464
467
474
475 /*
476 * Next 2 objects are MIDI CC info, if MIDI CC in track processor.
477 *
478 * Used as a cache.
479 */
480
483
486
489
491 int magic;
492
496} Port;
497
498static const cyaml_schema_field_t port_fields_schema[] = {
499 YAML_FIELD_INT (Port, schema_version),
500 YAML_FIELD_MAPPING_EMBEDDED (Port, id, port_identifier_fields_schema),
501 YAML_FIELD_INT (Port, exposed_to_backend),
502 YAML_FIELD_FLOAT (Port, control),
503 YAML_FIELD_FLOAT (Port, minf),
504 YAML_FIELD_FLOAT (Port, maxf),
505 YAML_FIELD_FLOAT (Port, zerof),
506 YAML_FIELD_FLOAT (Port, deff),
507 YAML_FIELD_INT (Port, carla_param_id),
508
509 CYAML_FIELD_END
510};
511
512static const cyaml_schema_value_t port_schema = {
513 YAML_VALUE_PTR_NULLABLE (Port, port_fields_schema),
514};
515
521typedef struct StereoPorts
522{
523 int schema_version;
524 Port * l;
525 Port * r;
527
528static const cyaml_schema_field_t stereo_ports_fields_schema[] = {
529 YAML_FIELD_INT (StereoPorts, schema_version),
530 YAML_FIELD_MAPPING_PTR (StereoPorts, l, port_fields_schema),
531 YAML_FIELD_MAPPING_PTR (StereoPorts, r, port_fields_schema),
532
533 CYAML_FIELD_END
534};
535
536static const cyaml_schema_value_t stereo_ports_schema = {
537 YAML_VALUE_PTR (StereoPorts, stereo_ports_fields_schema),
538};
539
547NONNULL void
548port_init_loaded (Port * self, void * owner);
549
550void
551port_set_owner (Port * self, PortOwnerType owner_type, void * owner);
552
553NONNULL Port *
554port_find_from_identifier (const PortIdentifier * const id);
555
556NONNULL static inline void
557stereo_ports_init_loaded (StereoPorts * sp, void * owner)
558{
559 port_init_loaded (sp->l, owner);
560 port_init_loaded (sp->r, owner);
561}
562
563NONNULL_ARGS (1)
564static inline void stereo_ports_set_owner (
565 StereoPorts * sp,
566 PortOwnerType owner_type,
567 void * owner)
568{
569 port_set_owner (sp->l, owner_type, owner);
570 port_set_owner (sp->r, owner_type, owner);
571}
572
576WARN_UNUSED_RESULT NONNULL Port *
577port_new_with_type (PortType type, PortFlow flow, const char * label);
578
579WARN_UNUSED_RESULT NONNULL Port *
580port_new_with_type_and_owner (
581 PortType type,
582 PortFlow flow,
583 const char * label,
584 PortOwnerType owner_type,
585 void * owner);
586
593NONNULL void
595
602NONNULL void
604
608NONNULL StereoPorts *
610
620 int in,
621 const char * name,
622 const char * symbol,
623 PortOwnerType owner_type,
624 void * owner);
625
634NONNULL void
635stereo_ports_connect (StereoPorts * src, StereoPorts * dest, int locked);
636
637NONNULL void
638stereo_ports_disconnect (StereoPorts * self);
639
641stereo_ports_clone (const StereoPorts * src);
642
643NONNULL void
644stereo_ports_free (StereoPorts * self);
645
654const void *
656 const char * port_sym,
657 void * user_data,
658 uint32_t * size,
659 uint32_t * type);
660
661#ifdef HAVE_JACK
666NONNULL void
667port_receive_midi_events_from_jack (
668 Port * self,
669 const nframes_t start_frames,
670 const nframes_t nframes);
671
676NONNULL void
677port_receive_audio_data_from_jack (
678 Port * self,
679 const nframes_t start_frames,
680 const nframes_t nframes);
681#endif
682
688NONNULL bool
690
696NONNULL void
697port_get_full_designation (Port * const self, char * buf);
698
699NONNULL void
700port_print_full_designation (Port * const self);
701
706void
707port_get_all (GPtrArray * ports);
708
709NONNULL Track *
710port_get_track (const Port * const self, int warn_if_fail);
711
712NONNULL Plugin *
713port_get_plugin (Port * const self, const bool warn_if_fail);
714
727void
729 Port * self,
730 const PortIdentifier * prev_id,
731 Track * track,
732 bool update_automation_track);
733
734#ifdef HAVE_RTMIDI
739NONNULL void
740port_prepare_rtmidi_events (Port * self);
741
746NONNULL void
747port_sum_data_from_rtmidi (
748 Port * self,
749 const nframes_t start_frame,
750 const nframes_t nframes);
751#endif
752
753#ifdef HAVE_RTAUDIO
758NONNULL void
759port_prepare_rtaudio_data (Port * self);
760
765NONNULL void
766port_sum_data_from_rtaudio (
767 Port * self,
768 const nframes_t start_frame,
769 const nframes_t nframes);
770#endif
771
775NONNULL void
777
785NONNULL void
786port_set_expose_to_backend (Port * self, int expose);
787
791NONNULL PURE static inline bool
792port_is_exposed_to_backend (const Port * self)
793{
794 return self->internal_type == INTERNAL_JACK_PORT
796 || self->id.owner_type == PORT_OWNER_TYPE_AUDIO_ENGINE
797 || self->exposed_to_backend;
798}
799
803NONNULL void
805
806#ifdef HAVE_ALSA
807
812Port *
813port_find_by_alsa_seq_id (const int id);
814#endif
815
833NONNULL void
835 Port * self,
836 const float val,
837 const bool is_normalized,
838 const bool forward_event);
839
847NONNULL HOT float
848port_get_control_value (Port * self, const bool normalize);
849
856#define port_connect(a, b, locked) \
857 port_connections_manager_ensure_connect ( \
858 PORT_CONNECTIONS_MGR, &((a)->id), &((b)->id), 1.f, locked, true)
859
863#define port_disconnect(a, b) \
864 port_connections_manager_ensure_disconnect ( \
865 PORT_CONNECTIONS_MGR, &((a)->id), &((b)->id))
866
871NONNULL int
873
878NONNULL int
880
888void
889port_update_track_name_hash (Port * self, Track * track, unsigned int new_hash);
890
898NONNULL static inline void
899port_apply_fader (
900 Port * port,
901 float amp,
902 nframes_t start_frame,
903 const nframes_t nframes)
904{
905 nframes_t end = start_frame + nframes;
906 while (start_frame < end)
907 {
908 port->buf[start_frame++] *= amp;
909 }
910}
911
917HOT NONNULL void
919 Port * port,
920 const EngineProcessTimeInfo time_nfo,
921 const bool noroll);
922
923#define ports_connected(a, b) \
924 (port_connections_manager_find_connection ( \
925 PORT_CONNECTIONS_MGR, &(a)->id, &(b)->id) \
926 != NULL)
927
933NONNULL bool
934ports_can_be_connected (const Port * src, const Port * dest);
935
939NONNULL void
940ports_disconnect (Port ** ports, int num_ports, int deleting);
941
949NONNULL void
951
959NONNULL void
960port_copy_values (Port * self, const Port * other);
961
972NONNULL void
974
981#define port_clear_buffer(_port) \
982 { \
983 if (_port->id.type == TYPE_AUDIO || _port->id.type == TYPE_CV) \
984 { \
985 if (_port->buf) \
986 { \
987 dsp_fill ( \
988 _port->buf, DENORMAL_PREVENTION_VAL, AUDIO_ENGINE->block_length); \
989 } \
990 } \
991 else if (_port->id.type == TYPE_EVENT) \
992 { \
993 if (_port->midi_events) \
994 _port->midi_events->num_events = 0; \
995 } \
996 }
997
1001HOT NONNULL OPTIMIZE_O3 void
1003
1007NONNULL int
1009
1013NONNULL void
1015 Port * l,
1016 Port * r,
1017 float pan,
1018 PanLaw pan_law,
1019 PanAlgorithm pan_algo);
1020
1028NONNULL void
1030 Port * port,
1031 float pan,
1032 PanLaw pan_law,
1033 PanAlgorithm pan_algo,
1034 nframes_t start_frame,
1035 const nframes_t nframes);
1036
1040NONNULL uint32_t
1041port_get_hash (const void * ptr);
1042
1046Port *
1047port_clone (const Port * src);
1048
1052NONNULL void
1054
1059#endif
NONNULL_ARGS(1) int undo_manager_undo(UndoManager *self
Undo last action.
NONNULL void port_init_loaded(Port *self, void *owner)
This function finds the Ports corresponding to the PortIdentifiers for srcs and dests.
NONNULL void port_set_expose_to_backend(Port *self, int expose)
Sets whether to expose the port to the backend and exposes it or removes it.
NONNULL int port_disconnect_all(Port *port)
Disconnects all srcs and dests from port.
NONNULL bool ports_can_be_connected(const Port *src, const Port *dest)
Returns whether the Port's can be connected (if the connection will be valid and won't break the acyc...
HOT NONNULL OPTIMIZE_O3 void port_clear_external_buffer(Port *port)
Clears the backend's port buffer.
NONNULL void port_copy_values(Port *self, const Port *other)
Copies the port values from other to self.
NONNULL void port_apply_pan(Port *port, float pan, PanLaw pan_law, PanAlgorithm pan_algo, nframes_t start_frame, const nframes_t nframes)
Applies the pan to the given port.
NONNULL int port_get_num_unlocked_srcs(const Port *self)
Returns the number of unlocked (user-editable) sources.
HOT NONNULL void port_process(Port *port, const EngineProcessTimeInfo time_nfo, const bool noroll)
First sets port buf to 0, then sums the given port signal from its inputs.
NONNULL StereoPorts * stereo_ports_new_from_existing(Port *l, Port *r)
Creates blank stereo ports.
void port_update_identifier(Port *self, const PortIdentifier *prev_id, Track *track, bool update_automation_track)
To be called when the port's identifier changes to update corresponding identifiers.
Port * port_clone(const Port *src)
To be used during serialization.
PortType
Type of signals the Port handles.
void port_get_all(GPtrArray *ports)
Gathers all ports in the project and appends them in the given array.
NONNULL void port_apply_pan_stereo(Port *l, Port *r, float pan, PanLaw pan_law, PanAlgorithm pan_algo)
Applies the pan to the given L/R ports.
NONNULL void stereo_ports_connect(StereoPorts *src, StereoPorts *dest, int locked)
Connects the internal ports using port_connect().
PortFlow
Direction of the signal.
PortInternalType
What the internal data is.
Definition port.h:100
NONNULL void port_allocate_bufs(Port *self)
Allocates buffers used during DSP.
NONNULL void port_free_bufs(Port *self)
Frees buffers.
void port_update_track_name_hash(Port *self, Track *track, unsigned int new_hash)
Updates the track name hash on a track port and all its source/destination identifiers.
StereoPorts * stereo_ports_new_generic(int in, const char *name, const char *symbol, PortOwnerType owner_type, void *owner)
Creates stereo ports for generic use.
NONNULL void ports_disconnect(Port **ports, int num_ports, int deleting)
Disconnects all the given ports.
NONNULL void port_restore_from_non_project(Port *self, Port *non_project)
Reverts the data on the corresponding project port for the given non-project port.
PortOwnerType
Type of owner.
NONNULL HOT float port_get_control_value(Port *self, const bool normalize)
Gets the given control value from the corresponding underlying structure in the Port.
NONNULL void port_get_full_designation(Port *const self, char *buf)
Copies a full designation of self in the format "Track/Port" or "Track/Plugin/Port" in buf.
NONNULL bool port_has_sound(Port *self)
If MIDI port, returns if there are any events, if audio port, returns if there is sound in the buffer...
NONNULL void port_copy_metadata_from_project(Port *self, Port *project_port)
Copies the metadata from a project port to the given port.
NONNULL void port_rename_backend(Port *self)
Renames the port on the backend side.
NONNULL void port_free(Port *port)
Deletes port, doing required cleanup and updating counters.
NONNULL int port_get_num_unlocked_dests(const Port *self)
Returns the number of unlocked (user-editable) destinations.
const void * port_get_value_from_symbol(const char *port_sym, void *user_data, uint32_t *size, uint32_t *type)
Function to get a port's value from its string symbol.
NONNULL void port_disconnect_hw_inputs(Port *self)
Disconnects all hardware inputs from the port.
NONNULL void port_set_control_value(Port *self, const float val, const bool is_normalized, const bool forward_event)
Sets the given control value to the corresponding underlying structure in the Port.
WARN_UNUSED_RESULT NONNULL Port * port_new_with_type(PortType type, PortFlow flow, const char *label)
Creates port.
NONNULL uint32_t port_get_hash(const void *ptr)
Generates a hash for a given port.
@ INTERNAL_PA_PORT
TODO.
Definition port.h:110
@ INTERNAL_LV2_PORT
Pointer to Lv2Port.
Definition port.h:104
@ INTERNAL_JACK_PORT
Pointer to jack_port_t.
Definition port.h:107
@ INTERNAL_ALSA_SEQ_PORT
Pointer to snd_seq_port_info_t.
Definition port.h:113
#define YAML_FIELD_MAPPING_EMBEDDED(owner, member, schema)
Mapping embedded inside the struct.
Definition yaml.h:31
uint32_t nframes_t
Frame count.
Definition types.h:35
uint8_t midi_byte_t
MIDI byte.
Definition types.h:32
#define YAML_FIELD_MAPPING_PTR(owner, member, schema)
Mapping pointer to a struct.
Definition yaml.h:37
#define YAML_VALUE_PTR(cc, fields_schema)
Schema to be used as a pointer.
Definition yaml.h:202
#define YAML_VALUE_PTR_NULLABLE(cc, fields_schema)
Schema to be used as a pointer that can be NULL.
Definition yaml.h:209
PanAlgorithm
See https://www.harmonycentral.com/articles/the-truth-about-panning-laws.
Definition pan.h:53
PanLaw
These are only useful when changing mono to stereo.
Definition pan.h:30
Port identifier.
Audio clips for the pool.
Definition clip.h:33
The audio engine.
Definition engine.h:364
Channel send.
A Channel is part of a Track (excluding Tracks that don't have Channels) and contains information rel...
Definition channel.h:61
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition types.h:138
External port.
Definition ext_port.h:77
A Fader is a processor that is used for volume controls and pan.
Definition fader.h:118
Container for passing midi events through ports.
Definition midi_event.h:68
Modulator macro button processor.
Widget for a control.
Definition plugin_gtk.h:29
The base plugin Inheriting plugins must have this as a child.
Definition plugin.h:74
A connection between two ports.
Struct used to identify Ports in the project.
PortOwnerType owner_type
Owner type.
Scale point.
Definition port.h:120
Must ONLY be created via port_new()
Definition port.h:138
int initialized
used when loading projects FIXME needed?
Definition port.h:357
int exposed_to_backend
Flag to indicate that this port is exposed to the backend.
Definition port.h:147
ExtPort * ext_port
Pointer to ExtPort, if hw.
Definition port.h:488
ZixRing * midi_ring
Ring buffer for saving MIDI events to be used in the UI instead of directly accessing the events.
Definition port.h:428
float minf
Minimum, maximum and zero values for this port.
Definition port.h:199
ZixSem mme_connections_sem
Semaphore for changing the connections atomically.
Definition port.h:246
gint64 last_midi_event_time
Used by the UI to detect when unprocessed MIDI events exist.
Definition port.h:401
int magic
Magic number to identify that this is a Port.
Definition port.h:491
midi_byte_t last_midi_status
Last known MIDI status byte received.
Definition port.h:445
AudioEngine * engine
Pointer to owner engine, if any.
Definition port.h:330
gint64 last_change
Last timestamp the control changed.
Definition port.h:318
float * buf
Buffer to be reallocated every time the buffer size changes.
Definition port.h:155
MidiEvents * midi_events
Contains raw MIDI data (MIDI ports only)
Definition port.h:160
midi_byte_t midi_cc_no
MIDI CC number, if not pitchbend/poly key/channel pressure.
Definition port.h:485
PortInternalType internal_type
Indicates whether data or lv2_port should be used.
Definition port.h:190
const PortConnection ** dest_connections
Caches filled when recalculating the graph.
Definition port.h:182
Transport * transport
Pointer to owner transport, if any.
Definition port.h:324
midi_byte_t midi_channel
MIDI channel, starting from 1.
Definition port.h:482
float base_value
For control ports, when a modulator is attached to the port the previous value will be saved here.
Definition port.h:365
size_t last_buf_sz
Last allocated buffer size (used for audio ports).
Definition port.h:495
ModulatorMacroProcessor * modulator_macro_processor
Pointer to owner modulator macro processor, if any.
Definition port.h:345
ZixRing * audio_ring
Ring buffer for saving the contents of the audio buffer to be used in the UI instead of directly acce...
Definition port.h:413
float control
The control value if control port, otherwise 0.0f.
Definition port.h:304
AutomationTrack * at
Automation track this port is attached to.
Definition port.h:473
const PortConnection ** src_connections
Caches filled when recalculating the graph.
Definition port.h:176
int has_midi_events
Whether the port has midi events not yet processed by the UI.
Definition port.h:397
gint64 last_midi_dequeue
Last time the port finished dequeueing MIDI events.
Definition port.h:254
Fader * fader
Pointer to owner fader, if any.
Definition port.h:333
ChannelSend * channel_send
Pointer to owner channel send, if any.
Definition port.h:327
long playback_latency
Playback latency.
Definition port.h:381
float unsnapped_control
Unsnapped value, used by widgets.
Definition port.h:307
Plugin * plugin
Pointer to owner plugin, if any.
Definition port.h:321
struct Port ** srcs
Caches filled when recalculating the graph.
Definition port.h:164
float zerof
The zero position of the port.
Definition port.h:209
struct Port ** dests
Caches filled when recalculating the graph.
Definition port.h:170
PluginGtkController * widget
Control widget, if applicable.
Definition port.h:452
bool received_ui_event
Whether the port received a UI event from the plugin UI in this cycle.
Definition port.h:463
int carla_param_id
Index of the control parameter (for Carla plugin ports).
Definition port.h:216
bool write_ring_buffers
Flag to indicate if the ring buffers below should be filled or not.
Definition port.h:394
bool automating
Whether this value was set via automation.
Definition port.h:466
Plugin * tmp_plugin
Temporary plugin pointer (used when the plugin doesn't exist yet in its supposed slot).
Definition port.h:354
long capture_latency
Capture latency.
Definition port.h:373
Track * track
Pointer to owner track, if any.
Definition port.h:341
int deleting
Port undergoing deletion.
Definition port.h:384
float deff
Default value, only used for controls.
Definition port.h:212
gint64 peak_timestamp
Last time Port.max_amp was set.
Definition port.h:435
PortScalePoint ** scale_points
Scale points.
Definition port.h:290
bool value_changed_from_reading
Flag that the value of the port changed from reading automation.
Definition port.h:311
float peak
Max amplitude during processing, if audio (fabsf).
Definition port.h:432
void * data
Pointer to arbitrary data.
Definition port.h:226
L & R port, for convenience.
Definition port.h:522
A TrackProcessor is a processor that is used as the first entry point when processing a track.
Track to be inserted into the Project's Tracklist.
Definition track.h:186
The transport.
Definition transport.h:148
Custom types.