From b9fd25ea18f3e87530e1558cc377f36645fcd980 Mon Sep 17 00:00:00 2001 From: Fernando Cosentino Date: Fri, 29 Dec 2023 23:29:10 +0000 Subject: [PATCH] Add MIDI controller device index to InputEventMIDI.device property. It is possible to query the OS for the connected MIDI controllers, but the event messages' device field was not being used. This implements controller index being sent in InputEventMIDI messages in the device property, matching the index from OS.get_connected_midi_inputs(). Based on the work done by @ramdor. Closes godotengine/godot-proposals#7733 Co-authored-by: Richie --- core/os/midi_driver.cpp | 3 ++- core/os/midi_driver.h | 2 +- drivers/alsamidi/midi_driver_alsamidi.cpp | 14 +++++++------- drivers/alsamidi/midi_driver_alsamidi.h | 4 ++-- drivers/coremidi/midi_driver_coremidi.cpp | 5 +++-- drivers/winmidi/midi_driver_winmidi.cpp | 4 ++-- 6 files changed, 17 insertions(+), 15 deletions(-) diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index 037851661bb..6870c84b498 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -42,9 +42,10 @@ void MIDIDriver::set_singleton() { singleton = this; } -void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length) { +void MIDIDriver::receive_input_packet(int device_index, uint64_t timestamp, uint8_t *data, uint32_t length) { Ref event; event.instantiate(); + event->set_device(device_index); uint32_t param_position = 1; if (length >= 1) { diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h index 6ad21c319e5..cad3d8189e0 100644 --- a/core/os/midi_driver.h +++ b/core/os/midi_driver.h @@ -51,7 +51,7 @@ public: virtual PackedStringArray get_connected_inputs(); - static void receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length); + static void receive_input_packet(int device_index, uint64_t timestamp, uint8_t *data, uint32_t length); MIDIDriver(); virtual ~MIDIDriver() {} diff --git a/drivers/alsamidi/midi_driver_alsamidi.cpp b/drivers/alsamidi/midi_driver_alsamidi.cpp index 6b35987f70e..b87be69cc59 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.cpp +++ b/drivers/alsamidi/midi_driver_alsamidi.cpp @@ -82,13 +82,13 @@ size_t MIDIDriverALSAMidi::msg_expected_data(uint8_t status_byte) { } void MIDIDriverALSAMidi::InputConnection::parse_byte(uint8_t byte, MIDIDriverALSAMidi &driver, - uint64_t timestamp) { + uint64_t timestamp, int device_index) { switch (msg_category(byte)) { case MessageCategory::RealTime: // Real-Time messages are single byte messages that can // occur at any point. // We pass them straight through. - driver.receive_input_packet(timestamp, &byte, 1); + driver.receive_input_packet(device_index, timestamp, &byte, 1); break; case MessageCategory::Data: @@ -100,7 +100,7 @@ void MIDIDriverALSAMidi::InputConnection::parse_byte(uint8_t byte, MIDIDriverALS // Forward a complete message and reset relevant state. if (received_data == expected_data) { - driver.receive_input_packet(timestamp, buffer, received_data + 1); + driver.receive_input_packet(device_index, timestamp, buffer, received_data + 1); received_data = 0; if (msg_category(buffer[0]) != MessageCategory::Voice) { @@ -130,13 +130,13 @@ void MIDIDriverALSAMidi::InputConnection::parse_byte(uint8_t byte, MIDIDriverALS expected_data = msg_expected_data(byte); skipping_sys_ex = false; if (expected_data == 0) { - driver.receive_input_packet(timestamp, &byte, 1); + driver.receive_input_packet(device_index, timestamp, &byte, 1); } break; } } -int MIDIDriverALSAMidi::InputConnection::read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp) { +int MIDIDriverALSAMidi::InputConnection::read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp, int device_index) { int ret; do { uint8_t byte = 0; @@ -147,7 +147,7 @@ int MIDIDriverALSAMidi::InputConnection::read_in(MIDIDriverALSAMidi &driver, uin ERR_PRINT("snd_rawmidi_read error: " + String(snd_strerror(ret))); } } else { - parse_byte(byte, driver, timestamp); + parse_byte(byte, driver, timestamp, device_index); } } while (ret > 0); @@ -165,7 +165,7 @@ void MIDIDriverALSAMidi::thread_func(void *p_udata) { size_t connection_count = md->connected_inputs.size(); for (size_t i = 0; i < connection_count; i++) { - connections[i].read_in(*md, timestamp); + connections[i].read_in(*md, timestamp, (int)i); } md->unlock(); diff --git a/drivers/alsamidi/midi_driver_alsamidi.h b/drivers/alsamidi/midi_driver_alsamidi.h index 80cc96310fa..95ded3b1c96 100644 --- a/drivers/alsamidi/midi_driver_alsamidi.h +++ b/drivers/alsamidi/midi_driver_alsamidi.h @@ -58,7 +58,7 @@ class MIDIDriverALSAMidi : public MIDIDriver { rawmidi_ptr{ midi_in } {} // Read in and parse available data, forwarding any complete messages through the driver. - int read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp); + int read_in(MIDIDriverALSAMidi &driver, uint64_t timestamp, int device_index); snd_rawmidi_t *rawmidi_ptr = nullptr; @@ -68,7 +68,7 @@ class MIDIDriverALSAMidi : public MIDIDriver { size_t expected_data = 0; size_t received_data = 0; bool skipping_sys_ex = false; - void parse_byte(uint8_t byte, MIDIDriverALSAMidi &driver, uint64_t timestamp); + void parse_byte(uint8_t byte, MIDIDriverALSAMidi &driver, uint64_t timestamp, int device_index); }; Vector connected_inputs; diff --git a/drivers/coremidi/midi_driver_coremidi.cpp b/drivers/coremidi/midi_driver_coremidi.cpp index ed991b3d9d9..87fc7612f72 100644 --- a/drivers/coremidi/midi_driver_coremidi.cpp +++ b/drivers/coremidi/midi_driver_coremidi.cpp @@ -39,8 +39,9 @@ void MIDIDriverCoreMidi::read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con) { MIDIPacket *packet = const_cast(packet_list->packet); + int *device_index = static_cast(src_conn_ref_con); for (UInt32 i = 0; i < packet_list->numPackets; i++) { - receive_input_packet(packet->timeStamp, packet->data, packet->length); + receive_input_packet(*device_index, packet->timeStamp, packet->data, packet->length); packet = MIDIPacketNext(packet); } } @@ -64,7 +65,7 @@ Error MIDIDriverCoreMidi::open() { for (int i = 0; i < sources; i++) { MIDIEndpointRef source = MIDIGetSource(i); if (source) { - MIDIPortConnectSource(port_in, source, (void *)this); + MIDIPortConnectSource(port_in, source, static_cast(&i)); connected_sources.insert(i, source); } } diff --git a/drivers/winmidi/midi_driver_winmidi.cpp b/drivers/winmidi/midi_driver_winmidi.cpp index cdbab489c48..07f0226c5d7 100644 --- a/drivers/winmidi/midi_driver_winmidi.cpp +++ b/drivers/winmidi/midi_driver_winmidi.cpp @@ -36,7 +36,7 @@ void MIDIDriverWinMidi::read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { if (wMsg == MIM_DATA) { - receive_input_packet((uint64_t)dwParam2, (uint8_t *)&dwParam1, 3); + receive_input_packet((int)dwInstance, (uint64_t)dwParam2, (uint8_t *)&dwParam1, 3); } } @@ -44,7 +44,7 @@ Error MIDIDriverWinMidi::open() { for (UINT i = 0; i < midiInGetNumDevs(); i++) { HMIDIIN midi_in; - MMRESULT res = midiInOpen(&midi_in, i, (DWORD_PTR)read, (DWORD_PTR)this, CALLBACK_FUNCTION); + MMRESULT res = midiInOpen(&midi_in, i, (DWORD_PTR)read, (DWORD_PTR)i, CALLBACK_FUNCTION); if (res == MMSYSERR_NOERROR) { midiInStart(midi_in); connected_sources.insert(i, midi_in);