From 52f56ad468f43e28bf22658586c69f3812600789 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 8 Apr 2018 01:06:26 +0200 Subject: [PATCH] Make sure midi channel is always set on output --- source/backend/CarlaEngine.hpp | 5 +- source/backend/engine/CarlaEngineBridge.cpp | 15 ++++-- source/backend/engine/CarlaEngineData.cpp | 40 ++++++--------- source/backend/engine/CarlaEngineJack.cpp | 40 +++++++++------ source/backend/engine/CarlaEngineNative.cpp | 13 ++--- source/backend/engine/CarlaEngineRtAudio.cpp | 39 ++++++++++----- .../bridges-plugin/CarlaBridgeSingleLV2.cpp | 50 +++++++++++-------- source/utils/CarlaBinaryUtils.hpp | 2 - source/utils/CarlaEngineUtils.hpp | 9 ++-- 9 files changed, 122 insertions(+), 91 deletions(-) diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index 2d46337c5..e40c61658 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2017 Filipe Coelho + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -169,8 +169,9 @@ struct CARLA_API EngineControlEvent { /*! * Convert this control event into MIDI data. + * Returns size. */ - void convertToMidiData(const uint8_t channel, uint8_t& size, uint8_t data[3]) const noexcept; + uint8_t convertToMidiData(const uint8_t channel, uint8_t data[3]) const noexcept; }; /*! diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index 2fd5e606b..2425777f2 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2017 Filipe Coelho + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -1251,9 +1251,8 @@ protected: if (event.type == kEngineEventTypeControl) { - uint8_t size; uint8_t data[3]; - event.ctrl.convertToMidiData(event.channel, size, data); + const uint8_t size = event.ctrl.convertToMidiData(event.channel, data); CARLA_SAFE_ASSERT_CONTINUE(size > 0 && size <= 3); if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + size >= kBridgeRtClientDataMidiOutSize) @@ -1262,18 +1261,21 @@ protected: // set time *(uint32_t*)midiData = event.time; midiData = midiData + 4; + curMidiDataPos += 4; // set port *midiData++ = 0; + ++curMidiDataPos; // set size *midiData++ = size; + ++curMidiDataPos; // set data for (uint8_t j=0; j + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -24,61 +24,53 @@ CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- // EngineControlEvent -void EngineControlEvent::convertToMidiData(const uint8_t channel, uint8_t& size, uint8_t data[3]) const noexcept +uint8_t EngineControlEvent::convertToMidiData(const uint8_t channel, uint8_t data[3]) const noexcept { - size = 0; - switch (type) { case kEngineControlEventTypeNull: break; case kEngineControlEventTypeParameter: - if (param >= MAX_MIDI_VALUE) - { - // out of bounds. do nothing - } - else if (MIDI_IS_CONTROL_BANK_SELECT(param)) + CARLA_SAFE_ASSERT_RETURN(param >= MAX_MIDI_VALUE, 0); + + data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); + + if (MIDI_IS_CONTROL_BANK_SELECT(param)) { - size = 3; - data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_BANK_SELECT; - data[2] = uint8_t(carla_fixedValue(0.0f, float(MAX_MIDI_VALUE-1), value)); + data[2] = uint8_t(carla_fixedValue(0.0f, static_cast(MAX_MIDI_VALUE-1), value)); } else { - size = 3; - data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = static_cast(param); - data[2] = uint8_t(carla_fixedValue(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); + data[2] = uint8_t(carla_fixedValue(0.0f, 1.0f, value) * static_cast(MAX_MIDI_VALUE-1)); } - break; + return 3; case kEngineControlEventTypeMidiBank: - size = 3; data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_BANK_SELECT; data[2] = uint8_t(carla_fixedValue(0, MAX_MIDI_VALUE-1, param)); - break; + return 3; case kEngineControlEventTypeMidiProgram: - size = 2; data[0] = static_cast(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = uint8_t(carla_fixedValue(0, MAX_MIDI_VALUE-1, param)); - break; + return 2; case kEngineControlEventTypeAllSoundOff: - size = 2; data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_ALL_SOUND_OFF; - break; + return 2; case kEngineControlEventTypeAllNotesOff: - size = 2; data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); data[1] = MIDI_CONTROL_ALL_NOTES_OFF; - break; + return 2; } + + return 0; } // ----------------------------------------------------------------------- diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 4f509297d..05aa0627e 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2017 Filipe Coelho + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -380,11 +380,10 @@ public: CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); } - uint8_t size = 0; uint8_t data[3] = { 0, 0, 0 }; EngineControlEvent ctrlEvent = { type, param, value }; - ctrlEvent.convertToMidiData(channel, size, data); + const uint8_t size = ctrlEvent.convertToMidiData(channel, data); if (size == 0) return false; @@ -1725,22 +1724,25 @@ protected: { jackbridge_midi_clear_buffer(eventOut); - uint8_t size = 0; - uint8_t data[3] = { 0, 0, 0 }; - const uint8_t* dataPtr = data; + uint8_t size = 0; + uint8_t mdata[3] = { 0, 0, 0 }; + const uint8_t* mdataPtr = mdata; + uint8_t mdataTmp[EngineMidiEvent::kDataSize]; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); - if (engineEvent.type == kEngineEventTypeNull) + /**/ if (engineEvent.type == kEngineEventTypeNull) + { break; - + } else if (engineEvent.type == kEngineEventTypeControl) { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); - ctrlEvent.convertToMidiData(engineEvent.channel, size, data); - dataPtr = data; + + size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); + mdataPtr = mdata; } else if (engineEvent.type == kEngineEventTypeMidi) { @@ -1748,10 +1750,20 @@ protected: size = midiEvent.size; - if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr) - dataPtr = midiEvent.dataExt; + if (size > EngineMidiEvent::kDataSize) + { + CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); + mdataPtr = midiEvent.dataExt; + } else - dataPtr = midiEvent.data; + { + // copy + carla_copy(mdataTmp, midiEvent.data, size); + // add channel + mdataTmp[0] = static_cast(mdataTmp[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); + // done + mdataPtr = mdataTmp; + } } else { @@ -1759,7 +1771,7 @@ protected: } if (size > 0) - jackbridge_midi_event_write(eventOut, engineEvent.time, dataPtr, size); + jackbridge_midi_event_write(eventOut, engineEvent.time, mdataPtr, size); } } } diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp index 4715dd77a..7a06b3c75 100644 --- a/source/backend/engine/CarlaEngineNative.cpp +++ b/source/backend/engine/CarlaEngineNative.cpp @@ -1571,33 +1571,34 @@ protected: if (engineEvent.type == kEngineEventTypeNull) break; + carla_zeroStruct(midiEvent); midiEvent.time = engineEvent.time; - if (engineEvent.type == CarlaBackend::kEngineEventTypeControl) + /**/ if (engineEvent.type == kEngineEventTypeControl) { midiEvent.port = 0; - engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.size, midiEvent.data); + midiEvent.size = engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.data); } else if (engineEvent.type == kEngineEventTypeMidi) { - if (engineEvent.midi.size > 4 || engineEvent.midi.dataExt != nullptr) + if (engineEvent.midi.size > 4) continue; midiEvent.port = engineEvent.midi.port; midiEvent.size = engineEvent.midi.size; - midiEvent.data[0] = static_cast(engineEvent.midi.data[0] + engineEvent.channel); + midiEvent.data[0] = static_cast(engineEvent.midi.data[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); for (uint8_t j=1; j < midiEvent.size; ++j) midiEvent.data[j] = engineEvent.midi.data[j]; } else { - carla_stderr("Unknown event type..."); continue; } - pHost->write_midi_event(pHost->handle, &midiEvent); + if (midiEvent.size > 0) + pHost->write_midi_event(pHost->handle, &midiEvent); } } } diff --git a/source/backend/engine/CarlaEngineRtAudio.cpp b/source/backend/engine/CarlaEngineRtAudio.cpp index 1f56ffc6f..42bf8107b 100644 --- a/source/backend/engine/CarlaEngineRtAudio.cpp +++ b/source/backend/engine/CarlaEngineRtAudio.cpp @@ -1,6 +1,6 @@ /* * Carla Plugin Host - * Copyright (C) 2011-2017 Filipe Coelho + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -173,7 +173,7 @@ public: fMidiInEvents(), fMidiOuts(), fMidiOutMutex(), - fMidiOutVector(3) + fMidiOutVector(EngineMidiEvent::kDataSize) { carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api); @@ -674,22 +674,25 @@ protected: if (fMidiOuts.count() > 0) { - uint8_t size = 0; - uint8_t data[3] = { 0, 0, 0 }; - const uint8_t* dataPtr = data; + uint8_t size = 0; + uint8_t mdata[3] = { 0, 0, 0 }; + const uint8_t* mdataPtr = mdata; + uint8_t mdataTmp[EngineMidiEvent::kDataSize]; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); - if (engineEvent.type == kEngineEventTypeNull) + /**/ if (engineEvent.type == kEngineEventTypeNull) + { break; - + } else if (engineEvent.type == kEngineEventTypeControl) { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); - ctrlEvent.convertToMidiData(engineEvent.channel, size, data); - dataPtr = data; + + size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); + mdataPtr = mdata; } else if (engineEvent.type == kEngineEventTypeMidi) { @@ -697,10 +700,20 @@ protected: size = midiEvent.size; - if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr) - dataPtr = midiEvent.dataExt; + if (size > EngineMidiEvent::kDataSize) + { + CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); + mdataPtr = midiEvent.dataExt; + } else - dataPtr = midiEvent.data; + { + // copy + carla_copy(mdataTmp, midiEvent.data, size); + // add channel + mdataTmp[0] = static_cast(mdataTmp[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); + // done + mdataPtr = mdataTmp; + } } else { @@ -709,7 +722,7 @@ protected: if (size > 0) { - fMidiOutVector.assign(dataPtr, dataPtr + size); + fMidiOutVector.assign(mdataPtr, mdataPtr + size); for (LinkedList::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) { diff --git a/source/bridges-plugin/CarlaBridgeSingleLV2.cpp b/source/bridges-plugin/CarlaBridgeSingleLV2.cpp index b0cce4eff..b9f03c805 100644 --- a/source/bridges-plugin/CarlaBridgeSingleLV2.cpp +++ b/source/bridges-plugin/CarlaBridgeSingleLV2.cpp @@ -1,6 +1,6 @@ /* * Carla LV2 Single Plugin - * Copyright (C) 2017 Filipe Coelho + * Copyright (C) 2017-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -197,43 +197,51 @@ public: if (fPorts.numMidiOuts > 0) { - uint8_t port = 0; - uint8_t size = 0; - uint8_t data[3] = { 0, 0, 0 }; - const uint8_t* dataPtr = data; + uint8_t port = 0; + uint8_t size = 0; + uint8_t mdata[3] = { 0, 0, 0 }; + const uint8_t* mdataPtr = mdata; + uint8_t mdataTmp[EngineMidiEvent::kDataSize]; for (ushort i=0; i < kMaxEngineEventInternalCount; ++i) { const EngineEvent& engineEvent(pData->events.out[i]); - switch (engineEvent.type) + /**/ if (engineEvent.type == kEngineEventTypeNull) { - case kEngineEventTypeNull: - break; - - case kEngineEventTypeControl: { - const EngineControlEvent& ctrlEvent(engineEvent.ctrl); - ctrlEvent.convertToMidiData(engineEvent.channel, size, data); - dataPtr = data; break; } + else if (engineEvent.type == kEngineEventTypeControl) + { + const EngineControlEvent& ctrlEvent(engineEvent.ctrl); - case kEngineEventTypeMidi: { + size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); + mdataPtr = mdata; + } + else if (engineEvent.type == kEngineEventTypeMidi) + { const EngineMidiEvent& midiEvent(engineEvent.midi); port = midiEvent.port; size = midiEvent.size; - if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr) - dataPtr = midiEvent.dataExt; + if (size > EngineMidiEvent::kDataSize) + { + CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); + mdataPtr = midiEvent.dataExt; + } else - dataPtr = midiEvent.data; - - break; - } + { + // copy + carla_copy(mdataTmp, midiEvent.data, size); + // add channel + mdataTmp[0] = static_cast(mdataTmp[0] | (engineEvent.channel & MIDI_CHANNEL_BIT)); + // done + mdataPtr = mdataTmp; + } } - if (size > 0 && ! writeMidiEvent(port, engineEvent.time, size, dataPtr)) + if (size > 0 && ! writeMidiEvent(port, engineEvent.time, size, mdataPtr)) break; } } diff --git a/source/utils/CarlaBinaryUtils.hpp b/source/utils/CarlaBinaryUtils.hpp index b6dfa3309..9d98f492a 100644 --- a/source/utils/CarlaBinaryUtils.hpp +++ b/source/utils/CarlaBinaryUtils.hpp @@ -142,8 +142,6 @@ BinaryType getBinaryTypeFromFile(const char* const filename) default: return BINARY_NATIVE; } - - return BINARY_NATIVE; } // -------------------------------------------------------------------------------------------------------------------- diff --git a/source/utils/CarlaEngineUtils.hpp b/source/utils/CarlaEngineUtils.hpp index fec60ffa0..ab92bdca1 100644 --- a/source/utils/CarlaEngineUtils.hpp +++ b/source/utils/CarlaEngineUtils.hpp @@ -1,6 +1,6 @@ /* * Carla Engine utils - * Copyright (C) 2011-2017 Filipe Coelho + * Copyright (C) 2011-2018 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -160,7 +160,7 @@ void fillWaterMidiBufferFromEngineEvents(water::MidiBuffer& midiBuffer, const En { const EngineEvent& engineEvent(engineEvents[i]); - if (engineEvent.type == kEngineEventTypeNull) + /**/ if (engineEvent.type == kEngineEventTypeNull) { break; } @@ -168,7 +168,7 @@ void fillWaterMidiBufferFromEngineEvents(water::MidiBuffer& midiBuffer, const En { const EngineControlEvent& ctrlEvent(engineEvent.ctrl); - ctrlEvent.convertToMidiData(engineEvent.channel, size, mdata); + size = ctrlEvent.convertToMidiData(engineEvent.channel, mdata); mdataPtr = mdata; } else if (engineEvent.type == kEngineEventTypeMidi) @@ -177,8 +177,9 @@ void fillWaterMidiBufferFromEngineEvents(water::MidiBuffer& midiBuffer, const En size = midiEvent.size; - if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr) + if (size > EngineMidiEvent::kDataSize) { + CARLA_SAFE_ASSERT_CONTINUE(midiEvent.dataExt != nullptr); mdataPtr = midiEvent.dataExt; } else