| @@ -1478,6 +1478,9 @@ | |||
| <layout class="QGridLayout" name="gridLayout_6"> | |||
| <item row="0" column="0" colspan="2"> | |||
| <widget class="QCheckBox" name="cb_wine_prefix_detect"> | |||
| <property name="enabled"> | |||
| <bool>false</bool> | |||
| </property> | |||
| <property name="text"> | |||
| <string>Auto-detect Wine prefix based on plugin filename</string> | |||
| </property> | |||
| @@ -1496,6 +1499,16 @@ | |||
| <item row="1" column="1"> | |||
| <widget class="QLineEdit" name="le_wine_prefix_fallback"/> | |||
| </item> | |||
| <item row="2" column="0" colspan="2"> | |||
| <widget class="QLabel" name="label_30"> | |||
| <property name="text"> | |||
| <string>Note: WINEPREFIX env var is prefered over this fallback</string> | |||
| </property> | |||
| <property name="alignment"> | |||
| <set>Qt::AlignCenter</set> | |||
| </property> | |||
| </widget> | |||
| </item> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| @@ -1667,7 +1680,7 @@ | |||
| <property name="sizeHint" stdset="0"> | |||
| <size> | |||
| <width>20</width> | |||
| <height>115</height> | |||
| <height>96</height> | |||
| </size> | |||
| </property> | |||
| </spacer> | |||
| @@ -1101,12 +1101,12 @@ typedef enum { | |||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 19, | |||
| /*! | |||
| * Fallback wineprefix to use if automatic detection fails or is diabled, and WINEPREFIX is not set. | |||
| * Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | |||
| */ | |||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 20, | |||
| /*! | |||
| * Enable realtie priority for Wine application and server threads. | |||
| * Enable realtime priority for Wine application and server threads. | |||
| */ | |||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 21, | |||
| @@ -255,7 +255,7 @@ struct CARLA_API EngineOptions { | |||
| uintptr_t frontendWinId; | |||
| struct Wine { | |||
| const char* exec; | |||
| const char* executable; | |||
| bool autoPrefix; | |||
| const char* fallbackPrefix; | |||
| @@ -264,13 +264,8 @@ struct CARLA_API EngineOptions { | |||
| int baseRtPrio; | |||
| int serverRtPrio; | |||
| Wine() | |||
| : exec(nullptr), | |||
| autoPrefix(true), | |||
| fallbackPrefix(nullptr), | |||
| rtPrio(true), | |||
| baseRtPrio(15), | |||
| serverRtPrio(10) {} | |||
| Wine() noexcept; | |||
| ~Wine() noexcept; | |||
| } wine; | |||
| #ifndef DOXYGEN | |||
| @@ -269,7 +269,22 @@ static void carla_engine_init_common() | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, strBuf); | |||
| } | |||
| else | |||
| { | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0"); | |||
| } | |||
| if (gStandalone.engineOptions.wine.executable != nullptr && gStandalone.engineOptions.wine.executable[0] != '\0') | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_EXECUTABLE, 0, gStandalone.engineOptions.wine.executable); | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_AUTO_PREFIX, gStandalone.engineOptions.wine.autoPrefix ? 1 : 0, nullptr); | |||
| if (gStandalone.engineOptions.wine.fallbackPrefix != nullptr && gStandalone.engineOptions.wine.fallbackPrefix[0] != '\0') | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, gStandalone.engineOptions.wine.fallbackPrefix); | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED, gStandalone.engineOptions.wine.rtPrio ? 1 : 0, nullptr); | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_BASE_RT_PRIO, gStandalone.engineOptions.wine.baseRtPrio, nullptr); | |||
| gStandalone.engine->setOption(CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO, gStandalone.engineOptions.wine.serverRtPrio, nullptr); | |||
| #endif | |||
| } | |||
| @@ -290,13 +305,6 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||
| carla_setenv("WINEASIO_CLIENT_NAME", clientName); | |||
| #endif | |||
| // TODO: make this an option, put somewhere else | |||
| if (std::getenv("WINE_RT") == nullptr) | |||
| { | |||
| carla_setenv("WINE_RT", "55"); | |||
| carla_setenv("WINE_SVR_RT", "70"); | |||
| } | |||
| gStandalone.engine = CarlaEngine::newDriverByName(driverName); | |||
| if (gStandalone.engine == nullptr) | |||
| @@ -626,6 +634,44 @@ void carla_set_engine_option(EngineOption option, int value, const char* valueSt | |||
| gStandalone.engineOptions.frontendWinId = static_cast<uintptr_t>(winId); | |||
| } break; | |||
| case CB::ENGINE_OPTION_WINE_EXECUTABLE: | |||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | |||
| if (gStandalone.engineOptions.wine.executable != nullptr) | |||
| delete[] gStandalone.engineOptions.wine.executable; | |||
| gStandalone.engineOptions.wine.executable = carla_strdup_safe(valueStr); | |||
| break; | |||
| case CB::ENGINE_OPTION_WINE_AUTO_PREFIX: | |||
| CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); | |||
| gStandalone.engineOptions.wine.autoPrefix = (value != 0); | |||
| break; | |||
| case CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX: | |||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | |||
| if (gStandalone.engineOptions.wine.fallbackPrefix != nullptr) | |||
| delete[] gStandalone.engineOptions.wine.fallbackPrefix; | |||
| gStandalone.engineOptions.wine.fallbackPrefix = carla_strdup_safe(valueStr); | |||
| break; | |||
| case CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED: | |||
| CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); | |||
| gStandalone.engineOptions.wine.rtPrio = (value != 0); | |||
| break; | |||
| case CB::ENGINE_OPTION_WINE_BASE_RT_PRIO: | |||
| CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,); | |||
| gStandalone.engineOptions.wine.baseRtPrio = value; | |||
| break; | |||
| case CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO: | |||
| CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,); | |||
| gStandalone.engineOptions.wine.serverRtPrio = value; | |||
| break; | |||
| case CB::ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT: | |||
| gStandalone.logThreadEnabled = (value != 0); | |||
| break; | |||
| @@ -1587,9 +1587,12 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||
| pData->options.resourceDir = carla_strdup_safe(valueStr); | |||
| break; | |||
| case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: | |||
| case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',); | |||
| #ifdef CARLA_OS_LINUX | |||
| const ScopedEngineEnvironmentLocker _seel(this); | |||
| if (value != 0) | |||
| { | |||
| CarlaString interposerPath(CarlaString(pData->options.binaryDir) + "/libcarla_interposer-safe.so"); | |||
| @@ -1600,7 +1603,7 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||
| ::unsetenv("LD_PRELOAD"); | |||
| } | |||
| #endif | |||
| break; | |||
| } break; | |||
| case ENGINE_OPTION_FRONTEND_WIN_ID: { | |||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | |||
| @@ -1609,6 +1612,44 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||
| pData->options.frontendWinId = static_cast<uintptr_t>(winId); | |||
| } break; | |||
| case ENGINE_OPTION_WINE_EXECUTABLE: | |||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | |||
| if (pData->options.wine.executable != nullptr) | |||
| delete[] pData->options.wine.executable; | |||
| pData->options.wine.executable = carla_strdup_safe(valueStr); | |||
| break; | |||
| case ENGINE_OPTION_WINE_AUTO_PREFIX: | |||
| CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); | |||
| pData->options.wine.autoPrefix = (value != 0); | |||
| break; | |||
| case ENGINE_OPTION_WINE_FALLBACK_PREFIX: | |||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | |||
| if (pData->options.wine.fallbackPrefix != nullptr) | |||
| delete[] pData->options.wine.fallbackPrefix; | |||
| pData->options.wine.fallbackPrefix = carla_strdup_safe(valueStr); | |||
| break; | |||
| case ENGINE_OPTION_WINE_RT_PRIO_ENABLED: | |||
| CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); | |||
| pData->options.wine.rtPrio = (value != 0); | |||
| break; | |||
| case ENGINE_OPTION_WINE_BASE_RT_PRIO: | |||
| CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,); | |||
| pData->options.wine.baseRtPrio = value; | |||
| break; | |||
| case ENGINE_OPTION_WINE_SERVER_RT_PRIO: | |||
| CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,); | |||
| pData->options.wine.serverRtPrio = value; | |||
| break; | |||
| case ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT: | |||
| break; | |||
| } | |||
| @@ -287,6 +287,29 @@ EngineOptions::~EngineOptions() noexcept | |||
| } | |||
| } | |||
| EngineOptions::Wine::Wine() noexcept | |||
| : executable(nullptr), | |||
| autoPrefix(true), | |||
| fallbackPrefix(nullptr), | |||
| rtPrio(true), | |||
| baseRtPrio(15), | |||
| serverRtPrio(10) {} | |||
| EngineOptions::Wine::~Wine() noexcept | |||
| { | |||
| if (executable != nullptr) | |||
| { | |||
| delete[] executable; | |||
| executable = nullptr; | |||
| } | |||
| if (fallbackPrefix != nullptr) | |||
| { | |||
| delete[] fallbackPrefix; | |||
| fallbackPrefix = nullptr; | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // EngineTimeInfoBBT | |||
| @@ -111,6 +111,11 @@ protected: | |||
| carla_stderr("CarlaPluginBridgeThread::run() - already running"); | |||
| } | |||
| char strBuf[STR_MAX+1]; | |||
| strBuf[STR_MAX] = '\0'; | |||
| const EngineOptions& options(kEngine->getOptions()); | |||
| String name(kPlugin->getName()); | |||
| String filename(kPlugin->getFilename()); | |||
| @@ -125,7 +130,47 @@ protected: | |||
| #ifndef CARLA_OS_WIN | |||
| // start with "wine" if needed | |||
| if (fBinary.endsWithIgnoreCase(".exe")) | |||
| arguments.add("wine"); | |||
| { | |||
| if (options.wine.executable != nullptr && options.wine.executable[0] != '\0') | |||
| arguments.add(options.wine.executable); | |||
| else | |||
| arguments.add("wine"); | |||
| #if 0 | |||
| if (options.wine.autoPrefix) | |||
| { | |||
| // TODO | |||
| } | |||
| else | |||
| #endif | |||
| if (std::getenv("WINEPREFIX") == nullptr && | |||
| options.wine.fallbackPrefix != nullptr && | |||
| options.wine.fallbackPrefix[0] != '\0') | |||
| { | |||
| carla_setenv("WINEPREFIX", options.wine.fallbackPrefix); | |||
| } | |||
| if (options.wine.rtPrio) | |||
| { | |||
| carla_setenv("STAGING_SHARED_MEMORY", "1"); | |||
| std::snprintf(strBuf, STR_MAX, "%i", options.wine.baseRtPrio); | |||
| carla_setenv("STAGING_RT_PRIORITY_BASE", strBuf); | |||
| carla_setenv("WINE_RT", strBuf); | |||
| std::snprintf(strBuf, STR_MAX, "%i", options.wine.serverRtPrio); | |||
| carla_setenv("STAGING_RT_PRIORITY_SERVER", strBuf); | |||
| carla_setenv("WINE_SVR_RT", strBuf); | |||
| } | |||
| else | |||
| { | |||
| carla_unsetenv("STAGING_SHARED_MEMORY"); | |||
| carla_unsetenv("STAGING_RT_PRIORITY_BASE"); | |||
| carla_unsetenv("STAGING_RT_PRIORITY_SERVER"); | |||
| carla_unsetenv("WINE_RT"); | |||
| carla_unsetenv("WINE_SVR_RT"); | |||
| } | |||
| } | |||
| #endif | |||
| // binary | |||
| @@ -146,10 +191,6 @@ protected: | |||
| bool started; | |||
| { | |||
| char strBuf[STR_MAX+1]; | |||
| strBuf[STR_MAX] = '\0'; | |||
| const EngineOptions& options(kEngine->getOptions()); | |||
| const ScopedEngineEnvironmentLocker _seel(kEngine); | |||
| #ifdef CARLA_OS_LINUX | |||
| @@ -790,8 +790,26 @@ ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 16 | |||
| # Set frontend winId, used to define as parent window for plugin UIs. | |||
| ENGINE_OPTION_FRONTEND_WIN_ID = 17 | |||
| # Set path to wine executable. | |||
| ENGINE_OPTION_WINE_EXECUTABLE = 18 | |||
| # Enable automatic wineprefix detection. | |||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 19 | |||
| # Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | |||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 20 | |||
| # Enable realtime priority for Wine application and server threads. | |||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 21 | |||
| # Base realtime priority for Wine threads. | |||
| ENGINE_OPTION_WINE_BASE_RT_PRIO = 22 | |||
| # Wine server realtime priority. | |||
| ENGINE_OPTION_WINE_SERVER_RT_PRIO = 23 | |||
| # Capture console output into debug callbacks | |||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 18 | |||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 24 | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Engine Process Mode | |||
| @@ -2459,8 +2459,6 @@ def initHost(initName, libPrefix, isControl, isPlugin, failError, HostClass = No | |||
| # -------------------------------------------------------------------------------------------------------- | |||
| # Init host | |||
| if failError: | |||
| # no try | |||
| host = HostClass() if HostClass is not None else CarlaHostQtDLL(libname, loadGlobal) | |||
| @@ -2726,6 +2724,23 @@ def setEngineSettings(host): | |||
| host.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL | |||
| host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, ENGINE_TRANSPORT_MODE_INTERNAL, "") | |||
| # -------------------------------------------------------------------------------------------------------- | |||
| # wine settings | |||
| optWineExecutable = settings.value(CARLA_KEY_WINE_EXECUTABLE, CARLA_DEFAULT_WINE_EXECUTABLE, type=str) | |||
| optWineAutoPrefix = settings.value(CARLA_KEY_WINE_AUTO_PREFIX, CARLA_DEFAULT_WINE_AUTO_PREFIX, type=bool) | |||
| optWineFallbackPrefix = settings.value(CARLA_KEY_WINE_FALLBACK_PREFIX, CARLA_DEFAULT_WINE_FALLBACK_PREFIX, type=str) | |||
| optWineRtPrioEnabled = settings.value(CARLA_KEY_WINE_RT_PRIO_ENABLED, CARLA_DEFAULT_WINE_RT_PRIO_ENABLED, type=bool) | |||
| optWineBaseRtPrio = settings.value(CARLA_KEY_WINE_BASE_RT_PRIO, CARLA_DEFAULT_WINE_BASE_RT_PRIO, type=int) | |||
| optWineServerRtPrio = settings.value(CARLA_KEY_WINE_SERVER_RT_PRIO, CARLA_DEFAULT_WINE_SERVER_RT_PRIO, type=int) | |||
| 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, "") | |||
| # -------------------------------------------------------------------------------------------------------- | |||
| # return selected driver name | |||
| @@ -331,6 +331,18 @@ const char* EngineOption2Str(const EngineOption option) noexcept | |||
| return "ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR"; | |||
| case ENGINE_OPTION_FRONTEND_WIN_ID: | |||
| return "ENGINE_OPTION_FRONTEND_WIN_ID"; | |||
| case ENGINE_OPTION_WINE_EXECUTABLE: | |||
| return "ENGINE_OPTION_WINE_EXECUTABLE"; | |||
| case ENGINE_OPTION_WINE_AUTO_PREFIX: | |||
| return "ENGINE_OPTION_WINE_AUTO_PREFIX"; | |||
| case ENGINE_OPTION_WINE_FALLBACK_PREFIX: | |||
| return "ENGINE_OPTION_WINE_FALLBACK_PREFIX"; | |||
| case ENGINE_OPTION_WINE_RT_PRIO_ENABLED: | |||
| return "ENGINE_OPTION_WINE_RT_PRIO_ENABLED"; | |||
| case ENGINE_OPTION_WINE_BASE_RT_PRIO: | |||
| return "ENGINE_OPTION_WINE_BASE_RT_PRIO"; | |||
| case ENGINE_OPTION_WINE_SERVER_RT_PRIO: | |||
| return "ENGINE_OPTION_WINE_SERVER_RT_PRIO"; | |||
| case ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT: | |||
| return "ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT"; | |||
| } | |||