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 /** 21 * \file 22 * 23 * Mapping MIDI CC to controls. 24 */ 25 26 #ifndef __AUDIO_MIDI_MAPPING_H__ 27 #define __AUDIO_MIDI_MAPPING_H__ 28 29 #include "audio/ext_port.h" 30 #include "audio/midi.h" 31 #include "audio/port.h" 32 33 /** 34 * @addtogroup audio 35 * 36 * @{ 37 */ 38 39 #define MIDI_MAPPING_SCHEMA_VERSION 1 40 #define MIDI_MAPPINGS_SCHEMA_VERSION 1 41 42 #define MIDI_MAPPINGS (PROJECT->midi_mappings) 43 44 /** 45 * A mapping from a MIDI value to a destination. 46 */ 47 typedef struct MidiMapping 48 { 49 int schema_version; 50 51 /** Raw MIDI signal. */ 52 midi_byte_t key[3]; 53 54 /** The device that this connection will be mapped 55 * for. */ 56 ExtPort * device_port; 57 58 /** Destination. */ 59 PortIdentifier dest_id; 60 61 /** 62 * Destination pointer, for convenience. 63 * 64 * @note This pointer is not owned by this 65 * instance. 66 */ 67 Port * dest; 68 69 /** Whether this binding is enabled. */ 70 volatile int enabled; 71 } MidiMapping; 72 73 static const cyaml_schema_field_t 74 midi_mapping_fields_schema[] = 75 { 76 YAML_FIELD_INT ( 77 MidiMapping, schema_version), 78 YAML_FIELD_FIXED_SIZE_PTR_ARRAY ( 79 MidiMapping, key, 80 uint8_t_schema, 3), 81 YAML_FIELD_MAPPING_PTR_OPTIONAL ( 82 MidiMapping, device_port, 83 ext_port_fields_schema), 84 YAML_FIELD_MAPPING_EMBEDDED ( 85 MidiMapping, dest_id, 86 port_identifier_fields_schema), 87 YAML_FIELD_INT ( 88 MidiMapping, enabled), 89 90 CYAML_FIELD_END 91 }; 92 93 static const cyaml_schema_value_t 94 midi_mapping_schema = 95 { 96 YAML_VALUE_PTR ( 97 MidiMapping, midi_mapping_fields_schema), 98 }; 99 100 #if 0 101 static const cyaml_schema_value_t 102 midi_mapping_schema_default = 103 { 104 YAML_VALUE_DEFAULT ( 105 MidiMapping, midi_mapping_fields_schema), 106 }; 107 #endif 108 109 /** 110 * All MIDI mappings in Zrythm. 111 */ 112 typedef struct MidiMappings 113 { 114 int schema_version; 115 116 MidiMapping ** mappings; 117 size_t mappings_size; 118 int num_mappings; 119 } MidiMappings; 120 121 static const cyaml_schema_field_t 122 midi_mappings_fields_schema[] = 123 { 124 YAML_FIELD_INT (MidiMappings, schema_version), 125 YAML_FIELD_DYN_PTR_ARRAY_VAR_COUNT_OPT ( 126 MidiMappings, mappings, 127 midi_mapping_schema), 128 129 CYAML_FIELD_END 130 }; 131 132 static const cyaml_schema_value_t 133 midi_mappings_schema = 134 { 135 YAML_VALUE_PTR ( 136 MidiMappings, midi_mappings_fields_schema), 137 }; 138 139 /** 140 * Initializes the MidiMappings after a Project 141 * is loaded. 142 */ 143 void 144 midi_mappings_init_loaded ( 145 MidiMappings * self); 146 147 /** 148 * Returns a newly allocated MidiMappings. 149 */ 150 MidiMappings * 151 midi_mappings_new (void); 152 153 #define midi_mappings_bind_device( \ 154 self,buf,dev_port,dest_port,fire_events) \ 155 midi_mappings_bind_at ( \ 156 self, buf, dev_port, dest_port, \ 157 (self)->num_mappings, fire_events) 158 159 #define midi_mappings_bind_track( \ 160 self,buf,dest_port,fire_events) \ 161 midi_mappings_bind_at ( \ 162 self, buf, NULL, dest_port, \ 163 (self)->num_mappings, fire_events) 164 165 /** 166 * Binds the CC represented by the given raw buffer 167 * (must be size 3) to the given Port. 168 * 169 * @param idx Index to insert at. 170 * @param buf The buffer used for matching at [0] and 171 * [1]. 172 * @param device_port Device port, if custom mapping. 173 */ 174 void 175 midi_mappings_bind_at ( 176 MidiMappings * self, 177 midi_byte_t * buf, 178 ExtPort * device_port, 179 Port * dest_port, 180 int idx, 181 bool fire_events); 182 183 /** 184 * Unbinds the given binding. 185 * 186 * @note This must be called inside a port operation 187 * lock, such as inside an undoable action. 188 */ 189 void 190 midi_mappings_unbind ( 191 MidiMappings * self, 192 int idx, 193 bool fire_events); 194 195 MidiMapping * 196 midi_mapping_new (void); 197 198 void 199 midi_mapping_set_enabled ( 200 MidiMapping * self, 201 bool enabled); 202 203 int 204 midi_mapping_get_index ( 205 MidiMappings * self, 206 MidiMapping * mapping); 207 208 NONNULL 209 MidiMapping * 210 midi_mapping_clone ( 211 const MidiMapping * src); 212 213 void 214 midi_mapping_free ( 215 MidiMapping * self); 216 217 /** 218 * Applies the events to the appropriate mapping. 219 * 220 * This is used only for TrackProcessor.cc_mappings. 221 * 222 * @note Must only be called while transport is 223 * recording. 224 */ 225 void 226 midi_mappings_apply_from_cc_events ( 227 MidiMappings * self, 228 MidiEvents * events, 229 bool queued); 230 231 /** 232 * Applies the given buffer to the matching ports. 233 */ 234 void 235 midi_mappings_apply ( 236 MidiMappings * self, 237 midi_byte_t * buf); 238 239 /** 240 * Get MIDI mappings for the given port. 241 * 242 * @param size Size to set. 243 * 244 * @return a newly allocated array that must be 245 * free'd with free(). 246 */ 247 MidiMapping ** 248 midi_mappings_get_for_port ( 249 MidiMappings * self, 250 Port * dest_port, 251 int * size); 252 253 MidiMappings * 254 midi_mappings_clone ( 255 const MidiMappings * src); 256 257 void 258 midi_mappings_free ( 259 MidiMappings * self); 260 261 /** 262 * @} 263 */ 264 265 #endif 266