| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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; | |||
| }; | |||
| /*! | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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<size; ++j) | |||
| *midiData++ = data[j]; | |||
| curMidiDataPos += kBridgeBaseMidiOutHeaderSize + size; | |||
| curMidiDataPos += size; | |||
| } | |||
| else if (event.type == kEngineEventTypeMidi) | |||
| { | |||
| @@ -1287,12 +1289,15 @@ protected: | |||
| // set time | |||
| *(uint32_t*)midiData = event.time; | |||
| midiData += 4; | |||
| curMidiDataPos += 4; | |||
| // set port | |||
| *midiData++ = _midiEvent.port; | |||
| ++curMidiDataPos; | |||
| // set size | |||
| *midiData++ = _midiEvent.size; | |||
| ++curMidiDataPos; | |||
| // set data | |||
| *midiData++ = uint8_t(_midiData[0] | (event.channel & MIDI_CHANNEL_BIT)); | |||
| @@ -1300,7 +1305,7 @@ protected: | |||
| for (uint8_t j=1; j<_midiEvent.size; ++j) | |||
| *midiData++ = _midiData[j]; | |||
| curMidiDataPos += kBridgeBaseMidiOutHeaderSize + _midiEvent.size; | |||
| curMidiDataPos += _midiEvent.size; | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| if (MIDI_IS_CONTROL_BANK_SELECT(param)) | |||
| { | |||
| size = 3; | |||
| data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = uint8_t(carla_fixedValue<float>(0.0f, float(MAX_MIDI_VALUE-1), value)); | |||
| data[2] = uint8_t(carla_fixedValue<float>(0.0f, static_cast<float>(MAX_MIDI_VALUE-1), value)); | |||
| } | |||
| else | |||
| { | |||
| size = 3; | |||
| data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| data[1] = static_cast<uint8_t>(param); | |||
| data[2] = uint8_t(carla_fixedValue<float>(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); | |||
| data[2] = uint8_t(carla_fixedValue<float>(0.0f, 1.0f, value) * static_cast<float>(MAX_MIDI_VALUE-1)); | |||
| } | |||
| break; | |||
| return 3; | |||
| case kEngineControlEventTypeMidiBank: | |||
| size = 3; | |||
| data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| data[1] = MIDI_CONTROL_BANK_SELECT; | |||
| data[2] = uint8_t(carla_fixedValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
| break; | |||
| return 3; | |||
| case kEngineControlEventTypeMidiProgram: | |||
| size = 2; | |||
| data[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| data[1] = uint8_t(carla_fixedValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
| break; | |||
| return 2; | |||
| case kEngineControlEventTypeAllSoundOff: | |||
| size = 2; | |||
| data[0] = static_cast<uint8_t>(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<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
| data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
| break; | |||
| return 2; | |||
| } | |||
| return 0; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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<uint8_t>(mdataTmp, midiEvent.data, size); | |||
| // add channel | |||
| mdataTmp[0] = static_cast<uint8_t>(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); | |||
| } | |||
| } | |||
| } | |||
| @@ -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<uint8_t>(engineEvent.midi.data[0] + engineEvent.channel); | |||
| midiEvent.data[0] = static_cast<uint8_t>(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); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Plugin Host | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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<uint8_t>(mdataTmp, midiEvent.data, size); | |||
| // add channel | |||
| mdataTmp[0] = static_cast<uint8_t>(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<MidiOutPort>::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next()) | |||
| { | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla LV2 Single Plugin | |||
| * Copyright (C) 2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2017-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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<uint8_t>(mdataTmp, midiEvent.data, size); | |||
| // add channel | |||
| mdataTmp[0] = static_cast<uint8_t>(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; | |||
| } | |||
| } | |||
| @@ -142,8 +142,6 @@ BinaryType getBinaryTypeFromFile(const char* const filename) | |||
| default: | |||
| return BINARY_NATIVE; | |||
| } | |||
| return BINARY_NATIVE; | |||
| } | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Engine utils | |||
| * Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * 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 | |||