@@ -1056,10 +1056,16 @@ typedef enum { | |||||
*/ | */ | ||||
ENGINE_OPTION_PATH_RESOURCES = 16, | ENGINE_OPTION_PATH_RESOURCES = 16, | ||||
/*! | |||||
* Prevent bad plugin and UI behaviour. | |||||
* @note: Linux only | |||||
*/ | |||||
ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 17, | |||||
/*! | /*! | ||||
* Set frontend winId, used to define as parent window for plugin UIs. | * Set frontend winId, used to define as parent window for plugin UIs. | ||||
*/ | */ | ||||
ENGINE_OPTION_FRONTEND_WIN_ID = 17 | |||||
ENGINE_OPTION_FRONTEND_WIN_ID = 18 | |||||
} EngineOption; | } EngineOption; | ||||
@@ -251,6 +251,7 @@ struct EngineOptions { | |||||
const char* binaryDir; | const char* binaryDir; | ||||
const char* resourceDir; | const char* resourceDir; | ||||
bool preventBadBehaviour; | |||||
uintptr_t frontendWinId; | uintptr_t frontendWinId; | ||||
#ifndef DOXYGEN | #ifndef DOXYGEN | ||||
@@ -780,6 +780,8 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||||
if (gStandalone.engineOptions.resourceDir != nullptr && gStandalone.engineOptions.resourceDir[0] != '\0') | if (gStandalone.engineOptions.resourceDir != nullptr && gStandalone.engineOptions.resourceDir[0] != '\0') | ||||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, gStandalone.engineOptions.resourceDir); | gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, gStandalone.engineOptions.resourceDir); | ||||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, gStandalone.engineOptions.preventBadBehaviour ? 1 : 0, nullptr); | |||||
if (gStandalone.engineOptions.frontendWinId != 0) | if (gStandalone.engineOptions.frontendWinId != 0) | ||||
{ | { | ||||
char strBuf[STR_MAX+1]; | char strBuf[STR_MAX+1]; | ||||
@@ -884,6 +886,9 @@ bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseNa | |||||
if (const char* const resourceDir = std::getenv("ENGINE_OPTION_PATH_RESOURCES")) | if (const char* const resourceDir = std::getenv("ENGINE_OPTION_PATH_RESOURCES")) | ||||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, resourceDir); | gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, resourceDir); | ||||
if (const char* const preventBadBehaviour = std::getenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR")) | |||||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, (std::strcmp(preventBadBehaviour, "true") == 0) ? 1 : 0, nullptr); | |||||
if (const char* const frontendWinId = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | if (const char* const frontendWinId = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID")) | ||||
gStandalone.engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, frontendWinId); | gStandalone.engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, frontendWinId); | ||||
@@ -1119,6 +1124,11 @@ void carla_set_engine_option(EngineOption option, int value, const char* valueSt | |||||
gStandalone.engineOptions.resourceDir = carla_strdup_safe(valueStr); | gStandalone.engineOptions.resourceDir = carla_strdup_safe(valueStr); | ||||
break; | break; | ||||
case CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: | |||||
CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,); | |||||
gStandalone.engineOptions.preventBadBehaviour = (value != 0); | |||||
break; | |||||
case CB::ENGINE_OPTION_FRONTEND_WIN_ID: | case CB::ENGINE_OPTION_FRONTEND_WIN_ID: | ||||
CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | ||||
const long long winId(std::strtoll(valueStr, nullptr, 16)); | const long long winId(std::strtoll(valueStr, nullptr, 16)); | ||||
@@ -1352,6 +1352,21 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||||
pData->options.resourceDir = carla_strdup_safe(valueStr); | pData->options.resourceDir = carla_strdup_safe(valueStr); | ||||
break; | break; | ||||
case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: | |||||
CARLA_SAFE_ASSERT_RETURN(pData->options.binaryDir != nullptr && pData->options.binaryDir[0] != '\0',); | |||||
#ifdef CARLA_OS_LINUX | |||||
if (value != 0) | |||||
{ | |||||
CarlaString interposerPath(CarlaString(pData->options.binaryDir) + CARLA_OS_SEP_STR "libcarlainterposer.so"); | |||||
::setenv("LD_PRELOAD", interposerPath.buffer(), 1); | |||||
} | |||||
else | |||||
{ | |||||
::unsetenv("LD_PRELOAD"); | |||||
} | |||||
#endif | |||||
break; | |||||
case ENGINE_OPTION_FRONTEND_WIN_ID: | case ENGINE_OPTION_FRONTEND_WIN_ID: | ||||
CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',); | ||||
const long long winId(std::strtoll(valueStr, nullptr, 16)); | const long long winId(std::strtoll(valueStr, nullptr, 16)); | ||||
@@ -211,6 +211,7 @@ EngineOptions::EngineOptions() noexcept | |||||
pathSFZ(nullptr), | pathSFZ(nullptr), | ||||
binaryDir(nullptr), | binaryDir(nullptr), | ||||
resourceDir(nullptr), | resourceDir(nullptr), | ||||
preventBadBehaviour(false), | |||||
frontendWinId(0) {} | frontendWinId(0) {} | ||||
EngineOptions::~EngineOptions() noexcept | EngineOptions::~EngineOptions() noexcept | ||||
@@ -235,9 +235,16 @@ void CarlaPluginThread::run() | |||||
else | else | ||||
carla_setenv("ENGINE_OPTION_PATH_RESOURCES", ""); | carla_setenv("ENGINE_OPTION_PATH_RESOURCES", ""); | ||||
carla_setenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR", bool2str(options.preventBadBehaviour)); | |||||
std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId); | std::snprintf(strBuf, STR_MAX, P_UINTPTR, options.frontendWinId); | ||||
carla_setenv("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf); | carla_setenv("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf); | ||||
#ifdef CARLA_OS_LINUX | |||||
const char* const oldPreload(std::getenv("LD_PRELOAD")); | |||||
::unsetenv("LD_PRELOAD"); | |||||
#endif | |||||
switch (fMode) | switch (fMode) | ||||
{ | { | ||||
case PLUGIN_THREAD_NULL: | case PLUGIN_THREAD_NULL: | ||||
@@ -280,6 +287,11 @@ void CarlaPluginThread::run() | |||||
fProcess->start(arguments); | fProcess->start(arguments); | ||||
#ifdef CARLA_OS_LINUX | |||||
if (oldPreload != nullptr) | |||||
::setenv("LD_PRELOAD", oldPreload, 1); | |||||
#endif | |||||
sEnvMutex.unlock(); | sEnvMutex.unlock(); | ||||
switch (fMode) | switch (fMode) | ||||
@@ -777,8 +777,12 @@ ENGINE_OPTION_PATH_BINARIES = 15 | |||||
# @note Must be set for some internal plugins to work | # @note Must be set for some internal plugins to work | ||||
ENGINE_OPTION_PATH_RESOURCES = 16 | ENGINE_OPTION_PATH_RESOURCES = 16 | ||||
# Prevent bad plugin and UI behaviour. | |||||
# @note: Linux only | |||||
ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 17 | |||||
# Set frontend winId, used to define as parent window for plugin UIs. | # Set frontend winId, used to define as parent window for plugin UIs. | ||||
ENGINE_OPTION_FRONTEND_WIN_ID = 17 | |||||
ENGINE_OPTION_FRONTEND_WIN_ID = 18 | |||||
# ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
# Engine Process Mode | # Engine Process Mode | ||||
@@ -1315,6 +1319,7 @@ class CarlaHostMeta(QObject): | |||||
self.forceStereo = False | self.forceStereo = False | ||||
self.preferPluginBridges = False | self.preferPluginBridges = False | ||||
self.preferUIBridges = False | self.preferUIBridges = False | ||||
self.preventBadBehaviour = False | |||||
self.uisAlwaysOnTop = False | self.uisAlwaysOnTop = False | ||||
self.maxParameters = 0 | self.maxParameters = 0 | ||||
self.uiBridgesTimeout = 0 | self.uiBridgesTimeout = 0 | ||||
@@ -1347,12 +1347,16 @@ def setHostSettings(host): | |||||
# kdevelop likes this :) | # kdevelop likes this :) | ||||
if False: host = CarlaHostMeta() | if False: host = CarlaHostMeta() | ||||
# TEST | |||||
host.preventBadBehaviour = True | |||||
host.set_engine_option(ENGINE_OPTION_FORCE_STEREO, host.forceStereo, "") | host.set_engine_option(ENGINE_OPTION_FORCE_STEREO, host.forceStereo, "") | ||||
host.set_engine_option(ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, host.preferPluginBridges, "") | host.set_engine_option(ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, host.preferPluginBridges, "") | ||||
host.set_engine_option(ENGINE_OPTION_PREFER_UI_BRIDGES, host.preferUIBridges, "") | host.set_engine_option(ENGINE_OPTION_PREFER_UI_BRIDGES, host.preferUIBridges, "") | ||||
host.set_engine_option(ENGINE_OPTION_UIS_ALWAYS_ON_TOP, host.uisAlwaysOnTop, "") | host.set_engine_option(ENGINE_OPTION_UIS_ALWAYS_ON_TOP, host.uisAlwaysOnTop, "") | ||||
host.set_engine_option(ENGINE_OPTION_MAX_PARAMETERS, host.maxParameters, "") | host.set_engine_option(ENGINE_OPTION_MAX_PARAMETERS, host.maxParameters, "") | ||||
host.set_engine_option(ENGINE_OPTION_UI_BRIDGES_TIMEOUT, host.uiBridgesTimeout, "") | host.set_engine_option(ENGINE_OPTION_UI_BRIDGES_TIMEOUT, host.uiBridgesTimeout, "") | ||||
host.set_engine_option(ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, host.preventBadBehaviour, "") | |||||
if host.isPlugin: | if host.isPlugin: | ||||
return | return | ||||
@@ -324,6 +324,8 @@ const char* EngineOption2Str(const EngineOption option) noexcept | |||||
return "ENGINE_OPTION_PATH_BINARIES"; | return "ENGINE_OPTION_PATH_BINARIES"; | ||||
case ENGINE_OPTION_PATH_RESOURCES: | case ENGINE_OPTION_PATH_RESOURCES: | ||||
return "ENGINE_OPTION_PATH_RESOURCES"; | return "ENGINE_OPTION_PATH_RESOURCES"; | ||||
case ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR: | |||||
return "ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR"; | |||||
case ENGINE_OPTION_FRONTEND_WIN_ID: | case ENGINE_OPTION_FRONTEND_WIN_ID: | ||||
return "ENGINE_OPTION_FRONTEND_WIN_ID"; | return "ENGINE_OPTION_FRONTEND_WIN_ID"; | ||||
} | } | ||||