@@ -834,14 +834,16 @@ public: | |||
static CarlaPlugin* newLV2(const Initializer& init); | |||
static CarlaPlugin* newVST(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* newFluidSynth(const Initializer& init, 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 | |||
// ------------------------------------------------------------------- | |||
@@ -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 | |||
// ----------------------------------------------------------------------- | |||
// Rack Patchbay stuff | |||
enum RackPatchbayGroupIds { | |||
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 { | |||
bool isReady; | |||
@@ -109,6 +140,7 @@ struct InternalAudio { | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// InternalEvents | |||
struct InternalEvents { | |||
EngineEvent* in; | |||
@@ -120,6 +152,7 @@ struct InternalEvents { | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// InternalTime | |||
struct InternalTime { | |||
bool playing; | |||
@@ -129,6 +162,7 @@ struct InternalTime { | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// NextAction | |||
enum EnginePostAction { | |||
kEnginePostActionNull, | |||
@@ -149,6 +183,7 @@ struct NextAction { | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// EnginePluginData | |||
struct EnginePluginData { | |||
CarlaPlugin* plugin; | |||
@@ -159,6 +194,7 @@ struct EnginePluginData { | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// CarlaEngineProtectedData | |||
struct CarlaEngineProtectedData { | |||
CarlaEngineOsc osc; | |||
@@ -15,9 +15,8 @@ | |||
* For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
*/ | |||
#include "CarlaEngineThread.hpp" | |||
#include "CarlaEngine.hpp" | |||
#include "CarlaEngineThread.hpp" | |||
#include "CarlaPlugin.hpp" | |||
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 = \ | |||
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 \ | |||
CarlaEngineThread.cpp.o | |||