From 1d24af0f28318f51f00050c8d1c64819f39e42f4 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 2 Sep 2023 17:49:38 +0200 Subject: [PATCH] Pass plugin path settings to auto-discovery Signed-off-by: falkTX --- source/backend/CarlaBackend.h | 1 - source/backend/CarlaUtils.h | 194 ++++++------- source/backend/plugin/CarlaPluginBridge.cpp | 52 ++-- source/backend/utils/PluginDiscovery.cpp | 137 ++++++++- source/frontend/CarlaFrontend.h | 32 ++- source/frontend/carla_frontend.py | 43 ++- source/frontend/carla_host.py | 266 ++++++++++++------ source/frontend/carla_shared.py | 4 + .../frontend/pluginlist/pluginlistdialog.cpp | 111 +++++--- .../frontend/pluginlist/pluginlistdialog.hpp | 12 +- 10 files changed, 576 insertions(+), 276 deletions(-) diff --git a/source/backend/CarlaBackend.h b/source/backend/CarlaBackend.h index 1c3e81430..33d9a51c4 100644 --- a/source/backend/CarlaBackend.h +++ b/source/backend/CarlaBackend.h @@ -644,7 +644,6 @@ typedef enum { /*! * VST3 plugin. - * @note Windows and MacOS only */ PLUGIN_VST3 = 6, diff --git a/source/backend/CarlaUtils.h b/source/backend/CarlaUtils.h index 0de117c37..2610d187b 100644 --- a/source/backend/CarlaUtils.h +++ b/source/backend/CarlaUtils.h @@ -22,6 +22,7 @@ #ifdef __cplusplus using CARLA_BACKEND_NAMESPACE::BinaryType; +using CARLA_BACKEND_NAMESPACE::EngineOption; using CARLA_BACKEND_NAMESPACE::PluginCategory; using CARLA_BACKEND_NAMESPACE::PluginType; #endif @@ -35,100 +36,6 @@ using CARLA_BACKEND_NAMESPACE::PluginType; * @{ */ -/*! - * Information about a cached plugin. - * @see carla_get_cached_plugin_info() - */ -typedef struct _CarlaCachedPluginInfo { - /*! - * Wherever the data in this struct is valid. - * For performance reasons, plugins are only checked on request, - * and as such, the count vs number of really valid plugins might not match. - * Use this field to skip on plugins which cannot be loaded in Carla. - */ - bool valid; - - /*! - * Plugin category. - */ - PluginCategory category; - - /*! - * Plugin hints. - * @see PluginHints - */ - uint hints; - - /*! - * Number of audio inputs. - */ - uint32_t audioIns; - - /*! - * Number of audio outputs. - */ - uint32_t audioOuts; - - /*! - * Number of CV inputs. - */ - uint32_t cvIns; - - /*! - * Number of CV outputs. - */ - uint32_t cvOuts; - - /*! - * Number of MIDI inputs. - */ - uint32_t midiIns; - - /*! - * Number of MIDI outputs. - */ - uint32_t midiOuts; - - /*! - * Number of input parameters. - */ - uint32_t parameterIns; - - /*! - * Number of output parameters. - */ - uint32_t parameterOuts; - - /*! - * Plugin name. - */ - const char* name; - - /*! - * Plugin label. - */ - const char* label; - - /*! - * Plugin author/maker. - */ - const char* maker; - - /*! - * Plugin copyright/license. - */ - const char* copyright; - -#ifdef __cplusplus - /*! - * C++ constructor. - */ - CARLA_API _CarlaCachedPluginInfo() noexcept; - CARLA_DECLARE_NON_COPYABLE(_CarlaCachedPluginInfo) -#endif - -} CarlaCachedPluginInfo; - /* -------------------------------------------------------------------------------------------------------------------- * plugin discovery */ @@ -330,9 +237,108 @@ CARLA_PLUGIN_EXPORT void carla_plugin_discovery_skip(CarlaPluginDiscoveryHandle */ CARLA_PLUGIN_EXPORT void carla_plugin_discovery_stop(CarlaPluginDiscoveryHandle handle); +/*! + * Set a plugin discovery setting, to be applied globally. + */ +CARLA_PLUGIN_EXPORT void carla_plugin_discovery_set_option(EngineOption option, int value, const char* valueStr); + /* -------------------------------------------------------------------------------------------------------------------- * cached plugins */ +/*! + * Information about a cached plugin. + * @see carla_get_cached_plugin_info() + */ +typedef struct _CarlaCachedPluginInfo { + /*! + * Wherever the data in this struct is valid. + * For performance reasons, plugins are only checked on request, + * and as such, the count vs number of really valid plugins might not match. + * Use this field to skip on plugins which cannot be loaded in Carla. + */ + bool valid; + + /*! + * Plugin category. + */ + PluginCategory category; + + /*! + * Plugin hints. + * @see PluginHints + */ + uint hints; + + /*! + * Number of audio inputs. + */ + uint32_t audioIns; + + /*! + * Number of audio outputs. + */ + uint32_t audioOuts; + + /*! + * Number of CV inputs. + */ + uint32_t cvIns; + + /*! + * Number of CV outputs. + */ + uint32_t cvOuts; + + /*! + * Number of MIDI inputs. + */ + uint32_t midiIns; + + /*! + * Number of MIDI outputs. + */ + uint32_t midiOuts; + + /*! + * Number of input parameters. + */ + uint32_t parameterIns; + + /*! + * Number of output parameters. + */ + uint32_t parameterOuts; + + /*! + * Plugin name. + */ + const char* name; + + /*! + * Plugin label. + */ + const char* label; + + /*! + * Plugin author/maker. + */ + const char* maker; + + /*! + * Plugin copyright/license. + */ + const char* copyright; + +#ifdef __cplusplus + /*! + * C++ constructor. + */ + CARLA_API _CarlaCachedPluginInfo() noexcept; + CARLA_DECLARE_NON_COPYABLE(_CarlaCachedPluginInfo) +#endif + +} CarlaCachedPluginInfo; + /*! * Get how many cached plugins are available. * Internal and LV2 plugin formats are cached and need to be discovered via this function. diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index bc1dc99f8..9dda057ee 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -52,6 +52,7 @@ static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; // -------------------------------------------------------------------------------------------------------------------- +#ifndef CARLA_OS_WIN static String findWinePrefix(const String filename, const int recursionLimit = 10) { if (recursionLimit == 0 || filename.length() < 5 || ! filename.contains("/")) @@ -64,6 +65,7 @@ static String findWinePrefix(const String filename, const int recursionLimit = 1 return findWinePrefix(path, recursionLimit-1); } +#endif // -------------------------------------------------------------------------------------------------------------------- @@ -128,15 +130,15 @@ public: fBridgeBinary(), fLabel(), fShmIds(), -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN fWinePrefix(), -#endif + #endif fProcess() {} void setData( -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN const char* const winePrefix, -#endif + #endif const char* const binaryArchName, const char* const bridgeBinary, const char* const label, @@ -146,9 +148,9 @@ public: CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',); CARLA_SAFE_ASSERT(! isThreadRunning()); -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN fWinePrefix = winePrefix; -#endif + #endif fBinaryArchName = binaryArchName; fBridgeBinary = bridgeBinary; fShmIds = shmIds; @@ -190,7 +192,7 @@ protected: StringArray arguments; -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN // start with "wine" if needed if (fBridgeBinary.endsWithIgnoreCase(".exe")) { @@ -212,7 +214,7 @@ protected: arguments.add(wineCMD); } -#endif + #endif // setup binary arch ChildProcess::Type childType; @@ -245,10 +247,10 @@ protected: { const ScopedEngineEnvironmentLocker _seel(kEngine); -#ifdef CARLA_OS_LINUX + #ifdef CARLA_OS_LINUX const CarlaScopedEnvVar sev1("LD_LIBRARY_PATH", nullptr); const CarlaScopedEnvVar sev2("LD_PRELOAD", nullptr); -#endif + #endif carla_setenv("ENGINE_OPTION_FORCE_STEREO", bool2str(options.forceStereo)); carla_setenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES", bool2str(options.preferPluginBridges)); @@ -318,7 +320,7 @@ protected: carla_setenv("ENGINE_BRIDGE_SHM_IDS", fShmIds.toRawUTF8()); -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN if (fWinePrefix.isNotEmpty()) { carla_setenv("WINEDEBUG", "-all"); @@ -354,12 +356,12 @@ protected: carla_stdout("Using WINEPREFIX '%s', without RT priorities", fWinePrefix.toRawUTF8()); } } -#endif + #endif carla_stdout("Starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64, fBridgeBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId()); -#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH const File projFolder(kEngine->getCurrentProjectFolder()); if (projFolder.isNotNull()) @@ -370,7 +372,7 @@ protected: oldFolder.setAsCurrentWorkingDirectory(); } else -#endif + #endif { started = fProcess->start(arguments, childType); } @@ -427,9 +429,9 @@ private: String fBridgeBinary; String fLabel; String fShmIds; -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN String fWinePrefix; -#endif + #endif CarlaScopedPointer fProcess; @@ -460,9 +462,9 @@ public: fShmRtClientControl(), fShmNonRtClientControl(), fShmNonRtServerControl(), -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN fWinePrefix(), -#endif + #endif fReceivingParamText(), fInfo(), fUniqueId(0), @@ -478,11 +480,11 @@ public: { carla_debug("CarlaPluginBridge::~CarlaPluginBridge()"); -#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH + #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH // close UI if (pData->hints & PLUGIN_HAS_CUSTOM_UI) pData->transientTryCounter = 0; -#endif + #endif pData->singleMutex.lock(); pData->masterMutex.lock(); @@ -2754,7 +2756,7 @@ public: return false; } -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN // --------------------------------------------------------------- // set wine prefix @@ -2767,7 +2769,7 @@ public: if (fWinePrefix.isEmpty()) { - const char* const envWinePrefix(std::getenv("WINEPREFIX")); + const char* const envWinePrefix = std::getenv("WINEPREFIX"); if (envWinePrefix != nullptr && envWinePrefix[0] != '\0') fWinePrefix = envWinePrefix; @@ -2777,7 +2779,7 @@ public: fWinePrefix = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine"; } } -#endif + #endif // --------------------------------------------------------------- // init bridge thread @@ -2914,9 +2916,9 @@ private: BridgeNonRtClientControl fShmNonRtClientControl; BridgeNonRtServerControl fShmNonRtServerControl; -#ifndef CARLA_OS_WIN + #ifndef CARLA_OS_WIN String fWinePrefix; -#endif + #endif class ReceivingParamText { public: diff --git a/source/backend/utils/PluginDiscovery.cpp b/source/backend/utils/PluginDiscovery.cpp index 9cb4adeb1..dac350162 100644 --- a/source/backend/utils/PluginDiscovery.cpp +++ b/source/backend/utils/PluginDiscovery.cpp @@ -33,6 +33,23 @@ namespace CB = CARLA_BACKEND_NAMESPACE; // -------------------------------------------------------------------------------------------------------------------- +#ifndef CARLA_OS_WIN +static water::String findWinePrefix(const water::String filename, const int recursionLimit = 10) +{ + if (recursionLimit == 0 || filename.length() < 5 || ! filename.contains("/")) + return ""; + + const water::String path(filename.upToLastOccurrenceOf("/", false, false)); + + if (water::File(path + "/dosdevices").isDirectory()) + return path; + + return findWinePrefix(path, recursionLimit-1); +} +#endif + +// -------------------------------------------------------------------------------------------------------------------- + static const char* const gPluginsDiscoveryNullCharPtr = ""; _CarlaPluginDiscoveryMetadata::_CarlaPluginDiscoveryMetadata() noexcept @@ -61,6 +78,24 @@ _CarlaPluginDiscoveryInfo::_CarlaPluginDiscoveryInfo() noexcept // -------------------------------------------------------------------------------------------------------------------- +struct CarlaPluginDiscoveryOptions { + #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) + struct { + bool autoPrefix; + CarlaString executable; + CarlaString fallbackPrefix; + } wine; + #endif + + static CarlaPluginDiscoveryOptions& getInstance() noexcept + { + static CarlaPluginDiscoveryOptions instance; + return instance; + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + class CarlaPluginDiscovery : private CarlaPipeServer { public: @@ -367,36 +402,59 @@ private: void start() { + using water::File; + using water::String; + fLastMessageTime = carla_gettime_ms(); fPluginsFoundInBinary = false; fNextSha1Sum.clear(); - const char* helperTool; + #ifndef CARLA_OS_WIN + const CarlaPluginDiscoveryOptions& options(CarlaPluginDiscoveryOptions::getInstance()); + + String helperTool; + switch (fBinaryType) { - #ifndef CARLA_OS_WIN case CB::BINARY_WIN32: - helperTool = "wine"; + if (options.wine.executable.isNotEmpty()) + helperTool = options.wine.executable.buffer(); + else + helperTool = "wine"; break; + case CB::BINARY_WIN64: - helperTool = "wine64"; + if (options.wine.executable.isNotEmpty()) + { + helperTool = options.wine.executable.buffer(); + + if (helperTool[0] == CARLA_OS_SEP && File(helperTool + "64").existsAsFile()) + helperTool += "64"; + } + else + { + helperTool = "wine"; + } break; - #endif + default: - helperTool = nullptr; break; } + #endif if (fBinaries.empty()) { - startPipeServer(helperTool, fDiscoveryTool, - getPluginTypeAsString(fPluginType), - ":all"); + #ifndef CARLA_OS_WIN + if (helperTool.isNotEmpty()) + startPipeServer(helperTool.toRawUTF8(), fDiscoveryTool, getPluginTypeAsString(fPluginType), ":all"); + else + #endif + startPipeServer(fDiscoveryTool, getPluginTypeAsString(fPluginType), ":all"); } else { - const water::File file(fBinaries[fBinaryIndex]); - const water::String filename(file.getFullPathName()); + const File file(fBinaries[fBinaryIndex]); + const String filename(file.getFullPathName()); if (fCheckCacheCallback != nullptr) { @@ -410,8 +468,36 @@ private: } } + #ifndef CARLA_OS_WIN + String winePrefix; + + if (options.wine.autoPrefix) + winePrefix = findWinePrefix(filename); + + if (winePrefix.isEmpty()) + { + const char* const envWinePrefix = std::getenv("WINEPREFIX"); + + if (envWinePrefix != nullptr && envWinePrefix[0] != '\0') + winePrefix = envWinePrefix; + else if (options.wine.fallbackPrefix != nullptr && options.wine.fallbackPrefix[0] != '\0') + winePrefix = options.wine.fallbackPrefix.buffer(); + else + winePrefix = File::getSpecialLocation(File::userHomeDirectory).getFullPathName() + "/.wine"; + } + + const CarlaScopedEnvVar sev1("WINEDEBUG", "-all"); + const CarlaScopedEnvVar sev2("WINEPREFIX", winePrefix.toRawUTF8()); + #endif + carla_stdout("Scanning \"%s\"...", filename.toRawUTF8()); - startPipeServer(helperTool, fDiscoveryTool, getPluginTypeAsString(fPluginType), filename.toRawUTF8()); + + #ifndef CARLA_OS_WIN + if (helperTool.isNotEmpty()) + startPipeServer(helperTool.toRawUTF8(), fDiscoveryTool, getPluginTypeAsString(fPluginType), filename.toRawUTF8()); + else + #endif + startPipeServer(fDiscoveryTool, getPluginTypeAsString(fPluginType), filename.toRawUTF8()); } } @@ -696,4 +782,31 @@ void carla_plugin_discovery_stop(const CarlaPluginDiscoveryHandle handle) delete static_cast(handle); } +void carla_plugin_discovery_set_option(const EngineOption option, const int value, const char* const valueStr) +{ + switch (option) + { + #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) + case CB::ENGINE_OPTION_WINE_EXECUTABLE: + if (valueStr != nullptr && valueStr[0] != '\0') + CarlaPluginDiscoveryOptions::getInstance().wine.executable = valueStr; + else + CarlaPluginDiscoveryOptions::getInstance().wine.executable.clear(); + break; + case CB::ENGINE_OPTION_WINE_AUTO_PREFIX: + CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); + CarlaPluginDiscoveryOptions::getInstance().wine.autoPrefix = value != 0; + break; + case CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX: + if (valueStr != nullptr && valueStr[0] != '\0') + CarlaPluginDiscoveryOptions::getInstance().wine.fallbackPrefix = valueStr; + else + CarlaPluginDiscoveryOptions::getInstance().wine.fallbackPrefix.clear(); + break; + #endif + default: + break; + } +} + // -------------------------------------------------------------------------------------------------------------------- diff --git a/source/frontend/CarlaFrontend.h b/source/frontend/CarlaFrontend.h index 0b2221901..a703affef 100644 --- a/source/frontend/CarlaFrontend.h +++ b/source/frontend/CarlaFrontend.h @@ -20,6 +20,7 @@ #include "CarlaBackend.h" #ifdef __cplusplus +using CARLA_BACKEND_NAMESPACE::PluginType; extern "C" { #endif @@ -31,6 +32,15 @@ typedef struct { const char* labelSetup; } JackAppDialogResults; +typedef struct _HostSettings { + bool showPluginBridges; + bool showWineBridges; + bool useSystemIcons; + bool wineAutoPrefix; + const char* wineExecutable; + const char* wineFallbackPrefix; +} HostSettings; + typedef struct { uint build; uint type; @@ -55,20 +65,28 @@ struct PluginListDialog; // -------------------------------------------------------------------------------------------------------------------- -CARLA_API void +CARLA_PLUGIN_EXPORT void carla_frontend_createAndExecAboutJuceDialog(void* parent); -CARLA_API const JackAppDialogResults* +CARLA_PLUGIN_EXPORT const JackAppDialogResults* carla_frontend_createAndExecJackAppDialog(void* parent, const char* projectFilename); -CARLA_API PluginListDialog* -carla_frontend_createPluginListDialog(void* parent); +CARLA_PLUGIN_EXPORT PluginListDialog* +carla_frontend_createPluginListDialog(void* parent, const HostSettings* hostSettings); + +CARLA_PLUGIN_EXPORT void +carla_frontend_destroyPluginListDialog(PluginListDialog* dialog); + +// TODO get favorites + +CARLA_PLUGIN_EXPORT void +carla_frontend_setPluginListDialogPath(PluginListDialog* dialog, int ptype, const char* path); -CARLA_API const PluginListDialogResults* +CARLA_PLUGIN_EXPORT const PluginListDialogResults* carla_frontend_execPluginListDialog(PluginListDialog* dialog); -CARLA_API const PluginListDialogResults* -carla_frontend_createAndExecPluginListDialog(void* parent/*, const HostSettings& hostSettings*/); +// CARLA_PLUGIN_EXPORT const PluginListDialogResults* +// carla_frontend_createAndExecPluginListDialog(void* parent, const HostSettings* hostSettings); // -------------------------------------------------------------------------------------------------------------------- diff --git a/source/frontend/carla_frontend.py b/source/frontend/carla_frontend.py index 6d9381a8d..8b38c0dae 100644 --- a/source/frontend/carla_frontend.py +++ b/source/frontend/carla_frontend.py @@ -23,7 +23,7 @@ # Imports (ctypes) from ctypes import ( - c_bool, c_char, c_char_p, c_uint, c_uint64, c_void_p, cast, + c_bool, c_char, c_char_p, c_int, c_uint, c_uint64, c_void_p, cast, cdll, Structure, POINTER ) @@ -53,6 +53,16 @@ class JackApplicationDialogResults(Structure): ("labelSetup", c_char_p) ] +class HostSettings(Structure): + _fields_ = [ + ("showPluginBridges", c_bool), + ("showWineBridges", c_bool), + ("useSystemIcons", c_bool), + ("wineAutoPrefix", c_bool), + ("wineExecutable", c_char_p), + ("wineFallbackPrefix", c_char_p), + ] + class PluginListDialogResults(Structure): _fields_ = [ ("build", c_uint), @@ -87,15 +97,18 @@ class CarlaFrontendLib(): self.lib.carla_frontend_createAndExecJackAppDialog.argtypes = (c_void_p, c_char_p) self.lib.carla_frontend_createAndExecJackAppDialog.restype = POINTER(JackApplicationDialogResults) - self.lib.carla_frontend_createPluginListDialog.argtypes = (c_void_p,) + self.lib.carla_frontend_createPluginListDialog.argtypes = (c_void_p, POINTER(HostSettings)) self.lib.carla_frontend_createPluginListDialog.restype = c_void_p + self.lib.carla_frontend_destroyPluginListDialog.argtypes = (c_void_p,) + self.lib.carla_frontend_destroyPluginListDialog.restype = None + + self.lib.carla_frontend_setPluginListDialogPath.argtypes = (c_void_p, c_int, c_char_p) + self.lib.carla_frontend_setPluginListDialogPath.restype = None + self.lib.carla_frontend_execPluginListDialog.argtypes = (c_void_p,) self.lib.carla_frontend_execPluginListDialog.restype = POINTER(PluginListDialogResults) - self.lib.carla_frontend_createAndExecPluginListDialog.argtypes = (c_void_p,) - self.lib.carla_frontend_createAndExecPluginListDialog.restype = POINTER(PluginListDialogResults) - # -------------------------------------------------------------------------------------------------------- def createAndExecAboutJuceDialog(self, parent): @@ -105,13 +118,23 @@ class CarlaFrontendLib(): return structToDictOrNull(self.lib.carla_frontend_createAndExecJackAppDialog(unwrapinstance(parent), projectFilename.encode("utf-8"))) - def createPluginListDialog(self, parent, useSystemIcons): - return self.lib.carla_frontend_createPluginListDialog(unwrapinstance(parent)) + def createPluginListDialog(self, parent, hostSettings): + hostSettingsC = HostSettings() + hostSettingsC.showPluginBridges = hostSettings['showPluginBridges'] + hostSettingsC.showWineBridges = hostSettings['showWineBridges'] + hostSettingsC.useSystemIcons = hostSettings['useSystemIcons'] + hostSettingsC.wineAutoPrefix = hostSettings['wineAutoPrefix'] + hostSettingsC.wineExecutable = hostSettings['wineExecutable'].encode("utf-8") + hostSettingsC.wineFallbackPrefix = hostSettings['wineFallbackPrefix'].encode("utf-8") + return self.lib.carla_frontend_createPluginListDialog(unwrapinstance(parent), hostSettingsC) + + def destroyPluginListDialog(self, dialog): + self.lib.carla_frontend_destroyPluginListDialog(dialog) + + def setPluginListDialogPath(self, dialog, ptype, path): + self.lib.carla_frontend_setPluginListDialogPath(dialog, ptype, path.encode("utf-8")) def execPluginListDialog(self, dialog): return structToDictOrNull(self.lib.carla_frontend_execPluginListDialog(dialog)) - def createAndExecPluginListDialog(self, parent, useSystemIcons): - return structToDictOrNull(self.lib.carla_frontend_createAndExecPluginListDialog(unwrapinstance(parent))) - # ------------------------------------------------------------------------------------------------------------ diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py index b6bdd2b8b..614080ca0 100644 --- a/source/frontend/carla_host.py +++ b/source/frontend/carla_host.py @@ -931,10 +931,11 @@ class HostWindow(QMainWindow): @pyqtSlot() def slot_engineStart(self): - audioDriver = setEngineSettings(self.host) - firstInit = self.fFirstEngineInit + audioDriver = setEngineSettings(self.host, self.fSavedSettings) + firstInit = self.fFirstEngineInit self.fFirstEngineInit = False + self.ui.text_logs.appendPlainText("======= Starting engine =======") if self.host.engine_init(audioDriver, self.fClientName): @@ -953,9 +954,11 @@ class HostWindow(QMainWindow): audioError = self.host.get_last_error() if audioError: - QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s', possible reasons:\n%s" % (audioDriver, audioError))) + QMessageBox.critical(self, self.tr("Error"), + self.tr("Could not connect to Audio backend '%s', possible reasons:\n%s" % (audioDriver, audioError))) else: - QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver)) + QMessageBox.critical(self, self.tr("Error"), + self.tr("Could not connect to Audio backend '%s'" % audioDriver)) @pyqtSlot() def slot_engineStop(self, forced = False): @@ -1209,10 +1212,27 @@ class HostWindow(QMainWindow): def showAddPluginDialog(self): # TODO self.fHasLoadedLv2Plugins if self.fPluginListDialog is None: - self.fPluginListDialog = gCarla.felib.createPluginListDialog(self.fParentOrSelf, - self.fSavedSettings[CARLA_KEY_MAIN_SYSTEM_ICONS]) + hostSettings = { + 'showPluginBridges': self.fSavedSettings[CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES], + 'showWineBridges': self.fSavedSettings[CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES], + 'useSystemIcons': self.fSavedSettings[CARLA_KEY_MAIN_SYSTEM_ICONS], + 'wineAutoPrefix': self.fSavedSettings[CARLA_KEY_WINE_AUTO_PREFIX], + 'wineExecutable': self.fSavedSettings[CARLA_KEY_WINE_EXECUTABLE], + 'wineFallbackPrefix': self.fSavedSettings[CARLA_KEY_WINE_FALLBACK_PREFIX], + } + self.fPluginListDialog = d = gCarla.felib.createPluginListDialog(self.fParentOrSelf, hostSettings) + + gCarla.felib.setPluginListDialogPath(d, PLUGIN_LADSPA, self.fSavedSettings[CARLA_KEY_PATHS_LADSPA]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_DSSI, self.fSavedSettings[CARLA_KEY_PATHS_DSSI]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_LV2, self.fSavedSettings[CARLA_KEY_PATHS_LV2]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_VST2, self.fSavedSettings[CARLA_KEY_PATHS_VST2]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_VST3, self.fSavedSettings[CARLA_KEY_PATHS_VST3]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_SF2, self.fSavedSettings[CARLA_KEY_PATHS_SF2]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_SFZ, self.fSavedSettings[CARLA_KEY_PATHS_SFZ]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_JSFX, self.fSavedSettings[CARLA_KEY_PATHS_JSFX]) + gCarla.felib.setPluginListDialogPath(d, PLUGIN_CLAP, self.fSavedSettings[CARLA_KEY_PATHS_CLAP]) + ret = gCarla.felib.execPluginListDialog(self.fPluginListDialog) - print(ret) # TODO #if dialog.fFavoritePluginsChanged: @@ -1940,6 +1960,10 @@ class HostWindow(QMainWindow): def loadSettings(self, firstTime): settings = QSafeSettings() + if self.fPluginListDialog is not None: + gCarla.felib.destroyPluginListDialog(self.fPluginListDialog) + self.fPluginListDialog = None + if firstTime: geometry = settings.value("Geometry", QByteArray(), QByteArray) if not geometry.isNull(): @@ -1990,6 +2014,13 @@ class HostWindow(QMainWindow): # TODO - complete this oldSettings = self.fSavedSettings + if self.host.audioDriverForced is not None: + audioDriver = self.host.audioDriverForced + else: + audioDriver = settings.value(CARLA_KEY_ENGINE_AUDIO_DRIVER, CARLA_DEFAULT_AUDIO_DRIVER, str) + + audioDriverPrefix = CARLA_KEY_ENGINE_DRIVER_PREFIX + audioDriver + self.fSavedSettings = { CARLA_KEY_MAIN_PROJECT_FOLDER: settings.value(CARLA_KEY_MAIN_PROJECT_FOLDER, CARLA_DEFAULT_MAIN_PROJECT_FOLDER, str), CARLA_KEY_MAIN_CONFIRM_EXIT: settings.value(CARLA_KEY_MAIN_CONFIRM_EXIT, CARLA_DEFAULT_MAIN_CONFIRM_EXIT, bool), @@ -2010,6 +2041,51 @@ class HostWindow(QMainWindow): CARLA_KEY_CANVAS_FULL_REPAINTS: settings.value(CARLA_KEY_CANVAS_FULL_REPAINTS, CARLA_DEFAULT_CANVAS_FULL_REPAINTS, bool), CARLA_KEY_CUSTOM_PAINTING: (settings.value(CARLA_KEY_MAIN_USE_PRO_THEME, True, bool) and settings.value(CARLA_KEY_MAIN_PRO_THEME_COLOR, "Black", str).lower() == "black"), + + # engine + CARLA_KEY_ENGINE_AUDIO_DRIVER: audioDriver, + CARLA_KEY_ENGINE_AUDIO_DEVICE: settings.value(audioDriverPrefix+"/Device", "", str), + CARLA_KEY_ENGINE_BUFFER_SIZE: settings.value(audioDriverPrefix+"/BufferSize", CARLA_DEFAULT_AUDIO_BUFFER_SIZE, int), + CARLA_KEY_ENGINE_SAMPLE_RATE: settings.value(audioDriverPrefix+"/SampleRate", CARLA_DEFAULT_AUDIO_SAMPLE_RATE, int), + CARLA_KEY_ENGINE_TRIPLE_BUFFER: settings.value(audioDriverPrefix+"/TripleBuffer", CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER, bool), + + # file paths + CARLA_KEY_PATHS_AUDIO: splitter.join(settings.value(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO, list)), + CARLA_KEY_PATHS_MIDI: splitter.join(settings.value(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI, list)), + + # plugin paths + CARLA_KEY_PATHS_LADSPA: splitter.join(settings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH, list)), + CARLA_KEY_PATHS_DSSI: splitter.join(settings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH, list)), + CARLA_KEY_PATHS_LV2: splitter.join(settings.value(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH, list)), + CARLA_KEY_PATHS_VST2: splitter.join(settings.value(CARLA_KEY_PATHS_VST2, CARLA_DEFAULT_VST2_PATH, list)), + CARLA_KEY_PATHS_VST3: splitter.join(settings.value(CARLA_KEY_PATHS_VST3, CARLA_DEFAULT_VST3_PATH, list)), + CARLA_KEY_PATHS_SF2: splitter.join(settings.value(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH, list)), + CARLA_KEY_PATHS_SFZ: splitter.join(settings.value(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH, list)), + CARLA_KEY_PATHS_JSFX: splitter.join(settings.value(CARLA_KEY_PATHS_JSFX, CARLA_DEFAULT_JSFX_PATH, list)), + CARLA_KEY_PATHS_CLAP: splitter.join(settings.value(CARLA_KEY_PATHS_CLAP, CARLA_DEFAULT_CLAP_PATH, list)), + + # osc + CARLA_KEY_OSC_ENABLED: settings.value(CARLA_KEY_OSC_ENABLED, CARLA_DEFAULT_OSC_ENABLED, bool), + CARLA_KEY_OSC_TCP_PORT_ENABLED: settings.value(CARLA_KEY_OSC_TCP_PORT_ENABLED, CARLA_DEFAULT_OSC_TCP_PORT_ENABLED, bool), + CARLA_KEY_OSC_TCP_PORT_RANDOM: settings.value(CARLA_KEY_OSC_TCP_PORT_RANDOM, CARLA_DEFAULT_OSC_TCP_PORT_RANDOM, bool), + CARLA_KEY_OSC_TCP_PORT_NUMBER: settings.value(CARLA_KEY_OSC_TCP_PORT_NUMBER, CARLA_DEFAULT_OSC_TCP_PORT_NUMBER, int), + CARLA_KEY_OSC_UDP_PORT_ENABLED: settings.value(CARLA_KEY_OSC_UDP_PORT_ENABLED, CARLA_DEFAULT_OSC_UDP_PORT_ENABLED, bool), + CARLA_KEY_OSC_UDP_PORT_RANDOM: settings.value(CARLA_KEY_OSC_UDP_PORT_RANDOM, CARLA_DEFAULT_OSC_UDP_PORT_RANDOM, bool), + CARLA_KEY_OSC_UDP_PORT_NUMBER: settings.value(CARLA_KEY_OSC_UDP_PORT_NUMBER, CARLA_DEFAULT_OSC_UDP_PORT_NUMBER, int), + + # wine + CARLA_KEY_WINE_EXECUTABLE: settings.value(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE, str), + CARLA_KEY_WINE_AUTO_PREFIX: settings.value(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX, bool), + CARLA_KEY_WINE_FALLBACK_PREFIX: settings.value(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX, str), + CARLA_KEY_WINE_RT_PRIO_ENABLED: settings.value(CARLA_KEY_WINE_RT_PRIO_ENABLED, CARLA_DEFAULT_WINE_RT_PRIO_ENABLED, bool), + CARLA_KEY_WINE_BASE_RT_PRIO: settings.value(CARLA_KEY_WINE_BASE_RT_PRIO, CARLA_DEFAULT_WINE_BASE_RT_PRIO, int), + CARLA_KEY_WINE_SERVER_RT_PRIO: settings.value(CARLA_KEY_WINE_SERVER_RT_PRIO, CARLA_DEFAULT_WINE_SERVER_RT_PRIO, int), + + # experimental switches + CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES: + settings.value(CARLA_KEY_EXPERIMENTAL_PLUGIN_BRIDGES, CARLA_DEFAULT_EXPERIMENTAL_PLUGIN_BRIDGES, bool), + CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES: + settings.value(CARLA_KEY_EXPERIMENTAL_WINE_BRIDGES, CARLA_DEFAULT_EXPERIMENTAL_WINE_BRIDGES, bool), } if not self.host.isControl: @@ -2027,7 +2103,7 @@ class HostWindow(QMainWindow): self.fMiniCanvasUpdateTimeout = 1000 if self.fSavedSettings[CARLA_KEY_CANVAS_FANCY_EYE_CANDY] else 0 - setEngineSettings(self.host) + setEngineSettings(self.host, self.fSavedSettings) self.restartTimersIfNeeded() if oldSettings.get(CARLA_KEY_MAIN_CLASSIC_SKIN, None) not in (self.fSavedSettings[CARLA_KEY_MAIN_CLASSIC_SKIN], None): @@ -3386,67 +3462,104 @@ def setHostSettings(host): if not (NSM_URL and host.nsmOK): host.set_engine_option(ENGINE_OPTION_CLIENT_NAME_PREFIX, 0, gCarla.cnprefix) -# ------------------------------------------------------------------------------------------------------------ +# --------------------------------------------------------------------------------------------------------------------- # Set Engine settings according to carla preferences. Returns selected audio driver. -def setEngineSettings(host, oscPort = None): +def setEngineSettings(host, settings, oscPort = None): # kdevelop likes this :) if False: host = CarlaHostNull() - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # do nothing if control if host.isControl: return "Control" - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- + # fetch settings as needed - settings = QSafeSettings("falkTX", "Carla2") + if settings is None: + qsettings = QSafeSettings("falkTX", "Carla2") - # -------------------------------------------------------------------------------------------------------- + if host.audioDriverForced is not None: + audioDriver = host.audioDriverForced + else: + audioDriver = qsettings.value(CARLA_KEY_ENGINE_AUDIO_DRIVER, CARLA_DEFAULT_AUDIO_DRIVER, str) + + audioDriverPrefix = CARLA_KEY_ENGINE_DRIVER_PREFIX + audioDriver + + settings = { + # engine + CARLA_KEY_ENGINE_AUDIO_DRIVER: audioDriver, + CARLA_KEY_ENGINE_AUDIO_DEVICE: qsettings.value(audioDriverPrefix+"/Device", "", str), + CARLA_KEY_ENGINE_BUFFER_SIZE: qsettings.value(audioDriverPrefix+"/BufferSize", CARLA_DEFAULT_AUDIO_BUFFER_SIZE, int), + CARLA_KEY_ENGINE_SAMPLE_RATE: qsettings.value(audioDriverPrefix+"/SampleRate", CARLA_DEFAULT_AUDIO_SAMPLE_RATE, int), + CARLA_KEY_ENGINE_TRIPLE_BUFFER: qsettings.value(audioDriverPrefix+"/TripleBuffer", CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER, bool), + + # file paths + CARLA_KEY_PATHS_AUDIO: splitter.join(qsettings.value(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO, list)), + CARLA_KEY_PATHS_MIDI: splitter.join(qsettings.value(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI, list)), + + # plugin paths + CARLA_KEY_PATHS_LADSPA: splitter.join(qsettings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH, list)), + CARLA_KEY_PATHS_DSSI: splitter.join(qsettings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH, list)), + CARLA_KEY_PATHS_LV2: splitter.join(qsettings.value(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH, list)), + CARLA_KEY_PATHS_VST2: splitter.join(qsettings.value(CARLA_KEY_PATHS_VST2, CARLA_DEFAULT_VST2_PATH, list)), + CARLA_KEY_PATHS_VST3: splitter.join(qsettings.value(CARLA_KEY_PATHS_VST3, CARLA_DEFAULT_VST3_PATH, list)), + CARLA_KEY_PATHS_SF2: splitter.join(qsettings.value(CARLA_KEY_PATHS_SF2, CARLA_DEFAULT_SF2_PATH, list)), + CARLA_KEY_PATHS_SFZ: splitter.join(qsettings.value(CARLA_KEY_PATHS_SFZ, CARLA_DEFAULT_SFZ_PATH, list)), + CARLA_KEY_PATHS_JSFX: splitter.join(qsettings.value(CARLA_KEY_PATHS_JSFX, CARLA_DEFAULT_JSFX_PATH, list)), + CARLA_KEY_PATHS_CLAP: splitter.join(qsettings.value(CARLA_KEY_PATHS_CLAP, CARLA_DEFAULT_CLAP_PATH, list)), + + # osc + CARLA_KEY_OSC_ENABLED: qsettings.value(CARLA_KEY_OSC_ENABLED, CARLA_DEFAULT_OSC_ENABLED, bool), + CARLA_KEY_OSC_TCP_PORT_ENABLED: qsettings.value(CARLA_KEY_OSC_TCP_PORT_ENABLED, CARLA_DEFAULT_OSC_TCP_PORT_ENABLED, bool), + CARLA_KEY_OSC_TCP_PORT_RANDOM: qsettings.value(CARLA_KEY_OSC_TCP_PORT_RANDOM, CARLA_DEFAULT_OSC_TCP_PORT_RANDOM, bool), + CARLA_KEY_OSC_TCP_PORT_NUMBER: qsettings.value(CARLA_KEY_OSC_TCP_PORT_NUMBER, CARLA_DEFAULT_OSC_TCP_PORT_NUMBER, int), + CARLA_KEY_OSC_UDP_PORT_ENABLED: qsettings.value(CARLA_KEY_OSC_UDP_PORT_ENABLED, CARLA_DEFAULT_OSC_UDP_PORT_ENABLED, bool), + CARLA_KEY_OSC_UDP_PORT_RANDOM: qsettings.value(CARLA_KEY_OSC_UDP_PORT_RANDOM, CARLA_DEFAULT_OSC_UDP_PORT_RANDOM, bool), + CARLA_KEY_OSC_UDP_PORT_NUMBER: qsettings.value(CARLA_KEY_OSC_UDP_PORT_NUMBER, CARLA_DEFAULT_OSC_UDP_PORT_NUMBER, int), + + # wine + CARLA_KEY_WINE_EXECUTABLE: qsettings.value(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE, str), + CARLA_KEY_WINE_AUTO_PREFIX: qsettings.value(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX, bool), + CARLA_KEY_WINE_FALLBACK_PREFIX: qsettings.value(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX, str), + CARLA_KEY_WINE_RT_PRIO_ENABLED: qsettings.value(CARLA_KEY_WINE_RT_PRIO_ENABLED, CARLA_DEFAULT_WINE_RT_PRIO_ENABLED, bool), + CARLA_KEY_WINE_BASE_RT_PRIO: qsettings.value(CARLA_KEY_WINE_BASE_RT_PRIO, CARLA_DEFAULT_WINE_BASE_RT_PRIO, int), + CARLA_KEY_WINE_SERVER_RT_PRIO: qsettings.value(CARLA_KEY_WINE_SERVER_RT_PRIO, CARLA_DEFAULT_WINE_SERVER_RT_PRIO, int), + } + + # ----------------------------------------------------------------------------------------------------------------- # main settings setHostSettings(host) - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # file paths - FILE_PATH_AUDIO = settings.value(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO, list) - FILE_PATH_MIDI = settings.value(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI, list) + host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, settings[CARLA_KEY_PATHS_AUDIO]) + host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI, settings[CARLA_KEY_PATHS_MIDI]) - host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, splitter.join(FILE_PATH_AUDIO)) - host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI, splitter.join(FILE_PATH_MIDI)) - - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # plugin paths - LADSPA_PATH = settings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH, list) - DSSI_PATH = settings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH, list) - LV2_PATH = settings.value(CARLA_KEY_PATHS_LV2, CARLA_DEFAULT_LV2_PATH, list) - VST2_PATH = settings.value(CARLA_KEY_PATHS_VST2, CARLA_DEFAULT_VST2_PATH, list) - VST3_PATH = settings.value(CARLA_KEY_PATHS_VST3, CARLA_DEFAULT_VST3_PATH, list) - 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)) - host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, splitter.join(LV2_PATH)) - host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST2, splitter.join(VST2_PATH)) - host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST3, splitter.join(VST3_PATH)) - 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)) - - # -------------------------------------------------------------------------------------------------------- + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LADSPA, settings[CARLA_KEY_PATHS_LADSPA]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_DSSI, settings[CARLA_KEY_PATHS_DSSI]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2, settings[CARLA_KEY_PATHS_LV2]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST2, settings[CARLA_KEY_PATHS_VST2]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_VST3, settings[CARLA_KEY_PATHS_VST3]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SF2, settings[CARLA_KEY_PATHS_SF2]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_SFZ, settings[CARLA_KEY_PATHS_SFZ]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_JSFX, settings[CARLA_KEY_PATHS_JSFX]) + host.set_engine_option(ENGINE_OPTION_PLUGIN_PATH, PLUGIN_CLAP, settings[CARLA_KEY_PATHS_CLAP]) + + # ----------------------------------------------------------------------------------------------------------------- # don't continue if plugin if host.isPlugin: return "Plugin" - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # osc settings if oscPort is not None and isinstance(oscPort, int): @@ -3454,84 +3567,65 @@ def setEngineSettings(host, oscPort = None): portNumTCP = portNumUDP = oscPort else: - oscEnabled = settings.value(CARLA_KEY_OSC_ENABLED, CARLA_DEFAULT_OSC_ENABLED, bool) + oscEnabled = settings[CARLA_KEY_OSC_ENABLED] - if not settings.value(CARLA_KEY_OSC_TCP_PORT_ENABLED, CARLA_DEFAULT_OSC_TCP_PORT_ENABLED, bool): + if not settings[CARLA_KEY_OSC_TCP_PORT_ENABLED]: portNumTCP = -1 - elif settings.value(CARLA_KEY_OSC_TCP_PORT_RANDOM, CARLA_DEFAULT_OSC_TCP_PORT_RANDOM, bool): + elif settings[CARLA_KEY_OSC_TCP_PORT_RANDOM]: portNumTCP = 0 else: - portNumTCP = settings.value(CARLA_KEY_OSC_TCP_PORT_NUMBER, CARLA_DEFAULT_OSC_TCP_PORT_NUMBER, int) + portNumTCP = settings[CARLA_KEY_OSC_TCP_PORT_NUMBER] - if not settings.value(CARLA_KEY_OSC_UDP_PORT_ENABLED, CARLA_DEFAULT_OSC_UDP_PORT_ENABLED, bool): + if not settings[CARLA_KEY_OSC_UDP_PORT_ENABLED]: portNumUDP = -1 - elif settings.value(CARLA_KEY_OSC_UDP_PORT_RANDOM, CARLA_DEFAULT_OSC_UDP_PORT_RANDOM, bool): + elif settings[CARLA_KEY_OSC_UDP_PORT_RANDOM]: portNumUDP = 0 else: - portNumUDP = settings.value(CARLA_KEY_OSC_UDP_PORT_NUMBER, CARLA_DEFAULT_OSC_UDP_PORT_NUMBER, int) + portNumUDP = settings[CARLA_KEY_OSC_UDP_PORT_NUMBER] host.set_engine_option(ENGINE_OPTION_OSC_ENABLED, 1 if oscEnabled else 0, "") host.set_engine_option(ENGINE_OPTION_OSC_PORT_TCP, portNumTCP, "") host.set_engine_option(ENGINE_OPTION_OSC_PORT_UDP, portNumUDP, "") - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # wine settings - optWineExecutable = settings.value(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE, str) - optWineAutoPrefix = settings.value(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX, bool) - optWineFallbackPrefix = settings.value(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX, str) - optWineRtPrioEnabled = settings.value(CARLA_KEY_WINE_RT_PRIO_ENABLED, CARLA_DEFAULT_WINE_RT_PRIO_ENABLED, bool) - optWineBaseRtPrio = settings.value(CARLA_KEY_WINE_BASE_RT_PRIO, CARLA_DEFAULT_WINE_BASE_RT_PRIO, int) - optWineServerRtPrio = settings.value(CARLA_KEY_WINE_SERVER_RT_PRIO, CARLA_DEFAULT_WINE_SERVER_RT_PRIO, int) + host.set_engine_option(ENGINE_OPTION_WINE_EXECUTABLE, 0, settings[CARLA_KEY_WINE_EXECUTABLE]) + host.set_engine_option(ENGINE_OPTION_WINE_AUTO_PREFIX, 1 if settings[CARLA_KEY_WINE_AUTO_PREFIX] else 0, "") + host.set_engine_option(ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, os.path.expanduser(settings[CARLA_KEY_WINE_FALLBACK_PREFIX])) + host.set_engine_option(ENGINE_OPTION_WINE_RT_PRIO_ENABLED, 1 if settings[CARLA_KEY_WINE_RT_PRIO_ENABLED] else 0, "") + host.set_engine_option(ENGINE_OPTION_WINE_BASE_RT_PRIO, settings[CARLA_KEY_WINE_BASE_RT_PRIO], "") + host.set_engine_option(ENGINE_OPTION_WINE_SERVER_RT_PRIO, settings[CARLA_KEY_WINE_SERVER_RT_PRIO], "") - host.set_engine_option(ENGINE_OPTION_WINE_EXECUTABLE, 0, optWineExecutable) - host.set_engine_option(ENGINE_OPTION_WINE_AUTO_PREFIX, 1 if optWineAutoPrefix else 0, "") - host.set_engine_option(ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, os.path.expanduser(optWineFallbackPrefix)) - host.set_engine_option(ENGINE_OPTION_WINE_RT_PRIO_ENABLED, 1 if optWineRtPrioEnabled else 0, "") - host.set_engine_option(ENGINE_OPTION_WINE_BASE_RT_PRIO, optWineBaseRtPrio, "") - host.set_engine_option(ENGINE_OPTION_WINE_SERVER_RT_PRIO, optWineServerRtPrio, "") - - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # driver and device settings # driver name - if host.audioDriverForced is not None: - audioDriver = host.audioDriverForced - else: - try: - audioDriver = settings.value(CARLA_KEY_ENGINE_AUDIO_DRIVER, CARLA_DEFAULT_AUDIO_DRIVER, str) - except: - audioDriver = CARLA_DEFAULT_AUDIO_DRIVER - - # driver options - audioDevice = settings.value("%s%s/Device" % (CARLA_KEY_ENGINE_DRIVER_PREFIX, audioDriver), "", str) - audioBufferSize = settings.value("%s%s/BufferSize" % (CARLA_KEY_ENGINE_DRIVER_PREFIX, audioDriver), CARLA_DEFAULT_AUDIO_BUFFER_SIZE, int) - audioSampleRate = settings.value("%s%s/SampleRate" % (CARLA_KEY_ENGINE_DRIVER_PREFIX, audioDriver), CARLA_DEFAULT_AUDIO_SAMPLE_RATE, int) - audioTripleBuffer = settings.value("%s%s/TripleBuffer" % (CARLA_KEY_ENGINE_DRIVER_PREFIX, audioDriver), CARLA_DEFAULT_AUDIO_TRIPLE_BUFFER, bool) + audioDriver = settings[CARLA_KEY_ENGINE_AUDIO_DRIVER] # Only setup audio things if engine is not running if not host.is_engine_running(): host.set_engine_option(ENGINE_OPTION_AUDIO_DRIVER, 0, audioDriver) - host.set_engine_option(ENGINE_OPTION_AUDIO_DEVICE, 0, audioDevice) + host.set_engine_option(ENGINE_OPTION_AUDIO_DEVICE, 0, settings[CARLA_KEY_ENGINE_AUDIO_DEVICE]) if not audioDriver.startswith("JACK"): - host.set_engine_option(ENGINE_OPTION_AUDIO_BUFFER_SIZE, audioBufferSize, "") - host.set_engine_option(ENGINE_OPTION_AUDIO_SAMPLE_RATE, audioSampleRate, "") - host.set_engine_option(ENGINE_OPTION_AUDIO_TRIPLE_BUFFER, 1 if audioTripleBuffer else 0, "") + host.set_engine_option(ENGINE_OPTION_AUDIO_BUFFER_SIZE, settings[CARLA_KEY_ENGINE_BUFFER_SIZE], "") + host.set_engine_option(ENGINE_OPTION_AUDIO_SAMPLE_RATE, settings[CARLA_KEY_ENGINE_SAMPLE_RATE], "") + host.set_engine_option(ENGINE_OPTION_AUDIO_TRIPLE_BUFFER, 1 if settings[CARLA_KEY_ENGINE_TRIPLE_BUFFER] else 0, "") - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # fix things if needed if audioDriver != "JACK" and host.transportMode == ENGINE_TRANSPORT_MODE_JACK: host.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, ENGINE_TRANSPORT_MODE_INTERNAL, host.transportExtra) - # -------------------------------------------------------------------------------------------------------- + # ----------------------------------------------------------------------------------------------------------------- # return selected driver name return audioDriver -# ------------------------------------------------------------------------------------------------------------ +# --------------------------------------------------------------------------------------------------------------------- # Run Carla without showing UI def runHostWithoutUI(host): @@ -3564,7 +3658,7 @@ def runHostWithoutUI(host): # -------------------------------------------------------------------------------------------------------- # Init engine - audioDriver = setEngineSettings(host, oscPort) + audioDriver = setEngineSettings(host, None, oscPort) if not host.engine_init(audioDriver, "Carla"): print("Engine failed to initialize, possible reasons:\n%s" % host.get_last_error()) sys.exit(1) diff --git a/source/frontend/carla_shared.py b/source/frontend/carla_shared.py index de954e41c..e22b64ac6 100644 --- a/source/frontend/carla_shared.py +++ b/source/frontend/carla_shared.py @@ -204,6 +204,10 @@ CARLA_KEY_CANVAS_FULL_REPAINTS = "Canvas/FullRepaints" # bool CARLA_KEY_ENGINE_DRIVER_PREFIX = "Engine/Driver-" CARLA_KEY_ENGINE_AUDIO_DRIVER = "Engine/AudioDriver" # str +CARLA_KEY_ENGINE_AUDIO_DEVICE = "Engine/AudioDevice" # str +CARLA_KEY_ENGINE_BUFFER_SIZE = "Engine/BufferSize" # int +CARLA_KEY_ENGINE_SAMPLE_RATE = "Engine/SampleRate" # int +CARLA_KEY_ENGINE_TRIPLE_BUFFER = "Engine/TripleBuffer" # bool CARLA_KEY_ENGINE_PROCESS_MODE = "Engine/ProcessMode" # enum CARLA_KEY_ENGINE_TRANSPORT_MODE = "Engine/TransportMode" # enum CARLA_KEY_ENGINE_TRANSPORT_EXTRA = "Engine/TransportExtra" # str diff --git a/source/frontend/pluginlist/pluginlistdialog.cpp b/source/frontend/pluginlist/pluginlistdialog.cpp index a99baea1d..c58594aca 100644 --- a/source/frontend/pluginlist/pluginlistdialog.cpp +++ b/source/frontend/pluginlist/pluginlistdialog.cpp @@ -33,7 +33,6 @@ #include "CarlaBackendUtils.hpp" #include "CarlaJuceUtils.hpp" -#include "CarlaFrontend.h" #include "CarlaUtils.h" #include "CarlaString.hpp" @@ -42,22 +41,6 @@ CARLA_BACKEND_USE_NAMESPACE -// -------------------------------------------------------------------------------------------------------------------- -// Carla Settings keys - -#define CARLA_KEY_PATHS_LADSPA "Paths/LADSPA" -#define CARLA_KEY_PATHS_DSSI "Paths/DSSI" -#define CARLA_KEY_PATHS_LV2 "Paths/LV2" -#define CARLA_KEY_PATHS_VST2 "Paths/VST2" -#define CARLA_KEY_PATHS_VST3 "Paths/VST3" -#define CARLA_KEY_PATHS_CLAP "Paths/CLAP" -#define CARLA_KEY_PATHS_SF2 "Paths/SF2" -#define CARLA_KEY_PATHS_SFZ "Paths/SFZ" -#define CARLA_KEY_PATHS_JSFX "Paths/JSFX" - -// -------------------------------------------------------------------------------------------------------------------- -// Carla Settings defaults - // -------------------------------------------------------------------------------------------------------------------- // getenv with a fallback value if unset @@ -381,11 +364,11 @@ struct PluginPaths { static inline int fontMetricsHorizontalAdvance(const QFontMetrics& fontMetrics, const QString& string) { -#if QT_VERSION >= 0x50b00 + #if QT_VERSION >= 0x50b00 return fontMetrics.horizontalAdvance(string); -#else + #else return fontMetrics.width(string); -#endif + #endif } // -------------------------------------------------------------------------------------------------------------------- @@ -692,6 +675,7 @@ struct PluginListDialog::PrivateData { carla_plugin_discovery_stop(handle); } + #ifndef CARLA_FRONTEND_ONLY_EMBEDDABLE_PLUGINS bool nextTool() { if (handle != nullptr) @@ -771,6 +755,7 @@ struct PluginListDialog::PrivateData { tool += ".exe"; #endif } + #endif // CARLA_FRONTEND_ONLY_EMBEDDABLE_PLUGINS } discovery; PluginPaths paths; @@ -825,13 +810,20 @@ struct PluginListDialog::PrivateData { // -------------------------------------------------------------------------------------------------------------------- // Plugin List Dialog -PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings& hostSettings) +PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings* const hostSettings) : QDialog(parent), p(new PrivateData) { ui.setupUi(this); - // p->hostSettings = hostSettings; + // ---------------------------------------------------------------------------------------------------------------- + // Set-up global discovery options + + #ifndef CARLA_OS_WIN + carla_plugin_discovery_set_option(ENGINE_OPTION_WINE_AUTO_PREFIX, hostSettings->wineAutoPrefix, nullptr); + carla_plugin_discovery_set_option(ENGINE_OPTION_WINE_EXECUTABLE, 0, hostSettings->wineExecutable); + carla_plugin_discovery_set_option(ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, hostSettings->wineFallbackPrefix); + #endif // ---------------------------------------------------------------------------------------------------------------- // Set-up GUI @@ -917,7 +909,7 @@ PluginListDialog::PluginListDialog(QWidget* const parent, const HostSettings& ho // ---------------------------------------------------------------------------------------------------------------- // Set-up Icons - if (hostSettings.useSystemIcons) + if (hostSettings->useSystemIcons) { #if 0 ui.b_add.setIcon(getIcon('list-add', 16, 'svgz')) @@ -1090,6 +1082,44 @@ bool PluginListDialog::checkPluginCache(const char* const filename, const char* return true; } +void PluginListDialog::setPluginPath(const PluginType ptype, const char* const path) +{ + switch (ptype) + { + case PLUGIN_LV2: + p->paths.lv2 = path; + break; + case PLUGIN_VST2: + p->paths.vst2 = path; + break; + case PLUGIN_VST3: + p->paths.vst3 = path; + break; + case PLUGIN_CLAP: + p->paths.clap = path; + break; + #ifndef CARLA_FRONTEND_ONLY_EMBEDDABLE_PLUGINS + case PLUGIN_LADSPA: + p->paths.ladspa = path; + break; + case PLUGIN_DSSI: + p->paths.dssi = path; + break; + case PLUGIN_SF2: + p->paths.sf2 = path; + break; + case PLUGIN_SFZ: + p->paths.sfz = path; + break; + case PLUGIN_JSFX: + p->paths.jsfx = path; + break; + #endif + default: + break; + } +} + // -------------------------------------------------------------------------------------------------------------------- // protected methods @@ -1239,7 +1269,9 @@ void PluginListDialog::timerEvent(QTimerEvent* const event) #endif default: // discovery complete + #ifndef CARLA_FRONTEND_ONLY_EMBEDDABLE_PLUGINS if (! p->discovery.nextTool()) + #endif refreshPluginsStop(); } @@ -1489,7 +1521,7 @@ void PluginListDialog::loadSettings() #endif } -// ----------------------------------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------------------------------------- // private slots void PluginListDialog::cellClicked(const int row, const int column) @@ -1994,12 +2026,24 @@ void PluginListDialog::saveSettings() // -------------------------------------------------------------------------------------------------------------------- PluginListDialog* -carla_frontend_createPluginListDialog(void* const parent) +carla_frontend_createPluginListDialog(void* const parent, const HostSettings* const hostSettings) { - const HostSettings hostSettings = {}; return new PluginListDialog(reinterpret_cast(parent), hostSettings); } +void +carla_frontend_destroyPluginListDialog(PluginListDialog* const dialog) +{ + dialog->close(); + delete dialog; +} + +void +carla_frontend_setPluginListDialogPath(PluginListDialog* const dialog, const int ptype, const char* const path) +{ + dialog->setPluginPath(static_cast(ptype), path); +} + const PluginListDialogResults* carla_frontend_execPluginListDialog(PluginListDialog* const dialog) { @@ -2046,13 +2090,12 @@ carla_frontend_execPluginListDialog(PluginListDialog* const dialog) // -------------------------------------------------------------------------------------------------------------------- -const PluginListDialogResults* -carla_frontend_createAndExecPluginListDialog(void* const parent/*, const HostSettings& hostSettings*/) -{ - const HostSettings hostSettings = {}; - PluginListDialog gui(reinterpret_cast(parent), hostSettings); - - return carla_frontend_execPluginListDialog(&gui); -} +// const PluginListDialogResults* +// carla_frontend_createAndExecPluginListDialog(void* const parent, const HostSettings* const hostSettings) +// { +// PluginListDialog gui(reinterpret_cast(parent), hostSettings); +// +// return carla_frontend_execPluginListDialog(&gui); +// } // -------------------------------------------------------------------------------------------------------------------- diff --git a/source/frontend/pluginlist/pluginlistdialog.hpp b/source/frontend/pluginlist/pluginlistdialog.hpp index 275afc046..9726de66e 100644 --- a/source/frontend/pluginlist/pluginlistdialog.hpp +++ b/source/frontend/pluginlist/pluginlistdialog.hpp @@ -6,6 +6,8 @@ #pragma once +#include "CarlaFrontend.h" + #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy" @@ -26,14 +28,9 @@ #include "ui_pluginlistdialog.h" -struct HostSettings { - bool showPluginBridges; - bool showWineBridges; - bool useSystemIcons; -}; - class QSafeSettings; typedef struct _CarlaPluginDiscoveryInfo CarlaPluginDiscoveryInfo; +typedef struct _HostSettings HostSettings; struct PluginInfo; // -------------------------------------------------------------------------------------------------------------------- @@ -63,12 +60,13 @@ class PluginListDialog : public QDialog // public methods public: - explicit PluginListDialog(QWidget* parent, const HostSettings& hostSettings); + explicit PluginListDialog(QWidget* parent, const HostSettings* hostSettings); ~PluginListDialog() override; const PluginInfo& getSelectedPluginInfo() const; void addPluginInfo(const CarlaPluginDiscoveryInfo* info, const char* sha1sum); bool checkPluginCache(const char* filename, const char* sha1sum); + void setPluginPath(PluginType ptype, const char* path); // ---------------------------------------------------------------------------------------------------------------- // protected methods