| @@ -707,6 +707,7 @@ public: | |||
| */ | |||
| virtual void clearBuffers() noexcept; | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| // OSC stuff | |||
| @@ -738,11 +739,12 @@ public: | |||
| * This is a handy function that waits for the GUI to respond and automatically asks it to show itself. | |||
| */ | |||
| bool waitForOscGuiShow(); | |||
| #endif | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| // MIDI events | |||
| #ifndef BUILD_BRIDGE | |||
| /*! | |||
| * Send a single midi note to be processed in the next audio callback. | |||
| * A note with 0 velocity means note-off. | |||
| @@ -2163,6 +2163,7 @@ const char* carla_get_host_osc_url_udp() | |||
| #include "CarlaPluginUI.cpp" | |||
| #include "CarlaDssiUtils.cpp" | |||
| #include "CarlaPatchbayUtils.cpp" | |||
| #include "CarlaPipeUtils.cpp" | |||
| #include "CarlaStateUtils.cpp" | |||
| #include "CarlaJuceEvents.cpp" | |||
| @@ -512,7 +512,9 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, cons | |||
| if (plugin == nullptr) | |||
| return false; | |||
| #ifndef BUILD_BRIDGE | |||
| plugin->registerToOscClient(); | |||
| #endif | |||
| EnginePluginData& pluginData(pData->plugins[id]); | |||
| pluginData.plugin = plugin; | |||
| @@ -2029,6 +2029,7 @@ CARLA_BACKEND_END_NAMESPACE | |||
| #include "CarlaHostCommon.cpp" | |||
| #include "CarlaPluginUI.cpp" | |||
| #include "CarlaDssiUtils.cpp" | |||
| #include "CarlaPatchbayUtils.cpp" | |||
| #include "CarlaPipeUtils.cpp" | |||
| #include "CarlaStateUtils.cpp" | |||
| #include "CarlaJuceEvents.cpp" | |||
| @@ -401,9 +401,11 @@ int CarlaEngineOsc::handleMsgUpdate(CARLA_ENGINE_OSC_HANDLE_ARGS2, const lo_addr | |||
| carla_debug("CarlaEngineOsc::handleMsgUpdate()"); | |||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); | |||
| #ifndef BUILD_BRIDGE | |||
| const char* const url = (const char*)&argv[0]->s; | |||
| plugin->updateOscData(source, url); | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -44,6 +44,8 @@ static const ParameterRanges kParameterRangesNull = { 0.0f, 0.0f, 1.0f, 0.01f, 0 | |||
| static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; | |||
| static const CustomData kCustomDataNull = { nullptr, nullptr, nullptr }; | |||
| static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; | |||
| static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr }; | |||
| static const PluginPostRtEvent kPluginPostRtEventFallback = { kPluginPostRtEventNull, 0, 0, 0.0f }; | |||
| // ------------------------------------------------------------------- | |||
| @@ -261,7 +263,7 @@ const MidiProgramData& CarlaPlugin::getMidiProgramData(const uint32_t index) con | |||
| const CustomData& CarlaPlugin::getCustomData(const uint32_t index) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < pData->custom.count(), kCustomDataNull); | |||
| return pData->custom.getAt(index, kCustomDataNull); | |||
| return pData->custom.getAt(index, kCustomDataFallback); | |||
| } | |||
| std::size_t CarlaPlugin::getChunkData(void** const dataPtr) noexcept | |||
| @@ -588,7 +590,7 @@ const CarlaStateSave& CarlaPlugin::getStateSave() | |||
| for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next()) | |||
| { | |||
| const CustomData& cData(it.getValue(kCustomDataNull)); | |||
| const CustomData& cData(it.getValue(kCustomDataFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(cData.isValid()); | |||
| CarlaStateSave::CustomData* stateCustomData(new CarlaStateSave::CustomData()); | |||
| @@ -613,7 +615,10 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin(); it.valid(); it.next()) | |||
| { | |||
| const CarlaStateSave::CustomData* const stateCustomData(it.getValue()); | |||
| const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid()); | |||
| const char* const key(stateCustomData->key); | |||
| bool wantData = false; | |||
| @@ -693,7 +698,8 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| for (CarlaStateSave::ParameterItenerator it = stateSave.parameters.begin(); it.valid(); it.next()) | |||
| { | |||
| CarlaStateSave::Parameter* const stateParameter(it.getValue()); | |||
| CarlaStateSave::Parameter* const stateParameter(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(stateParameter != nullptr); | |||
| int32_t index = -1; | |||
| @@ -704,7 +710,9 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| { | |||
| for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin(); it2.valid(); it2.next()) | |||
| { | |||
| ParamSymbol* const paramSymbol(it2.getValue()); | |||
| ParamSymbol* const paramSymbol(it2.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr); | |||
| if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) | |||
| { | |||
| @@ -725,7 +733,9 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| { | |||
| for (LinkedList<ParamSymbol*>::Itenerator it2 = paramSymbols.begin(); it2.valid(); it2.next()) | |||
| { | |||
| ParamSymbol* const paramSymbol(it2.getValue()); | |||
| ParamSymbol* const paramSymbol(it2.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(paramSymbol != nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(paramSymbol->symbol != nullptr); | |||
| if (std::strcmp(stateParameter->symbol, paramSymbol->symbol) == 0) | |||
| { | |||
| @@ -772,7 +782,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| for (LinkedList<ParamSymbol*>::Itenerator it = paramSymbols.begin(); it.valid(); it.next()) | |||
| { | |||
| ParamSymbol* const paramSymbol(it.getValue()); | |||
| ParamSymbol* const paramSymbol(it.getValue(nullptr)); | |||
| delete paramSymbol; | |||
| } | |||
| @@ -783,7 +793,10 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave) | |||
| for (CarlaStateSave::CustomDataItenerator it = stateSave.customData.begin(); it.valid(); it.next()) | |||
| { | |||
| const CarlaStateSave::CustomData* const stateCustomData(it.getValue()); | |||
| const CarlaStateSave::CustomData* const stateCustomData(it.getValue(nullptr)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(stateCustomData != nullptr); | |||
| CARLA_SAFE_ASSERT_CONTINUE(stateCustomData->isValid()); | |||
| const char* const key(stateCustomData->key); | |||
| if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)) | |||
| @@ -1197,7 +1210,7 @@ void CarlaPlugin::setCustomData(const char* const type, const char* const key, c | |||
| // Check if we already have this key | |||
| for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next()) | |||
| { | |||
| CustomData& customData(it.getValue()); | |||
| CustomData& customData(it.getValue(kCustomDataFallbackNC)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); | |||
| if (std::strcmp(customData.key, key) == 0) | |||
| @@ -1422,6 +1435,7 @@ void CarlaPlugin::clearBuffers() noexcept | |||
| pData->clearBuffers(); | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| // OSC stuff | |||
| @@ -1617,7 +1631,7 @@ void CarlaPlugin::updateOscData(const lo_address& source, const char* const url) | |||
| for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next()) | |||
| { | |||
| const CustomData& customData(it.getValue(kCustomDataNull)); | |||
| const CustomData& customData(it.getValue(kCustomDataFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); | |||
| if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0) | |||
| @@ -1682,6 +1696,7 @@ bool CarlaPlugin::waitForOscGuiShow() | |||
| carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout); | |||
| return false; | |||
| } | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // MIDI events | |||
| @@ -26,7 +26,9 @@ CARLA_BACKEND_START_NAMESPACE | |||
| // ------------------------------------------------------------------- | |||
| // Fallback data | |||
| static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; | |||
| static const MidiProgramData kMidiProgramDataNull = { 0, 0, nullptr }; | |||
| static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; | |||
| static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr }; | |||
| // ----------------------------------------------------------------------- | |||
| // PluginAudioData | |||
| @@ -405,7 +407,8 @@ void CarlaPlugin::ProtectedData::PostRtEvents::trySplice() noexcept | |||
| { | |||
| if (mutex.tryLock()) | |||
| { | |||
| dataPendingRT.spliceAppendTo(data); | |||
| if (dataPendingRT.count() > 0) | |||
| dataPendingRT.moveTo(data, true); | |||
| mutex.unlock(); | |||
| } | |||
| } | |||
| @@ -525,31 +528,32 @@ CarlaPlugin::ProtectedData::~ProtectedData() noexcept | |||
| for (LinkedList<CustomData>::Itenerator it = custom.begin(); it.valid(); it.next()) | |||
| { | |||
| CustomData& cData(it.getValue()); | |||
| CustomData& customData(it.getValue(kCustomDataFallbackNC)); | |||
| //CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); | |||
| if (cData.type != nullptr) | |||
| if (customData.type != nullptr) | |||
| { | |||
| delete[] cData.type; | |||
| cData.type = nullptr; | |||
| delete[] customData.type; | |||
| customData.type = nullptr; | |||
| } | |||
| else | |||
| carla_safe_assert("cData.type != nullptr", __FILE__, __LINE__); | |||
| carla_safe_assert("customData.type != nullptr", __FILE__, __LINE__); | |||
| if (cData.key != nullptr) | |||
| if (customData.key != nullptr) | |||
| { | |||
| delete[] cData.key; | |||
| cData.key = nullptr; | |||
| delete[] customData.key; | |||
| customData.key = nullptr; | |||
| } | |||
| else | |||
| carla_safe_assert("cData.key != nullptr", __FILE__, __LINE__); | |||
| carla_safe_assert("customData.key != nullptr", __FILE__, __LINE__); | |||
| if (cData.value != nullptr) | |||
| if (customData.value != nullptr) | |||
| { | |||
| delete[] cData.value; | |||
| cData.value = nullptr; | |||
| delete[] customData.value; | |||
| customData.value = nullptr; | |||
| } | |||
| else | |||
| carla_safe_assert("cData.value != nullptr", __FILE__, __LINE__); | |||
| carla_safe_assert("customData.value != nullptr", __FILE__, __LINE__); | |||
| } | |||
| prog.clear(); | |||
| @@ -36,7 +36,9 @@ public: | |||
| // might have some leftovers | |||
| for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next()) | |||
| { | |||
| Lib& lib(it.getValue()); | |||
| static Lib libFallback = { nullptr, nullptr, 0, false }; | |||
| Lib& lib(it.getValue(libFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr); | |||
| @@ -73,7 +75,9 @@ public: | |||
| for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next()) | |||
| { | |||
| Lib& lib(it.getValue()); | |||
| static Lib libFallback = { nullptr, nullptr, 0, false }; | |||
| Lib& lib(it.getValue(libFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.filename != nullptr); | |||
| @@ -116,7 +120,9 @@ public: | |||
| for (LinkedList<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next()) | |||
| { | |||
| Lib& lib(it.getValue()); | |||
| static Lib libFallback = { nullptr, nullptr, 0, false }; | |||
| Lib& lib(it.getValue(libFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.count > 0); | |||
| CARLA_SAFE_ASSERT_CONTINUE(lib.lib != nullptr); | |||
| @@ -0,0 +1,85 @@ | |||
| /* | |||
| * Carla patchbay utils | |||
| * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaPatchbayUtils.hpp" | |||
| static const GroupNameToId kGroupNameToIdFallback = { 0, { '\0' } }; | |||
| static const PortNameToId kPortNameToIdFallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| uint PatchbayGroupList::getGroupId(const char* const groupName) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(groupName != nullptr && groupName[0] != '\0', 0); | |||
| for (LinkedList<GroupNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| const GroupNameToId& groupNameToId(it.getValue(kGroupNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); | |||
| if (std::strncmp(groupNameToId.name, groupName, STR_MAX) == 0) | |||
| return groupNameToId.group; | |||
| } | |||
| return 0; | |||
| } | |||
| const char* PatchbayGroupList::getGroupName(const uint groupId) const noexcept | |||
| { | |||
| static const char fallback[] = { '\0' }; | |||
| for (LinkedList<GroupNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| const GroupNameToId& groupNameToId(it.getValue(kGroupNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); | |||
| if (groupNameToId.group == groupId) | |||
| return groupNameToId.name; | |||
| } | |||
| return fallback; | |||
| } | |||
| const char* PatchbayPortList::getFullPortName(const uint groupId, const uint portId) const noexcept | |||
| { | |||
| static const char fallback[] = { '\0' }; | |||
| for (LinkedList<PortNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); | |||
| if (portNameToId.group == groupId && portNameToId.port == portId) | |||
| return portNameToId.fullName; | |||
| } | |||
| return fallback; | |||
| } | |||
| const PortNameToId& PatchbayPortList::getPortNameToId(const char* const fullPortName) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr && fullPortName[0] != '\0', kPortNameToIdFallback); | |||
| for (LinkedList<PortNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| const PortNameToId& portNameToId(it.getValue(kPortNameToIdFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); | |||
| if (std::strncmp(portNameToId.fullName, fullPortName, STR_MAX) == 0) | |||
| return portNameToId; | |||
| } | |||
| return kPortNameToIdFallback; | |||
| } | |||
| @@ -75,41 +75,10 @@ struct PatchbayGroupList { | |||
| list.clear(); | |||
| } | |||
| uint getGroupId(const char* const groupName) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(groupName != nullptr && groupName[0] != '\0', 0); | |||
| for (LinkedList<GroupNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| static const GroupNameToId groupNameFallback = { 0, { '\0' } }; | |||
| const GroupNameToId& groupNameToId(it.getValue(groupNameFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); | |||
| if (std::strncmp(groupNameToId.name, groupName, STR_MAX) == 0) | |||
| return groupNameToId.group; | |||
| } | |||
| return 0; | |||
| } | |||
| uint getGroupId(const char* const groupName) const noexcept; | |||
| const char* getGroupName(const uint groupId) const noexcept | |||
| { | |||
| static const char fallback[] = { '\0' }; | |||
| for (LinkedList<GroupNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| static const GroupNameToId groupNameFallback = { 0, { '\0' } }; | |||
| const GroupNameToId& groupNameToId(it.getValue(groupNameFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(groupNameToId.group != 0); | |||
| if (groupNameToId.group == groupId) | |||
| return groupNameToId.name; | |||
| } | |||
| return fallback; | |||
| } | |||
| // always returns valid pointer (non-null) | |||
| const char* getGroupName(const uint groupId) const noexcept; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -175,41 +144,10 @@ struct PatchbayPortList { | |||
| list.clear(); | |||
| } | |||
| const char* getFullPortName(const uint groupId, const uint portId) const noexcept | |||
| { | |||
| static const char fallback[] = { '\0' }; | |||
| for (LinkedList<PortNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| static const PortNameToId portNameFallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| const PortNameToId& portNameToId(it.getValue(portNameFallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); | |||
| if (portNameToId.group == groupId && portNameToId.port == portId) | |||
| return portNameToId.fullName; | |||
| } | |||
| return fallback; | |||
| } | |||
| // always returns valid pointer (non-null) | |||
| const char* getFullPortName(const uint groupId, const uint portId) const noexcept; | |||
| const PortNameToId& getPortNameToId(const char* const fullPortName) const noexcept | |||
| { | |||
| static const PortNameToId fallback = { 0, 0, { '\0' }, { '\0' } }; | |||
| CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr && fullPortName[0] != '\0', fallback); | |||
| for (LinkedList<PortNameToId>::Itenerator it = list.begin(); it.valid(); it.next()) | |||
| { | |||
| const PortNameToId& portNameToId(it.getValue(fallback)); | |||
| CARLA_SAFE_ASSERT_CONTINUE(portNameToId.group != 0); | |||
| if (std::strncmp(portNameToId.fullName, fullPortName, STR_MAX) == 0) | |||
| return portNameToId; | |||
| } | |||
| return fallback; | |||
| } | |||
| const PortNameToId& getPortNameToId(const char* const fullPortName) const noexcept; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -129,6 +129,13 @@ public: | |||
| data->value = value; | |||
| } | |||
| // TODO: remove this, fallback should be mandatory | |||
| T& getValue() const noexcept | |||
| { | |||
| Data* const data(list_entry(fEntry, Data, siblings)); | |||
| return data->value; | |||
| } | |||
| private: | |||
| ListHead* fEntry; | |||
| ListHead* fEntry2; | |||