1 /* 2 * Copyright (C) 2019-2021 Alexandros Theodotou <alex at zrythm dot org> 3 * 4 * This file is part of Zrythm 5 * 6 * Zrythm is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Affero General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Zrythm is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Affero General Public License for more details. 15 * 16 * You should have received a copy of the GNU Affero General Public License 17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef __AUDIO_EXT_PORT_H__ 21 #define __AUDIO_EXT_PORT_H__ 22 23 /** 24 * \file 25 * 26 * External ports. 27 */ 28 29 #include "zrythm-config.h" 30 31 #include "audio/fader.h" 32 #include "plugins/plugin.h" 33 #include "utils/audio.h" 34 #include "utils/types.h" 35 #include "utils/yaml.h" 36 37 #include <gdk/gdk.h> 38 39 #ifdef HAVE_JACK 40 #include "weak_libjack.h" 41 #endif 42 43 #ifdef HAVE_RTMIDI 44 #include <rtmidi/rtmidi_c.h> 45 #endif 46 47 typedef struct WindowsMmeDevice WindowsMmeDevice; 48 typedef struct HardwareProcessor HardwareProcessor; 49 50 /** 51 * @addtogroup audio 52 * 53 * @{ 54 */ 55 56 #define EXT_PORT_SCHEMA_VERSION 1 57 58 /** 59 * Maximum external ports. 60 * 61 * Used for fixed-size arrays. 62 */ 63 #define EXT_PORTS_MAX 1024 64 65 #define ext_port_is_in_active_project(self) \ 66 (self->hw_processor \ 67 && \ 68 hw_processor_is_in_active_project ( \ 69 (self)->hw_processor)) 70 71 /** 72 * External port type. 73 */ 74 typedef enum ExtPortType 75 { 76 EXT_PORT_TYPE_JACK, 77 EXT_PORT_TYPE_ALSA, 78 EXT_PORT_TYPE_WINDOWS_MME, 79 EXT_PORT_TYPE_RTMIDI, 80 EXT_PORT_TYPE_RTAUDIO, 81 } ExtPortType; 82 83 static const cyaml_strval_t 84 ext_port_type_strings[] = 85 { 86 { "JACK", EXT_PORT_TYPE_JACK }, 87 { "ALSA", EXT_PORT_TYPE_ALSA }, 88 { "Windows MME", EXT_PORT_TYPE_WINDOWS_MME }, 89 { "RtMidi", EXT_PORT_TYPE_RTMIDI }, 90 { "RtAudio", EXT_PORT_TYPE_RTAUDIO }, 91 }; 92 93 /** 94 * External port. 95 */ 96 typedef struct ExtPort 97 { 98 int schema_version; 99 100 /** JACK port. */ 101 #ifdef HAVE_JACK 102 jack_port_t * jport; 103 #else 104 void * jport; 105 #endif 106 107 /** Full port name, used also as ID. */ 108 char * full_name; 109 110 /** Short port name. */ 111 char * short_name; 112 113 /** Alias #1 if any. */ 114 char * alias1; 115 116 /** Alias #2 if any. */ 117 char * alias2; 118 119 int num_aliases; 120 121 #ifdef _WOE32 122 /** 123 * Pointer to a WindowsMmeDevice. 124 * 125 * This must be one of the devices in AudioEngine. 126 * It must NOT be allocated or free'd. 127 */ 128 WindowsMmeDevice * mme_dev; 129 #else 130 void * mme_dev; 131 #endif 132 133 /** RtAudio channel index. */ 134 unsigned int rtaudio_channel_idx; 135 136 /** RtAudio device name. */ 137 char * rtaudio_dev_name; 138 139 /** RtAudio device index. */ 140 unsigned int rtaudio_id; 141 142 /** Whether the channel is input. */ 143 bool rtaudio_is_input; 144 bool rtaudio_is_duplex; 145 146 #ifdef HAVE_RTAUDIO 147 RtAudioDevice * rtaudio_dev; 148 #else 149 void * rtaudio_dev; 150 #endif 151 152 /** RtMidi port index. */ 153 unsigned int rtmidi_id; 154 155 #ifdef HAVE_RTMIDI 156 RtMidiDevice * rtmidi_dev; 157 #else 158 void * rtmidi_dev; 159 #endif 160 161 ExtPortType type; 162 163 /** True if MIDI, false if audio. */ 164 bool is_midi; 165 166 /** Index in the HW processor (cache for real-time 167 * use) */ 168 int hw_processor_index; 169 170 /** Pointer to owner hardware processor, if any. */ 171 HardwareProcessor * hw_processor; 172 173 /** Whether the port is active and receiving 174 * events (for use by hw processor). */ 175 bool active; 176 177 /** 178 * Temporary port to receive data. 179 */ 180 Port * port; 181 } ExtPort; 182 183 static const cyaml_schema_field_t 184 ext_port_fields_schema[] = 185 { 186 YAML_FIELD_INT ( 187 ExtPort, schema_version), 188 YAML_FIELD_STRING_PTR ( 189 ExtPort, full_name), 190 YAML_FIELD_STRING_PTR_OPTIONAL ( 191 ExtPort, short_name), 192 YAML_FIELD_STRING_PTR_OPTIONAL ( 193 ExtPort, alias1), 194 YAML_FIELD_STRING_PTR_OPTIONAL ( 195 ExtPort, alias2), 196 YAML_FIELD_STRING_PTR_OPTIONAL ( 197 ExtPort, rtaudio_dev_name), 198 YAML_FIELD_INT ( 199 ExtPort, num_aliases), 200 YAML_FIELD_INT ( 201 ExtPort, is_midi), 202 YAML_FIELD_ENUM ( 203 ExtPort, type, ext_port_type_strings), 204 YAML_FIELD_UINT ( 205 ExtPort, rtaudio_channel_idx), 206 207 CYAML_FIELD_END 208 }; 209 210 static const cyaml_schema_value_t 211 ext_port_schema = 212 { 213 YAML_VALUE_PTR ( 214 ExtPort, ext_port_fields_schema), 215 }; 216 217 /** 218 * Inits the ExtPort after loading a project. 219 */ 220 COLD 221 NONNULL_ARGS (1) 222 void 223 ext_port_init_loaded ( 224 ExtPort * self, 225 HardwareProcessor * hw_processor); 226 227 /** 228 * Prints the port info. 229 */ 230 void 231 ext_port_print ( 232 ExtPort * self); 233 234 /** 235 * Returns if the ext port matches the current 236 * backend. 237 */ 238 bool 239 ext_port_matches_backend ( 240 ExtPort * self); 241 242 /** 243 * Returns a unique identifier (full name prefixed 244 * with backend type). 245 */ 246 char * 247 ext_port_get_id ( 248 ExtPort * ext_port); 249 250 /** 251 * Returns the buffer of the external port. 252 */ 253 float * 254 ext_port_get_buffer ( 255 ExtPort * ext_port, 256 nframes_t nframes); 257 258 /** 259 * Clears the buffer of the external port. 260 */ 261 void 262 ext_port_clear_buffer ( 263 ExtPort * ext_port, 264 nframes_t nframes); 265 266 /** 267 * Exposes the given Port if not exposed and makes 268 * the connection from the Port to the ExtPort (eg in 269 * JACK) or backwards. 270 * 271 * @param src 1 if the ext_port is the source, 0 if it 272 * is the destination. 273 */ 274 void 275 ext_port_connect ( 276 ExtPort * ext_port, 277 Port * port, 278 int src); 279 280 /** 281 * Disconnects the Port from the ExtPort. 282 * 283 * @param src 1 if the ext_port is the source, 0 if it 284 * is the destination. 285 */ 286 void 287 ext_port_disconnect ( 288 ExtPort * ext_port, 289 Port * port, 290 int src); 291 292 /** 293 * Activates the port (starts receiving data) or 294 * deactivates it. 295 * 296 * @param port Port to send the output to. 297 */ 298 void 299 ext_port_activate ( 300 ExtPort * self, 301 Port * port, 302 bool activate); 303 304 /** 305 * Checks in the GSettings whether this port is 306 * marked as enabled by the user. 307 * 308 * @note Not realtime safe. 309 * 310 * @return Whether the port is enabled. 311 */ 312 bool 313 ext_port_get_enabled ( 314 ExtPort * self); 315 316 /** 317 * Collects external ports of the given type. 318 * 319 * @param flow The signal flow. Note that this is 320 * inverse to what Zrythm sees. E.g., to get 321 * MIDI inputs like MIDI keyboards, pass 322 * \ref FLOW_OUTPUT here. 323 * @param hw Hardware or not. 324 */ 325 void 326 ext_ports_get ( 327 PortType type, 328 PortFlow flow, 329 bool hw, 330 GPtrArray * ports); 331 332 /** 333 * Creates a shallow clone of the port. 334 */ 335 ExtPort * 336 ext_port_clone ( 337 ExtPort * ext_port); 338 339 /** 340 * Frees an array of ExtPort pointers. 341 */ 342 void 343 ext_ports_free ( 344 ExtPort ** ext_port, 345 int size); 346 347 /** 348 * Frees the ext_port. 349 */ 350 void 351 ext_port_free ( 352 ExtPort * ext_port); 353 354 /** 355 * @} 356 */ 357 358 #endif 359