@@ -232,12 +232,12 @@ struct EngineOptions { | |||
bool preferUiBridges; | |||
bool uisAlwaysOnTop; | |||
unsigned int maxParameters; | |||
unsigned int uiBridgesTimeout; | |||
unsigned int audioNumPeriods; | |||
unsigned int audioBufferSize; | |||
unsigned int audioSampleRate; | |||
const char* audioDevice; | |||
uint maxParameters; | |||
uint uiBridgesTimeout; | |||
uint audioNumPeriods; | |||
uint audioBufferSize; | |||
uint audioSampleRate; | |||
const char* audioDevice; | |||
const char* binaryDir; | |||
const char* resourceDir; | |||
@@ -48,6 +48,11 @@ CARLA_BACKEND_START_NAMESPACE | |||
} // Fix editor indentation | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Fallback data | |||
static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; | |||
// ----------------------------------------------------------------------- | |||
// EngineControlEvent | |||
@@ -300,6 +305,217 @@ bool EngineTimeInfo::operator!=(const EngineTimeInfo& timeInfo) const noexcept | |||
return !operator==(timeInfo); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine port (Abstract) | |||
CarlaEnginePort::CarlaEnginePort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: fEngine(engine), | |||
fIsInput(isInputPort) | |||
{ | |||
carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEnginePort::~CarlaEnginePort() noexcept | |||
{ | |||
carla_debug("CarlaEnginePort::~CarlaEnginePort()"); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Audio port | |||
CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr) | |||
{ | |||
carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); | |||
} | |||
void CarlaEngineAudioPort::initBuffer() noexcept | |||
{ | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine CV port | |||
CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr) | |||
{ | |||
carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEngineCVPort::~CarlaEngineCVPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); | |||
} | |||
void CarlaEngineCVPort::initBuffer() noexcept | |||
{ | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Event port | |||
CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr), | |||
fProcessMode(engine.getProccessMode()) | |||
{ | |||
carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort)); | |||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
fBuffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
} | |||
CarlaEngineEventPort::~CarlaEngineEventPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); | |||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||
delete[] fBuffer; | |||
fBuffer = nullptr; | |||
} | |||
} | |||
void CarlaEngineEventPort::initBuffer() noexcept | |||
{ | |||
if (fProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || fProcessMode == ENGINE_PROCESS_MODE_BRIDGE) | |||
fBuffer = fEngine.getInternalEventBuffer(fIsInput); | |||
else if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fIsInput) | |||
carla_zeroStruct<EngineEvent>(fBuffer, kMaxEngineEventInternalCount); | |||
} | |||
uint32_t CarlaEngineEventPort::getEventCount() const noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsInput, 0); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0); | |||
uint32_t i=0; | |||
for (; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
if (fBuffer[i].type == kEngineEventTypeNull) | |||
break; | |||
} | |||
return i; | |||
} | |||
const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent); | |||
return fBuffer[index]; | |||
} | |||
const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept | |||
{ | |||
return fBuffer[index]; | |||
} | |||
bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); | |||
CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); | |||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||
CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); | |||
if (type == kEngineControlEventTypeParameter) { | |||
CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); | |||
} | |||
// FIXME? should not fix range if midi-program | |||
const float fixedValue(carla_fixValue<float>(0.0f, 1.0f, value)); | |||
for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
EngineEvent& event(fBuffer[i]); | |||
if (event.type != kEngineEventTypeNull) | |||
continue; | |||
event.type = kEngineEventTypeControl; | |||
event.time = time; | |||
event.channel = channel; | |||
event.ctrl.type = type; | |||
event.ctrl.param = param; | |||
event.ctrl.value = fixedValue; | |||
return true; | |||
} | |||
carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full"); | |||
return false; | |||
} | |||
bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept | |||
{ | |||
return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t size, const uint8_t* const data) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); | |||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||
CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false); | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||
for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
EngineEvent& event(fBuffer[i]); | |||
if (event.type != kEngineEventTypeNull) | |||
continue; | |||
event.type = kEngineEventTypeMidi; | |||
event.time = time; | |||
event.channel = channel; | |||
event.midi.port = port; | |||
event.midi.size = size; | |||
event.midi.data[0] = uint8_t(MIDI_GET_STATUS_FROM_DATA(data)); | |||
uint8_t j=1; | |||
for (; j < size; ++j) | |||
event.midi.data[j] = data[j]; | |||
for (; j < EngineMidiEvent::kDataSize; ++j) | |||
event.midi.data[j] = 0; | |||
return true; | |||
} | |||
carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full"); | |||
return false; | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept | |||
{ | |||
return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), 0, size, data); | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept | |||
{ | |||
return writeMidiEvent(time, channel, midi.port, midi.size, midi.data); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine client (Abstract) | |||
@@ -510,44 +726,61 @@ CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName) | |||
if (std::strcmp(driverName, "JACK") == 0) | |||
return newJack(); | |||
// ------------------------------------------------------------------- | |||
// common | |||
if (std::strncmp(driverName, "JACK ", 5) == 0) | |||
return newRtAudio(AUDIO_API_JACK); | |||
// ------------------------------------------------------------------- | |||
// linux | |||
#if 0//def HAVE_JUCE | |||
if (std::strcmp(driverName, "ALSA") == 0) | |||
{ | |||
#if 0//def HAVE_JUCE | |||
return newJuce(AUDIO_API_ALSA); | |||
#else | |||
if (std::strcmp(driverName, "ALSA") == 0) | |||
return newRtAudio(AUDIO_API_ALSA); | |||
#endif | |||
} | |||
if (std::strcmp(driverName, "OSS") == 0) | |||
return newRtAudio(AUDIO_API_OSS); | |||
if (std::strcmp(driverName, "PulseAudio") == 0) | |||
return newRtAudio(AUDIO_API_PULSE); | |||
// ------------------------------------------------------------------- | |||
// macos | |||
#if 0//def HAVE_JUCE | |||
if (std::strcmp(driverName, "CoreAudio") == 0) | |||
{ | |||
#if 0//def HAVE_JUCE | |||
return newJuce(AUDIO_API_CORE); | |||
#else | |||
if (std::strcmp(driverName, "CoreAudio") == 0) | |||
return newRtAudio(AUDIO_API_CORE); | |||
#endif | |||
} | |||
// ------------------------------------------------------------------- | |||
// windows | |||
#if 0//def HAVE_JUCE | |||
if (std::strcmp(driverName, "ASIO") == 0) | |||
{ | |||
#if 0//def HAVE_JUCE | |||
return newJuce(AUDIO_API_ASIO); | |||
if (std::strcmp(driverName, "DirectSound") == 0) | |||
return newJuce(AUDIO_API_DS); | |||
#else | |||
if (std::strcmp(driverName, "ASIO") == 0) | |||
return newRtAudio(AUDIO_API_ASIO); | |||
#endif | |||
} | |||
if (std::strcmp(driverName, "DirectSound") == 0) | |||
{ | |||
#if 0//def HAVE_JUCE | |||
return newJuce(AUDIO_API_DS); | |||
#else | |||
return newRtAudio(AUDIO_API_DS); | |||
#endif | |||
} | |||
carla_stderr("CarlaEngine::newDriverByName(\"%s\") - invalid driver name", driverName); | |||
return nullptr; | |||
@@ -603,8 +836,8 @@ bool CarlaEngine::init(const char* const clientName) | |||
case ENGINE_PROCESS_MODE_CONTINUOUS_RACK: | |||
pData->maxPluginNumber = MAX_RACK_PLUGINS; | |||
pData->events.in = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.out = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.in = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.out = new EngineEvent[kMaxEngineEventInternalCount]; | |||
break; | |||
case ENGINE_PROCESS_MODE_PATCHBAY: | |||
@@ -613,8 +846,8 @@ bool CarlaEngine::init(const char* const clientName) | |||
case ENGINE_PROCESS_MODE_BRIDGE: | |||
pData->maxPluginNumber = 1; | |||
pData->events.in = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.out = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.in = new EngineEvent[kMaxEngineEventInternalCount]; | |||
pData->events.out = new EngineEvent[kMaxEngineEventInternalCount]; | |||
break; | |||
} | |||
@@ -633,8 +866,15 @@ bool CarlaEngine::init(const char* const clientName) | |||
pData->plugins[i].clear(); | |||
pData->osc.init(clientName); | |||
#ifndef BUILD_BRIDGE | |||
pData->oscData = pData->osc.getControlData(); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
pData->graph.isRack = (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK); | |||
pData->graph.create(); | |||
} | |||
#endif | |||
pData->nextAction.ready(); | |||
@@ -662,9 +902,15 @@ bool CarlaEngine::close() | |||
pData->nextAction.ready(); | |||
#ifndef BUILD_BRIDGE | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
pData->graph.clear(); | |||
} | |||
if (pData->osc.isControlRegistered()) | |||
oscSend_control_exit(); | |||
#endif | |||
pData->osc.close(); | |||
pData->oscData = nullptr; | |||
@@ -1710,18 +1956,15 @@ bool CarlaEngine::patchbayConnect(const int groupA, const int portA, const int g | |||
return false; | |||
} | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) | |||
if (pData->graph.isRack) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.rack != nullptr, nullptr); | |||
return pData->graph.rack->connect(this, groupA, portA, groupB, portB); | |||
} | |||
else | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.patchbay != nullptr, nullptr); | |||
setLastError("Not implemented yet"); | |||
return false; | |||
return pData->graph.patchbay->connect(this, groupA, portA, groupB, portB); | |||
} | |||
} | |||
@@ -1729,17 +1972,17 @@ bool CarlaEngine::patchbayDisconnect(const uint 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->audio.isReady, false); | |||
CARLA_SAFE_ASSERT_RETURN(pData->audio.buffer != nullptr, false); | |||
carla_debug("CarlaEngineRtAudio::patchbayDisconnect(%i)", connectionId); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) | |||
if (pData->graph.isRack) | |||
{ | |||
return pData->audio.rack->disconnect(this, connectionId); | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.rack != nullptr, nullptr); | |||
return pData->graph.rack->disconnect(this, connectionId); | |||
} | |||
else | |||
{ | |||
setLastError("Not implemented yet"); | |||
return false; | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.patchbay != nullptr, nullptr); | |||
return pData->graph.patchbay->disconnect(this, connectionId); | |||
} | |||
} | |||
@@ -2029,17 +2272,15 @@ const char* const* CarlaEngine::getPatchbayConnections() const | |||
{ | |||
carla_debug("CarlaEngine::getPatchbayConnections()"); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) | |||
if (pData->graph.isRack) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->audio.rack != nullptr, nullptr); | |||
return pData->audio.rack->getConnections(); | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.rack != nullptr, nullptr); | |||
return pData->graph.rack->getConnections(); | |||
} | |||
else | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->audio.patchbay != nullptr, nullptr); | |||
setLastError("Not implemented yet"); | |||
return nullptr; | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.patchbay != nullptr, nullptr); | |||
return pData->graph.patchbay->getConnections(); | |||
} | |||
} | |||
@@ -2049,13 +2290,13 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const | |||
CARLA_SAFE_ASSERT_RETURN(connTarget != nullptr && connTarget[0] != '\0',); | |||
carla_debug("CarlaEngine::restorePatchbayConnection(\"%s\", \"%s\")", connSource, connTarget); | |||
#if 0 | |||
if (pData->audio.usePatchbay) | |||
if (pData->graph.isRack) | |||
{ | |||
// TODO | |||
} | |||
else | |||
{ | |||
#if 0 | |||
int sourceGroup, targetGroup; | |||
int sourcePort, targetPort; | |||
@@ -2125,8 +2366,8 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const | |||
CARLA_SAFE_ASSERT_RETURN(targetGroup == RACK_PATCHBAY_GROUP_MAX || targetPort == RACK_PATCHBAY_PORT_MAX,); | |||
patchbayConnect(targetGroup, targetPort, sourceGroup, sourcePort); | |||
} | |||
#endif | |||
} | |||
} | |||
#endif | |||
@@ -237,9 +237,222 @@ bool RackGraph::disconnect(CarlaEngine* const engine, const uint connectionId) n | |||
return false; | |||
} | |||
void RackGraph::refresh(CarlaEngine* const engine) noexcept | |||
void RackGraph::refresh(CarlaEngine* const engine, const LinkedList<PortNameToId>& /*midiIns*/, const LinkedList<PortNameToId>& /*midiOuts*/) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); | |||
#if 0 | |||
CARLA_SAFE_ASSERT_RETURN(pData->audio.isReady, false); | |||
fUsedMidiIns.clear(); | |||
fUsedMidiOuts.clear(); | |||
pData->audio.initPatchbay(); | |||
if (! pData->audio.isRack) | |||
{ | |||
// not implemented yet | |||
return false; | |||
} | |||
char strBuf[STR_MAX+1]; | |||
strBuf[STR_MAX] = '\0'; | |||
AbstractEngineBuffer* const rack(pData->audio.buffer); | |||
// Main | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_CARLA, PATCHBAY_ICON_CARLA, -1, 0.0f, getName()); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out"); | |||
} | |||
// Audio In | |||
{ | |||
if (fDeviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Capture (%s)", fDeviceName.buffer()); | |||
else | |||
std::strncpy(strBuf, "Capture", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
for (uint i=0; i < pData->audio.inCount; ++i) | |||
{ | |||
std::snprintf(strBuf, STR_MAX, "capture_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, static_cast<int>(i), PATCHBAY_PORT_TYPE_AUDIO, 0.0f, strBuf); | |||
} | |||
} | |||
// Audio Out | |||
{ | |||
if (fDeviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Playback (%s)", fDeviceName.buffer()); | |||
else | |||
std::strncpy(strBuf, "Playback", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
for (uint i=0; i < pData->audio.outCount; ++i) | |||
{ | |||
std::snprintf(strBuf, STR_MAX, "playback_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, static_cast<int>(i), PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, strBuf); | |||
} | |||
} | |||
// MIDI In | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI, PATCHBAY_ICON_HARDWARE, -1, 0.0f, "Readable MIDI ports"); | |||
for (uint i=0, count=fDummyMidiIn.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.portId = static_cast<int>(i); | |||
std::strncpy(portNameToId.name, fDummyMidiIn.getPortName(i).c_str(), STR_MAX); | |||
portNameToId.name[STR_MAX] = '\0'; | |||
fUsedMidiIns.append(portNameToId); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI, 0.0f, portNameToId.name); | |||
} | |||
} | |||
// MIDI Out | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI, PATCHBAY_ICON_HARDWARE, -1, 0.0f, "Writable MIDI ports"); | |||
for (uint i=0, count=fDummyMidiOut.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.portId = static_cast<int>(i); | |||
std::strncpy(portNameToId.name, fDummyMidiOut.getPortName(i).c_str(), STR_MAX); | |||
portNameToId.name[STR_MAX] = '\0'; | |||
fUsedMidiOuts.append(portNameToId); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, portNameToId.name); | |||
} | |||
} | |||
// Connections | |||
rack->connectLock.enter(); | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->audio.inCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portOut = port; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->audio.inCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portOut = port; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->audio.outCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portIn = port; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->audio.outCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portIn = port; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
pData->audio.rack->connectLock.leave(); | |||
for (LinkedList<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next()) | |||
{ | |||
const MidiPort& midiPort(it.getValue()); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_MIDI; | |||
connectionToId.portOut = midiPort.portId; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_MIDI_IN; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next()) | |||
{ | |||
const MidiPort& midiPort(it.getValue()); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_MIDI_OUT; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_MIDI; | |||
connectionToId.portIn = midiPort.portId; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
#endif | |||
} | |||
const char* const* RackGraph::getConnections() const | |||
@@ -339,9 +552,9 @@ bool PatchbayGraph::disconnect(CarlaEngine* const engine, const uint /*connectio | |||
return false; | |||
} | |||
void PatchbayGraph::refresh(CarlaEngine* const engine) noexcept | |||
void PatchbayGraph::refresh(CarlaEngine* const engine, const LinkedList<PortNameToId>& /*midiIns*/, const LinkedList<PortNameToId>& /*midiOuts*/) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(engine != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(engine != nullptr,); | |||
} | |||
const char* const* PatchbayGraph::getConnections() const | |||
@@ -463,8 +676,8 @@ void CarlaEngineProtectedData::doNextPluginAction(const bool unlock) noexcept | |||
#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,); | |||
CARLA_SAFE_ASSERT_RETURN(events.in != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(events.out != nullptr,); | |||
// safe copy | |||
float inBuf0[frames]; | |||
@@ -480,7 +693,7 @@ void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2] | |||
FLOAT_CLEAR(outBuf[1], frames); | |||
// initialize event outputs (zero) | |||
carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(events.out, kMaxEngineEventInternalCount); | |||
bool processed = false; | |||
@@ -506,9 +719,9 @@ void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2] | |||
FLOAT_CLEAR(outBuf[1], frames); | |||
// if plugin has no midi out, add previous events | |||
if (oldMidiOutCount == 0 && bufEvents.in[0].type != kEngineEventTypeNull) | |||
if (oldMidiOutCount == 0 && events.in[0].type != kEngineEventTypeNull) | |||
{ | |||
if (bufEvents.out[0].type != kEngineEventTypeNull) | |||
if (events.out[0].type != kEngineEventTypeNull) | |||
{ | |||
// TODO: carefully add to input, sorted events | |||
} | |||
@@ -517,10 +730,10 @@ void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2] | |||
else | |||
{ | |||
// initialize event inputs from previous outputs | |||
carla_copyStruct<EngineEvent>(bufEvents.in, bufEvents.out, kMaxEngineEventInternalCount); | |||
carla_copyStruct<EngineEvent>(events.in, events.out, kMaxEngineEventInternalCount); | |||
// initialize event outputs (zero) | |||
carla_zeroStruct<EngineEvent>(bufEvents.out, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(events.out, kMaxEngineEventInternalCount); | |||
} | |||
} | |||
@@ -622,93 +835,91 @@ void CarlaEngineProtectedData::processRack(float* inBufReal[2], float* outBuf[2] | |||
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((EngineRackBuffers*)bufAudio.buffer); | |||
const CarlaCriticalSectionScope _cs2(rack->connectLock); | |||
const CarlaCriticalSectionScope _cs(graph.rack->connectLock); | |||
// connect input buffers | |||
if (rack->connectedIn1.count() == 0) | |||
if (graph.rack->connectedIn1.count() == 0) | |||
{ | |||
FLOAT_CLEAR(rack->in[0], nframes); | |||
FLOAT_CLEAR(audio.inBuf[0], nframes); | |||
} | |||
else | |||
{ | |||
bool first = true; | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn1.begin(); it.valid(); it.next()) | |||
for (LinkedList<int>::Itenerator it = graph.rack->connectedIn1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount)); | |||
if (first) | |||
{ | |||
FLOAT_COPY(rack->in[0], inBuf[port], nframes); | |||
FLOAT_COPY(audio.inBuf[0], inBuf[port], nframes); | |||
first = false; | |||
} | |||
else | |||
{ | |||
FLOAT_ADD(rack->in[0], inBuf[port], nframes); | |||
FLOAT_ADD(audio.inBuf[0], inBuf[port], nframes); | |||
} | |||
} | |||
if (first) | |||
FLOAT_CLEAR(rack->in[0], nframes); | |||
FLOAT_CLEAR(audio.inBuf[0], nframes); | |||
} | |||
if (rack->connectedIn2.count() == 0) | |||
if (graph.rack->connectedIn2.count() == 0) | |||
{ | |||
FLOAT_CLEAR(rack->in[1], nframes); | |||
FLOAT_CLEAR(audio.inBuf[1], nframes); | |||
} | |||
else | |||
{ | |||
bool first = true; | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn2.begin(); it.valid(); it.next()) | |||
for (LinkedList<int>::Itenerator it = graph.rack->connectedIn2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(inCount)); | |||
if (first) | |||
{ | |||
FLOAT_COPY(rack->in[1], inBuf[port], nframes); | |||
FLOAT_COPY(audio.inBuf[1], inBuf[port], nframes); | |||
first = false; | |||
} | |||
else | |||
{ | |||
FLOAT_ADD(rack->in[1], inBuf[port], nframes); | |||
FLOAT_ADD(audio.inBuf[1], inBuf[port], nframes); | |||
} | |||
} | |||
if (first) | |||
FLOAT_CLEAR(rack->in[1], nframes); | |||
FLOAT_CLEAR(audio.inBuf[1], nframes); | |||
} | |||
FLOAT_CLEAR(rack->out[0], nframes); | |||
FLOAT_CLEAR(rack->out[1], nframes); | |||
FLOAT_CLEAR(audio.outBuf[0], nframes); | |||
FLOAT_CLEAR(audio.outBuf[1], nframes); | |||
// process | |||
processRack(rack->in, rack->out, nframes, isOffline); | |||
processRack(audio.inBuf, audio.outBuf, nframes, isOffline); | |||
// connect output buffers | |||
if (rack->connectedOut1.count() != 0) | |||
if (graph.rack->connectedOut1.count() != 0) | |||
{ | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut1.begin(); it.valid(); it.next()) | |||
for (LinkedList<int>::Itenerator it = graph.rack->connectedOut1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount)); | |||
FLOAT_ADD(outBuf[port], rack->out[0], nframes); | |||
FLOAT_ADD(outBuf[port], audio.outBuf[0], nframes); | |||
} | |||
} | |||
if (rack->connectedOut2.count() != 0) | |||
if (graph.rack->connectedOut2.count() != 0) | |||
{ | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut2.begin(); it.valid(); it.next()) | |||
for (LinkedList<int>::Itenerator it = graph.rack->connectedOut2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(outCount)); | |||
FLOAT_ADD(outBuf[port], rack->out[1], nframes); | |||
FLOAT_ADD(outBuf[port], audio.outBuf[1], nframes); | |||
} | |||
} | |||
} | |||
@@ -45,6 +45,7 @@ CARLA_BACKEND_START_NAMESPACE | |||
const unsigned short kMaxEngineEventInternalCount = 512; | |||
#ifndef BUILD_BRIDGE | |||
// ----------------------------------------------------------------------- | |||
// Rack Graph stuff | |||
@@ -141,6 +142,7 @@ struct PatchbayGraph { | |||
const char* const* getConnections() const; | |||
}; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// InternalAudio | |||
@@ -281,6 +283,7 @@ struct EngineInternalEvents { | |||
CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalEvents) | |||
}; | |||
#ifndef BUILD_BRIDGE | |||
// ----------------------------------------------------------------------- | |||
// InternalGraph | |||
@@ -329,25 +332,9 @@ struct EngineInternalGraph { | |||
} | |||
} | |||
void init() noexcept | |||
{ | |||
if (isRack) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(rack != nullptr,); | |||
rack->lastConnectionId = 0; | |||
rack->usedConnections.clear(); | |||
} | |||
else | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,); | |||
// TODO | |||
} | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalGraph) | |||
}; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// InternalTime | |||
@@ -1294,7 +1294,7 @@ protected: | |||
float* outBuf[2] = { audioOut1, audioOut2 }; | |||
// initialize input events | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount); | |||
{ | |||
uint32_t engineEventIndex = 0; | |||
@@ -1308,7 +1308,7 @@ protected: | |||
CARLA_SAFE_ASSERT_CONTINUE(jackEvent.size <= 0xFF /* uint8_t max */); | |||
EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]); | |||
EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); | |||
engineEvent.time = jackEvent.time; | |||
engineEvent.fillFromMidiData(static_cast<uint8_t>(jackEvent.size), jackEvent.buffer); | |||
@@ -1327,7 +1327,7 @@ protected: | |||
for (unsigned short i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
const EngineEvent& engineEvent(pData->bufEvents.out[i]); | |||
const EngineEvent& engineEvent(pData->events.out[i]); | |||
uint8_t size = 0; | |||
uint8_t data[3] = { 0, 0, 0 }; | |||
@@ -100,8 +100,6 @@ public: | |||
return false; | |||
} | |||
pData->bufAudio.usePatchbay = (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY); | |||
String deviceName; | |||
if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0') | |||
@@ -152,12 +150,12 @@ public: | |||
pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples()); | |||
pData->sampleRate = fDevice->getCurrentSampleRate(); | |||
pData->bufAudio.inCount = static_cast<uint32_t>(inputChannels.countNumberOfSetBits()); | |||
pData->bufAudio.outCount = static_cast<uint32_t>(outputChannels.countNumberOfSetBits()); | |||
pData->audio.inCount = static_cast<uint32_t>(inputChannels.countNumberOfSetBits()); | |||
pData->audio.outCount = static_cast<uint32_t>(outputChannels.countNumberOfSetBits()); | |||
CARLA_SAFE_ASSERT(pData->bufAudio.outCount > 0); | |||
CARLA_SAFE_ASSERT(pData->audio.outCount > 0); | |||
pData->bufAudio.create(pData->bufferSize); | |||
pData->audio.create(pData->bufferSize); | |||
fDevice->start(this); | |||
@@ -171,7 +169,7 @@ public: | |||
{ | |||
carla_debug("CarlaEngineJuce::close()"); | |||
pData->bufAudio.isReady = false; | |||
pData->audio.isReady = false; | |||
bool hasError = !CarlaEngine::close(); | |||
@@ -186,7 +184,7 @@ public: | |||
fDevice = nullptr; | |||
} | |||
pData->bufAudio.clear(); | |||
pData->audio.clear(); | |||
return !hasError; | |||
} | |||
@@ -216,91 +214,7 @@ public: | |||
bool patchbayRefresh() override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false); | |||
pData->bufAudio.initPatchbay(); | |||
if (pData->bufAudio.usePatchbay) | |||
{ | |||
// not implemented yet | |||
return false; | |||
} | |||
char strBuf[STR_MAX+1]; | |||
strBuf[STR_MAX] = '\0'; | |||
//EngineRackBuffers* const rack(pData->bufAudio.rack); | |||
// Main | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_CARLA, PATCHBAY_ICON_CARLA, -1, 0.0f, getName()); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out"); | |||
} | |||
const String& deviceName(fDevice->getName()); | |||
// Audio In | |||
{ | |||
if (deviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Capture (%s)", deviceName.toRawUTF8()); | |||
else | |||
std::strncpy(strBuf, "Capture", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
StringArray inputNames(fDevice->getInputChannelNames()); | |||
CARLA_SAFE_ASSERT(inputNames.size() == static_cast<int>(pData->bufAudio.inCount)); | |||
for (uint i=0; i < pData->bufAudio.inCount; ++i) | |||
{ | |||
String inputName(inputNames[static_cast<int>(i)]); | |||
if (inputName.trim().isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "%s", inputName.toRawUTF8()); | |||
else | |||
std::snprintf(strBuf, STR_MAX, "capture_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, static_cast<int>(i), PATCHBAY_PORT_TYPE_AUDIO, 0.0f, strBuf); | |||
} | |||
} | |||
// Audio Out | |||
{ | |||
if (deviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Playback (%s)", deviceName.toRawUTF8()); | |||
else | |||
std::strncpy(strBuf, "Playback", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
StringArray outputNames(fDevice->getOutputChannelNames()); | |||
CARLA_SAFE_ASSERT(outputNames.size() == static_cast<int>(pData->bufAudio.outCount)); | |||
for (uint i=0; i < pData->bufAudio.outCount; ++i) | |||
{ | |||
String outputName(outputNames[static_cast<int>(i)]); | |||
if (outputName.trim().isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "%s", outputName.toRawUTF8()); | |||
else | |||
std::snprintf(strBuf, STR_MAX, "playback_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, static_cast<int>(i), static_cast<int>(PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT), 0.0f, strBuf); | |||
} | |||
} | |||
// MIDI In | |||
// MIDI Out | |||
// Connections | |||
// const String& deviceName(fDevice->getName()); | |||
return true; | |||
} | |||
@@ -310,28 +224,28 @@ protected: | |||
void audioDeviceIOCallback(const float** inputChannelData, int numInputChannels, float** outputChannelData, int numOutputChannels, int numSamples) override | |||
{ | |||
// assert juce buffers | |||
CARLA_SAFE_ASSERT_RETURN(numInputChannels == static_cast<int>(pData->bufAudio.inCount),); | |||
CARLA_SAFE_ASSERT_RETURN(numOutputChannels == static_cast<int>(pData->bufAudio.outCount),); | |||
CARLA_SAFE_ASSERT_RETURN(numInputChannels == static_cast<int>(pData->audio.inCount),); | |||
CARLA_SAFE_ASSERT_RETURN(numOutputChannels == static_cast<int>(pData->audio.outCount),); | |||
CARLA_SAFE_ASSERT_RETURN(outputChannelData != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(numSamples == static_cast<int>(pData->bufferSize),); | |||
if (numOutputChannels == 0 || ! pData->bufAudio.isReady) | |||
if (numOutputChannels == 0 || ! pData->audio.isReady) | |||
return runPendingRtEvents(); | |||
// initialize input events | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount); | |||
// TODO - get events from juce | |||
if (pData->bufAudio.usePatchbay) | |||
{ | |||
} | |||
else | |||
if (pData->graph.isRack) | |||
{ | |||
pData->processRackFull(const_cast<float**>(inputChannelData), static_cast<uint32_t>(numInputChannels), | |||
outputChannelData, static_cast<uint32_t>(numOutputChannels), | |||
static_cast<uint32_t>(numSamples), false); | |||
} | |||
else | |||
{ | |||
} | |||
// output events | |||
{ | |||
@@ -1067,8 +1067,8 @@ protected: | |||
// --------------------------------------------------------------- | |||
// initialize events | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.out, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.out, kMaxEngineEventInternalCount); | |||
// --------------------------------------------------------------- | |||
// events input (before processing) | |||
@@ -1079,7 +1079,7 @@ protected: | |||
for (uint32_t i=0; i < midiEventCount && engineEventIndex < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
const NativeMidiEvent& midiEvent(midiEvents[i]); | |||
EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]); | |||
EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); | |||
engineEvent.time = midiEvent.time; | |||
engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data); | |||
@@ -1120,14 +1120,14 @@ protected: | |||
// --------------------------------------------------------------- | |||
// events output (after processing) | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount); | |||
{ | |||
NativeMidiEvent midiEvent; | |||
for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
const EngineEvent& engineEvent(pData->bufEvents.out[i]); | |||
const EngineEvent& engineEvent(pData->events.out[i]); | |||
if (engineEvent.type == kEngineEventTypeNull) | |||
break; | |||
@@ -1137,7 +1137,7 @@ protected: | |||
if (engineEvent.type == CarlaBackend::kEngineEventTypeControl) | |||
{ | |||
midiEvent.port = 0; | |||
engineEvent.ctrl.dumpToMidiData(engineEvent.channel, midiEvent.size, midiEvent.data); | |||
engineEvent.ctrl.convertToMidiData(engineEvent.channel, midiEvent.size, midiEvent.data); | |||
} | |||
else if (engineEvent.type == kEngineEventTypeMidi) | |||
{ | |||
@@ -28,222 +28,6 @@ CARLA_BACKEND_START_NAMESPACE | |||
} // Fix editor indentation | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
// Fallback data | |||
static const EngineEvent kFallbackEngineEvent = { kEngineEventTypeNull, 0, 0, {{ kEngineControlEventTypeNull, 0, 0.0f }} }; | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine port (Abstract) | |||
CarlaEnginePort::CarlaEnginePort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: fEngine(engine), | |||
fIsInput(isInputPort) | |||
{ | |||
carla_debug("CarlaEnginePort::CarlaEnginePort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEnginePort::~CarlaEnginePort() noexcept | |||
{ | |||
carla_debug("CarlaEnginePort::~CarlaEnginePort()"); | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Audio port | |||
CarlaEngineAudioPort::CarlaEngineAudioPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr) | |||
{ | |||
carla_debug("CarlaEngineAudioPort::CarlaEngineAudioPort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEngineAudioPort::~CarlaEngineAudioPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineAudioPort::~CarlaEngineAudioPort()"); | |||
} | |||
void CarlaEngineAudioPort::initBuffer() noexcept | |||
{ | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine CV port | |||
CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr) | |||
{ | |||
carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort)); | |||
} | |||
CarlaEngineCVPort::~CarlaEngineCVPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineCVPort::~CarlaEngineCVPort()"); | |||
} | |||
void CarlaEngineCVPort::initBuffer() noexcept | |||
{ | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Carla Engine Event port | |||
CarlaEngineEventPort::CarlaEngineEventPort(const CarlaEngine& engine, const bool isInputPort) noexcept | |||
: CarlaEnginePort(engine, isInputPort), | |||
fBuffer(nullptr), | |||
fProcessMode(engine.getProccessMode()) | |||
{ | |||
carla_debug("CarlaEngineEventPort::CarlaEngineEventPort(%s)", bool2str(isInputPort)); | |||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
fBuffer = new EngineEvent[kMaxEngineEventInternalCount]; | |||
} | |||
CarlaEngineEventPort::~CarlaEngineEventPort() noexcept | |||
{ | |||
carla_debug("CarlaEngineEventPort::~CarlaEngineEventPort()"); | |||
if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); | |||
delete[] fBuffer; | |||
fBuffer = nullptr; | |||
} | |||
} | |||
void CarlaEngineEventPort::initBuffer() noexcept | |||
{ | |||
if (fProcessMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || fProcessMode == ENGINE_PROCESS_MODE_BRIDGE) | |||
fBuffer = fEngine.getInternalEventBuffer(fIsInput); | |||
else if (fProcessMode == ENGINE_PROCESS_MODE_PATCHBAY && ! fIsInput) | |||
carla_zeroStruct<EngineEvent>(fBuffer, kMaxEngineEventInternalCount); | |||
} | |||
uint32_t CarlaEngineEventPort::getEventCount() const noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsInput, 0); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, 0); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, 0); | |||
uint32_t i=0; | |||
for (; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
if (fBuffer[i].type == kEngineEventTypeNull) | |||
break; | |||
} | |||
return i; | |||
} | |||
const EngineEvent& CarlaEngineEventPort::getEvent(const uint32_t index) const noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, kFallbackEngineEvent); | |||
CARLA_SAFE_ASSERT_RETURN(index < kMaxEngineEventInternalCount, kFallbackEngineEvent); | |||
return fBuffer[index]; | |||
} | |||
const EngineEvent& CarlaEngineEventPort::getEventUnchecked(const uint32_t index) const noexcept | |||
{ | |||
return fBuffer[index]; | |||
} | |||
bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); | |||
CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false); | |||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||
CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f); | |||
if (type == kEngineControlEventTypeParameter) { | |||
CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param)); | |||
} | |||
// FIXME? should not fix range if midi-program | |||
const float fixedValue(carla_fixValue<float>(0.0f, 1.0f, value)); | |||
for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
EngineEvent& event(fBuffer[i]); | |||
if (event.type != kEngineEventTypeNull) | |||
continue; | |||
event.type = kEngineEventTypeControl; | |||
event.time = time; | |||
event.channel = channel; | |||
event.ctrl.type = type; | |||
event.ctrl.param = param; | |||
event.ctrl.value = fixedValue; | |||
return true; | |||
} | |||
carla_stderr2("CarlaEngineEventPort::writeControlEvent() - buffer full"); | |||
return false; | |||
} | |||
bool CarlaEngineEventPort::writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEvent& ctrl) noexcept | |||
{ | |||
return writeControlEvent(time, channel, ctrl.type, ctrl.param, ctrl.value); | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t size, const uint8_t* const data) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(! fIsInput, false); | |||
CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(fProcessMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT && fProcessMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, false); | |||
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||
CARLA_SAFE_ASSERT_RETURN(size > 0 && size <= EngineMidiEvent::kDataSize, false); | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||
for (uint32_t i=0; i < kMaxEngineEventInternalCount; ++i) | |||
{ | |||
EngineEvent& event(fBuffer[i]); | |||
if (event.type != kEngineEventTypeNull) | |||
continue; | |||
event.type = kEngineEventTypeMidi; | |||
event.time = time; | |||
event.channel = channel; | |||
event.midi.port = port; | |||
event.midi.size = size; | |||
event.midi.data[0] = uint8_t(MIDI_GET_STATUS_FROM_DATA(data)); | |||
uint8_t j=1; | |||
for (; j < size; ++j) | |||
event.midi.data[j] = data[j]; | |||
for (; j < EngineMidiEvent::kDataSize; ++j) | |||
event.midi.data[j] = 0; | |||
return true; | |||
} | |||
carla_stderr2("CarlaEngineEventPort::writeMidiEvent() - buffer full"); | |||
return false; | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t size, const uint8_t* const data) noexcept | |||
{ | |||
return writeMidiEvent(time, uint8_t(MIDI_GET_CHANNEL_FROM_DATA(data)), 0, size, data); | |||
} | |||
bool CarlaEngineEventPort::writeMidiEvent(const uint32_t time, const uint8_t channel, const EngineMidiEvent& midi) noexcept | |||
{ | |||
return writeMidiEvent(time, channel, midi.port, midi.size, midi.data); | |||
} | |||
// ----------------------------------------------------------------------- | |||
CARLA_BACKEND_END_NAMESPACE |
@@ -199,8 +199,6 @@ public: | |||
return false; | |||
} | |||
pData->bufAudio.isRack = (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK); | |||
RtAudio::StreamParameters iParams, oParams; | |||
bool deviceSet = false; | |||
@@ -271,28 +269,28 @@ public: | |||
pData->bufferSize = bufferFrames; | |||
pData->sampleRate = fAudio.getStreamSampleRate(); | |||
pData->bufAudio.inCount = iParams.nChannels; | |||
pData->bufAudio.outCount = oParams.nChannels; | |||
pData->audio.inCount = iParams.nChannels; | |||
pData->audio.outCount = oParams.nChannels; | |||
CARLA_SAFE_ASSERT(pData->bufAudio.outCount > 0); | |||
CARLA_SAFE_ASSERT(pData->audio.outCount > 0); | |||
if (pData->bufAudio.inCount > 0) | |||
if (pData->audio.inCount > 0) | |||
{ | |||
fAudioBufIn = new float*[pData->bufAudio.inCount]; | |||
fAudioBufIn = new float*[pData->audio.inCount]; | |||
for (uint i=0; i < pData->bufAudio.inCount; ++i) | |||
for (uint i=0; i < pData->audio.inCount; ++i) | |||
fAudioBufIn[i] = new float[pData->bufferSize]; | |||
} | |||
if (pData->bufAudio.outCount > 0) | |||
if (pData->audio.outCount > 0) | |||
{ | |||
fAudioBufOut = new float*[pData->bufAudio.outCount]; | |||
fAudioBufOut = new float*[pData->audio.outCount]; | |||
for (uint i=0; i < pData->bufAudio.outCount; ++i) | |||
for (uint i=0; i < pData->audio.outCount; ++i) | |||
fAudioBufOut[i] = new float[pData->bufferSize]; | |||
} | |||
pData->bufAudio.create(pData->bufferSize); | |||
pData->audio.create(pData->bufferSize); | |||
try { | |||
fAudio.startStream(); | |||
@@ -315,7 +313,7 @@ public: | |||
CARLA_SAFE_ASSERT(fAudioBufOut != nullptr); | |||
carla_debug("CarlaEngineRtAudio::close()"); | |||
pData->bufAudio.isReady = false; | |||
pData->audio.isReady = false; | |||
bool hasError = !CarlaEngine::close(); | |||
@@ -341,7 +339,7 @@ public: | |||
if (fAudioBufIn != nullptr) | |||
{ | |||
for (uint i=0; i < pData->bufAudio.inCount; ++i) | |||
for (uint i=0; i < pData->audio.inCount; ++i) | |||
delete[] fAudioBufIn[i]; | |||
delete[] fAudioBufIn; | |||
@@ -350,14 +348,14 @@ public: | |||
if (fAudioBufOut != nullptr) | |||
{ | |||
for (uint i=0; i < pData->bufAudio.outCount; ++i) | |||
for (uint i=0; i < pData->audio.outCount; ++i) | |||
delete[] fAudioBufOut[i]; | |||
delete[] fAudioBufOut; | |||
fAudioBufOut = nullptr; | |||
} | |||
pData->bufAudio.clear(); | |||
pData->audio.clear(); | |||
fDeviceName.clear(); | |||
@@ -412,217 +410,6 @@ public: | |||
bool patchbayRefresh() override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false); | |||
fUsedMidiIns.clear(); | |||
fUsedMidiOuts.clear(); | |||
pData->bufAudio.initPatchbay(); | |||
if (! pData->bufAudio.isRack) | |||
{ | |||
// not implemented yet | |||
return false; | |||
} | |||
char strBuf[STR_MAX+1]; | |||
strBuf[STR_MAX] = '\0'; | |||
AbstractEngineBuffer* const rack(pData->bufAudio.buffer); | |||
// Main | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_CARLA, PATCHBAY_ICON_CARLA, -1, 0.0f, getName()); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in"); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_CARLA_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out"); | |||
} | |||
// Audio In | |||
{ | |||
if (fDeviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Capture (%s)", fDeviceName.buffer()); | |||
else | |||
std::strncpy(strBuf, "Capture", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
for (uint i=0; i < pData->bufAudio.inCount; ++i) | |||
{ | |||
std::snprintf(strBuf, STR_MAX, "capture_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, static_cast<int>(i), PATCHBAY_PORT_TYPE_AUDIO, 0.0f, strBuf); | |||
} | |||
} | |||
// Audio Out | |||
{ | |||
if (fDeviceName.isNotEmpty()) | |||
std::snprintf(strBuf, STR_MAX, "Playback (%s)", fDeviceName.buffer()); | |||
else | |||
std::strncpy(strBuf, "Playback", STR_MAX); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, PATCHBAY_ICON_HARDWARE, -1, 0.0f, strBuf); | |||
for (uint i=0; i < pData->bufAudio.outCount; ++i) | |||
{ | |||
std::snprintf(strBuf, STR_MAX, "playback_%i", i+1); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO, static_cast<int>(i), PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, strBuf); | |||
} | |||
} | |||
// MIDI In | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI, PATCHBAY_ICON_HARDWARE, -1, 0.0f, "Readable MIDI ports"); | |||
for (uint i=0, count=fDummyMidiIn.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.portId = static_cast<int>(i); | |||
std::strncpy(portNameToId.name, fDummyMidiIn.getPortName(i).c_str(), STR_MAX); | |||
portNameToId.name[STR_MAX] = '\0'; | |||
fUsedMidiIns.append(portNameToId); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI, 0.0f, portNameToId.name); | |||
} | |||
} | |||
// MIDI Out | |||
{ | |||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI, PATCHBAY_ICON_HARDWARE, -1, 0.0f, "Writable MIDI ports"); | |||
for (uint i=0, count=fDummyMidiOut.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.portId = static_cast<int>(i); | |||
std::strncpy(portNameToId.name, fDummyMidiOut.getPortName(i).c_str(), STR_MAX); | |||
portNameToId.name[STR_MAX] = '\0'; | |||
fUsedMidiOuts.append(portNameToId); | |||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, portNameToId.name); | |||
} | |||
} | |||
// Connections | |||
rack->connectLock.enter(); | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->bufAudio.inCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portOut = port; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_AUDIO_IN1; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedIn2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->bufAudio.inCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portOut = port; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_AUDIO_IN2; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut1.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->bufAudio.outCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT1; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portIn = port; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<int>::Itenerator it = rack->connectedOut2.begin(); it.valid(); it.next()) | |||
{ | |||
const int& port(it.getValue()); | |||
CARLA_SAFE_ASSERT_CONTINUE(port >= 0 && port < static_cast<int>(pData->bufAudio.outCount)); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_AUDIO_OUT2; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_AUDIO; | |||
connectionToId.portIn = port; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
pData->bufAudio.rack->connectLock.leave(); | |||
for (LinkedList<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next()) | |||
{ | |||
const MidiPort& midiPort(it.getValue()); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_MIDI; | |||
connectionToId.portOut = midiPort.portId; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portIn = RACK_PATCHBAY_CARLA_PORT_MIDI_IN; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
for (LinkedList<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next()) | |||
{ | |||
const MidiPort& midiPort(it.getValue()); | |||
ConnectionToId connectionToId; | |||
connectionToId.id = rack->lastConnectionId; | |||
connectionToId.groupOut = RACK_PATCHBAY_GROUP_CARLA; | |||
connectionToId.portOut = RACK_PATCHBAY_CARLA_PORT_MIDI_OUT; | |||
connectionToId.groupIn = RACK_PATCHBAY_GROUP_MIDI; | |||
connectionToId.portIn = midiPort.portId; | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupOut, connectionToId.portOut, connectionToId.groupIn, connectionToId.portIn); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, 0, 0, 0.0f, strBuf); | |||
rack->usedConnections.append(connectionToId); | |||
++rack->lastConnectionId; | |||
} | |||
return true; | |||
} | |||
@@ -639,32 +426,32 @@ protected: | |||
CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,); | |||
CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,); | |||
if (pData->bufAudio.outCount == 0 || ! pData->bufAudio.isReady) | |||
if (pData->audio.outCount == 0 || ! pData->audio.isReady) | |||
return runPendingRtEvents(); | |||
// initialize rtaudio input | |||
if (fIsAudioInterleaved) | |||
{ | |||
for (unsigned int i=0, j=0, count=nframes*pData->bufAudio.inCount; i < count; ++i) | |||
for (unsigned int i=0, j=0, count=nframes*pData->audio.inCount; i < count; ++i) | |||
{ | |||
fAudioBufIn[i/pData->bufAudio.inCount][j] = insPtr[i]; | |||
fAudioBufIn[i/pData->audio.inCount][j] = insPtr[i]; | |||
if ((i+1) % pData->bufAudio.inCount == 0) | |||
if ((i+1) % pData->audio.inCount == 0) | |||
j += 1; | |||
} | |||
} | |||
else | |||
{ | |||
for (unsigned int i=0; i < pData->bufAudio.inCount; ++i) | |||
for (unsigned int i=0; i < pData->audio.inCount; ++i) | |||
FLOAT_COPY(fAudioBufIn[i], insPtr+(nframes*i), nframes); | |||
} | |||
// initialize rtaudio output | |||
for (unsigned int i=0; i < pData->bufAudio.outCount; ++i) | |||
for (unsigned int i=0; i < pData->audio.outCount; ++i) | |||
FLOAT_CLEAR(fAudioBufOut[i], nframes); | |||
// initialize input events | |||
carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount); | |||
carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount); | |||
if (fMidiInEvents.mutex.tryLock()) | |||
{ | |||
@@ -674,7 +461,7 @@ protected: | |||
while (! fMidiInEvents.data.isEmpty()) | |||
{ | |||
const RtMidiEvent& midiEvent(fMidiInEvents.data.getFirst(true)); | |||
EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]); | |||
EngineEvent& engineEvent(pData->events.in[engineEventIndex++]); | |||
if (midiEvent.time < pData->timeInfo.frame) | |||
{ | |||
@@ -697,9 +484,9 @@ protected: | |||
fMidiInEvents.mutex.unlock(); | |||
} | |||
if (pData->bufAudio.isRack) | |||
if (pData->graph.isRack) | |||
{ | |||
pData->processRackFull(fAudioBufIn, pData->bufAudio.inCount, fAudioBufOut, pData->bufAudio.outCount, nframes, false); | |||
pData->processRackFull(fAudioBufIn, pData->audio.inCount, fAudioBufOut, pData->audio.outCount, nframes, false); | |||
} | |||
else | |||
{ | |||
@@ -708,17 +495,17 @@ protected: | |||
// output audio | |||
if (fIsAudioInterleaved) | |||
{ | |||
for (unsigned int i=0, j=0; i < nframes*pData->bufAudio.outCount; ++i) | |||
for (unsigned int i=0, j=0; i < nframes*pData->audio.outCount; ++i) | |||
{ | |||
outsPtr[i] = fAudioBufOut[i/pData->bufAudio.outCount][j]; | |||
outsPtr[i] = fAudioBufOut[i/pData->audio.outCount][j]; | |||
if ((i+1) % pData->bufAudio.outCount == 0) | |||
if ((i+1) % pData->audio.outCount == 0) | |||
j += 1; | |||
} | |||
} | |||
else | |||
{ | |||
for (unsigned int i=0; i < pData->bufAudio.outCount; ++i) | |||
for (unsigned int i=0; i < pData->audio.outCount; ++i) | |||
FLOAT_COPY(outsPtr+(nframes*i), fAudioBufOut[i], nframes); | |||
} | |||
@@ -738,7 +525,7 @@ protected: | |||
void handleMidiCallback(double timeStamp, std::vector<unsigned char>* const message) | |||
{ | |||
if (! pData->bufAudio.isReady) | |||
if (! pData->audio.isReady) | |||
return; | |||
const size_t messageSize(message->size()); | |||