@@ -834,14 +834,16 @@ public: | |||||
static CarlaPlugin* newLV2(const Initializer& init); | static CarlaPlugin* newLV2(const Initializer& init); | ||||
static CarlaPlugin* newVST(const Initializer& init); | static CarlaPlugin* newVST(const Initializer& init); | ||||
static CarlaPlugin* newAU(const Initializer& init); | static CarlaPlugin* newAU(const Initializer& init); | ||||
static CarlaPlugin* newCsound(const Initializer& init); | |||||
static CarlaPlugin* newGIG(const Initializer& init, const bool use16Outs); | |||||
static CarlaPlugin* newSF2(const Initializer& init, const bool use16Outs); | |||||
static CarlaPlugin* newSFZ(const Initializer& init, const bool use16Outs); | |||||
static CarlaPlugin* newCsound(const Initializer& init); | |||||
static CarlaPlugin* newJuce(const Initializer& init, const char* const format); | static CarlaPlugin* newJuce(const Initializer& init, const char* const format); | ||||
static CarlaPlugin* newFluidSynth(const Initializer& init, const bool use16Outs); | static CarlaPlugin* newFluidSynth(const Initializer& init, const bool use16Outs); | ||||
static CarlaPlugin* newLinuxSampler(const Initializer& init, const char* const format, const bool use16Outs); | static CarlaPlugin* newLinuxSampler(const Initializer& init, const char* const format, const bool use16Outs); | ||||
static CarlaPlugin* newFileCSD(const Initializer& init); | |||||
static CarlaPlugin* newFileGIG(const Initializer& init, const bool use16Outs); | |||||
static CarlaPlugin* newFileSF2(const Initializer& init, const bool use16Outs); | |||||
static CarlaPlugin* newFileSFZ(const Initializer& init); | |||||
#endif | #endif | ||||
// ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
@@ -0,0 +1,893 @@ | |||||
/* | |||||
* 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 "CarlaPlugin.hpp" | |||||
#include "CarlaMIDI.h" | |||||
#ifndef HAVE_JUCE | |||||
# include <cmath> | |||||
#else | |||||
# include "juce_audio_basics.h" | |||||
using juce::FloatVectorOperations; | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
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 | |||||
{ | |||||
switch (type) | |||||
{ | |||||
case kEngineControlEventTypeNull: | |||||
break; | |||||
case kEngineControlEventTypeParameter: | |||||
if (MIDI_IS_CONTROL_BANK_SELECT(param)) | |||||
{ | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
data[2] = static_cast<uint8_t>(value); | |||||
} | |||||
else | |||||
{ | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = static_cast<uint8_t>(param); | |||||
data[2] = uint8_t(value * 127.0f); | |||||
} | |||||
break; | |||||
case kEngineControlEventTypeMidiBank: | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
data[2] = static_cast<uint8_t>(param); | |||||
break; | |||||
case kEngineControlEventTypeMidiProgram: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE + channel); | |||||
data[1] = static_cast<uint8_t>(param); | |||||
break; | |||||
case kEngineControlEventTypeAllSoundOff: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||||
break; | |||||
case kEngineControlEventTypeAllNotesOff: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||||
break; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// EngineEvent | |||||
void EngineEvent::fillFromMidiData(const uint8_t size, const uint8_t* const data) noexcept | |||||
{ | |||||
// 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(data[2]); | |||||
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) {} | |||||
EngineOptions::~EngineOptions() | |||||
{ | |||||
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 | |||||
EngineRackBuffers::EngineRackBuffers(const uint32_t bufferSize) | |||||
: lastConnectionId(0) | |||||
{ | |||||
resize(bufferSize); | |||||
} | |||||
EngineRackBuffers::~EngineRackBuffers() | |||||
{ | |||||
clear(); | |||||
} | |||||
void EngineRackBuffers::clear() | |||||
{ | |||||
lastConnectionId = 0; | |||||
if (in[0] != nullptr) | |||||
{ | |||||
delete[] in[0]; | |||||
in[0] = nullptr; | |||||
} | |||||
if (in[1] != nullptr) | |||||
{ | |||||
delete[] in[1]; | |||||
in[1] = nullptr; | |||||
} | |||||
if (out[0] != nullptr) | |||||
{ | |||||
delete[] out[0]; | |||||
out[0] = nullptr; | |||||
} | |||||
if (out[1] != nullptr) | |||||
{ | |||||
delete[] out[1]; | |||||
out[1] = nullptr; | |||||
} | |||||
connectedIns[0].clear(); | |||||
connectedIns[1].clear(); | |||||
connectedOuts[0].clear(); | |||||
connectedOuts[1].clear(); | |||||
usedConnections.clear(); | |||||
} | |||||
void EngineRackBuffers::resize(const uint32_t bufferSize) | |||||
{ | |||||
if (bufferSize > 0) | |||||
{ | |||||
in[0] = new float[bufferSize]; | |||||
in[1] = new float[bufferSize]; | |||||
out[0] = new float[bufferSize]; | |||||
out[1] = new float[bufferSize]; | |||||
} | |||||
else | |||||
{ | |||||
in[0] = nullptr; | |||||
in[1] = nullptr; | |||||
out[0] = nullptr; | |||||
out[1] = nullptr; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// EnginePatchbayBuffers | |||||
EnginePatchbayBuffers::EnginePatchbayBuffers(const uint32_t bufferSize) | |||||
{ | |||||
resize(bufferSize); | |||||
} | |||||
EnginePatchbayBuffers::~EnginePatchbayBuffers() | |||||
{ | |||||
clear(); | |||||
} | |||||
void EnginePatchbayBuffers::clear() | |||||
{ | |||||
} | |||||
void EnginePatchbayBuffers::resize(const uint32_t /*bufferSize*/) | |||||
{ | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// InternalAudio | |||||
InternalAudio::InternalAudio() noexcept | |||||
: isReady(false), | |||||
usePatchbay(false), | |||||
inCount(0), | |||||
outCount(0) | |||||
{ | |||||
rack = nullptr; | |||||
} | |||||
InternalAudio::~InternalAudio() noexcept | |||||
{ | |||||
CARLA_ASSERT(! isReady); | |||||
CARLA_ASSERT(rack == nullptr); | |||||
} | |||||
void InternalAudio::initPatchbay() noexcept | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
rack->lastConnectionId = 0; | |||||
rack->usedConnections.clear(); | |||||
} | |||||
} | |||||
void InternalAudio::clear() | |||||
{ | |||||
isReady = false; | |||||
inCount = 0; | |||||
outCount = 0; | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
delete patchbay; | |||||
patchbay = nullptr; | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
delete rack; | |||||
rack = nullptr; | |||||
} | |||||
} | |||||
void InternalAudio::create(const uint32_t bufferSize) | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,); | |||||
patchbay = new EnginePatchbayBuffers(bufferSize); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack == nullptr,); | |||||
rack = new EngineRackBuffers(bufferSize); | |||||
} | |||||
isReady = true; | |||||
} | |||||
void InternalAudio::resize(const uint32_t bufferSize) | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
patchbay->resize(bufferSize); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
rack->resize(bufferSize); | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// InternalEvents | |||||
InternalEvents::InternalEvents() noexcept | |||||
: in(nullptr), | |||||
out(nullptr) {} | |||||
InternalEvents::~InternalEvents() noexcept | |||||
{ | |||||
CARLA_ASSERT(in == nullptr); | |||||
CARLA_ASSERT(out == nullptr); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// InternalTime | |||||
InternalTime::InternalTime() noexcept | |||||
: playing(false), | |||||
frame(0) {} | |||||
// ----------------------------------------------------------------------- | |||||
// NextAction | |||||
NextAction::NextAction() noexcept | |||||
: opcode(kEnginePostActionNull), | |||||
pluginId(0), | |||||
value(0) {} | |||||
NextAction::~NextAction() noexcept | |||||
{ | |||||
CARLA_ASSERT(opcode == kEnginePostActionNull); | |||||
} | |||||
void NextAction::ready() noexcept | |||||
{ | |||||
mutex.lock(); | |||||
mutex.unlock(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// EnginePluginData | |||||
void EnginePluginData::clear() noexcept | |||||
{ | |||||
plugin = nullptr; | |||||
insPeak[0] = insPeak[1] = 0.0f; | |||||
outsPeak[0] = outsPeak[1] = 0.0f; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// CarlaEngineProtectedData | |||||
CarlaEngineProtectedData::CarlaEngineProtectedData(CarlaEngine* const engine) | |||||
: osc(engine), | |||||
thread(engine), | |||||
oscData(nullptr), | |||||
callback(nullptr), | |||||
callbackPtr(nullptr), | |||||
hints(0x0), | |||||
bufferSize(0), | |||||
sampleRate(0.0), | |||||
aboutToClose(false), | |||||
curPluginCount(0), | |||||
maxPluginNumber(0), | |||||
nextPluginId(0), | |||||
plugins(nullptr) {} | |||||
CarlaEngineProtectedData::~CarlaEngineProtectedData() noexcept | |||||
{ | |||||
CARLA_ASSERT(curPluginCount == 0); | |||||
CARLA_ASSERT(maxPluginNumber == 0); | |||||
CARLA_ASSERT(nextPluginId == 0); | |||||
CARLA_ASSERT(plugins == nullptr); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void CarlaEngineProtectedData::doPluginRemove() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,); | |||||
--curPluginCount; | |||||
// move all plugins 1 spot backwards | |||||
for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i) | |||||
{ | |||||
CarlaPlugin* const plugin(plugins[i+1].plugin); | |||||
CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); | |||||
plugin->setId(i); | |||||
plugins[i].plugin = plugin; | |||||
plugins[i].insPeak[0] = 0.0f; | |||||
plugins[i].insPeak[1] = 0.0f; | |||||
plugins[i].outsPeak[0] = 0.0f; | |||||
plugins[i].outsPeak[1] = 0.0f; | |||||
} | |||||
const unsigned int id(curPluginCount); | |||||
// reset last plugin (now removed) | |||||
plugins[id].plugin = nullptr; | |||||
plugins[id].insPeak[0] = 0.0f; | |||||
plugins[id].insPeak[1] = 0.0f; | |||||
plugins[id].outsPeak[0] = 0.0f; | |||||
plugins[id].outsPeak[1] = 0.0f; | |||||
} | |||||
void CarlaEngineProtectedData::doPluginsSwitch() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,); | |||||
const unsigned int idA(nextAction.pluginId); | |||||
const unsigned int idB(nextAction.value); | |||||
CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,); | |||||
#if 0 | |||||
std::swap(plugins[idA].plugin, plugins[idB].plugin); | |||||
#else | |||||
CarlaPlugin* const tmp(plugins[idA].plugin); | |||||
plugins[idA].plugin = plugins[idB].plugin; | |||||
plugins[idB].plugin = tmp; | |||||
#endif | |||||
} | |||||
void CarlaEngineProtectedData::doNextPluginAction(const bool unlock) noexcept | |||||
{ | |||||
switch (nextAction.opcode) | |||||
{ | |||||
case kEnginePostActionNull: | |||||
break; | |||||
case kEnginePostActionZeroCount: | |||||
curPluginCount = 0; | |||||
break; | |||||
case kEnginePostActionRemovePlugin: | |||||
doPluginRemove(); | |||||
break; | |||||
case kEnginePostActionSwitchPlugins: | |||||
doPluginsSwitch(); | |||||
break; | |||||
} | |||||
nextAction.opcode = kEnginePostActionNull; | |||||
nextAction.pluginId = 0; | |||||
nextAction.value = 0; | |||||
if (unlock) | |||||
nextAction.mutex.unlock(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
#ifndef BUILD_BRIDGE | |||||
void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2], const uint32_t frames, const bool isOffline) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(bufEvents.in != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(bufEvents.out != nullptr,); | |||||
// safe copy | |||||
float inBuf0[frames]; | |||||
float inBuf1[frames]; | |||||
float* inBuf[2] = { inBuf0, inBuf1 }; | |||||
// initialize audio inputs | |||||
FLOAT_COPY(inBuf0, inBufReal[0], frames); | |||||
FLOAT_COPY(inBuf1, inBufReal[1], frames); | |||||
// initialize audio outputs (zero) | |||||
FLOAT_CLEAR(outBuf[0], frames); | |||||
FLOAT_CLEAR(outBuf[1], frames); | |||||
// initialize event outputs (zero) | |||||
carla_zeroStruct<EngineEvent>(bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
bool processed = false; | |||||
uint32_t oldAudioInCount = 0; | |||||
uint32_t oldMidiOutCount = 0; | |||||
// process plugins | |||||
for (unsigned int i=0; i < curPluginCount; ++i) | |||||
{ | |||||
CarlaPlugin* const plugin = plugins[i].plugin; | |||||
if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline)) | |||||
continue; | |||||
if (processed) | |||||
{ | |||||
// initialize audio inputs (from previous outputs) | |||||
FLOAT_COPY(inBuf0, outBuf[0], frames); | |||||
FLOAT_COPY(inBuf1, outBuf[1], frames); | |||||
// initialize audio outputs (zero) | |||||
FLOAT_CLEAR(outBuf[0], frames); | |||||
FLOAT_CLEAR(outBuf[1], frames); | |||||
// if plugin has no midi out, add previous events | |||||
if (oldMidiOutCount == 0 && bufEvents.in[0].type != kEngineEventTypeNull) | |||||
{ | |||||
if (bufEvents.out[0].type != kEngineEventTypeNull) | |||||
{ | |||||
// TODO: carefully add to input, sorted events | |||||
} | |||||
// else nothing needed | |||||
} | |||||
else | |||||
{ | |||||
// initialize event inputs from previous outputs | |||||
carla_copyStruct<EngineEvent>(bufEvents.in, bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
// initialize event outputs (zero) | |||||
carla_zeroStruct<EngineEvent>(bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
} | |||||
} | |||||
oldAudioInCount = plugin->getAudioInCount(); | |||||
oldMidiOutCount = plugin->getMidiOutCount(); | |||||
// process | |||||
plugin->initBuffers(); | |||||
plugin->process(inBuf, outBuf, frames); | |||||
plugin->unlock(); | |||||
// if plugin has no audio inputs, add input buffer | |||||
if (oldAudioInCount == 0) | |||||
{ | |||||
FLOAT_ADD(outBuf[0], inBuf0, frames); | |||||
FLOAT_ADD(outBuf[1], inBuf1, frames); | |||||
} | |||||
// set peaks | |||||
{ | |||||
EnginePluginData& pluginData(plugins[i]); | |||||
#ifdef HAVE_JUCE | |||||
float tmpMin, tmpMax; | |||||
if (oldAudioInCount > 0) | |||||
{ | |||||
FloatVectorOperations::findMinAndMax(inBuf0, frames, tmpMin, tmpMax); | |||||
pluginData.insPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
FloatVectorOperations::findMinAndMax(inBuf1, frames, tmpMin, tmpMax); | |||||
pluginData.insPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
} | |||||
else | |||||
{ | |||||
pluginData.insPeak[0] = 0.0f; | |||||
pluginData.insPeak[1] = 0.0f; | |||||
} | |||||
if (plugin->getAudioOutCount() > 0) | |||||
{ | |||||
FloatVectorOperations::findMinAndMax(outBuf[0], frames, tmpMin, tmpMax); | |||||
pluginData.outsPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
FloatVectorOperations::findMinAndMax(outBuf[1], frames, tmpMin, tmpMax); | |||||
pluginData.outsPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
} | |||||
else | |||||
{ | |||||
pluginData.outsPeak[0] = 0.0f; | |||||
pluginData.outsPeak[1] = 0.0f; | |||||
} | |||||
#else | |||||
float peak1, peak2; | |||||
if (oldAudioInCount > 0) | |||||
{ | |||||
peak1 = peak2 = 0.0f; | |||||
for (uint32_t k=0; k < frames; ++k) | |||||
{ | |||||
peak1 = carla_max<float>(peak1, std::fabs(inBuf0[k]), 1.0f); | |||||
peak2 = carla_max<float>(peak2, std::fabs(inBuf1[k]), 1.0f); | |||||
} | |||||
pluginData.insPeak[0] = peak1; | |||||
pluginData.insPeak[1] = peak2; | |||||
} | |||||
else | |||||
{ | |||||
pluginData.insPeak[0] = 0.0f; | |||||
pluginData.insPeak[1] = 0.0f; | |||||
} | |||||
if (plugin->getAudioOutCount() > 0) | |||||
{ | |||||
peak1 = peak2 = 0.0f; | |||||
for (uint32_t k=0; k < frames; ++k) | |||||
{ | |||||
peak1 = carla_max<float>(peak1, std::fabs(outBuf[0][k]), 1.0f); | |||||
peak2 = carla_max<float>(peak2, std::fabs(outBuf[1][k]), 1.0f); | |||||
} | |||||
pluginData.outsPeak[0] = peak1; | |||||
pluginData.outsPeak[1] = peak2; | |||||
} | |||||
else | |||||
{ | |||||
pluginData.outsPeak[0] = 0.0f; | |||||
pluginData.outsPeak[1] = 0.0f; | |||||
} | |||||
#endif | |||||
} | |||||
processed = true; | |||||
} | |||||
} | |||||
void CarlaEngineProtectedData::processRackFull(float** const inBuf, const uint32_t inCount, float** const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline) | |||||
{ | |||||
EngineRackBuffers* const rack(bufAudio.rack); | |||||
const CarlaMutex::ScopedLocker sl(rack->connectLock); | |||||
// connect input buffers | |||||
if (rack->connectedIns[0].count() == 0) | |||||
{ | |||||
FLOAT_CLEAR(rack->in[0], nframes); | |||||
} | |||||
else | |||||
{ | |||||
bool first = true; | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedIns[0].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < inCount); | |||||
if (first) | |||||
{ | |||||
FLOAT_COPY(rack->in[0], inBuf[port], nframes); | |||||
first = false; | |||||
} | |||||
else | |||||
{ | |||||
FLOAT_ADD(rack->in[0], inBuf[port], nframes); | |||||
} | |||||
} | |||||
if (first) | |||||
FLOAT_CLEAR(rack->in[0], nframes); | |||||
} | |||||
if (rack->connectedIns[1].count() == 0) | |||||
{ | |||||
FLOAT_CLEAR(rack->in[1], nframes); | |||||
} | |||||
else | |||||
{ | |||||
bool first = true; | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedIns[1].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < inCount); | |||||
if (first) | |||||
{ | |||||
FLOAT_COPY(rack->in[1], inBuf[port], nframes); | |||||
first = false; | |||||
} | |||||
else | |||||
{ | |||||
FLOAT_ADD(rack->in[1], inBuf[port], nframes); | |||||
} | |||||
} | |||||
if (first) | |||||
FLOAT_CLEAR(rack->in[1], nframes); | |||||
} | |||||
FLOAT_CLEAR(rack->out[0], nframes); | |||||
FLOAT_CLEAR(rack->out[1], nframes); | |||||
// process | |||||
processRack(rack->in, rack->out, nframes, isOffline); | |||||
// connect output buffers | |||||
if (rack->connectedOuts[0].count() != 0) | |||||
{ | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedOuts[0].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < outCount); | |||||
FLOAT_ADD(outBuf[port], rack->out[0], nframes); | |||||
} | |||||
} | |||||
if (rack->connectedOuts[1].count() != 0) | |||||
{ | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedOuts[1].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < outCount); | |||||
FLOAT_ADD(outBuf[port], rack->out[1], nframes); | |||||
} | |||||
} | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// ScopedActionLock | |||||
CarlaEngineProtectedData::ScopedActionLock::ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait) noexcept | |||||
: fData(data) | |||||
{ | |||||
fData->nextAction.mutex.lock(); | |||||
CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode == kEnginePostActionNull,); | |||||
fData->nextAction.opcode = action; | |||||
fData->nextAction.pluginId = pluginId; | |||||
fData->nextAction.value = value; | |||||
if (lockWait) | |||||
{ | |||||
// block wait for unlock on processing side | |||||
carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId); | |||||
fData->nextAction.mutex.lock(); | |||||
carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId); | |||||
} | |||||
else | |||||
{ | |||||
fData->doNextPluginAction(false); | |||||
} | |||||
} | |||||
CarlaEngineProtectedData::ScopedActionLock::~ScopedActionLock() noexcept | |||||
{ | |||||
fData->nextAction.mutex.unlock(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -52,6 +52,7 @@ CARLA_BACKEND_START_NAMESPACE | |||||
#endif | #endif | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// Rack Patchbay stuff | |||||
enum RackPatchbayGroupIds { | enum RackPatchbayGroupIds { | ||||
RACK_PATCHBAY_GROUP_CARLA = -1, | RACK_PATCHBAY_GROUP_CARLA = -1, | ||||
@@ -84,9 +85,39 @@ struct ConnectionToId { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// EngineRackBuffers | |||||
struct EngineRackBuffers; | |||||
struct EnginePatchbayBuffers; | |||||
struct EngineRackBuffers { | |||||
float* in[2]; | |||||
float* out[2]; | |||||
// connections stuff | |||||
LinkedList<uint> connectedIns[2]; | |||||
LinkedList<uint> connectedOuts[2]; | |||||
CarlaMutex connectLock; | |||||
int lastConnectionId; | |||||
LinkedList<ConnectionToId> usedConnections; | |||||
EngineRackBuffers(const uint32_t bufferSize); | |||||
~EngineRackBuffers(); | |||||
void clear(); | |||||
void resize(const uint32_t bufferSize); | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// EnginePatchbayBuffers | |||||
struct EnginePatchbayBuffers { | |||||
// TODO | |||||
EnginePatchbayBuffers(const uint32_t bufferSize); | |||||
~EnginePatchbayBuffers(); | |||||
void clear(); | |||||
void resize(const uint32_t bufferSize); | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// InternalAudio | |||||
struct InternalAudio { | struct InternalAudio { | ||||
bool isReady; | bool isReady; | ||||
@@ -109,6 +140,7 @@ struct InternalAudio { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// InternalEvents | |||||
struct InternalEvents { | struct InternalEvents { | ||||
EngineEvent* in; | EngineEvent* in; | ||||
@@ -120,6 +152,7 @@ struct InternalEvents { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// InternalTime | |||||
struct InternalTime { | struct InternalTime { | ||||
bool playing; | bool playing; | ||||
@@ -129,6 +162,7 @@ struct InternalTime { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// NextAction | |||||
enum EnginePostAction { | enum EnginePostAction { | ||||
kEnginePostActionNull, | kEnginePostActionNull, | ||||
@@ -149,6 +183,7 @@ struct NextAction { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// EnginePluginData | |||||
struct EnginePluginData { | struct EnginePluginData { | ||||
CarlaPlugin* plugin; | CarlaPlugin* plugin; | ||||
@@ -159,6 +194,7 @@ struct EnginePluginData { | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// CarlaEngineProtectedData | |||||
struct CarlaEngineProtectedData { | struct CarlaEngineProtectedData { | ||||
CarlaEngineOsc osc; | CarlaEngineOsc osc; | ||||
@@ -15,9 +15,8 @@ | |||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
*/ | */ | ||||
#include "CarlaEngineThread.hpp" | |||||
#include "CarlaEngine.hpp" | #include "CarlaEngine.hpp" | ||||
#include "CarlaEngineThread.hpp" | |||||
#include "CarlaPlugin.hpp" | #include "CarlaPlugin.hpp" | ||||
CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
@@ -1,271 +0,0 @@ | |||||
/* | |||||
* 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 "CarlaEngine.hpp" | |||||
#include "CarlaMIDI.h" | |||||
#include "CarlaUtils.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 | |||||
{ | |||||
switch (type) | |||||
{ | |||||
case kEngineControlEventTypeNull: | |||||
break; | |||||
case kEngineControlEventTypeParameter: | |||||
if (MIDI_IS_CONTROL_BANK_SELECT(param)) | |||||
{ | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
data[2] = static_cast<uint8_t>(value); | |||||
} | |||||
else | |||||
{ | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = static_cast<uint8_t>(param); | |||||
data[2] = uint8_t(value * 127.0f); | |||||
} | |||||
break; | |||||
case kEngineControlEventTypeMidiBank: | |||||
size = 3; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||||
data[2] = static_cast<uint8_t>(param); | |||||
break; | |||||
case kEngineControlEventTypeMidiProgram: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_PROGRAM_CHANGE + channel); | |||||
data[1] = static_cast<uint8_t>(param); | |||||
break; | |||||
case kEngineControlEventTypeAllSoundOff: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||||
break; | |||||
case kEngineControlEventTypeAllNotesOff: | |||||
size = 2; | |||||
data[0] = static_cast<uint8_t>(MIDI_STATUS_CONTROL_CHANGE + channel); | |||||
data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||||
break; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// EngineEvent | |||||
void EngineEvent::fillFromMidiData(const uint8_t size, const uint8_t* const data) noexcept | |||||
{ | |||||
// 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(data[2]); | |||||
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) {} | |||||
EngineOptions::~EngineOptions() | |||||
{ | |||||
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 |
@@ -1,384 +0,0 @@ | |||||
/* | |||||
* 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 "CarlaPlugin.hpp" | |||||
#ifndef HAVE_JUCE | |||||
# include <cmath> | |||||
#else | |||||
# include "juce_audio_basics.h" | |||||
using juce::FloatVectorOperations; | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_START_NAMESPACE | |||||
#if 0 | |||||
} // Fix editor indentation | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// InternalEvents | |||||
InternalEvents::InternalEvents() noexcept | |||||
: in(nullptr), | |||||
out(nullptr) {} | |||||
InternalEvents::~InternalEvents() noexcept | |||||
{ | |||||
CARLA_ASSERT(in == nullptr); | |||||
CARLA_ASSERT(out == nullptr); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// InternalTime | |||||
InternalTime::InternalTime() noexcept | |||||
: playing(false), | |||||
frame(0) {} | |||||
// ----------------------------------------------------------------------- | |||||
// NextAction | |||||
NextAction::NextAction() noexcept | |||||
: opcode(kEnginePostActionNull), | |||||
pluginId(0), | |||||
value(0) {} | |||||
NextAction::~NextAction() noexcept | |||||
{ | |||||
CARLA_ASSERT(opcode == kEnginePostActionNull); | |||||
} | |||||
void NextAction::ready() noexcept | |||||
{ | |||||
mutex.lock(); | |||||
mutex.unlock(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void EnginePluginData::clear() noexcept | |||||
{ | |||||
plugin = nullptr; | |||||
insPeak[0] = insPeak[1] = 0.0f; | |||||
outsPeak[0] = outsPeak[1] = 0.0f; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CarlaEngineProtectedData::CarlaEngineProtectedData(CarlaEngine* const engine) | |||||
: osc(engine), | |||||
thread(engine), | |||||
oscData(nullptr), | |||||
callback(nullptr), | |||||
callbackPtr(nullptr), | |||||
hints(0x0), | |||||
bufferSize(0), | |||||
sampleRate(0.0), | |||||
aboutToClose(false), | |||||
curPluginCount(0), | |||||
maxPluginNumber(0), | |||||
nextPluginId(0), | |||||
plugins(nullptr) {} | |||||
CarlaEngineProtectedData::~CarlaEngineProtectedData() noexcept | |||||
{ | |||||
CARLA_ASSERT(curPluginCount == 0); | |||||
CARLA_ASSERT(maxPluginNumber == 0); | |||||
CARLA_ASSERT(nextPluginId == 0); | |||||
CARLA_ASSERT(plugins == nullptr); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void CarlaEngineProtectedData::doPluginRemove() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,); | |||||
--curPluginCount; | |||||
// move all plugins 1 spot backwards | |||||
for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i) | |||||
{ | |||||
CarlaPlugin* const plugin(plugins[i+1].plugin); | |||||
CARLA_SAFE_ASSERT_BREAK(plugin != nullptr); | |||||
plugin->setId(i); | |||||
plugins[i].plugin = plugin; | |||||
plugins[i].insPeak[0] = 0.0f; | |||||
plugins[i].insPeak[1] = 0.0f; | |||||
plugins[i].outsPeak[0] = 0.0f; | |||||
plugins[i].outsPeak[1] = 0.0f; | |||||
} | |||||
const unsigned int id(curPluginCount); | |||||
// reset last plugin (now removed) | |||||
plugins[id].plugin = nullptr; | |||||
plugins[id].insPeak[0] = 0.0f; | |||||
plugins[id].insPeak[1] = 0.0f; | |||||
plugins[id].outsPeak[0] = 0.0f; | |||||
plugins[id].outsPeak[1] = 0.0f; | |||||
} | |||||
void CarlaEngineProtectedData::doPluginsSwitch() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,); | |||||
const unsigned int idA(nextAction.pluginId); | |||||
const unsigned int idB(nextAction.value); | |||||
CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,); | |||||
#if 0 | |||||
std::swap(plugins[idA].plugin, plugins[idB].plugin); | |||||
#else | |||||
CarlaPlugin* const tmp(plugins[idA].plugin); | |||||
plugins[idA].plugin = plugins[idB].plugin; | |||||
plugins[idB].plugin = tmp; | |||||
#endif | |||||
} | |||||
void CarlaEngineProtectedData::doNextPluginAction(const bool unlock) noexcept | |||||
{ | |||||
switch (nextAction.opcode) | |||||
{ | |||||
case kEnginePostActionNull: | |||||
break; | |||||
case kEnginePostActionZeroCount: | |||||
curPluginCount = 0; | |||||
break; | |||||
case kEnginePostActionRemovePlugin: | |||||
doPluginRemove(); | |||||
break; | |||||
case kEnginePostActionSwitchPlugins: | |||||
doPluginsSwitch(); | |||||
break; | |||||
} | |||||
nextAction.opcode = kEnginePostActionNull; | |||||
nextAction.pluginId = 0; | |||||
nextAction.value = 0; | |||||
if (unlock) | |||||
nextAction.mutex.unlock(); | |||||
} | |||||
#ifndef BUILD_BRIDGE | |||||
void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2], const uint32_t frames, const bool isOffline) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(bufEvents.in != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(bufEvents.out != nullptr,); | |||||
// safe copy | |||||
float inBuf0[frames]; | |||||
float inBuf1[frames]; | |||||
float* inBuf[2] = { inBuf0, inBuf1 }; | |||||
// initialize audio inputs | |||||
FLOAT_COPY(inBuf0, inBufReal[0], frames); | |||||
FLOAT_COPY(inBuf1, inBufReal[1], frames); | |||||
// initialize audio outputs (zero) | |||||
FLOAT_CLEAR(outBuf[0], frames); | |||||
FLOAT_CLEAR(outBuf[1], frames); | |||||
// initialize event outputs (zero) | |||||
carla_zeroStruct<EngineEvent>(bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
bool processed = false; | |||||
uint32_t oldAudioInCount = 0; | |||||
uint32_t oldMidiOutCount = 0; | |||||
// process plugins | |||||
for (unsigned int i=0; i < curPluginCount; ++i) | |||||
{ | |||||
CarlaPlugin* const plugin = plugins[i].plugin; | |||||
if (plugin == nullptr || ! plugin->isEnabled() || ! plugin->tryLock(isOffline)) | |||||
continue; | |||||
if (processed) | |||||
{ | |||||
// initialize audio inputs (from previous outputs) | |||||
FLOAT_COPY(inBuf0, outBuf[0], frames); | |||||
FLOAT_COPY(inBuf1, outBuf[1], frames); | |||||
// initialize audio outputs (zero) | |||||
FLOAT_CLEAR(outBuf[0], frames); | |||||
FLOAT_CLEAR(outBuf[1], frames); | |||||
// if plugin has no midi out, add previous events | |||||
if (oldMidiOutCount == 0 && bufEvents.in[0].type != kEngineEventTypeNull) | |||||
{ | |||||
if (bufEvents.out[0].type != kEngineEventTypeNull) | |||||
{ | |||||
// TODO: carefully add to input, sorted events | |||||
} | |||||
// else nothing needed | |||||
} | |||||
else | |||||
{ | |||||
// initialize event inputs from previous outputs | |||||
carla_copyStruct<EngineEvent>(bufEvents.in, bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
// initialize event outputs (zero) | |||||
carla_zeroStruct<EngineEvent>(bufEvents.out, EngineEvent::kMaxInternalCount); | |||||
} | |||||
} | |||||
oldAudioInCount = plugin->getAudioInCount(); | |||||
oldMidiOutCount = plugin->getMidiOutCount(); | |||||
// process | |||||
plugin->initBuffers(); | |||||
plugin->process(inBuf, outBuf, frames); | |||||
plugin->unlock(); | |||||
// if plugin has no audio inputs, add input buffer | |||||
if (oldAudioInCount == 0) | |||||
{ | |||||
FLOAT_ADD(outBuf[0], inBuf0, frames); | |||||
FLOAT_ADD(outBuf[1], inBuf1, frames); | |||||
} | |||||
// set peaks | |||||
{ | |||||
EnginePluginData& pluginData(plugins[i]); | |||||
#ifdef HAVE_JUCE | |||||
float tmpMin, tmpMax; | |||||
if (oldAudioInCount > 0) | |||||
{ | |||||
FloatVectorOperations::findMinAndMax(inBuf0, frames, tmpMin, tmpMax); | |||||
pluginData.insPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
FloatVectorOperations::findMinAndMax(inBuf1, frames, tmpMin, tmpMax); | |||||
pluginData.insPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
} | |||||
else | |||||
{ | |||||
pluginData.insPeak[0] = 0.0f; | |||||
pluginData.insPeak[1] = 0.0f; | |||||
} | |||||
if (plugin->getAudioOutCount() > 0) | |||||
{ | |||||
FloatVectorOperations::findMinAndMax(outBuf[0], frames, tmpMin, tmpMax); | |||||
pluginData.outsPeak[0] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
FloatVectorOperations::findMinAndMax(outBuf[1], frames, tmpMin, tmpMax); | |||||
pluginData.outsPeak[1] = carla_max<float>(std::abs(tmpMin), std::abs(tmpMax), 1.0f); | |||||
} | |||||
else | |||||
{ | |||||
pluginData.outsPeak[0] = 0.0f; | |||||
pluginData.outsPeak[1] = 0.0f; | |||||
} | |||||
#else | |||||
float peak1, peak2; | |||||
if (oldAudioInCount > 0) | |||||
{ | |||||
peak1 = peak2 = 0.0f; | |||||
for (uint32_t k=0; k < frames; ++k) | |||||
{ | |||||
peak1 = carla_max<float>(peak1, std::fabs(inBuf0[k]), 1.0f); | |||||
peak2 = carla_max<float>(peak2, std::fabs(inBuf1[k]), 1.0f); | |||||
} | |||||
pluginData.insPeak[0] = peak1; | |||||
pluginData.insPeak[1] = peak2; | |||||
} | |||||
else | |||||
{ | |||||
pluginData.insPeak[0] = 0.0f; | |||||
pluginData.insPeak[1] = 0.0f; | |||||
} | |||||
if (plugin->getAudioOutCount() > 0) | |||||
{ | |||||
peak1 = peak2 = 0.0f; | |||||
for (uint32_t k=0; k < frames; ++k) | |||||
{ | |||||
peak1 = carla_max<float>(peak1, std::fabs(outBuf[0][k]), 1.0f); | |||||
peak2 = carla_max<float>(peak2, std::fabs(outBuf[1][k]), 1.0f); | |||||
} | |||||
pluginData.outsPeak[0] = peak1; | |||||
pluginData.outsPeak[1] = peak2; | |||||
} | |||||
else | |||||
{ | |||||
pluginData.outsPeak[0] = 0.0f; | |||||
pluginData.outsPeak[1] = 0.0f; | |||||
} | |||||
#endif | |||||
} | |||||
processed = true; | |||||
} | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
CarlaEngineProtectedData::ScopedActionLock::ScopedActionLock(CarlaEngineProtectedData* const data, const EnginePostAction action, const unsigned int pluginId, const unsigned int value, const bool lockWait) noexcept | |||||
: fData(data) | |||||
{ | |||||
fData->nextAction.mutex.lock(); | |||||
CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode == kEnginePostActionNull,); | |||||
fData->nextAction.opcode = action; | |||||
fData->nextAction.pluginId = pluginId; | |||||
fData->nextAction.value = value; | |||||
if (lockWait) | |||||
{ | |||||
// block wait for unlock on processing side | |||||
carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId); | |||||
fData->nextAction.mutex.lock(); | |||||
carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId); | |||||
} | |||||
else | |||||
{ | |||||
fData->doNextPluginAction(false); | |||||
} | |||||
} | |||||
CarlaEngineProtectedData::ScopedActionLock::~ScopedActionLock() noexcept | |||||
{ | |||||
fData->nextAction.mutex.unlock(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -1,738 +0,0 @@ | |||||
/* | |||||
* 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 "CarlaUtils.hpp" | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_START_NAMESPACE | |||||
#if 0 | |||||
} // Fix editor indentation | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// OSC Stuff | |||||
#ifdef BUILD_BRIDGE | |||||
bool CarlaEngine::isOscBridgeRegistered() const noexcept | |||||
{ | |||||
return (pData->oscData != nullptr); | |||||
} | |||||
#else | |||||
bool CarlaEngine::isOscControlRegistered() const noexcept | |||||
{ | |||||
return pData->osc.isControlRegistered(); | |||||
} | |||||
#endif | |||||
void CarlaEngine::idleOsc() const noexcept | |||||
{ | |||||
try { | |||||
pData->osc.idle(); | |||||
} catch(...) {} | |||||
} | |||||
const char* CarlaEngine::getOscServerPathTCP() const noexcept | |||||
{ | |||||
return pData->osc.getServerPathTCP(); | |||||
} | |||||
const char* CarlaEngine::getOscServerPathUDP() const noexcept | |||||
{ | |||||
return pData->osc.getServerPathUDP(); | |||||
} | |||||
#ifdef BUILD_BRIDGE | |||||
void CarlaEngine::setOscBridgeData(const CarlaOscData* const oscData) const noexcept | |||||
{ | |||||
pData->oscData = oscData; | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
// Bridge/Controller OSC stuff | |||||
#ifdef BUILD_BRIDGE | |||||
void CarlaEngine::oscSend_bridge_plugin_info1(const PluginCategory category, const uint hints, const long uniqueId) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_plugin_info1(%i:%s, %X, %l)", category, PluginCategory2Str(category), hints, uniqueId); | |||||
char targetPath[std::strlen(pData->oscData->path)+21]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_plugin_info1"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iih", static_cast<int32_t>(category), static_cast<int32_t>(hints), static_cast<int64_t>(uniqueId)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_plugin_info2(const char* const realName, const char* const label, const char* const maker, const char* const copyright) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(realName != nullptr && realName[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(maker != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(copyright != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_plugin_info2(\"%s\", \"%s\", \"%s\", \"%s\")", realName, label, maker, copyright); | |||||
char targetPath[std::strlen(pData->oscData->path)+21]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_plugin_info2"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ssss", realName, label, maker, copyright); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_audio_count(const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_audio_count(%i, %i)", ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+20]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_audio_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_midi_count(const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_midi_count(%i, %i)", ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+19]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_midi_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_count(const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_count(%i, %i)", ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+24]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_program_count(const uint32_t count) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_program_count(%i)", count); | |||||
char targetPath[std::strlen(pData->oscData->path)+22]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_program_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", static_cast<int32_t>(count)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_midi_program_count(const uint32_t count) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_midi_program_count(%i)", count); | |||||
char targetPath[std::strlen(pData->oscData->path)+27]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_midi_program_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", static_cast<int32_t>(count)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_data(const uint32_t index, const int32_t rindex, const ParameterType type, const uint hints, const char* const name, const char* const unit) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(unit != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_data(%i, %i, %i:%s, %X, \"%s\", \"%s\")", index, rindex, type, ParameterType2Str(type), hints, name, unit); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiiiss", static_cast<int32_t>(index), static_cast<int32_t>(rindex), static_cast<int32_t>(type), static_cast<int32_t>(hints), name, unit); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_ranges1(const uint32_t index, const float def, const float min, const float max) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_ranges(%i, %f, %f, %f)", index, def, min, max); | |||||
char targetPath[std::strlen(pData->oscData->path)+26]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_ranges1"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ifff", static_cast<int32_t>(index), def, min, max); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_ranges2(const uint32_t index, const float step, const float stepSmall, const float stepLarge) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_ranges(%i, %f, %f, %f)", index, step, stepSmall, stepLarge); | |||||
char targetPath[std::strlen(pData->oscData->path)+26]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_ranges2"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ifff", static_cast<int32_t>(index), step, stepSmall, stepLarge); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_midi_cc(const uint32_t index, const int16_t cc) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_midi_cc(%i, %i)", index, cc); | |||||
char targetPath[std::strlen(pData->oscData->path)+26]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_midi_cc"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(index), static_cast<int32_t>(cc)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_midi_channel(const uint32_t index, const uint8_t channel) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_midi_channel(%i, %i)", index, channel); | |||||
char targetPath[std::strlen(pData->oscData->path)+31]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_midi_channel"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(index), static_cast<int32_t>(channel)); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_parameter_value(const int32_t index, const float value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(index != PARAMETER_NULL,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_parameter_value(%i, %f)", index, value); | |||||
char targetPath[std::strlen(pData->oscData->path)+24]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_parameter_value"); | |||||
try_lo_send(pData->oscData->target, targetPath, "if", index, value); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_default_value(const uint32_t index, const float value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_default_value(%i, %f)", index, value); | |||||
char targetPath[std::strlen(pData->oscData->path)+22]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_default_value"); | |||||
try_lo_send(pData->oscData->target, targetPath, "if", static_cast<int32_t>(index), value); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_current_program(const int32_t index) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_current_program(%i)", index); | |||||
char targetPath[std::strlen(pData->oscData->path)+20]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_current_program"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", index); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_current_midi_program(const int32_t index) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_current_midi_program(%i)", index); | |||||
char targetPath[std::strlen(pData->oscData->path)+25]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_current_midi_program"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", index); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_program_name(const uint32_t index, const char* const name) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_program_name(%i, \"%s\")", index, name); | |||||
char targetPath[std::strlen(pData->oscData->path)+21]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_program_name"); | |||||
try_lo_send(pData->oscData->target, targetPath, "is", static_cast<int32_t>(index), name); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_midi_program_data(const uint32_t index, const uint32_t bank, const uint32_t program, const char* const name) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_midi_program_data(%i, %i, %i, \"%s\")", index, bank, program, name); | |||||
char targetPath[std::strlen(pData->oscData->path)+26]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_midi_program_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiis", static_cast<int32_t>(index), static_cast<int32_t>(bank), static_cast<int32_t>(program), name); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_configure(const char* const key, const char* const value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(value != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_configure(\"%s\", \"%s\")", key, value); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_configure"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ss", key, value); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_set_custom_data(const char* const type, const char* const key, const char* const value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_bridge_set_custom_data(\"%s\", \"%s\", \"%s\")", type, key, value); | |||||
char targetPath[std::strlen(pData->oscData->path)+24]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_set_custom_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "sss", type, key, value); | |||||
} | |||||
void CarlaEngine::oscSend_bridge_set_chunk_data(const char* const chunkFile) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(chunkFile != nullptr && chunkFile[0] != '\0',); | |||||
carla_debug("CarlaEngine::oscSend_bridge_set_chunk_data(\"%s\")", chunkFile); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/bridge_set_chunk_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "s", chunkFile); | |||||
} | |||||
// TODO? | |||||
//void oscSend_bridge_set_peaks() const; | |||||
#else | |||||
void CarlaEngine::oscSend_control_add_plugin_start(const uint pluginId, const char* const pluginName) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginName != nullptr && pluginName[0] != '\0',); | |||||
carla_debug("CarlaEngine::oscSend_control_add_plugin_start(%i, \"%s\")", pluginId, pluginName); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/add_plugin_start"); | |||||
try_lo_send(pData->oscData->target, targetPath, "is", static_cast<int32_t>(pluginId), pluginName); | |||||
} | |||||
void CarlaEngine::oscSend_control_add_plugin_end(const uint pluginId) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_add_plugin_end(%i)", pluginId); | |||||
char targetPath[std::strlen(pData->oscData->path)+16]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/add_plugin_end"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", static_cast<int32_t>(pluginId)); | |||||
} | |||||
void CarlaEngine::oscSend_control_remove_plugin(const uint pluginId) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_remove_plugin(%i)", pluginId); | |||||
char targetPath[std::strlen(pData->oscData->path)+15]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/remove_plugin"); | |||||
try_lo_send(pData->oscData->target, targetPath, "i", static_cast<int32_t>(pluginId)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_plugin_info1(const uint pluginId, const PluginType type, const PluginCategory category, const uint hints, const long uniqueId) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(type != PLUGIN_NONE,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_plugin_data(%i, %i:%s, %i:%s, %X, %l)", pluginId, type, PluginType2Str(type), category, PluginCategory2Str(category), hints, uniqueId); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_plugin_info1"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiiih", static_cast<int32_t>(pluginId), static_cast<int32_t>(type), static_cast<int32_t>(category), static_cast<int32_t>(hints), static_cast<int64_t>(uniqueId)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_plugin_info2(const uint pluginId, const char* const realName, const char* const label, const char* const maker, const char* const copyright) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(realName != nullptr && realName[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(label != nullptr && label[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(maker != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(copyright != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_plugin_data(%i, \"%s\", \"%s\", \"%s\", \"%s\")", pluginId, realName, label, maker, copyright); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_plugin_info2"); | |||||
try_lo_send(pData->oscData->target, targetPath, "issss", static_cast<int32_t>(pluginId), realName, label, maker, copyright); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_audio_count(const uint pluginId, const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_audio_count(%i, %i, %i)", pluginId, ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_audio_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_midi_count(const uint pluginId, const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_midi_count(%i, %i, %i)", pluginId, ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_midi_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_count(const uint pluginId, const uint32_t ins, const uint32_t outs) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_count(%i, %i, %i)", pluginId, ins, outs); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(ins), static_cast<int32_t>(outs)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_program_count(const uint pluginId, const uint32_t count) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_program_count(%i, %i)", pluginId, count); | |||||
char targetPath[std::strlen(pData->oscData->path)+19]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_program_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(pluginId), static_cast<int32_t>(count)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_midi_program_count(const uint pluginId, const uint32_t count) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_midi_program_count(%i, %i)", pluginId, count); | |||||
char targetPath[std::strlen(pData->oscData->path)+24]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_midi_program_count"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(pluginId), static_cast<int32_t>(count)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_data(const uint pluginId, const uint32_t index, const ParameterType type, const uint hints, const char* const name, const char* const unit) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(unit != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_data(%i, %i, %i:%s, %X, \"%s\", \"%s\")", pluginId, index, type, ParameterType2Str(type), hints, name, unit); | |||||
char targetPath[std::strlen(pData->oscData->path)+20]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiiiss", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), static_cast<int32_t>(type), static_cast<int32_t>(hints), name, unit); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_ranges1(const uint pluginId, const uint32_t index, const float def, const float min, const float max) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(def <= min && def >= max,); | |||||
CARLA_SAFE_ASSERT_RETURN(min < max,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_ranges1(%i, %i, %f, %f, %f)", pluginId, index, def, min, max, def); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_ranges1"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iifff", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), def, min, max); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_ranges2(const uint pluginId, const uint32_t index, const float step, const float stepSmall, const float stepLarge) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(step <= stepSmall && step >= stepLarge,); | |||||
CARLA_SAFE_ASSERT_RETURN(stepSmall <= stepLarge,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_ranges2(%i, %i, %f, %f, %f)", pluginId, index, step, stepSmall, stepLarge); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_ranges"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iifff", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), step, stepSmall, stepLarge); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_midi_cc(const uint pluginId, const uint32_t index, const int16_t cc) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(cc <= 0x5F,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_midi_cc(%i, %i, %i)", pluginId, index, cc); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_midi_cc"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), static_cast<int32_t>(cc)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_midi_channel(const uint pluginId, const uint32_t index, const uint8_t channel) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_midi_channel(%i, %i, %i)", pluginId, index, channel); | |||||
char targetPath[std::strlen(pData->oscData->path)+28]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_midi_channel"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), static_cast<int32_t>(channel)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_parameter_value(const uint pluginId, const int32_t index, const float value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(index != PARAMETER_NULL,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_parameter_value(%i, %i:%s, %f)", pluginId, index, (index < 0) ? InternalParameterIndex2Str(static_cast<InternalParameterIndex>(index)) : "(none)", value); | |||||
char targetPath[std::strlen(pData->oscData->path)+21]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_parameter_value"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iif", static_cast<int32_t>(pluginId), index, value); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_default_value(const uint pluginId, const uint32_t index, const float value) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_default_value(%i, %i, %f)", pluginId, index, value); | |||||
char targetPath[std::strlen(pData->oscData->path)+19]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_default_value"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iif", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), value); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_current_program(const uint pluginId, const int32_t index) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_current_program(%i, %i)", pluginId, index); | |||||
char targetPath[std::strlen(pData->oscData->path)+21]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_current_program"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(pluginId), index); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_current_midi_program(const uint pluginId, const int32_t index) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_current_midi_program(%i, %i)", pluginId, index); | |||||
char targetPath[std::strlen(pData->oscData->path)+26]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_current_midi_program"); | |||||
try_lo_send(pData->oscData->target, targetPath, "ii", static_cast<int32_t>(pluginId), index); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_program_name(const uint pluginId, const uint32_t index, const char* const name) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_program_name(%i, %i, \"%s\")", pluginId, index, name); | |||||
char targetPath[std::strlen(pData->oscData->path)+18]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_program_name"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iis", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), name); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_midi_program_data(const uint pluginId, const uint32_t index, const uint32_t bank, const uint32_t program, const char* const name) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_control_set_midi_program_data(%i, %i, %i, %i, \"%s\")", pluginId, index, bank, program, name); | |||||
char targetPath[std::strlen(pData->oscData->path)+23]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_midi_program_data"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiiis", static_cast<int32_t>(pluginId), static_cast<int32_t>(index), static_cast<int32_t>(bank), static_cast<int32_t>(program), name); | |||||
} | |||||
void CarlaEngine::oscSend_control_note_on(const uint pluginId, const uint8_t channel, const uint8_t note, const uint8_t velo) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,); | |||||
carla_debug("CarlaEngine::oscSend_control_note_on(%i, %i, %i, %i)", pluginId, channel, note, velo); | |||||
char targetPath[std::strlen(pData->oscData->path)+9]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/note_on"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iiii", static_cast<int32_t>(pluginId), static_cast<int32_t>(channel), static_cast<int32_t>(note), static_cast<int32_t>(velo)); | |||||
} | |||||
void CarlaEngine::oscSend_control_note_off(const uint pluginId, const uint8_t channel, const uint8_t note) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
carla_debug("CarlaEngine::oscSend_control_note_off(%i, %i, %i)", pluginId, channel, note); | |||||
char targetPath[std::strlen(pData->oscData->path)+10]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/note_off"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iii", static_cast<int32_t>(pluginId), static_cast<int32_t>(channel), static_cast<int32_t>(note)); | |||||
} | |||||
void CarlaEngine::oscSend_control_set_peaks(const uint pluginId) const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pluginId < pData->curPluginCount,); | |||||
// TODO - try and see if we can get peaks[4] ref | |||||
const EnginePluginData& epData(pData->plugins[pluginId]); | |||||
char targetPath[std::strlen(pData->oscData->path)+11]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/set_peaks"); | |||||
try_lo_send(pData->oscData->target, targetPath, "iffff", static_cast<int32_t>(pluginId), epData.insPeak[0], epData.insPeak[1], epData.outsPeak[0], epData.outsPeak[1]); | |||||
} | |||||
void CarlaEngine::oscSend_control_exit() const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->path != nullptr && pData->oscData->path[0] != '\0',); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->oscData->target != nullptr,); | |||||
carla_debug("CarlaEngine::oscSend_control_exit()"); | |||||
char targetPath[std::strlen(pData->oscData->path)+6]; | |||||
std::strcpy(targetPath, pData->oscData->path); | |||||
std::strcat(targetPath, "/exit"); | |||||
try_lo_send(pData->oscData->target, targetPath, ""); | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -1,527 +0,0 @@ | |||||
/* | |||||
* 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. | |||||
*/ | |||||
#ifdef BUILD_BRIDGE | |||||
# error This file should not be compiled if building bridge | |||||
#endif | |||||
#include "CarlaEngineInternal.hpp" | |||||
#include "LinkedList.hpp" | |||||
#ifdef HAVE_JUCE | |||||
# include "juce_audio_basics.h" | |||||
using juce::FloatVectorOperations; | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_START_NAMESPACE | |||||
#if 0 | |||||
} // Fix editor indentation | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
struct EngineRackBuffers { | |||||
float* in[2]; | |||||
float* out[2]; | |||||
// connections stuff | |||||
LinkedList<uint> connectedIns[2]; | |||||
LinkedList<uint> connectedOuts[2]; | |||||
CarlaMutex connectLock; | |||||
int lastConnectionId; | |||||
LinkedList<ConnectionToId> usedConnections; | |||||
EngineRackBuffers(const uint32_t bufferSize); | |||||
~EngineRackBuffers(); | |||||
void clear(); | |||||
void resize(const uint32_t bufferSize); | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
struct EnginePatchbayBuffers { | |||||
// TODO | |||||
EnginePatchbayBuffers(const uint32_t bufferSize); | |||||
~EnginePatchbayBuffers(); | |||||
void clear(); | |||||
void resize(const uint32_t bufferSize); | |||||
}; | |||||
// ----------------------------------------------------------------------- | |||||
// EngineRackBuffers | |||||
EngineRackBuffers::EngineRackBuffers(const uint32_t bufferSize) | |||||
: lastConnectionId(0) | |||||
{ | |||||
resize(bufferSize); | |||||
} | |||||
EngineRackBuffers::~EngineRackBuffers() | |||||
{ | |||||
clear(); | |||||
} | |||||
void EngineRackBuffers::clear() | |||||
{ | |||||
lastConnectionId = 0; | |||||
if (in[0] != nullptr) | |||||
{ | |||||
delete[] in[0]; | |||||
in[0] = nullptr; | |||||
} | |||||
if (in[1] != nullptr) | |||||
{ | |||||
delete[] in[1]; | |||||
in[1] = nullptr; | |||||
} | |||||
if (out[0] != nullptr) | |||||
{ | |||||
delete[] out[0]; | |||||
out[0] = nullptr; | |||||
} | |||||
if (out[1] != nullptr) | |||||
{ | |||||
delete[] out[1]; | |||||
out[1] = nullptr; | |||||
} | |||||
connectedIns[0].clear(); | |||||
connectedIns[1].clear(); | |||||
connectedOuts[0].clear(); | |||||
connectedOuts[1].clear(); | |||||
usedConnections.clear(); | |||||
} | |||||
void EngineRackBuffers::resize(const uint32_t bufferSize) | |||||
{ | |||||
if (bufferSize > 0) | |||||
{ | |||||
in[0] = new float[bufferSize]; | |||||
in[1] = new float[bufferSize]; | |||||
out[0] = new float[bufferSize]; | |||||
out[1] = new float[bufferSize]; | |||||
} | |||||
else | |||||
{ | |||||
in[0] = nullptr; | |||||
in[1] = nullptr; | |||||
out[0] = nullptr; | |||||
out[1] = nullptr; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// EnginePatchbayBuffers | |||||
EnginePatchbayBuffers::EnginePatchbayBuffers(const uint32_t bufferSize) | |||||
{ | |||||
resize(bufferSize); | |||||
} | |||||
EnginePatchbayBuffers::~EnginePatchbayBuffers() | |||||
{ | |||||
clear(); | |||||
} | |||||
void EnginePatchbayBuffers::clear() | |||||
{ | |||||
} | |||||
void EnginePatchbayBuffers::resize(const uint32_t /*bufferSize*/) | |||||
{ | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// InternalAudio | |||||
InternalAudio::InternalAudio() noexcept | |||||
: isReady(false), | |||||
usePatchbay(false), | |||||
inCount(0), | |||||
outCount(0) | |||||
{ | |||||
rack = nullptr; | |||||
} | |||||
InternalAudio::~InternalAudio() noexcept | |||||
{ | |||||
CARLA_ASSERT(! isReady); | |||||
CARLA_ASSERT(rack == nullptr); | |||||
} | |||||
void InternalAudio::initPatchbay() noexcept | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
rack->lastConnectionId = 0; | |||||
rack->usedConnections.clear(); | |||||
} | |||||
} | |||||
void InternalAudio::clear() | |||||
{ | |||||
isReady = false; | |||||
inCount = 0; | |||||
outCount = 0; | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
delete patchbay; | |||||
patchbay = nullptr; | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
delete rack; | |||||
rack = nullptr; | |||||
} | |||||
} | |||||
void InternalAudio::create(const uint32_t bufferSize) | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,); | |||||
patchbay = new EnginePatchbayBuffers(bufferSize); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack == nullptr,); | |||||
rack = new EngineRackBuffers(bufferSize); | |||||
} | |||||
isReady = true; | |||||
} | |||||
void InternalAudio::resize(const uint32_t bufferSize) | |||||
{ | |||||
if (usePatchbay) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||||
patchbay->resize(bufferSize); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||||
rack->resize(bufferSize); | |||||
} | |||||
} | |||||
void CarlaEngineProtectedData::processRackFull(float** const inBuf, const uint32_t inCount, float** const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline) | |||||
{ | |||||
EngineRackBuffers* const rack(bufAudio.rack); | |||||
const CarlaMutex::ScopedLocker sl(rack->connectLock); | |||||
// connect input buffers | |||||
if (rack->connectedIns[0].count() == 0) | |||||
{ | |||||
FLOAT_CLEAR(rack->in[0], nframes); | |||||
} | |||||
else | |||||
{ | |||||
bool first = true; | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedIns[0].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < inCount); | |||||
if (first) | |||||
{ | |||||
FLOAT_COPY(rack->in[0], inBuf[port], nframes); | |||||
first = false; | |||||
} | |||||
else | |||||
{ | |||||
FLOAT_ADD(rack->in[0], inBuf[port], nframes); | |||||
} | |||||
} | |||||
if (first) | |||||
FLOAT_CLEAR(rack->in[0], nframes); | |||||
} | |||||
if (rack->connectedIns[1].count() == 0) | |||||
{ | |||||
FLOAT_CLEAR(rack->in[1], nframes); | |||||
} | |||||
else | |||||
{ | |||||
bool first = true; | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedIns[1].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < inCount); | |||||
if (first) | |||||
{ | |||||
FLOAT_COPY(rack->in[1], inBuf[port], nframes); | |||||
first = false; | |||||
} | |||||
else | |||||
{ | |||||
FLOAT_ADD(rack->in[1], inBuf[port], nframes); | |||||
} | |||||
} | |||||
if (first) | |||||
FLOAT_CLEAR(rack->in[1], nframes); | |||||
} | |||||
FLOAT_CLEAR(rack->out[0], nframes); | |||||
FLOAT_CLEAR(rack->out[1], nframes); | |||||
// process | |||||
processRack(rack->in, rack->out, nframes, isOffline); | |||||
// connect output buffers | |||||
if (rack->connectedOuts[0].count() != 0) | |||||
{ | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedOuts[0].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < outCount); | |||||
FLOAT_ADD(outBuf[port], rack->out[0], nframes); | |||||
} | |||||
} | |||||
if (rack->connectedOuts[1].count() != 0) | |||||
{ | |||||
for (LinkedList<uint>::Itenerator it = rack->connectedOuts[1].begin(); it.valid(); it.next()) | |||||
{ | |||||
const uint& port(it.getValue()); | |||||
CARLA_SAFE_ASSERT_CONTINUE(port < outCount); | |||||
FLOAT_ADD(outBuf[port], rack->out[1], nframes); | |||||
} | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Patchbay | |||||
bool CarlaEngine::patchbayConnect(const int portA, const int portB) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false); | |||||
carla_debug("CarlaEngineRtAudio::patchbayConnect(%i, %i)", portA, portB); | |||||
if (pData->bufAudio.usePatchbay) | |||||
{ | |||||
// not implemented yet | |||||
return false; | |||||
} | |||||
EngineRackBuffers* const rack(pData->bufAudio.rack); | |||||
CARLA_SAFE_ASSERT_RETURN_ERR(portA > RACK_PATCHBAY_PORT_MAX, "Invalid output port"); | |||||
CARLA_SAFE_ASSERT_RETURN_ERR(portB > RACK_PATCHBAY_PORT_MAX, "Invalid input port"); | |||||
// only allow connections between Carla and other ports | |||||
if (portA < 0 && portB < 0) | |||||
{ | |||||
setLastError("Invalid connection (1)"); | |||||
return false; | |||||
} | |||||
if (portA >= 0 && portB >= 0) | |||||
{ | |||||
setLastError("Invalid connection (2)"); | |||||
return false; | |||||
} | |||||
const int carlaPort = (portA < 0) ? portA : portB; | |||||
const int targetPort = (carlaPort == portA) ? portB : portA; | |||||
bool makeConnection = false; | |||||
switch (carlaPort) | |||||
{ | |||||
case RACK_PATCHBAY_PORT_AUDIO_IN1: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_AUDIO_IN*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_AUDIO_IN*1000+999); | |||||
rack->connectLock.lock(); | |||||
rack->connectedIns[0].append(targetPort - RACK_PATCHBAY_GROUP_AUDIO_IN*1000); | |||||
rack->connectLock.unlock(); | |||||
makeConnection = true; | |||||
break; | |||||
case RACK_PATCHBAY_PORT_AUDIO_IN2: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_AUDIO_IN*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_AUDIO_IN*1000+999); | |||||
rack->connectLock.lock(); | |||||
rack->connectedIns[1].append(targetPort - RACK_PATCHBAY_GROUP_AUDIO_IN*1000); | |||||
rack->connectLock.unlock(); | |||||
makeConnection = true; | |||||
break; | |||||
case RACK_PATCHBAY_PORT_AUDIO_OUT1: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000+999); | |||||
rack->connectLock.lock(); | |||||
rack->connectedOuts[0].append(targetPort - RACK_PATCHBAY_GROUP_AUDIO_OUT*1000); | |||||
rack->connectLock.unlock(); | |||||
makeConnection = true; | |||||
break; | |||||
case RACK_PATCHBAY_PORT_AUDIO_OUT2: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000+999); | |||||
rack->connectLock.lock(); | |||||
rack->connectedOuts[1].append(targetPort - RACK_PATCHBAY_GROUP_AUDIO_OUT*1000); | |||||
rack->connectLock.unlock(); | |||||
makeConnection = true; | |||||
break; | |||||
case RACK_PATCHBAY_PORT_MIDI_IN: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_MIDI_IN*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_MIDI_IN*1000+999); | |||||
makeConnection = connectRackMidiInPort(targetPort - RACK_PATCHBAY_GROUP_MIDI_IN*1000); | |||||
break; | |||||
case RACK_PATCHBAY_PORT_MIDI_OUT: | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort >= RACK_PATCHBAY_GROUP_MIDI_OUT*1000); | |||||
CARLA_SAFE_ASSERT_BREAK(targetPort <= RACK_PATCHBAY_GROUP_MIDI_OUT*1000+999); | |||||
makeConnection = connectRackMidiOutPort(targetPort - RACK_PATCHBAY_GROUP_MIDI_OUT*1000); | |||||
break; | |||||
} | |||||
if (! makeConnection) | |||||
{ | |||||
setLastError("Invalid connection (3)"); | |||||
return false; | |||||
} | |||||
ConnectionToId connectionToId; | |||||
connectionToId.id = rack->lastConnectionId; | |||||
connectionToId.portOut = portA; | |||||
connectionToId.portIn = portB; | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, portA, portB, 0.0f, nullptr); | |||||
rack->usedConnections.append(connectionToId); | |||||
rack->lastConnectionId++; | |||||
return true; | |||||
} | |||||
bool CarlaEngine::patchbayDisconnect(const int connectionId) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY, false); | |||||
CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false); | |||||
carla_debug("CarlaEngineRtAudio::patchbayDisconnect(%i)", connectionId); | |||||
if (pData->bufAudio.usePatchbay) | |||||
{ | |||||
// not implemented yet | |||||
return false; | |||||
} | |||||
EngineRackBuffers* const rack(pData->bufAudio.rack); | |||||
CARLA_SAFE_ASSERT_RETURN_ERR(rack->usedConnections.count() > 0, "No connections available"); | |||||
for (LinkedList<ConnectionToId>::Itenerator it=rack->usedConnections.begin(); it.valid(); it.next()) | |||||
{ | |||||
const ConnectionToId& connection(it.getValue()); | |||||
if (connection.id == connectionId) | |||||
{ | |||||
const int targetPort((connection.portOut >= 0) ? connection.portOut : connection.portIn); | |||||
const int carlaPort((targetPort == connection.portOut) ? connection.portIn : connection.portOut); | |||||
if (targetPort >= RACK_PATCHBAY_GROUP_MIDI_OUT*1000) | |||||
{ | |||||
const int portId(targetPort-RACK_PATCHBAY_GROUP_MIDI_OUT*1000); | |||||
disconnectRackMidiInPort(portId); | |||||
} | |||||
else if (targetPort >= RACK_PATCHBAY_GROUP_MIDI_IN*1000) | |||||
{ | |||||
const int portId(targetPort-RACK_PATCHBAY_GROUP_MIDI_IN*1000); | |||||
disconnectRackMidiOutPort(portId); | |||||
} | |||||
else if (targetPort >= RACK_PATCHBAY_GROUP_AUDIO_OUT*1000) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT1 || carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT2, false); | |||||
const int portId(targetPort-RACK_PATCHBAY_GROUP_AUDIO_OUT*1000); | |||||
rack->connectLock.lock(); | |||||
if (carlaPort == RACK_PATCHBAY_PORT_AUDIO_OUT1) | |||||
rack->connectedOuts[0].removeAll(portId); | |||||
else | |||||
rack->connectedOuts[1].removeAll(portId); | |||||
rack->connectLock.unlock(); | |||||
} | |||||
else if (targetPort >= RACK_PATCHBAY_GROUP_AUDIO_IN*1000) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN1 || carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN2, false); | |||||
const int portId(targetPort-RACK_PATCHBAY_GROUP_AUDIO_IN*1000); | |||||
rack->connectLock.lock(); | |||||
if (carlaPort == RACK_PATCHBAY_PORT_AUDIO_IN1) | |||||
rack->connectedIns[0].removeAll(portId); | |||||
else | |||||
rack->connectedIns[1].removeAll(portId); | |||||
rack->connectLock.unlock(); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(false, false); | |||||
} | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connection.id, connection.portOut, connection.portIn, 0.0f, nullptr); | |||||
rack->usedConnections.remove(it); | |||||
break; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
bool CarlaEngine::patchbayRefresh() | |||||
{ | |||||
setLastError("Unsupported operation"); | |||||
return false; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -1,273 +0,0 @@ | |||||
/* | |||||
* 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 "CarlaEngine.hpp" | |||||
#include "CarlaMIDI.h" | |||||
#include "CarlaUtils.hpp" | |||||
// ----------------------------------------------------------------------- | |||||
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 isInput) | |||||
: fEngine(engine), | |||||
fIsInput(isInput) | |||||
{ | |||||
carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInput)); | |||||
} | |||||
CarlaEnginePort::~CarlaEnginePort() | |||||
{ | |||||
carla_debug("CarlaEnginePort::~CarlaEnginePort()"); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Carla Engine Audio port | |||||
CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngine& engine, const bool isInput) | |||||
: CarlaEnginePort(engine, isInput), | |||||
fBuffer(nullptr) | |||||
{ | |||||
carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInput)); | |||||
} | |||||
CarlaEngineAudioPort::~CarlaEngineAudioPort() | |||||
{ | |||||
carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); | |||||
} | |||||
void CarlaEngineAudioPort::initBuffer() | |||||
{ | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Carla Engine CV port | |||||
CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngine& engine, const bool isInput) | |||||
: CarlaEnginePort(engine, isInput), | |||||
fBuffer(nullptr), | |||||
fProcessMode(engine.getProccessMode()) | |||||
{ | |||||
carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInput)); | |||||
if (fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) | |||||
fBuffer = new float[engine.getBufferSize()]; | |||||
} | |||||
CarlaEngineCVPort::~CarlaEngineCVPort() | |||||
{ | |||||
carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); | |||||
if (fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||||
delete[] fBuffer; | |||||
fBuffer = nullptr; | |||||
} | |||||
} | |||||
void CarlaEngineCVPort::initBuffer() | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS,); | |||||
carla_zeroFloat(fBuffer, fEngine.getBufferSize()); | |||||
} | |||||
void CarlaEngineCVPort::setBufferSize(const uint32_t bufferSize) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS,); | |||||
delete[] fBuffer; | |||||
fBuffer = new float[bufferSize]; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Carla Engine Event port | |||||
CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngine& engine, const bool isInput) | |||||
: CarlaEnginePort(engine, isInput), | |||||
fBuffer(nullptr), | |||||
fProcessMode(engine.getProccessMode()) | |||||
{ | |||||
carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInput)); | |||||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||||
fBuffer = new EngineEvent[EngineEvent::kMaxInternalCount]; | |||||
} | |||||
CarlaEngineEventPort::~CarlaEngineEventPort() | |||||
{ | |||||
carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); | |||||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||||
delete[] fBuffer; | |||||
fBuffer = nullptr; | |||||
} | |||||
} | |||||
void CarlaEngineEventPort::initBuffer() | |||||
{ | |||||
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, EngineEvent::kMaxInternalCount); | |||||
} | |||||
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 < EngineEvent::kMaxInternalCount; ++i) | |||||
{ | |||||
if (fBuffer[i].type == kEngineEventTypeNull) | |||||
break; | |||||
} | |||||
return i; | |||||
} | |||||
const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) 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 < EngineEvent::kMaxInternalCount, kFallbackEngineEvent); | |||||
return fBuffer[index]; | |||||
} | |||||
const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) 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) | |||||
{ | |||||
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)); | |||||
} | |||||
const float fixedValue(carla_fixValue<float>(0.0f, 1.0f, value)); | |||||
for (uint32_t i=0; i < EngineEvent::kMaxInternalCount; ++i) | |||||
{ | |||||
if (fBuffer[i].type != kEngineEventTypeNull) | |||||
continue; | |||||
EngineEvent& event(fBuffer[i]); | |||||
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) | |||||
{ | |||||
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) | |||||
{ | |||||
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 < EngineEvent::kMaxInternalCount; ++i) | |||||
{ | |||||
if (fBuffer[i].type != kEngineEventTypeNull) | |||||
continue; | |||||
EngineEvent& event(fBuffer[i]); | |||||
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) | |||||
{ | |||||
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) | |||||
{ | |||||
return writeMidiEvent(time, channel, midi.port, midi.size, midi.data); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -10,11 +10,7 @@ include ../Makefile.mk | |||||
OBJS = \ | OBJS = \ | ||||
CarlaEngine.cpp.o \ | CarlaEngine.cpp.o \ | ||||
CarlaEngine_data.cpp.o \ | |||||
CarlaEngine_internal.cpp.o \ | |||||
CarlaEngine_osc.cpp.o \ | |||||
CarlaEngine_patchbay.cpp.o \ | |||||
CarlaEngine_ports.cpp.o \ | |||||
CarlaEngineInternal.cpp.o \ | |||||
CarlaEngineOsc.cpp.o \ | CarlaEngineOsc.cpp.o \ | ||||
CarlaEngineThread.cpp.o | CarlaEngineThread.cpp.o | ||||