Signed-off-by: falkTX <falktx@falktx.com>tags/v2.5.1
| @@ -36,8 +36,8 @@ CARLA_BACKEND_START_NAMESPACE | |||
| // ----------------------------------------------------------------------- | |||
| // Fallback data | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| static /* */ PortNameToId kPortNameToIdFallbackNC = { 0, 0, { '\0' }, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' }, { '\0' } }; | |||
| static /* */ PortNameToId kPortNameToIdFallbackNC = { 0, 0, { '\0' }, { '\0' }, { '\0' } }; | |||
| // ----------------------------------------------------------------------- | |||
| // External Graph stuff | |||
| @@ -108,14 +108,34 @@ const char* ExternalGraphPorts::getName(const bool isInput, const uint portId) c | |||
| return nullptr; | |||
| } | |||
| uint ExternalGraphPorts::getPortId(const bool isInput, const char portName[], bool* const ok) const noexcept | |||
| uint ExternalGraphPorts::getPortIdFromName(const bool isInput, const char name[], bool* const ok) const noexcept | |||
| { | |||
| for (LinkedList<PortNameToId>::Itenerator it = isInput ? ins.begin2() : outs.begin2(); it.valid(); it.next()) | |||
| { | |||
| const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); | |||
| if (std::strncmp(portNameToId.name, portName, STR_MAX) == 0) | |||
| if (std::strncmp(portNameToId.name, name, STR_MAX) == 0) | |||
| { | |||
| if (ok != nullptr) | |||
| *ok = true; | |||
| return portNameToId.port; | |||
| } | |||
| } | |||
| if (ok != nullptr) | |||
| *ok = false; | |||
| return 0; | |||
| } | |||
| uint ExternalGraphPorts::getPortIdFromIdentifier(const bool isInput, const char identifier[], bool* const ok) const noexcept | |||
| { | |||
| for (LinkedList<PortNameToId>::Itenerator it = isInput ? ins.begin2() : outs.begin2(); it.valid(); it.next()) | |||
| { | |||
| const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group > 0); | |||
| if (std::strncmp(portNameToId.identifier, identifier, STR_MAX) == 0) | |||
| { | |||
| if (ok != nullptr) | |||
| *ok = true; | |||
| @@ -420,7 +440,6 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| const CarlaString groupNameIn(strBuf); | |||
| int h = 0; | |||
| for (LinkedList<PortNameToId>::Itenerator it = audioPorts.ins.begin2(); it.valid(); it.next()) | |||
| { | |||
| PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); | |||
| @@ -431,7 +450,7 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| kEngine->callback(sendHost, sendOSC, | |||
| ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, | |||
| kExternalGraphGroupAudioIn, | |||
| ++h, | |||
| portNameToId.port, | |||
| PATCHBAY_PORT_TYPE_AUDIO, | |||
| 0, 0.0f, | |||
| portNameToId.name); | |||
| @@ -453,7 +472,6 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| const CarlaString groupNameOut(strBuf); | |||
| h = 0; | |||
| for (LinkedList<PortNameToId>::Itenerator it = audioPorts.outs.begin2(); it.valid(); it.next()) | |||
| { | |||
| PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); | |||
| @@ -464,7 +482,7 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| kEngine->callback(sendHost, sendOSC, | |||
| ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, | |||
| kExternalGraphGroupAudioOut, | |||
| ++h, | |||
| portNameToId.port, | |||
| PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, | |||
| 0, 0.0f, | |||
| portNameToId.name); | |||
| @@ -483,7 +501,6 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| const CarlaString groupNamePlus("Readable MIDI ports:"); | |||
| int h = 0; | |||
| for (LinkedList<PortNameToId>::Itenerator it = midiPorts.ins.begin2(); it.valid(); it.next()) | |||
| { | |||
| PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); | |||
| @@ -494,7 +511,7 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| kEngine->callback(sendHost, sendOSC, | |||
| ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, | |||
| kExternalGraphGroupMidiIn, | |||
| ++h, | |||
| portNameToId.port, | |||
| PATCHBAY_PORT_TYPE_MIDI, | |||
| 0, 0.0f, | |||
| portNameToId.name); | |||
| @@ -513,7 +530,6 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| const CarlaString groupNamePlus("Writable MIDI ports:"); | |||
| int h = 0; | |||
| for (LinkedList<PortNameToId>::Itenerator it = midiPorts.outs.begin2(); it.valid(); it.next()) | |||
| { | |||
| PortNameToId& portNameToId(it.getValue(kPortNameToIdFallbackNC)); | |||
| @@ -524,7 +540,7 @@ void ExternalGraph::refresh(const bool sendHost, const bool sendOSC, const char* | |||
| kEngine->callback(sendHost, sendOSC, | |||
| ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, | |||
| kExternalGraphGroupMidiOut, | |||
| ++h, | |||
| portNameToId.port, | |||
| PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, | |||
| 0, 0.0f, | |||
| portNameToId.name); | |||
| @@ -661,7 +677,7 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName | |||
| if (const char* const portName = fullPortName+8) | |||
| { | |||
| bool ok; | |||
| portId = audioPorts.getPortId(true, portName, &ok); | |||
| portId = audioPorts.getPortIdFromName(true, portName, &ok); | |||
| return ok; | |||
| } | |||
| } | |||
| @@ -672,7 +688,7 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName | |||
| if (const char* const portName = fullPortName+9) | |||
| { | |||
| bool ok; | |||
| portId = audioPorts.getPortId(false, portName, &ok); | |||
| portId = audioPorts.getPortIdFromName(false, portName, &ok); | |||
| return ok; | |||
| } | |||
| } | |||
| @@ -683,7 +699,7 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName | |||
| if (const char* const portName = fullPortName+7) | |||
| { | |||
| bool ok; | |||
| portId = midiPorts.getPortId(true, portName, &ok); | |||
| portId = midiPorts.getPortIdFromName(true, portName, &ok); | |||
| return ok; | |||
| } | |||
| } | |||
| @@ -694,7 +710,7 @@ bool ExternalGraph::getGroupAndPortIdFromFullName(const char* const fullPortName | |||
| if (const char* const portName = fullPortName+8) | |||
| { | |||
| bool ok; | |||
| portId = midiPorts.getPortId(false, portName, &ok); | |||
| portId = midiPorts.getPortIdFromName(false, portName, &ok); | |||
| return ok; | |||
| } | |||
| } | |||
| @@ -78,7 +78,8 @@ struct ExternalGraphPorts { | |||
| LinkedList<PortNameToId> ins; | |||
| LinkedList<PortNameToId> outs; | |||
| const char* getName(bool isInput, uint portId) const noexcept; | |||
| uint getPortId(bool isInput, const char portName[], bool* ok = nullptr) const noexcept; | |||
| uint getPortIdFromName(bool isInput, const char name[], bool* ok = nullptr) const noexcept; | |||
| uint getPortIdFromIdentifier(bool isInput, const char identifier[], bool* ok = nullptr) const noexcept; | |||
| ExternalGraphPorts() noexcept; | |||
| CARLA_PREVENT_HEAP_ALLOCATION | |||
| CARLA_DECLARE_NON_COPYABLE(ExternalGraphPorts) | |||
| @@ -122,8 +122,8 @@ struct CarlaJackPortHints { | |||
| #ifndef BUILD_BRIDGE | |||
| static const GroupNameToId kGroupNameToIdFallback = { 0, { '\0' } }; | |||
| static /* */ PortNameToId kPortNameToIdFallbackNC = { 0, 0, { '\0' }, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| static /* */ PortNameToId kPortNameToIdFallbackNC = { 0, 0, { '\0' }, { '\0' }, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' }, { '\0' } }; | |||
| static const ConnectionToId kConnectionToIdFallback = { 0, 0, 0, 0, 0 }; | |||
| #endif | |||
| static EngineEvent kFallbackJackEngineEvent = { | |||
| @@ -43,12 +43,14 @@ CARLA_BACKEND_START_NAMESPACE | |||
| struct MidiInPort { | |||
| juce::MidiInput* port; | |||
| char name[STR_MAX+1]; | |||
| char name[STR_MAX]; | |||
| char identifier[STR_MAX]; | |||
| }; | |||
| struct MidiOutPort { | |||
| juce::MidiOutput* port; | |||
| char name[STR_MAX+1]; | |||
| char name[STR_MAX]; | |||
| char identifier[STR_MAX]; | |||
| }; | |||
| struct RtMidiEvent { | |||
| @@ -60,10 +62,10 @@ struct RtMidiEvent { | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Fallback data | |||
| static const MidiInPort kMidiInPortFallback = { nullptr, { '\0' } }; | |||
| static /* */ MidiInPort kMidiInPortFallbackNC = { nullptr, { '\0' } }; | |||
| static const MidiOutPort kMidiOutPortFallback = { nullptr, { '\0' } }; | |||
| static /* */ MidiOutPort kMidiOutPortFallbackNC = { nullptr, { '\0' } }; | |||
| static const MidiInPort kMidiInPortFallback = { nullptr, { '\0' }, { '\0' } }; | |||
| static /* */ MidiInPort kMidiInPortFallbackNC = { nullptr, { '\0' }, { '\0' } }; | |||
| static const MidiOutPort kMidiOutPortFallback = { nullptr, { '\0' }, { '\0' } }; | |||
| static /* */ MidiOutPort kMidiOutPortFallbackNC = { nullptr, { '\0' }, { '\0' } }; | |||
| static const RtMidiEvent kRtMidiEventFallback = { 0, 0, { 0 } }; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -465,16 +467,18 @@ public: | |||
| // MIDI In | |||
| { | |||
| juce::StringArray midiIns(juce::MidiInput::getDevices()); | |||
| juce::Array<juce::MidiDeviceInfo> midiIns(juce::MidiInput::getAvailableDevices()); | |||
| for (int i=0, count=midiIns.size(); i<count; ++i) | |||
| { | |||
| const juce::String name(midiIns[i]); | |||
| if (name == "a2jmidid - port") | |||
| const juce::MidiDeviceInfo devInfo(midiIns[i]); | |||
| if (devInfo.name == "a2jmidid - port") | |||
| continue; | |||
| PortNameToId portNameToId; | |||
| portNameToId.setData(kExternalGraphGroupMidiIn, uint(i+1), name.toRawUTF8(), ""); | |||
| portNameToId.setDataWithIdentifier(kExternalGraphGroupMidiIn, static_cast<uint>(i + 1), | |||
| devInfo.name.toRawUTF8(), devInfo.identifier.toRawUTF8()); | |||
| extGraph.midiPorts.ins.append(portNameToId); | |||
| } | |||
| @@ -482,16 +486,18 @@ public: | |||
| // MIDI Out | |||
| { | |||
| juce::StringArray midiOuts(juce::MidiOutput::getDevices()); | |||
| juce::Array<juce::MidiDeviceInfo> midiOuts(juce::MidiOutput::getAvailableDevices()); | |||
| for (int i=0, count=midiOuts.size(); i<count; ++i) | |||
| { | |||
| const juce::String name(midiOuts[i]); | |||
| if (name == "a2jmidid - port") | |||
| const juce::MidiDeviceInfo devInfo(midiOuts[i]); | |||
| if (devInfo.name == "a2jmidid - port") | |||
| continue; | |||
| PortNameToId portNameToId; | |||
| portNameToId.setData(kExternalGraphGroupMidiOut, uint(i+1), name.toRawUTF8(), ""); | |||
| portNameToId.setDataWithIdentifier(kExternalGraphGroupMidiOut, static_cast<uint>(i + 1), | |||
| devInfo.name.toRawUTF8(), devInfo.identifier.toRawUTF8()); | |||
| extGraph.midiPorts.outs.append(portNameToId); | |||
| } | |||
| @@ -518,8 +524,9 @@ public: | |||
| const MidiInPort& inPort(it.getValue(kMidiInPortFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); | |||
| const uint portId(extGraph.midiPorts.getPortId(true, inPort.name)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.ins.count()); | |||
| bool ok; | |||
| const uint portId = extGraph.midiPorts.getPortIdFromIdentifier(true, inPort.identifier, &ok); | |||
| CARLA_SAFE_ASSERT_UINT_CONTINUE(ok, portId); | |||
| ConnectionToId connectionToId; | |||
| connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn); | |||
| @@ -543,8 +550,9 @@ public: | |||
| const MidiOutPort& outPort(it.getValue(kMidiOutPortFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); | |||
| const uint portId(extGraph.midiPorts.getPortId(false, outPort.name)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.outs.count()); | |||
| bool ok; | |||
| const uint portId = extGraph.midiPorts.getPortIdFromIdentifier(false, outPort.identifier, &ok); | |||
| CARLA_SAFE_ASSERT_UINT_CONTINUE(ok, portId); | |||
| ConnectionToId connectionToId; | |||
| connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId); | |||
| @@ -754,44 +762,66 @@ protected: | |||
| return CarlaEngine::connectExternalGraphPort(connectionType, portId, portName); | |||
| case kExternalGraphConnectionMidiInput: { | |||
| juce::StringArray midiIns(juce::MidiInput::getDevices()); | |||
| juce::Array<juce::MidiDeviceInfo> midiIns(juce::MidiInput::getAvailableDevices()); | |||
| if (! midiIns.contains(portName)) | |||
| return false; | |||
| for (int i=0, count=midiIns.size(); i<count; ++i) | |||
| { | |||
| const juce::MidiDeviceInfo devInfo(midiIns[i]); | |||
| std::unique_ptr<juce::MidiInput> juceMidiIn(juce::MidiInput::openDevice(midiIns.indexOf(portName), this)); | |||
| juceMidiIn->start(); | |||
| if (devInfo.name != portName) | |||
| continue; | |||
| MidiInPort midiPort; | |||
| midiPort.port = juceMidiIn.release(); | |||
| std::unique_ptr<juce::MidiInput> juceMidiIn(juce::MidiInput::openDevice(devInfo.identifier, this)); | |||
| juceMidiIn->start(); | |||
| std::strncpy(midiPort.name, portName, STR_MAX); | |||
| midiPort.name[STR_MAX] = '\0'; | |||
| MidiInPort midiPort; | |||
| midiPort.port = juceMidiIn.release(); | |||
| fMidiIns.append(midiPort); | |||
| return true; | |||
| } break; | |||
| std::strncpy(midiPort.name, portName, STR_MAX-1); | |||
| midiPort.name[STR_MAX-1] = '\0'; | |||
| std::strncpy(midiPort.identifier, devInfo.identifier.toRawUTF8(), STR_MAX-1); | |||
| midiPort.identifier[STR_MAX-1] = '\0'; | |||
| carla_stdout("MIDI CON '%s' '%s'", midiPort.name, midiPort.identifier); | |||
| fMidiIns.append(midiPort); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| case kExternalGraphConnectionMidiOutput: { | |||
| juce::StringArray midiOuts(juce::MidiOutput::getDevices()); | |||
| juce::Array<juce::MidiDeviceInfo> midiOuts(juce::MidiOutput::getAvailableDevices()); | |||
| if (! midiOuts.contains(portName)) | |||
| return false; | |||
| for (int i=0, count=midiOuts.size(); i<count; ++i) | |||
| { | |||
| const juce::MidiDeviceInfo devInfo(midiOuts[i]); | |||
| std::unique_ptr<juce::MidiOutput> juceMidiOut(juce::MidiOutput::openDevice(midiOuts.indexOf(portName))); | |||
| juceMidiOut->startBackgroundThread(); | |||
| if (devInfo.name != portName) | |||
| continue; | |||
| MidiOutPort midiPort; | |||
| midiPort.port = juceMidiOut.release(); | |||
| std::unique_ptr<juce::MidiOutput> juceMidiOut(juce::MidiOutput::openDevice(devInfo.identifier)); | |||
| juceMidiOut->startBackgroundThread(); | |||
| std::strncpy(midiPort.name, portName, STR_MAX); | |||
| midiPort.name[STR_MAX] = '\0'; | |||
| MidiOutPort midiPort; | |||
| midiPort.port = juceMidiOut.release(); | |||
| const CarlaMutexLocker cml(fMidiOutMutex); | |||
| std::strncpy(midiPort.name, portName, STR_MAX-1); | |||
| midiPort.name[STR_MAX-1] = '\0'; | |||
| fMidiOuts.append(midiPort); | |||
| return true; | |||
| } break; | |||
| std::strncpy(midiPort.identifier, devInfo.identifier.toRawUTF8(), STR_MAX-1); | |||
| midiPort.identifier[STR_MAX-1] = '\0'; | |||
| const CarlaMutexLocker cml(fMidiOutMutex); | |||
| fMidiOuts.append(midiPort); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| @@ -549,8 +549,8 @@ public: | |||
| const MidiInPort& inPort(it.getValue(fallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr); | |||
| const uint portId(extGraph.midiPorts.getPortId(true, inPort.name)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.ins.count()); | |||
| const uint portId = extGraph.midiPorts.getPortIdFromName(true, inPort.name); | |||
| CARLA_SAFE_ASSERT_UINT_CONTINUE(portId < extGraph.midiPorts.ins.count(), portId); | |||
| ConnectionToId connectionToId; | |||
| connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn); | |||
| @@ -575,8 +575,8 @@ public: | |||
| const MidiOutPort& outPort(it.getValue(fallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr); | |||
| const uint portId(extGraph.midiPorts.getPortId(false, outPort.name)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portId < extGraph.midiPorts.outs.count()); | |||
| const uint portId = extGraph.midiPorts.getPortIdFromName(false, outPort.name); | |||
| CARLA_SAFE_ASSERT_UINT_CONTINUE(portId < extGraph.midiPorts.outs.count(), portId); | |||
| ConnectionToId connectionToId; | |||
| connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId); | |||
| @@ -18,7 +18,7 @@ | |||
| #include "CarlaPatchbayUtils.hpp" | |||
| static const GroupNameToId kGroupNameToIdFallback = { 0, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' }, { '\0' } }; | |||
| uint PatchbayGroupList::getGroupId(const char* const groupName) const noexcept | |||
| { | |||
| @@ -82,4 +82,4 @@ const PortNameToId& PatchbayPortList::getPortNameToId(const char* const fullPort | |||
| } | |||
| return kPortNameToIdFallback; | |||
| } | |||
| } | |||
| @@ -91,6 +91,7 @@ struct PortNameToId { | |||
| uint port; | |||
| char name[STR_MAX]; // locally unique (within the same group) | |||
| char fullName[STR_MAX]; // globally unique | |||
| char identifier[STR_MAX]; // globally unique, if used | |||
| void clear() noexcept | |||
| { | |||
| @@ -98,6 +99,7 @@ struct PortNameToId { | |||
| port = 0; | |||
| name[0] = '\0'; | |||
| fullName[0] = '\0'; | |||
| identifier[0] = '\0'; | |||
| } | |||
| void setData(const uint g, const uint p, const char n[], const char fn[]) noexcept | |||
| @@ -107,6 +109,20 @@ struct PortNameToId { | |||
| rename(n, fn); | |||
| } | |||
| void setDataWithIdentifier(const uint g, const uint p, const char n[], const char id[]) noexcept | |||
| { | |||
| group = g; | |||
| port = p; | |||
| std::strncpy(name, n, STR_MAX-1); | |||
| name[STR_MAX-1] = '\0'; | |||
| fullName[0] = '\0'; | |||
| std::strncpy(identifier, id, STR_MAX-1); | |||
| identifier[STR_MAX-1] = '\0'; | |||
| } | |||
| void setFullName(const char fn[]) noexcept | |||
| { | |||
| std::strncpy(fullName, fn, STR_MAX-1); | |||