diff options
author | Ibrahn Sahir <ibrahn.sahir@gmail.com> | 2024-04-10 10:50:28 +0100 |
---|---|---|
committer | Ibrahn Sahir <ibrahn.sahir@gmail.com> | 2024-06-25 16:46:30 +0100 |
commit | 607c5ec49f605966c6870e34cebcd2f967be12d3 (patch) | |
tree | 5a23b3a590a8518fe6ec4cd0d667adb3afa72fdb /drivers/coremidi/midi_driver_coremidi.cpp | |
parent | 6b281c0c07b07f2142b1fc8a6b3158091a9b124c (diff) | |
download | redot-engine-607c5ec49f605966c6870e34cebcd2f967be12d3.tar.gz |
Move MIDI parsing up from ALSA driver to platform independent driver.
Aims for more consistent MIDI support across Windows, MacOS, Linux and
to provide a base for adding MIDI drivers for other platforms.
Reworks the MIDIDriverALSAMidi MIDI parsing implementation as a platform
independent version in MIDIDriver::Parser.
Uses MIDIDriver::Parser to provide running status support in MacOS
MIDIDriverCoreMidi.
Collects connected input names at open, ensuring devices indices reported
in events match names in array returned from get_connected_inputs.
Fixes #77035.
Fixes #79811.
With code review changes by: A Thousand Ships (she/her)
<96648715+AThousandShips@users.noreply.github.com>
Diffstat (limited to 'drivers/coremidi/midi_driver_coremidi.cpp')
-rw-r--r-- | drivers/coremidi/midi_driver_coremidi.cpp | 79 |
1 files changed, 47 insertions, 32 deletions
diff --git a/drivers/coremidi/midi_driver_coremidi.cpp b/drivers/coremidi/midi_driver_coremidi.cpp index 87fc7612f7..f6cc59471e 100644 --- a/drivers/coremidi/midi_driver_coremidi.cpp +++ b/drivers/coremidi/midi_driver_coremidi.cpp @@ -37,16 +37,30 @@ #import <CoreAudio/HostTime.h> #import <CoreServices/CoreServices.h> +Mutex MIDIDriverCoreMidi::mutex; +bool MIDIDriverCoreMidi::core_midi_closed = false; + +MIDIDriverCoreMidi::InputConnection::InputConnection(int p_device_index, MIDIEndpointRef p_source) : + parser(p_device_index), source(p_source) {} + void MIDIDriverCoreMidi::read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con) { - MIDIPacket *packet = const_cast<MIDIPacket *>(packet_list->packet); - int *device_index = static_cast<int *>(src_conn_ref_con); - for (UInt32 i = 0; i < packet_list->numPackets; i++) { - receive_input_packet(*device_index, packet->timeStamp, packet->data, packet->length); - packet = MIDIPacketNext(packet); + MutexLock lock(mutex); + if (!core_midi_closed) { + InputConnection *source = static_cast<InputConnection *>(src_conn_ref_con); + const MIDIPacket *packet = packet_list->packet; + for (UInt32 packet_index = 0; packet_index < packet_list->numPackets; packet_index++) { + for (UInt16 data_index = 0; data_index < packet->length; data_index++) { + source->parser.parse_fragment(packet->data[data_index]); + } + packet = MIDIPacketNext(packet); + } } } Error MIDIDriverCoreMidi::open() { + ERR_FAIL_COND_V_MSG(client || core_midi_closed, FAILED, + "MIDIDriverCoreMidi cannot be reopened."); + CFStringRef name = CFStringCreateWithCString(nullptr, "Godot", kCFStringEncodingASCII); OSStatus result = MIDIClientCreate(name, nullptr, nullptr, &client); CFRelease(name); @@ -61,12 +75,27 @@ Error MIDIDriverCoreMidi::open() { return ERR_CANT_OPEN; } - int sources = MIDIGetNumberOfSources(); - for (int i = 0; i < sources; i++) { + int source_count = MIDIGetNumberOfSources(); + int connection_index = 0; + for (int i = 0; i < source_count; i++) { MIDIEndpointRef source = MIDIGetSource(i); if (source) { - MIDIPortConnectSource(port_in, source, static_cast<void *>(&i)); - connected_sources.insert(i, source); + InputConnection *conn = memnew(InputConnection(connection_index, source)); + const OSStatus res = MIDIPortConnectSource(port_in, source, static_cast<void *>(conn)); + if (res != noErr) { + memdelete(conn); + } else { + connected_sources.push_back(conn); + + CFStringRef nameRef = nullptr; + char name[256]; + MIDIObjectGetStringProperty(source, kMIDIPropertyDisplayName, &nameRef); + CFStringGetCString(nameRef, name, sizeof(name), kCFStringEncodingUTF8); + CFRelease(nameRef); + connected_input_names.push_back(name); + + connection_index++; // Contiguous index for successfully connected inputs. + } } } @@ -74,11 +103,17 @@ Error MIDIDriverCoreMidi::open() { } void MIDIDriverCoreMidi::close() { - for (int i = 0; i < connected_sources.size(); i++) { - MIDIEndpointRef source = connected_sources[i]; - MIDIPortDisconnectSource(port_in, source); + mutex.lock(); + core_midi_closed = true; + mutex.unlock(); + + for (InputConnection *conn : connected_sources) { + MIDIPortDisconnectSource(port_in, conn->source); + memdelete(conn); } + connected_sources.clear(); + connected_input_names.clear(); if (port_in != 0) { MIDIPortDispose(port_in); @@ -91,26 +126,6 @@ void MIDIDriverCoreMidi::close() { } } -PackedStringArray MIDIDriverCoreMidi::get_connected_inputs() { - PackedStringArray list; - - for (int i = 0; i < connected_sources.size(); i++) { - MIDIEndpointRef source = connected_sources[i]; - CFStringRef ref = nullptr; - char name[256]; - - MIDIObjectGetStringProperty(source, kMIDIPropertyDisplayName, &ref); - CFStringGetCString(ref, name, sizeof(name), kCFStringEncodingUTF8); - CFRelease(ref); - - list.push_back(name); - } - - return list; -} - -MIDIDriverCoreMidi::MIDIDriverCoreMidi() {} - MIDIDriverCoreMidi::~MIDIDriverCoreMidi() { close(); } |