diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index 2084d1dca..ab85afc40 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -740,7 +740,7 @@ public: /*! * Process all the post-poned events. - * This function must be called from the main thread (ie, idleGui()) if PLUGIN_USES_SINGLE_THREAD is set. + * This function must be called from the main thread (ie, idle()) if PLUGIN_USES_SINGLE_THREAD is set. */ void postRtEventsRun(); diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 98821046d..3b16f1c06 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -48,306 +48,6 @@ CARLA_BACKEND_START_NAMESPACE } // Fix editor indentation #endif -// ----------------------------------------------------------------------- -// Fallback data - -static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; - -// ----------------------------------------------------------------------- -// Carla Engine port (Abstract) - -CarlaEnginePort::CarlaEnginePort(const CarlaEngine& engine, const bool isInputPort) noexcept - : fEngine(engine), - fIsInput(isInputPort) -{ - carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort)); -} - -CarlaEnginePort::~CarlaEnginePort() noexcept -{ - carla_debug("CarlaEnginePort::~CarlaEnginePort()"); -} - -// ----------------------------------------------------------------------- -// Carla Engine Audio port - -CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngine& engine, const bool isInputPort) noexcept - : CarlaEnginePort(engine, isInputPort), - fBuffer(nullptr) -{ - carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort)); -} - -CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept -{ - carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); -} - -void CarlaEngineAudioPort::initBuffer() noexcept -{ -} - -// ----------------------------------------------------------------------- -// Carla Engine CV port - -CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngine& engine, const bool isInputPort) noexcept - : CarlaEnginePort(engine, isInputPort), - fBuffer(nullptr) -{ - carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort)); -} - -CarlaEngineCVPort::~CarlaEngineCVPort() noexcept -{ - carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); -} - -void CarlaEngineCVPort::initBuffer() noexcept -{ -} - -// ----------------------------------------------------------------------- -// Carla Engine Event port - -CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngine& engine, const bool isInputPort) noexcept - : CarlaEnginePort(engine, isInputPort), - fBuffer(nullptr), - fProcessMode(engine.getProccessMode()) -{ - carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort)); - - if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) - fBuffer = new EngineEvent[kMaxEngineEventInternalCount]; -} - -CarlaEngineEventPort::~CarlaEngineEventPort() noexcept -{ - carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); - - if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) - { - CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); - - delete[] fBuffer; - fBuffer = nullptr; - } -} - -void CarlaEngineEventPort::initBuffer() noexcept -{ - if (fProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || fProcessMode == ENGINE_PROCESS_MODE_BRIDGE) - fBuffer = fEngine.getInternalEventBuffer(fIsInput); - else if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fIsInput) - carla_zeroStruct(fBuffer, kMaxEngineEventInternalCount); -} - -uint32_t CarlaEngineEventPort::getEventCount() const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(fIsInput, 0); - CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0); - CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0); - - uint32_t i=0; - - for (; i < kMaxEngineEventInternalCount; ++i) - { - if (fBuffer[i].type == kEngineEventTypeNull) - break; - } - - return i; -} - -const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackEngineEvent); - CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent); - CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent); - CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent); - - return fBuffer[index]; -} - -const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept -{ - return fBuffer[index]; -} - -bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept -{ - CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); - CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); - CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); - CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); - CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); - CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); - - if (type == kEngineControlEventTypeParameter) { - CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); - } - - // FIXME? should not fix range if midi-program - const float fixedValue(carla_fixValue(0.0f, 1.0f, value)); - - for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) - { - EngineEvent& event(fBuffer[i]); - - if (event.type != kEngineEventTypeNull) - continue; - - event.type = kEngineEventTypeControl; - event.time = time; - event.channel = channel; - - event.ctrl.type = type; - event.ctrl.param = param; - event.ctrl.value = fixedValue; - - return true; - } - - carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full"); - return false; -} - -bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept -{ - return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); -} - -bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t size, const uint8_t* const data) noexcept -{ - CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); - CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); - CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); - CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); - CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false); - CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); - - for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) - { - EngineEvent& event(fBuffer[i]); - - if (event.type != kEngineEventTypeNull) - continue; - - event.type = kEngineEventTypeMidi; - event.time = time; - event.channel = channel; - - event.midi.port = port; - event.midi.size = size; - - event.midi.data[0] = uint8_t(MIDI_GET_STATUS_FROM_DATA(data)); - - uint8_t j=1; - for (; j < size; ++j) - event.midi.data[j] = data[j]; - for (; j < EngineMidiEvent::kDataSize; ++j) - event.midi.data[j] = 0; - - return true; - } - - carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full"); - return false; -} - -bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept -{ - return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), 0, size, data); -} - -bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept -{ - return writeMidiEvent(time, channel, midi.port, midi.size, midi.data); -} - -// ----------------------------------------------------------------------- -// Carla Engine client (Abstract) - -CarlaEngineClient::CarlaEngineClient(const CarlaEngine& engine) - : fEngine(engine), - fActive(false), - fLatency(0) -{ - carla_debug("CarlaEngineClient::CarlaEngineClient()"); -} - -CarlaEngineClient::~CarlaEngineClient() -{ - CARLA_SAFE_ASSERT(! fActive); - carla_debug("CarlaEngineClient::~CarlaEngineClient()"); -} - -void CarlaEngineClient::activate() noexcept -{ - CARLA_SAFE_ASSERT(! fActive); - carla_debug("CarlaEngineClient::activate()"); - - fActive = true; -} - -void CarlaEngineClient::deactivate() noexcept -{ - CARLA_SAFE_ASSERT(fActive); - carla_debug("CarlaEngineClient::deactivate()"); - - fActive = false; -} - -bool CarlaEngineClient::isActive() const noexcept -{ - return fActive; -} - -bool CarlaEngineClient::isOk() const noexcept -{ - return true; -} - -uint32_t CarlaEngineClient::getLatency() const noexcept -{ - return fLatency; -} - -void CarlaEngineClient::setLatency(const uint32_t samples) noexcept -{ - fLatency = samples; -} - -CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput) /*noexcept*/ -{ - CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); - carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput)); - - CarlaEnginePort* ret = nullptr; - - try { - switch (portType) - { - case kEnginePortTypeNull: - break; - case kEnginePortTypeAudio: - ret = new CarlaEngineAudioPort(fEngine, isInput); - case kEnginePortTypeCV: - ret = new CarlaEngineCVPort(fEngine, isInput); - case kEnginePortTypeEvent: - ret = new CarlaEngineEventPort(fEngine, isInput); - } - } - catch(...) { - return nullptr; - } - - if (ret != nullptr) - return ret; - - carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); - return nullptr; -} - // ----------------------------------------------------------------------- // Carla Engine diff --git a/source/backend/engine/CarlaEngineClient.cpp b/source/backend/engine/CarlaEngineClient.cpp new file mode 100644 index 000000000..262e41901 --- /dev/null +++ b/source/backend/engine/CarlaEngineClient.cpp @@ -0,0 +1,115 @@ +/* + * Carla Plugin Host + * Copyright (C) 2011-2014 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 + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaEngineInternal.hpp" +#include "CarlaEngineUtils.hpp" + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_START_NAMESPACE + +#if 0 +} // Fix editor indentation +#endif + +// ----------------------------------------------------------------------- +// Carla Engine client (Abstract) + +CarlaEngineClient::CarlaEngineClient(const CarlaEngine& engine) + : fEngine(engine), + fActive(false), + fLatency(0) +{ + carla_debug("CarlaEngineClient::CarlaEngineClient()"); +} + +CarlaEngineClient::~CarlaEngineClient() +{ + CARLA_SAFE_ASSERT(! fActive); + carla_debug("CarlaEngineClient::~CarlaEngineClient()"); +} + +void CarlaEngineClient::activate() noexcept +{ + CARLA_SAFE_ASSERT(! fActive); + carla_debug("CarlaEngineClient::activate()"); + + fActive = true; +} + +void CarlaEngineClient::deactivate() noexcept +{ + CARLA_SAFE_ASSERT(fActive); + carla_debug("CarlaEngineClient::deactivate()"); + + fActive = false; +} + +bool CarlaEngineClient::isActive() const noexcept +{ + return fActive; +} + +bool CarlaEngineClient::isOk() const noexcept +{ + return true; +} + +uint32_t CarlaEngineClient::getLatency() const noexcept +{ + return fLatency; +} + +void CarlaEngineClient::setLatency(const uint32_t samples) noexcept +{ + fLatency = samples; +} + +CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput) /*noexcept*/ +{ + CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); + carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput)); + + CarlaEnginePort* ret = nullptr; + + try { + switch (portType) + { + case kEnginePortTypeNull: + break; + case kEnginePortTypeAudio: + ret = new CarlaEngineAudioPort(fEngine, isInput); + case kEnginePortTypeCV: + ret = new CarlaEngineCVPort(fEngine, isInput); + case kEnginePortTypeEvent: + ret = new CarlaEngineEventPort(fEngine, isInput); + } + } + catch(...) { + return nullptr; + } + + if (ret != nullptr) + return ret; + + carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); + return nullptr; +} + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/engine/CarlaEngineData.cpp b/source/backend/engine/CarlaEngineData.cpp new file mode 100644 index 000000000..0de96b3a4 --- /dev/null +++ b/source/backend/engine/CarlaEngineData.cpp @@ -0,0 +1,285 @@ +/* + * Carla Plugin Host + * Copyright (C) 2011-2014 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 + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaEngineInternal.hpp" +#include "CarlaMIDI.h" + +#include "CarlaMathUtils.hpp" + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_START_NAMESPACE + +#if 0 +} // Fix editor indentation +#endif + +// ----------------------------------------------------------------------- +// EngineControlEvent + +void EngineControlEvent::dumpToMidiData(const uint8_t channel, uint8_t& size, 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)) + { + 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_fixValue(0.0f, float(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_fixValue(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); + } + break; + + 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_fixValue(0, MAX_MIDI_VALUE-1, param)); + break; + + case kEngineControlEventTypeMidiProgram: + size = 2; + data[0] = static_cast(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); + data[1] = uint8_t(carla_fixValue(0, MAX_MIDI_VALUE-1, param)); + break; + + case kEngineControlEventTypeAllSoundOff: + size = 2; + data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); + data[1] = MIDI_CONTROL_ALL_SOUND_OFF; + break; + + case kEngineControlEventTypeAllNotesOff: + size = 2; + data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); + data[1] = MIDI_CONTROL_ALL_NOTES_OFF; + break; + } +} + +// ----------------------------------------------------------------------- +// EngineEvent + +void EngineEvent::fillFromMidiData(const uint8_t size, const uint8_t* const data) noexcept +{ + if (size == 0 || data == nullptr || data[0] < MIDI_STATUS_NOTE_OFF) + { + type = kEngineEventTypeNull; + channel = 0; + return; + } + + // get channel + channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)); + + // get status + const uint8_t midiStatus(uint8_t(MIDI_GET_STATUS_FROM_DATA(data))); + + if (midiStatus == MIDI_STATUS_CONTROL_CHANGE) + { + type = kEngineEventTypeControl; + + const uint8_t midiControl(data[1]); + + if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) + { + CARLA_SAFE_ASSERT_INT(size == 3, size); + + const uint8_t midiBank(data[2]); + + ctrl.type = kEngineControlEventTypeMidiBank; + ctrl.param = midiBank; + ctrl.value = 0.0f; + } + else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) + { + CARLA_SAFE_ASSERT_INT(size == 2, size); + + ctrl.type = kEngineControlEventTypeAllSoundOff; + ctrl.param = 0; + ctrl.value = 0.0f; + } + else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) + { + CARLA_SAFE_ASSERT_INT(size == 2, size); + + ctrl.type = kEngineControlEventTypeAllNotesOff; + ctrl.param = 0; + ctrl.value = 0.0f; + } + else + { + CARLA_SAFE_ASSERT_INT2(size == 3, size, midiControl); + + const uint8_t midiValue(carla_fixValue(0, 127, data[2])); // ensures 0.0<->1.0 value range + + ctrl.type = kEngineControlEventTypeParameter; + ctrl.param = midiControl; + ctrl.value = float(midiValue)/127.0f; + } + } + else if (midiStatus == MIDI_STATUS_PROGRAM_CHANGE) + { + CARLA_SAFE_ASSERT_INT2(size == 2, size, data[1]); + + type = kEngineEventTypeControl; + + const uint8_t midiProgram(data[1]); + + ctrl.type = kEngineControlEventTypeMidiProgram; + ctrl.param = midiProgram; + ctrl.value = 0.0f; + } + else + { + type = kEngineEventTypeMidi; + + midi.port = 0; + midi.size = size; + + if (size > EngineMidiEvent::kDataSize) + { + midi.dataExt = data; + std::memset(midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize); + } + else + { + midi.data[0] = midiStatus; + + uint8_t i=1; + for (; i < midi.size; ++i) + midi.data[i] = data[i]; + for (; i < EngineMidiEvent::kDataSize; ++i) + midi.data[i] = 0; + + midi.dataExt = nullptr; + } + } +} + +// ----------------------------------------------------------------------- +// EngineOptions + +EngineOptions::EngineOptions() noexcept +#ifdef CARLA_OS_LINUX + : processMode(ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS), + transportMode(ENGINE_TRANSPORT_MODE_JACK), +#else + : processMode(ENGINE_PROCESS_MODE_CONTINUOUS_RACK), + transportMode(ENGINE_TRANSPORT_MODE_INTERNAL), +#endif + forceStereo(false), + preferPluginBridges(false), + preferUiBridges(true), + uisAlwaysOnTop(true), + maxParameters(MAX_DEFAULT_PARAMETERS), + uiBridgesTimeout(4000), + audioNumPeriods(2), + audioBufferSize(512), + audioSampleRate(44100), + audioDevice(nullptr), + binaryDir(nullptr), + resourceDir(nullptr), + frontendWinId(0) {} + +EngineOptions::~EngineOptions() noexcept +{ + if (audioDevice != nullptr) + { + delete[] audioDevice; + audioDevice = nullptr; + } + + if (binaryDir != nullptr) + { + delete[] binaryDir; + binaryDir = nullptr; + } + + if (resourceDir != nullptr) + { + delete[] resourceDir; + resourceDir = nullptr; + } +} + +// ----------------------------------------------------------------------- +// EngineTimeInfoBBT + +EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept + : bar(0), + beat(0), + tick(0), + barStartTick(0.0), + beatsPerBar(0.0f), + beatType(0.0f), + ticksPerBeat(0.0), + beatsPerMinute(0.0) {} + +// ----------------------------------------------------------------------- +// EngineTimeInfo + +EngineTimeInfo::EngineTimeInfo() noexcept + : playing(false), + frame(0), + usecs(0), + valid(0x0) {} + +void EngineTimeInfo::clear() noexcept +{ + playing = false; + frame = 0; + usecs = 0; + valid = 0x0; +} + +bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept +{ + if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.valid != valid) + return false; + if ((valid & kValidBBT) == 0) + return true; + if (timeInfo.bbt.beatsPerMinute != bbt.beatsPerMinute) + return false; + return true; +} + +bool EngineTimeInfo::operator!=(const EngineTimeInfo& timeInfo) const noexcept +{ + return !operator==(timeInfo); +} + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/engine/CarlaEngineInternal.cpp b/source/backend/engine/CarlaEngineInternal.cpp index 019765152..2ef87a488 100644 --- a/source/backend/engine/CarlaEngineInternal.cpp +++ b/source/backend/engine/CarlaEngineInternal.cpp @@ -29,258 +29,6 @@ CARLA_BACKEND_START_NAMESPACE } // Fix editor indentation #endif -// ----------------------------------------------------------------------- -// EngineControlEvent - -void EngineControlEvent::dumpToMidiData(const uint8_t channel, uint8_t& size, 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)) - { - 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_fixValue(0.0f, float(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_fixValue(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); - } - break; - - 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_fixValue(0, MAX_MIDI_VALUE-1, param)); - break; - - case kEngineControlEventTypeMidiProgram: - size = 2; - data[0] = static_cast(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); - data[1] = uint8_t(carla_fixValue(0, MAX_MIDI_VALUE-1, param)); - break; - - case kEngineControlEventTypeAllSoundOff: - size = 2; - data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); - data[1] = MIDI_CONTROL_ALL_SOUND_OFF; - break; - - case kEngineControlEventTypeAllNotesOff: - size = 2; - data[0] = static_cast(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); - data[1] = MIDI_CONTROL_ALL_NOTES_OFF; - break; - } -} - -// ----------------------------------------------------------------------- -// EngineEvent - -void EngineEvent::fillFromMidiData(const uint8_t size, const uint8_t* const data) noexcept -{ - if (size == 0 || data == nullptr || data[0] < MIDI_STATUS_NOTE_OFF) - { - type = kEngineEventTypeNull; - channel = 0; - return; - } - - // get channel - channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)); - - // get status - const uint8_t midiStatus(uint8_t(MIDI_GET_STATUS_FROM_DATA(data))); - - if (midiStatus == MIDI_STATUS_CONTROL_CHANGE) - { - type = kEngineEventTypeControl; - - const uint8_t midiControl(data[1]); - - if (MIDI_IS_CONTROL_BANK_SELECT(midiControl)) - { - CARLA_SAFE_ASSERT_INT(size == 3, size); - - const uint8_t midiBank(data[2]); - - ctrl.type = kEngineControlEventTypeMidiBank; - ctrl.param = midiBank; - ctrl.value = 0.0f; - } - else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) - { - CARLA_SAFE_ASSERT_INT(size == 2, size); - - ctrl.type = kEngineControlEventTypeAllSoundOff; - ctrl.param = 0; - ctrl.value = 0.0f; - } - else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) - { - CARLA_SAFE_ASSERT_INT(size == 2, size); - - ctrl.type = kEngineControlEventTypeAllNotesOff; - ctrl.param = 0; - ctrl.value = 0.0f; - } - else - { - CARLA_SAFE_ASSERT_INT2(size == 3, size, midiControl); - - const uint8_t midiValue(carla_fixValue(0, 127, data[2])); // ensures 0.0<->1.0 value range - - ctrl.type = kEngineControlEventTypeParameter; - ctrl.param = midiControl; - ctrl.value = float(midiValue)/127.0f; - } - } - else if (midiStatus == MIDI_STATUS_PROGRAM_CHANGE) - { - CARLA_SAFE_ASSERT_INT2(size == 2, size, data[1]); - - type = kEngineEventTypeControl; - - const uint8_t midiProgram(data[1]); - - ctrl.type = kEngineControlEventTypeMidiProgram; - ctrl.param = midiProgram; - ctrl.value = 0.0f; - } - else - { - type = kEngineEventTypeMidi; - - midi.port = 0; - midi.size = size; - - if (size > EngineMidiEvent::kDataSize) - { - midi.dataExt = data; - std::memset(midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize); - } - else - { - midi.data[0] = midiStatus; - - uint8_t i=1; - for (; i < midi.size; ++i) - midi.data[i] = data[i]; - for (; i < EngineMidiEvent::kDataSize; ++i) - midi.data[i] = 0; - - midi.dataExt = nullptr; - } - } -} - -// ----------------------------------------------------------------------- -// EngineOptions - -EngineOptions::EngineOptions() noexcept -#ifdef CARLA_OS_LINUX - : processMode(ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS), - transportMode(ENGINE_TRANSPORT_MODE_JACK), -#else - : processMode(ENGINE_PROCESS_MODE_CONTINUOUS_RACK), - transportMode(ENGINE_TRANSPORT_MODE_INTERNAL), -#endif - forceStereo(false), - preferPluginBridges(false), - preferUiBridges(true), - uisAlwaysOnTop(true), - maxParameters(MAX_DEFAULT_PARAMETERS), - uiBridgesTimeout(4000), - audioNumPeriods(2), - audioBufferSize(512), - audioSampleRate(44100), - audioDevice(nullptr), - binaryDir(nullptr), - resourceDir(nullptr), - frontendWinId(0) {} - -EngineOptions::~EngineOptions() noexcept -{ - if (audioDevice != nullptr) - { - delete[] audioDevice; - audioDevice = nullptr; - } - - if (binaryDir != nullptr) - { - delete[] binaryDir; - binaryDir = nullptr; - } - - if (resourceDir != nullptr) - { - delete[] resourceDir; - resourceDir = nullptr; - } -} - -// ----------------------------------------------------------------------- -// EngineTimeInfoBBT - -EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept - : bar(0), - beat(0), - tick(0), - barStartTick(0.0), - beatsPerBar(0.0f), - beatType(0.0f), - ticksPerBeat(0.0), - beatsPerMinute(0.0) {} - -// ----------------------------------------------------------------------- -// EngineTimeInfo - -EngineTimeInfo::EngineTimeInfo() noexcept - : playing(false), - frame(0), - usecs(0), - valid(0x0) {} - -void EngineTimeInfo::clear() noexcept -{ - playing = false; - frame = 0; - usecs = 0; - valid = 0x0; -} - -bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept -{ - if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.valid != valid) - return false; - if ((valid & kValidBBT) == 0) - return true; - if (timeInfo.bbt.beatsPerMinute != bbt.beatsPerMinute) - return false; - return true; -} - -bool EngineTimeInfo::operator!=(const EngineTimeInfo& timeInfo) const noexcept -{ - return !operator==(timeInfo); -} - // ----------------------------------------------------------------------- // EngineRackBuffers diff --git a/source/backend/engine/CarlaEngineOsc.cpp b/source/backend/engine/CarlaEngineOsc.cpp index f3b850af1..add256f71 100644 --- a/source/backend/engine/CarlaEngineOsc.cpp +++ b/source/backend/engine/CarlaEngineOsc.cpp @@ -37,7 +37,7 @@ extern int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBr // ----------------------------------------------------------------------- -CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) +CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) noexcept : fEngine(engine), fServerTCP(nullptr), fServerUDP(nullptr) @@ -46,7 +46,7 @@ CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) carla_debug("CarlaEngineOsc::CarlaEngineOsc(%p)", engine); } -CarlaEngineOsc::~CarlaEngineOsc() +CarlaEngineOsc::~CarlaEngineOsc() noexcept { CARLA_SAFE_ASSERT(fName.isEmpty()); CARLA_SAFE_ASSERT(fServerPathTCP.isEmpty()); @@ -58,7 +58,7 @@ CarlaEngineOsc::~CarlaEngineOsc() // ----------------------------------------------------------------------- -void CarlaEngineOsc::init(const char* const name) +void CarlaEngineOsc::init(const char* const name) noexcept { CARLA_SAFE_ASSERT_RETURN(fName.isEmpty(),); CARLA_SAFE_ASSERT_RETURN(fServerPathTCP.isEmpty(),); @@ -106,18 +106,38 @@ void CarlaEngineOsc::init(const char* const name) CARLA_SAFE_ASSERT(fServerUDP != nullptr); } -void CarlaEngineOsc::idle() const +void CarlaEngineOsc::idle() const noexcept { - if (fServerTCP != nullptr) { - while (lo_server_recv_noblock(fServerTCP, 0) != 0) {} + if (fServerTCP != nullptr) + { + for (;;) + { + try { + if (lo_server_recv_noblock(fServerTCP, 0) == 0) + break; + } + catch(...) { + break; + } + } } - if (fServerUDP != nullptr) { - while (lo_server_recv_noblock(fServerUDP, 0) != 0) {} + if (fServerUDP != nullptr) + { + for (;;) + { + try { + if (lo_server_recv_noblock(fServerUDP, 0) == 0) + break; + } + catch(...) { + break; + } + } } } -void CarlaEngineOsc::close() +void CarlaEngineOsc::close() noexcept { CARLA_SAFE_ASSERT(fName.isNotEmpty()); CARLA_SAFE_ASSERT(fServerPathTCP.isNotEmpty()); @@ -130,15 +150,23 @@ void CarlaEngineOsc::close() if (fServerTCP != nullptr) { - lo_server_del_method(fServerTCP, nullptr, nullptr); - lo_server_free(fServerTCP); + try { + lo_server_del_method(fServerTCP, nullptr, nullptr); + } catch(...) {} + try { + lo_server_free(fServerTCP); + } catch(...) {} fServerTCP = nullptr; } if (fServerUDP != nullptr) { - lo_server_del_method(fServerUDP, nullptr, nullptr); - lo_server_free(fServerUDP); + try { + lo_server_del_method(fServerUDP, nullptr, nullptr); + } catch(...) {} + try { + lo_server_free(fServerUDP); + } catch(...) {} fServerUDP = nullptr; } diff --git a/source/backend/engine/CarlaEngineOsc.hpp b/source/backend/engine/CarlaEngineOsc.hpp index 469e87c59..5e9bb905d 100644 --- a/source/backend/engine/CarlaEngineOsc.hpp +++ b/source/backend/engine/CarlaEngineOsc.hpp @@ -57,12 +57,12 @@ CARLA_BACKEND_START_NAMESPACE class CarlaEngineOsc { public: - CarlaEngineOsc(CarlaEngine* const engine); - ~CarlaEngineOsc(); + CarlaEngineOsc(CarlaEngine* const engine) noexcept; + ~CarlaEngineOsc() noexcept; - void init(const char* const name); - void idle() const; - void close(); + void init(const char* const name) noexcept; + void idle() const noexcept; + void close() noexcept; // ------------------------------------------------------------------- @@ -76,9 +76,9 @@ public: return fServerPathUDP; } +#ifndef BUILD_BRIDGE // ------------------------------------------------------------------- -#ifndef BUILD_BRIDGE bool isControlRegistered() const noexcept { return (fControlData.target != nullptr); diff --git a/source/backend/engine/CarlaEnginePort.cpp b/source/backend/engine/CarlaEnginePort.cpp new file mode 100644 index 000000000..88ddca560 --- /dev/null +++ b/source/backend/engine/CarlaEnginePort.cpp @@ -0,0 +1,249 @@ +/* + * Carla Plugin Host + * Copyright (C) 2011-2014 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 + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaEngineInternal.hpp" + +#include "CarlaMathUtils.hpp" +#include "CarlaMIDI.h" + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_START_NAMESPACE + +#if 0 +} // Fix editor indentation +#endif + +// ----------------------------------------------------------------------- +// Fallback data + +static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; + +// ----------------------------------------------------------------------- +// Carla Engine port (Abstract) + +CarlaEnginePort::CarlaEnginePort(const CarlaEngine& engine, const bool isInputPort) noexcept + : fEngine(engine), + fIsInput(isInputPort) +{ + carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort)); +} + +CarlaEnginePort::~CarlaEnginePort() noexcept +{ + carla_debug("CarlaEnginePort::~CarlaEnginePort()"); +} + +// ----------------------------------------------------------------------- +// Carla Engine Audio port + +CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngine& engine, const bool isInputPort) noexcept + : CarlaEnginePort(engine, isInputPort), + fBuffer(nullptr) +{ + carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort)); +} + +CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept +{ + carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); +} + +void CarlaEngineAudioPort::initBuffer() noexcept +{ +} + +// ----------------------------------------------------------------------- +// Carla Engine CV port + +CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngine& engine, const bool isInputPort) noexcept + : CarlaEnginePort(engine, isInputPort), + fBuffer(nullptr) +{ + carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort)); +} + +CarlaEngineCVPort::~CarlaEngineCVPort() noexcept +{ + carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); +} + +void CarlaEngineCVPort::initBuffer() noexcept +{ +} + +// ----------------------------------------------------------------------- +// Carla Engine Event port + +CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngine& engine, const bool isInputPort) noexcept + : CarlaEnginePort(engine, isInputPort), + fBuffer(nullptr), + fProcessMode(engine.getProccessMode()) +{ + carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort)); + + if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) + fBuffer = new EngineEvent[kMaxEngineEventInternalCount]; +} + +CarlaEngineEventPort::~CarlaEngineEventPort() noexcept +{ + carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); + + if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) + { + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); + + delete[] fBuffer; + fBuffer = nullptr; + } +} + +void CarlaEngineEventPort::initBuffer() noexcept +{ + if (fProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || fProcessMode == ENGINE_PROCESS_MODE_BRIDGE) + fBuffer = fEngine.getInternalEventBuffer(fIsInput); + else if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fIsInput) + carla_zeroStruct(fBuffer, kMaxEngineEventInternalCount); +} + +uint32_t CarlaEngineEventPort::getEventCount() const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(fIsInput, 0); + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0); + CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0); + + uint32_t i=0; + + for (; i < kMaxEngineEventInternalCount; ++i) + { + if (fBuffer[i].type == kEngineEventTypeNull) + break; + } + + return i; +} + +const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackEngineEvent); + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent); + CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent); + CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent); + + return fBuffer[index]; +} + +const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept +{ + return fBuffer[index]; +} + +bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept +{ + CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); + CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); + CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); + CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); + CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); + + if (type == kEngineControlEventTypeParameter) { + CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); + } + + // FIXME? should not fix range if midi-program + const float fixedValue(carla_fixValue(0.0f, 1.0f, value)); + + for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) + { + EngineEvent& event(fBuffer[i]); + + if (event.type != kEngineEventTypeNull) + continue; + + event.type = kEngineEventTypeControl; + event.time = time; + event.channel = channel; + + event.ctrl.type = type; + event.ctrl.param = param; + event.ctrl.value = fixedValue; + + return true; + } + + carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full"); + return false; +} + +bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept +{ + return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); +} + +bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t size, const uint8_t* const data) noexcept +{ + CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); + CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); + CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); + CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false); + CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); + + for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) + { + EngineEvent& event(fBuffer[i]); + + if (event.type != kEngineEventTypeNull) + continue; + + event.type = kEngineEventTypeMidi; + event.time = time; + event.channel = channel; + + event.midi.port = port; + event.midi.size = size; + + event.midi.data[0] = uint8_t(MIDI_GET_STATUS_FROM_DATA(data)); + + uint8_t j=1; + for (; j < size; ++j) + event.midi.data[j] = data[j]; + for (; j < EngineMidiEvent::kDataSize; ++j) + event.midi.data[j] = 0; + + return true; + } + + carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full"); + return false; +} + +bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept +{ + return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), 0, size, data); +} + +bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept +{ + return writeMidiEvent(time, channel, midi.port, midi.size, midi.data); +} + +// ----------------------------------------------------------------------- + +CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/engine/CarlaEngineThread.cpp b/source/backend/engine/CarlaEngineThread.cpp index 071847e23..654f39c23 100644 --- a/source/backend/engine/CarlaEngineThread.cpp +++ b/source/backend/engine/CarlaEngineThread.cpp @@ -23,7 +23,7 @@ CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- -CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) +CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) noexcept : CarlaThread("CarlaEngineThread"), fEngine(engine) { @@ -31,14 +31,14 @@ CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); } -CarlaEngineThread::~CarlaEngineThread() +CarlaEngineThread::~CarlaEngineThread() noexcept { carla_debug("CarlaEngineThread::~CarlaEngineThread()"); } // ----------------------------------------------------------------------- -void CarlaEngineThread::run() +void CarlaEngineThread::run() noexcept { CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,); CARLA_SAFE_ASSERT(fEngine->isRunning()); @@ -71,7 +71,14 @@ void CarlaEngineThread::run() if (oscRegisted || ! needsSingleThread) { if (! needsSingleThread) - plugin->postRtEventsRun(); + { + try { + plugin->postRtEventsRun(); + } + catch (...) { + carla_stderr2("Caught exception during postRtEventsRun()"); + } + } if (hasUi || oscRegisted) { diff --git a/source/backend/engine/CarlaEngineThread.hpp b/source/backend/engine/CarlaEngineThread.hpp index 73e3fd3c6..48ed5b2ef 100644 --- a/source/backend/engine/CarlaEngineThread.hpp +++ b/source/backend/engine/CarlaEngineThread.hpp @@ -28,15 +28,16 @@ CARLA_BACKEND_START_NAMESPACE #endif // ----------------------------------------------------------------------- +// CarlaEngineThread class CarlaEngineThread : public CarlaThread { public: - CarlaEngineThread(CarlaEngine* const engine); - ~CarlaEngineThread() override; + CarlaEngineThread(CarlaEngine* const engine) noexcept; + ~CarlaEngineThread() noexcept override; protected: - void run() override; + void run() noexcept override; private: CarlaEngine* const fEngine; diff --git a/source/includes/CarlaDefines.h b/source/includes/CarlaDefines.h index 63165945c..690818887 100644 --- a/source/includes/CarlaDefines.h +++ b/source/includes/CarlaDefines.h @@ -188,6 +188,13 @@ private: \ static void operator delete(void*); #endif +/* Define CARLA_CATCH_MSG */ +#define CARLA_CATCH_MSG(msg, after) \ + catch(...) { \ + carla_stderr2("Caught exception: " msg); \ + after \ + } + /* Define EXTERN_C */ #ifdef __cplusplus # define EXTERN_C extern "C" diff --git a/source/tests/Exception.cpp b/source/tests/Exception.cpp new file mode 100644 index 000000000..edcf02d75 --- /dev/null +++ b/source/tests/Exception.cpp @@ -0,0 +1,61 @@ +/* + * Carla Tests + * Copyright (C) 2013-2014 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 + * published by the Free Software Foundation; either version 2 of + * the License, or any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaDefines.h" +#include "CarlaUtils.hpp" + +struct Struct1 { + Struct1() noexcept {} + ~Struct1() noexcept {} + + void throwHere() + { + throw 1; + } +}; + +struct Struct2 { + Struct2() { throw 2; } + ~Struct2() noexcept {} + + void throwHere() + { + throw 3; + } +}; + +int main() +{ + Struct1 a; + Struct2* b = nullptr; + + try { + a.throwHere(); + } CARLA_CATCH_MSG("Struct1 throw", carla_stdout("after text1 here");) + + try { + b = new Struct2; + } CARLA_CATCH_MSG("Struct2 throw", carla_stdout("after text2 here");) + + if (b != nullptr) + { + delete b; + b = nullptr; + } + + return 0; +} diff --git a/source/tests/Makefile b/source/tests/Makefile index 450d94302..d6f0029cd 100644 --- a/source/tests/Makefile +++ b/source/tests/Makefile @@ -69,6 +69,10 @@ Engine: Engine.cpp env LD_LIBRARY_PATH=../backend valgrind --leak-check=full ./$@ # ../modules/juce_audio_basics.a ../modules/juce_core.a \ +Exception: Exception.cpp + $(CXX) $< $(PEDANTIC_CXX_FLAGS) -o $@ +# valgrind ./$@ + EngineEvents: EngineEvents.cpp $(CXX) $< $(PEDANTIC_CXX_FLAGS) -L../backend -lcarla_standalone2 -o $@ env LD_LIBRARY_PATH=../backend valgrind ./$@