@@ -31,66 +31,84 @@ using juce::MidiBuffer; | |||
CARLA_BACKEND_START_NAMESPACE | |||
// ----------------------------------------------------------------------- | |||
// External Graph stuff | |||
enum ExternalGraphGroupIds { | |||
kExternalGraphGroupNull = 0, | |||
kExternalGraphGroupCarla = 1, | |||
kExternalGraphGroupAudioIn = 2, | |||
kExternalGraphGroupAudioOut = 3, | |||
kExternalGraphGroupMidiIn = 4, | |||
kExternalGraphGroupMidiOut = 5, | |||
kExternalGraphGroupMax = 6 | |||
}; | |||
enum ExternalGraphCarlaPortIds { | |||
kExternalGraphCarlaPortNull = 0, | |||
kExternalGraphCarlaPortAudioIn1 = 1, | |||
kExternalGraphCarlaPortAudioIn2 = 2, | |||
kExternalGraphCarlaPortAudioOut1 = 3, | |||
kExternalGraphCarlaPortAudioOut2 = 4, | |||
kExternalGraphCarlaPortMidiIn = 5, | |||
kExternalGraphCarlaPortMidiOut = 6, | |||
kExternalGraphCarlaPortMax = 7 | |||
}; | |||
struct GraphPorts { | |||
struct ExternalGraphBuffers { | |||
CarlaRecursiveMutex mutex; | |||
LinkedList<uint> connectedIn1; | |||
LinkedList<uint> connectedIn2; | |||
LinkedList<uint> connectedOut1; | |||
LinkedList<uint> connectedOut2; | |||
float* inBuf[2]; | |||
float* inBufTmp[2]; | |||
float* outBuf[2]; | |||
ExternalGraphBuffers() noexcept; | |||
void setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPY_CLASS(ExternalGraphBuffers) | |||
}; | |||
struct ExternalGraphPorts { | |||
LinkedList<PortNameToId> ins; | |||
LinkedList<PortNameToId> outs; | |||
const char* getName(const bool isInput, const uint portId) const noexcept; | |||
uint getPortId(const bool isInput, const char portName[], bool* const ok = nullptr) const noexcept; | |||
GraphPorts() noexcept; | |||
ExternalGraphPorts() noexcept; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPY_CLASS(GraphPorts) | |||
CARLA_DECLARE_NON_COPY_CLASS(ExternalGraphPorts) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// Rack Graph stuff | |||
enum RackGraphGroupIds { | |||
RACK_GRAPH_GROUP_NULL = 0, | |||
RACK_GRAPH_GROUP_CARLA = 1, | |||
RACK_GRAPH_GROUP_AUDIO_IN = 2, | |||
RACK_GRAPH_GROUP_AUDIO_OUT = 3, | |||
RACK_GRAPH_GROUP_MIDI_IN = 4, | |||
RACK_GRAPH_GROUP_MIDI_OUT = 5, | |||
RACK_GRAPH_GROUP_MAX = 6 | |||
}; | |||
struct ExternalGraph { | |||
PatchbayConnectionList connections; | |||
ExternalGraphBuffers audioBuffers; | |||
ExternalGraphPorts audioPorts, midiPorts; | |||
mutable CharStringListPtr retCon; | |||
ExternalGraph(CarlaEngine* const engine) noexcept; | |||
void clearConnections() noexcept; | |||
void clearPorts() noexcept; | |||
enum RackGraphCarlaPortIds { | |||
RACK_GRAPH_CARLA_PORT_NULL = 0, | |||
RACK_GRAPH_CARLA_PORT_AUDIO_IN1 = 1, | |||
RACK_GRAPH_CARLA_PORT_AUDIO_IN2 = 2, | |||
RACK_GRAPH_CARLA_PORT_AUDIO_OUT1 = 3, | |||
RACK_GRAPH_CARLA_PORT_AUDIO_OUT2 = 4, | |||
RACK_GRAPH_CARLA_PORT_MIDI_IN = 5, | |||
RACK_GRAPH_CARLA_PORT_MIDI_OUT = 6, | |||
RACK_GRAPH_CARLA_PORT_MAX = 7 | |||
bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept; | |||
bool disconnect(const uint connectionId) noexcept; | |||
void refresh(const char* const deviceName); | |||
const char* const* getConnections() const noexcept; | |||
bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept; | |||
CarlaEngine* const kEngine; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPY_CLASS(ExternalGraph) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// RackGraph | |||
struct RackGraph { | |||
PatchbayConnectionList connections; | |||
ExternalGraph extGraph; | |||
const uint32_t inputs; | |||
const uint32_t outputs; | |||
bool isOffline; | |||
mutable CharStringListPtr retCon; | |||
struct AudioBuffers { | |||
CarlaRecursiveMutex mutex; | |||
LinkedList<uint> connectedIn1; | |||
LinkedList<uint> connectedIn2; | |||
LinkedList<uint> connectedOut1; | |||
LinkedList<uint> connectedOut2; | |||
float* inBuf[2]; | |||
float* inBufTmp[2]; | |||
float* outBuf[2]; | |||
AudioBuffers() noexcept; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPY_CLASS(AudioBuffers) | |||
} audioBuffers; | |||
GraphPorts audioPorts, midiPorts; | |||
RackGraph(CarlaEngine* const engine, const uint32_t inputs, const uint32_t outputs) noexcept; | |||
~RackGraph() noexcept; | |||
@@ -127,15 +145,15 @@ struct PatchbayGraph { | |||
MidiBuffer midiBuffer; | |||
const uint32_t inputs; | |||
const uint32_t outputs; | |||
bool ignorePathbay; | |||
mutable CharStringListPtr retCon; | |||
bool usingExternal; | |||
GraphPorts audioPorts, midiPorts; | |||
ExternalGraph extGraph; | |||
PatchbayGraph(CarlaEngine* const engine, const uint32_t inputs, const uint32_t outputs); | |||
~PatchbayGraph(); | |||
void setBufferSize(const int bufferSize); | |||
void setBufferSize(const uint32_t bufferSize); | |||
void setSampleRate(const double sampleRate); | |||
void setOffline(const bool offline); | |||
@@ -147,12 +165,11 @@ struct PatchbayGraph { | |||
bool connect(const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept; | |||
bool disconnect(const uint connectionId) noexcept; | |||
void disconnectGroup(const uint groupId) noexcept; | |||
void clearPorts() noexcept; | |||
void clearConnections(); | |||
void clearInternalConnections(); | |||
void refresh(const char* const deviceName); | |||
const char* const* getConnections(const bool external) const; | |||
bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const; | |||
bool getGroupAndPortIdFromFullName(const bool external, const char* const fullPortName, uint& groupId, uint& portId) const; | |||
void process(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const int frames); | |||
@@ -86,7 +86,7 @@ public: | |||
void removePlugin(CarlaPlugin* const plugin); | |||
void removeAllPlugins(); | |||
void setIgnorePatchbay(const bool ignore) noexcept; | |||
void setUsingExternal(const bool usingExternal) noexcept; | |||
private: | |||
bool fIsRack; | |||
@@ -817,6 +817,7 @@ public: | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) | |||
{ | |||
pData->graph.create(0, 0); | |||
patchbayRefresh(true); | |||
} | |||
else | |||
{ | |||
@@ -1154,7 +1155,7 @@ public: | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
{ | |||
fExternalPatchbay = external; | |||
pData->graph.setIgnorePatchbay(external); | |||
pData->graph.setUsingExternal(external); | |||
if (! external) | |||
return CarlaEngine::patchbayRefresh(false); | |||
@@ -403,7 +403,7 @@ public: | |||
// Patchbay | |||
template<class Graph> | |||
void refreshGraphPorts(Graph* const graph) | |||
bool refreshGraphPorts(Graph& graph) | |||
{ | |||
char strBuf[STR_MAX+1]; | |||
strBuf[STR_MAX] = '\0'; | |||
@@ -411,7 +411,7 @@ public: | |||
// --------------------------------------------------------------- | |||
// clear last ports | |||
graph->clearPorts(); | |||
graph.clearPorts(); | |||
// --------------------------------------------------------------- | |||
// fill in new ones | |||
@@ -422,9 +422,9 @@ public: | |||
std::snprintf(strBuf, STR_MAX, "capture_%i", i+1); | |||
PortNameToId portNameToId; | |||
portNameToId.setData(RACK_GRAPH_GROUP_AUDIO_IN, i+1, strBuf, ""); | |||
portNameToId.setData(kExternalGraphGroupAudioIn, i+1, strBuf, ""); | |||
graph->audioPorts.ins.append(portNameToId); | |||
graph.audioPorts.ins.append(portNameToId); | |||
} | |||
// Audio Out | |||
@@ -433,9 +433,9 @@ public: | |||
std::snprintf(strBuf, STR_MAX, "playback_%i", i+1); | |||
PortNameToId portNameToId; | |||
portNameToId.setData(RACK_GRAPH_GROUP_AUDIO_OUT, i+1, strBuf, ""); | |||
portNameToId.setData(kExternalGraphGroupAudioOut, i+1, strBuf, ""); | |||
graph->audioPorts.outs.append(portNameToId); | |||
graph.audioPorts.outs.append(portNameToId); | |||
} | |||
// MIDI In | |||
@@ -445,9 +445,9 @@ public: | |||
for (uint i=0, count = midiIn.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.setData(RACK_GRAPH_GROUP_MIDI_IN, i+1, midiIn.getPortName(i).c_str(), ""); | |||
portNameToId.setData(kExternalGraphGroupMidiIn, i+1, midiIn.getPortName(i).c_str(), ""); | |||
graph->midiPorts.ins.append(portNameToId); | |||
graph.midiPorts.ins.append(portNameToId); | |||
} | |||
} | |||
@@ -458,16 +458,16 @@ public: | |||
for (uint i=0, count = midiOut.getPortCount(); i < count; ++i) | |||
{ | |||
PortNameToId portNameToId; | |||
portNameToId.setData(RACK_GRAPH_GROUP_MIDI_OUT, i+1, midiOut.getPortName(i).c_str(), ""); | |||
portNameToId.setData(kExternalGraphGroupMidiOut, i+1, midiOut.getPortName(i).c_str(), ""); | |||
graph->midiPorts.outs.append(portNameToId); | |||
graph.midiPorts.outs.append(portNameToId); | |||
} | |||
} | |||
// --------------------------------------------------------------- | |||
// now refresh | |||
graph->refresh(fDeviceName.buffer()); | |||
graph.refresh(fDeviceName.buffer()); | |||
// --------------------------------------------------------------- | |||
// add midi connections | |||
@@ -479,17 +479,17 @@ public: | |||
const MidiInPort& inPort(it.getValue(fallback)); | |||
CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); | |||
const uint portId(graph->midiPorts.getPortId(true, inPort.name)); | |||
CARLA_SAFE_ASSERT_CONTINUE(portId < graph->midiPorts.ins.count()); | |||
const uint portId(graph.midiPorts.getPortId(true, inPort.name)); | |||
CARLA_SAFE_ASSERT_CONTINUE(portId < graph.midiPorts.ins.count()); | |||
ConnectionToId connectionToId; | |||
connectionToId.setData(++(graph->connections.lastId), RACK_GRAPH_GROUP_MIDI_IN, portId, RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_IN); | |||
connectionToId.setData(++(graph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn); | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf); | |||
graph->connections.list.append(connectionToId); | |||
graph.connections.list.append(connectionToId); | |||
} | |||
fMidiOutMutex.lock(); | |||
@@ -501,39 +501,40 @@ public: | |||
const MidiOutPort& outPort(it.getValue(fallback)); | |||
CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); | |||
const uint portId(graph->midiPorts.getPortId(false, outPort.name)); | |||
CARLA_SAFE_ASSERT_CONTINUE(portId < graph->midiPorts.outs.count()); | |||
const uint portId(graph.midiPorts.getPortId(false, outPort.name)); | |||
CARLA_SAFE_ASSERT_CONTINUE(portId < graph.midiPorts.outs.count()); | |||
ConnectionToId connectionToId; | |||
connectionToId.setData(++(graph->connections.lastId), RACK_GRAPH_GROUP_CARLA, RACK_GRAPH_CARLA_PORT_MIDI_OUT, RACK_GRAPH_GROUP_MIDI_OUT, portId); | |||
connectionToId.setData(++(graph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId); | |||
std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB); | |||
callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, 0, 0, 0.0f, strBuf); | |||
graph->connections.list.append(connectionToId); | |||
graph.connections.list.append(connectionToId); | |||
} | |||
fMidiOutMutex.unlock(); | |||
return true; | |||
} | |||
bool patchbayRefresh(const bool /*external*/) override | |||
bool patchbayRefresh(const bool external) override | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false); | |||
if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK) | |||
{ | |||
RackGraph* const graph(pData->graph.getRackGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
refreshGraphPorts<RackGraph>(graph); | |||
return refreshGraphPorts<ExternalGraph>(pData->graph.getRackGraph()->extGraph); | |||
} | |||
else | |||
{ | |||
PatchbayGraph* const graph(pData->graph.getPatchbayGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
pData->graph.setUsingExternal(external); | |||
if (! external) | |||
return CarlaEngine::patchbayRefresh(false); | |||
refreshGraphPorts<PatchbayGraph>(graph); | |||
return refreshGraphPorts<ExternalGraph>(pData->graph.getPatchbayGraph()->extGraph); | |||
} | |||
return true; | |||
@@ -740,7 +741,7 @@ protected: | |||
RackGraph* const graph(pData->graph.getRackGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->midiPorts.ins.count() > 0, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false); | |||
CarlaString newRtMidiPortName; | |||
newRtMidiPortName += getName(); | |||
@@ -795,7 +796,7 @@ protected: | |||
RackGraph* const graph(pData->graph.getRackGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->midiPorts.ins.count() > 0, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false); | |||
CarlaString newRtMidiPortName; | |||
newRtMidiPortName += getName(); | |||
@@ -850,7 +851,7 @@ protected: | |||
RackGraph* const graph(pData->graph.getRackGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->midiPorts.ins.count() > 0, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.ins.count() > 0, false); | |||
for (LinkedList<MidiInPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next()) | |||
{ | |||
@@ -880,7 +881,7 @@ protected: | |||
RackGraph* const graph(pData->graph.getRackGraph()); | |||
CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->midiPorts.outs.count() > 0, false); | |||
CARLA_SAFE_ASSERT_RETURN(graph->extGraph.midiPorts.outs.count() > 0, false); | |||
const CarlaMutexLocker cml(fMidiOutMutex); | |||
@@ -612,7 +612,7 @@ class HostWindow(QMainWindow): | |||
self.ui.act_canvas_show_internal.blockSignals(True) | |||
self.ui.act_canvas_show_external.blockSignals(True) | |||
if processMode == ENGINE_PROCESS_MODE_PATCHBAY and driverName == "JACK": | |||
if processMode == ENGINE_PROCESS_MODE_PATCHBAY and not self.host.isPlugin: | |||
self.ui.act_canvas_show_internal.setChecked(True) | |||
self.ui.act_canvas_show_internal.setVisible(True) | |||
self.ui.act_canvas_show_external.setChecked(False) | |||