diff --git a/resources/ui/carla_settings.ui b/resources/ui/carla_settings.ui index e499be796..224d66a0b 100644 --- a/resources/ui/carla_settings.ui +++ b/resources/ui/carla_settings.ui @@ -2159,6 +2159,11 @@ JSFX + + + CLAP + + @@ -2385,6 +2390,28 @@ + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index e286c285f..45b560635 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -681,7 +681,12 @@ typedef enum { /*! * CLAP plugin. */ - PLUGIN_CLAP = 14 + PLUGIN_CLAP = 14, + + /*! + * Terminator/count, not a plugin type. + */ + PLUGIN_TYPE_COUNT = 15 } PluginType; diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index b9f16a479..e5811cc6e 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -277,6 +277,7 @@ struct CARLA_API EngineOptions { const char* pathSF2; const char* pathSFZ; const char* pathJSFX; + const char* pathCLAP; const char* binaryDir; const char* resourceDir; diff --git a/source/backend/CarlaStandalone.cpp b/source/backend/CarlaStandalone.cpp index a4ef3df73..d9151ff04 100644 --- a/source/backend/CarlaStandalone.cpp +++ b/source/backend/CarlaStandalone.cpp @@ -272,6 +272,9 @@ static void carla_engine_init_common(const CarlaHostStandalone& standalone, Carl if (const char* const pathJSFX = std::getenv("ENGINE_OPTION_PLUGIN_PATH_JSFX")) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_JSFX, pathJSFX); + if (const char* const pathCLAP = std::getenv("ENGINE_OPTION_PLUGIN_PATH_CLAP")) + engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_CLAP, pathCLAP); + if (const char* const binaryDir = std::getenv("ENGINE_OPTION_PATH_BINARIES")) engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, binaryDir); else @@ -339,6 +342,9 @@ static void carla_engine_init_common(const CarlaHostStandalone& standalone, Carl if (standalone.engineOptions.pathJSFX != nullptr) engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_JSFX, standalone.engineOptions.pathJSFX); + if (standalone.engineOptions.pathCLAP != nullptr) + engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_CLAP, standalone.engineOptions.pathCLAP); + if (standalone.engineOptions.binaryDir != nullptr && standalone.engineOptions.binaryDir[0] != '\0') engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, standalone.engineOptions.binaryDir); else @@ -843,7 +849,7 @@ void carla_set_engine_option(CarlaHostHandle handle, EngineOption option, int va case CB::ENGINE_OPTION_PLUGIN_PATH: CARLA_SAFE_ASSERT_RETURN(value > CB::PLUGIN_NONE,); - CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_JSFX,); + CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_TYPE_COUNT,); CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); switch (value) @@ -888,6 +894,11 @@ void carla_set_engine_option(CarlaHostHandle handle, EngineOption option, int va delete[] shandle.engineOptions.pathJSFX; shandle.engineOptions.pathJSFX = carla_strdup_safe(valueStr); break; + case CB::PLUGIN_CLAP: + if (shandle.engineOptions.pathCLAP != nullptr) + delete[] shandle.engineOptions.pathCLAP; + shandle.engineOptions.pathCLAP = carla_strdup_safe(valueStr); + break; } break; diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index cc4876acd..a9149fa73 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -737,6 +737,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, switch (ptype) { case PLUGIN_NONE: + case PLUGIN_TYPE_COUNT: break; case PLUGIN_LADSPA: @@ -1424,6 +1425,9 @@ bool CarlaEngine::loadFile(const char* const filename) if (extension == "vst3") return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_VST3, filename, nullptr, nullptr, 0, nullptr); + if (extension == "clap") + return addPlugin(getBinaryTypeFromFile(filename), PLUGIN_CLAP, filename, nullptr, nullptr, 0, nullptr); + // ------------------------------------------------------------------- setLastError("Unknown file extension"); @@ -2048,7 +2052,7 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch break; case ENGINE_OPTION_PLUGIN_PATH: CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,); - CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_JSFX,); + CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_TYPE_COUNT,); switch (value) { @@ -2116,6 +2120,14 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch else pData->options.pathJSFX = nullptr; break; + case PLUGIN_CLAP: + if (pData->options.pathCLAP != nullptr) + delete[] pData->options.pathCLAP; + if (valueStr != nullptr) + pData->options.pathCLAP = carla_strdup_safe(valueStr); + else + pData->options.pathCLAP = nullptr; + break; default: return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type", option, EngineOption2Str(option), value, valueStr); @@ -2419,6 +2431,7 @@ void CarlaEngine::saveProjectInternal(water::MemoryOutputStream& outStream) cons outSettings << " " << xmlSafeString(options.pathSF2, true) << "\n"; outSettings << " " << xmlSafeString(options.pathSFZ, true) << "\n"; outSettings << " " << xmlSafeString(options.pathJSFX, true) << "\n"; + outSettings << " " << xmlSafeString(options.pathCLAP, true) << "\n"; } outSettings << " \n"; @@ -2841,6 +2854,12 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw value = PLUGIN_JSFX; valueStr = text.toRawUTF8(); } + else if (tag == "CLAP_PATH") + { + option = ENGINE_OPTION_PLUGIN_PATH; + value = PLUGIN_CLAP; + valueStr = text.toRawUTF8(); + } } if (option == -1) @@ -2853,7 +2872,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw continue; if (tag == "VST3_PATH" || tag == "AU_PATH") continue; - if (tag == "SF2_PATH" || tag == "SFZ_PATH" || tag == "JSFX_PATH") + if (tag == "SF2_PATH" || tag == "SFZ_PATH" || tag == "JSFX_PATH" || tag == "CLAP_PATH") continue; // hmm something is wrong.. @@ -3040,7 +3059,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw const void* extraStuff = nullptr; static const char kTrue[] = "true"; - const PluginType ptype(getPluginTypeFromString(stateSave.type)); + const PluginType ptype = getPluginTypeFromString(stateSave.type); switch (ptype) { @@ -3054,6 +3073,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw case PLUGIN_VST3: case PLUGIN_SFZ: case PLUGIN_JSFX: + case PLUGIN_CLAP: if (stateSave.binary != nullptr && stateSave.binary[0] != '\0' && ! (File::isAbsolutePath(stateSave.binary) && File(stateSave.binary).exists())) { @@ -3068,6 +3088,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw case PLUGIN_SF2: searchPath = pData->options.pathSF2; break; case PLUGIN_SFZ: searchPath = pData->options.pathSFZ; break; case PLUGIN_JSFX: searchPath = pData->options.pathJSFX; break; + case PLUGIN_CLAP: searchPath = pData->options.pathCLAP; break; default: searchPath = nullptr; break; } @@ -3089,6 +3110,7 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc, const bool alw case PLUGIN_SF2: searchPath = std::getenv("SF2_PATH"); break; case PLUGIN_SFZ: searchPath = std::getenv("SFZ_PATH"); break; case PLUGIN_JSFX: searchPath = std::getenv("JSFX_PATH"); break; + case PLUGIN_CLAP: searchPath = std::getenv("CLAP_PATH"); break; default: searchPath = nullptr; break; } diff --git a/source/backend/engine/CarlaEngineData.cpp b/source/backend/engine/CarlaEngineData.cpp index 9af889c9f..a2fb54608 100644 --- a/source/backend/engine/CarlaEngineData.cpp +++ b/source/backend/engine/CarlaEngineData.cpp @@ -239,6 +239,7 @@ EngineOptions::EngineOptions() noexcept pathSF2(nullptr), pathSFZ(nullptr), pathJSFX(nullptr), + pathCLAP(nullptr), binaryDir(nullptr), resourceDir(nullptr), clientNamePrefix(nullptr), @@ -312,6 +313,11 @@ EngineOptions::~EngineOptions() noexcept delete[] pathJSFX; pathJSFX = nullptr; } + if (pathCLAP != nullptr) + { + delete[] pathCLAP; + pathCLAP = nullptr; + } if (binaryDir != nullptr) { delete[] binaryDir; diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py index 4ea7db76f..12ba51a44 100644 --- a/source/frontend/carla_host.py +++ b/source/frontend/carla_host.py @@ -3421,6 +3421,7 @@ def setEngineSettings(host, oscPort = None): SF2_PATH = settings.value(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH, list) SFZ_PATH = settings.value(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH, list) JSFX_PATH = settings.value(CARLA_KEY_PATHS_JSFX, CARLA_DEFAULT_JSFX_PATH, list) + CLAP_PATH = settings.value(CARLA_KEY_PATHS_CLAP, CARLA_DEFAULT_CLAP_PATH, list) host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LADSPA, splitter.join(LADSPA_PATH)) host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_DSSI, splitter.join(DSSI_PATH)) @@ -3430,6 +3431,7 @@ def setEngineSettings(host, oscPort = None): host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SF2, splitter.join(SF2_PATH)) host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SFZ, splitter.join(SFZ_PATH)) host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_JSFX, splitter.join(JSFX_PATH)) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_CLAP, splitter.join(CLAP_PATH)) # -------------------------------------------------------------------------------------------------------- # don't continue if plugin diff --git a/source/frontend/carla_settings.py b/source/frontend/carla_settings.py index 76a2c7fd2..4038d3e5b 100755 --- a/source/frontend/carla_settings.py +++ b/source/frontend/carla_settings.py @@ -46,7 +46,8 @@ from carla_backend import ( PLUGIN_VST3, PLUGIN_SF2, PLUGIN_SFZ, - PLUGIN_JSFX + PLUGIN_JSFX, + PLUGIN_CLAP, ) from carla_shared import ( @@ -99,6 +100,7 @@ from carla_shared import ( CARLA_KEY_PATHS_SF2, CARLA_KEY_PATHS_SFZ, CARLA_KEY_PATHS_JSFX, + CARLA_KEY_PATHS_CLAP, CARLA_KEY_WINE_EXECUTABLE, CARLA_KEY_WINE_AUTO_PREFIX, CARLA_KEY_WINE_FALLBACK_PREFIX, @@ -174,6 +176,7 @@ from carla_shared import ( CARLA_DEFAULT_SF2_PATH, CARLA_DEFAULT_SFZ_PATH, CARLA_DEFAULT_JSFX_PATH, + CARLA_DEFAULT_CLAP_PATH, getAndSetPath, getIcon, fontMetricsHorizontalAdvance, @@ -511,6 +514,7 @@ class CarlaSettingsW(QDialog): PLUGINPATH_INDEX_SF2 = 5 PLUGINPATH_INDEX_SFZ = 6 PLUGINPATH_INDEX_JSFX = 7 + PLUGINPATH_INDEX_CLAP = 8 # Single and Multiple client mode is only for JACK, # but we still want to match QComboBox index to backend defines, @@ -640,6 +644,7 @@ class CarlaSettingsW(QDialog): self.ui.lw_sf2.currentRowChanged.connect(self.slot_pluginPathRowChanged) self.ui.lw_sfz.currentRowChanged.connect(self.slot_pluginPathRowChanged) self.ui.lw_jsfx.currentRowChanged.connect(self.slot_pluginPathRowChanged) + self.ui.lw_clap.currentRowChanged.connect(self.slot_pluginPathRowChanged) self.ui.b_filepaths_add.clicked.connect(self.slot_addFilePath) self.ui.b_filepaths_remove.clicked.connect(self.slot_removeFilePath) @@ -666,6 +671,7 @@ class CarlaSettingsW(QDialog): self.ui.lw_sf2.setCurrentRow(0) self.ui.lw_sfz.setCurrentRow(0) self.ui.lw_jsfx.setCurrentRow(0) + self.ui.lw_clap.setCurrentRow(0) self.ui.lw_files_audio.setCurrentRow(0) self.ui.lw_files_midi.setCurrentRow(0) @@ -877,6 +883,7 @@ class CarlaSettingsW(QDialog): sf2s = settings.value(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH, list) sfzs = settings.value(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH, list) jsfxs = settings.value(CARLA_KEY_PATHS_JSFX, CARLA_DEFAULT_JSFX_PATH, list) + claps = settings.value(CARLA_KEY_PATHS_CLAP, CARLA_DEFAULT_CLAP_PATH, list) ladspas.sort() dssis.sort() @@ -886,6 +893,7 @@ class CarlaSettingsW(QDialog): sf2s.sort() sfzs.sort() jsfxs.sort() + claps.sort() for ladspa in ladspas: if not ladspa: @@ -927,6 +935,11 @@ class CarlaSettingsW(QDialog): continue self.ui.lw_jsfx.addItem(jsfx) + for clap in claps: + if not clap: + continue + self.ui.lw_clap.addItem(clap) + # ------------------------------------------------------------------------------------------------------------- # Wine @@ -1098,6 +1111,7 @@ class CarlaSettingsW(QDialog): sf2s = [] sfzs = [] jsfxs = [] + claps = [] for i in range(self.ui.lw_ladspa.count()): ladspas.append(self.ui.lw_ladspa.item(i).text()) @@ -1123,6 +1137,9 @@ class CarlaSettingsW(QDialog): for i in range(self.ui.lw_jsfx.count()): jsfxs.append(self.ui.lw_jsfx.item(i).text()) + for i in range(self.ui.lw_clap.count()): + claps.append(self.ui.lw_clap.item(i).text()) + self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LADSPA, splitter.join(ladspas)) self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_DSSI, splitter.join(dssis)) self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, splitter.join(lv2s)) @@ -1131,6 +1148,7 @@ class CarlaSettingsW(QDialog): self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SF2, splitter.join(sf2s)) self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SFZ, splitter.join(sfzs)) self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_JSFX, splitter.join(jsfxs)) + self.host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_CLAP, splitter.join(claps)) settings.setValue(CARLA_KEY_PATHS_LADSPA, ladspas) settings.setValue(CARLA_KEY_PATHS_DSSI, dssis) @@ -1140,6 +1158,7 @@ class CarlaSettingsW(QDialog): settings.setValue(CARLA_KEY_PATHS_SF2, sf2s) settings.setValue(CARLA_KEY_PATHS_SFZ, sfzs) settings.setValue(CARLA_KEY_PATHS_JSFX, jsfxs) + settings.setValue(CARLA_KEY_PATHS_CLAP, claps) # ------------------------------------------------------------------------------------------------------------- # Wine @@ -1337,6 +1356,16 @@ class CarlaSettingsW(QDialog): continue self.ui.lw_jsfx.addItem(path) + elif curIndex == self.PLUGINPATH_INDEX_CLAP: + paths = CARLA_DEFAULT_CLAP_PATH + paths.sort() + self.ui.lw_clap.clear() + + for path in paths: + if not path: + continue + self.ui.lw_clap.addItem(path) + # ------------------------------------------------------------------------------------------------------------- # Wine @@ -1467,6 +1496,8 @@ class CarlaSettingsW(QDialog): self.ui.lw_sfz.addItem(newPath) elif curIndex == self.PLUGINPATH_INDEX_JSFX: self.ui.lw_jsfx.addItem(newPath) + elif curIndex == self.PLUGINPATH_INDEX_CLAP: + self.ui.lw_clap.addItem(newPath) @pyqtSlot() def slot_removePluginPath(self): @@ -1488,6 +1519,8 @@ class CarlaSettingsW(QDialog): self.ui.lw_sfz.takeItem(self.ui.lw_sfz.currentRow()) elif curIndex == self.PLUGINPATH_INDEX_JSFX: self.ui.lw_jsfx.takeItem(self.ui.lw_jsfx.currentRow()) + elif curIndex == self.PLUGINPATH_INDEX_CLAP: + self.ui.lw_clap.takeItem(self.ui.lw_clap.currentRow()) @pyqtSlot() def slot_changePluginPath(self): @@ -1509,6 +1542,8 @@ class CarlaSettingsW(QDialog): currentPath = self.ui.lw_sfz.currentItem().text() elif curIndex == self.PLUGINPATH_INDEX_JSFX: currentPath = self.ui.lw_jsfx.currentItem().text() + elif curIndex == self.PLUGINPATH_INDEX_CLAP: + currentPath = self.ui.lw_clap.currentItem().text() else: currentPath = "" @@ -1533,6 +1568,8 @@ class CarlaSettingsW(QDialog): self.ui.lw_sfz.currentItem().setText(newPath) elif curIndex == self.PLUGINPATH_INDEX_JSFX: self.ui.lw_jsfx.currentItem().setText(newPath) + elif curIndex == self.PLUGINPATH_INDEX_CLAP: + self.ui.lw_clap.currentItem().setText(newPath) # ----------------------------------------------------------------------------------------------------------------- @@ -1554,6 +1591,8 @@ class CarlaSettingsW(QDialog): row = self.ui.lw_sfz.currentRow() elif index == self.PLUGINPATH_INDEX_JSFX: row = self.ui.lw_jsfx.currentRow() + elif index == self.PLUGINPATH_INDEX_CLAP: + row = self.ui.lw_clap.currentRow() else: row = -1 diff --git a/source/utils/CarlaBackendUtils.hpp b/source/utils/CarlaBackendUtils.hpp index 22784a015..f71c12c8b 100644 --- a/source/utils/CarlaBackendUtils.hpp +++ b/source/utils/CarlaBackendUtils.hpp @@ -131,6 +131,8 @@ const char* PluginType2Str(const PluginType type) noexcept return "PLUGIN_JSFX"; case PLUGIN_CLAP: return "PLUGIN_CLAP"; + case PLUGIN_TYPE_COUNT: + break; } carla_stderr("CarlaBackend::PluginType2Str(%i) - invalid type", type); @@ -604,6 +606,8 @@ const char* getPluginTypeAsString(const PluginType type) noexcept return "JSFX"; case PLUGIN_CLAP: return "CLAP"; + case PLUGIN_TYPE_COUNT: + break; } carla_stderr("CarlaBackend::getPluginTypeAsString(%i) - invalid type", type); diff --git a/source/utils/CarlaStateUtils.cpp b/source/utils/CarlaStateUtils.cpp index 12ba80faa..071662f2a 100644 --- a/source/utils/CarlaStateUtils.cpp +++ b/source/utils/CarlaStateUtils.cpp @@ -594,9 +594,12 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const infoXml << " \n"; break; case PLUGIN_AU: - case PLUGIN_CLAP: infoXml << " " << xmlSafeString(label, true) << "\n"; break; + case PLUGIN_CLAP: + infoXml << " " << xmlSafeString(binary, true) << "\n"; + infoXml << " " << xmlSafeString(label, true) << "\n"; + break; case PLUGIN_DLS: case PLUGIN_GIG: case PLUGIN_SF2: @@ -611,6 +614,8 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const infoXml << " " << xmlSafeString(binary, true) << "\n"; infoXml << " " << xmlSafeString(label, true) << "\n"; break; + case PLUGIN_TYPE_COUNT: + break; } infoXml << " \n\n";