@@ -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(); | |||
@@ -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<EngineEvent>(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<float>(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 | |||
@@ -0,0 +1,115 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2014 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 | |||
* 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 |
@@ -0,0 +1,285 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2014 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 | |||
* 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<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||
data[2] = uint8_t(carla_fixValue<float>(0.0f, 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_fixValue<float>(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); | |||
} | |||
break; | |||
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_fixValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
break; | |||
case kEngineControlEventTypeMidiProgram: | |||
size = 2; | |||
data[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
data[1] = uint8_t(carla_fixValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
break; | |||
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; | |||
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; | |||
} | |||
} | |||
// ----------------------------------------------------------------------- | |||
// 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<uint8_t>(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 |
@@ -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<uint8_t>(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||
data[2] = uint8_t(carla_fixValue<float>(0.0f, 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_fixValue<float>(0.0f, 1.0f, value) * float(MAX_MIDI_VALUE-1)); | |||
} | |||
break; | |||
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_fixValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
break; | |||
case kEngineControlEventTypeMidiProgram: | |||
size = 2; | |||
data[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
data[1] = uint8_t(carla_fixValue<uint16_t>(0, MAX_MIDI_VALUE-1, param)); | |||
break; | |||
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; | |||
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; | |||
} | |||
} | |||
// ----------------------------------------------------------------------- | |||
// 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<uint8_t>(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 | |||
@@ -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; | |||
} | |||
@@ -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); | |||
@@ -0,0 +1,249 @@ | |||
/* | |||
* Carla Plugin Host | |||
* Copyright (C) 2011-2014 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 | |||
* 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<EngineEvent>(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<float>(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 |
@@ -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) | |||
{ | |||
@@ -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; | |||
@@ -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" | |||
@@ -0,0 +1,61 @@ | |||
/* | |||
* Carla Tests | |||
* Copyright (C) 2013-2014 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 | |||
* 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; | |||
} |
@@ -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 ./$@ | |||