diff --git a/lib/macro/macro-action-script.cpp b/lib/macro/macro-action-script.cpp index 0fbe385d..8ec122d4 100644 --- a/lib/macro/macro-action-script.cpp +++ b/lib/macro/macro-action-script.cpp @@ -6,14 +6,17 @@ namespace advss { -MacroActionScript::MacroActionScript(Macro *m, const std::string &id, - const OBSData &defaultSettings, - const std::string &propertiesSignalName, - const std::string &triggerSignal, - const std::string &completionSignal) +MacroActionScript::MacroActionScript( + Macro *m, const std::string &id, const OBSData &defaultSettings, + const std::string &propertiesSignalName, + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName) : MacroAction(m), MacroSegmentScript(defaultSettings, propertiesSignalName, - triggerSignal, completionSignal), + triggerSignalName, completionSignalName, + newInstanceSignalName, deletedInstanceSignalName), _id(id) { } @@ -89,4 +92,29 @@ void MacroActionScript::WaitForCompletion() const } } +void MacroActionScript::RegisterTempVarHelper(const std::string &variableId, + const std::string &name, + const std::string &helpText) +{ + AddTempvar(variableId, name, helpText); +} + +void MacroActionScript::DeregisterAllTempVarsHelper() +{ + MacroSegment::SetupTempVars(); +} + +void MacroActionScript::SetTempVarValueHelper(const std::string &variableId, + const std::string &value) +{ + MacroAction::SetTempVarValue(variableId, value); +} + +void MacroActionScript::SetupTempVars() +{ + // This just exists so MacroSegment::SetupTempVars() is not called. + // We want the ScriptHandler to handle the registration and clearing of + // the temp vars. +} + } // namespace advss diff --git a/lib/macro/macro-action-script.hpp b/lib/macro/macro-action-script.hpp index 90fae0c2..93157d75 100644 --- a/lib/macro/macro-action-script.hpp +++ b/lib/macro/macro-action-script.hpp @@ -10,8 +10,10 @@ public: MacroActionScript(Macro *m, const std::string &id, const OBSData &defaultSettings, const std::string &propertiesSignalName, - const std::string &triggerSignal, - const std::string &signalComplete); + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName); MacroActionScript(const advss::MacroActionScript &); bool PerformAction(); void LogAction() const; @@ -22,6 +24,13 @@ public: private: void WaitForCompletion() const; + void RegisterTempVarHelper(const std::string &variableId, + const std::string &name, + const std::string &helpText); + void DeregisterAllTempVarsHelper(); + void SetTempVarValueHelper(const std::string &variableId, + const std::string &value); + void SetupTempVars(); std::string _id = ""; }; diff --git a/lib/macro/macro-condition-script.cpp b/lib/macro/macro-condition-script.cpp index bac1c9cd..fabc3d15 100644 --- a/lib/macro/macro-condition-script.cpp +++ b/lib/macro/macro-condition-script.cpp @@ -8,10 +8,14 @@ namespace advss { MacroConditionScript::MacroConditionScript( Macro *m, const std::string &id, const OBSData &defaultSettings, const std::string &propertiesSignalName, - const std::string &triggerSignal, const std::string &completionSignal) + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName) : MacroCondition(m), MacroSegmentScript(defaultSettings, propertiesSignalName, - triggerSignal, completionSignal), + triggerSignalName, completionSignalName, + newInstanceSignalName, deletedInstanceSignalName), _id(id) { } @@ -76,4 +80,29 @@ void MacroConditionScript::WaitForCompletion() const } } +void MacroConditionScript::RegisterTempVarHelper(const std::string &variableId, + const std::string &name, + const std::string &helpText) +{ + AddTempvar(variableId, name, helpText); +} + +void MacroConditionScript::DeregisterAllTempVarsHelper() +{ + MacroSegment::SetupTempVars(); +} + +void MacroConditionScript::SetTempVarValueHelper(const std::string &variableId, + const std::string &value) +{ + MacroCondition::SetTempVarValue(variableId, value); +} + +void MacroConditionScript::SetupTempVars() +{ + // This just exists so MacroSegment::SetupTempVars() is not called. + // We want the ScriptHandler to handle the registration and clearing of + // the temp vars. +} + } // namespace advss diff --git a/lib/macro/macro-condition-script.hpp b/lib/macro/macro-condition-script.hpp index 33b01348..dead6c94 100644 --- a/lib/macro/macro-condition-script.hpp +++ b/lib/macro/macro-condition-script.hpp @@ -10,8 +10,10 @@ public: MacroConditionScript(Macro *m, const std::string &id, const OBSData &defaultSettings, const std::string &propertiesSignalName, - const std::string &triggerSignal, - const std::string &signalComplete); + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName); MacroConditionScript(const advss::MacroConditionScript &); bool CheckCondition(); bool Save(obs_data_t *obj) const; @@ -20,6 +22,13 @@ public: private: void WaitForCompletion() const; + void RegisterTempVarHelper(const std::string &variableId, + const std::string &name, + const std::string &helpText); + void DeregisterAllTempVarsHelper(); + void SetTempVarValueHelper(const std::string &variableId, + const std::string &value); + void SetupTempVars(); std::string _id = ""; }; diff --git a/lib/macro/macro-script-handler.cpp b/lib/macro/macro-script-handler.cpp index 16ada6a7..60f0d1cd 100644 --- a/lib/macro/macro-script-handler.cpp +++ b/lib/macro/macro-script-handler.cpp @@ -29,6 +29,10 @@ static constexpr std::string_view defaultSettingsParam = "default_settings"; static constexpr std::string_view propertiesSignalParam = "properties_signal_name"; static constexpr std::string_view triggerSignalParam = "trigger_signal_name"; +static constexpr std::string_view newInstanceSignalNameParam = + "new_instance_signal_name"; +static constexpr std::string_view deletedInstanceSignalNameParam = + "deleted_instance_signal_name"; static std::string getRegisterScriptSegmentDeclString(const char *funcName) { @@ -72,16 +76,37 @@ static const std::string deregisterScriptConditionDeclString = /* Script variables */ static constexpr std::string_view valueParam = "value"; +static constexpr std::string_view tempVarIdParam = "temp_var_id"; +static constexpr std::string_view tempVarNameParam = "temp_var_name"; +static constexpr std::string_view tempVarHelpParam = "temp_var_help"; static constexpr std::string_view getVariableValueFuncName = "advss_get_variable_value"; static constexpr std::string_view setVariableValueFuncName = "advss_set_variable_value"; +static constexpr std::string_view registerTempVarFuncName = + "advss_register_temp_var"; +static constexpr std::string_view deregisterAllTempVarsFuncName = + "advss_deregister_temp_vars"; +static constexpr std::string_view setTempVarValueFuncName = + "advss_set_temp_var_value"; static const std::string getVariableValueDeclString = std::string("bool ") + getVariableValueFuncName.data() + "(in string " + nameParam.data() + ", out string " + valueParam.data() + ")"; static const std::string setVariableValueDeclString = std::string("bool ") + setVariableValueFuncName.data() + "(in string " + nameParam.data() + ", in string " + valueParam.data() + ")"; +static const std::string registerTempVarDeclString = + std::string("bool ") + registerTempVarFuncName.data() + "(in string " + + tempVarIdParam.data() + ", in string " + tempVarNameParam.data() + + ", in string " + tempVarHelpParam.data() + ", in int " + + GetInstanceIdParamName().data() + ")"; +static const std::string deregisterAllTempVarsDeclString = + std::string("bool ") + deregisterAllTempVarsFuncName.data() + + "(in int " + GetInstanceIdParamName().data() + ")"; +static const std::string setTempVarValueDeclString = + std::string("bool ") + setTempVarValueFuncName.data() + "(in string " + + tempVarIdParam.data() + ", in string " + valueParam.data() + + ", in int " + GetInstanceIdParamName().data() + ")"; static bool setup(); static bool setupDone = setup(); @@ -103,13 +128,23 @@ static bool setup() &ScriptHandler::GetVariableValue, nullptr); proc_handler_add(ph, setVariableValueDeclString.c_str(), &ScriptHandler::SetVariableValue, nullptr); + proc_handler_add(ph, registerTempVarDeclString.c_str(), + &ScriptHandler::RegisterTempVar, nullptr); + proc_handler_add(ph, deregisterAllTempVarsDeclString.c_str(), + &ScriptHandler::DeregisterAllTempVars, nullptr); + proc_handler_add(ph, setTempVarValueDeclString.c_str(), + &ScriptHandler::SetTempVarValue, nullptr); return true; } -static void replaceWhitespace(std::string &string) +static void replaceProblematicChars(std::string &string) { std::transform(string.begin(), string.end(), string.begin(), [](char c) { - return std::isspace(static_cast(c)) ? '_' : c; + if (std::isspace(static_cast(c)) || c == '(' || + c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { + return '_'; + } + return c; }); } @@ -122,7 +157,7 @@ static std::string getTriggerSignal(const std::string &name, const bool isAction) { std::string signal = name; - replaceWhitespace(signal); + replaceProblematicChars(signal); signal += "_run"; signal += isAction ? "_action" : "_condition"; return signal; @@ -140,12 +175,32 @@ static std::string getPropertiesSignal(const std::string &name, const bool isAction) { std::string signal = name; - replaceWhitespace(signal); + replaceProblematicChars(signal); signal += isAction ? "_action" : "_condition"; signal += "_get_properties"; return signal; } +static std::string getNewInstanceSignal(const std::string &name, + const bool isAction) +{ + std::string signal = name; + replaceProblematicChars(signal); + signal += isAction ? "_action" : "_condition"; + signal += "_new_instance"; + return signal; +} + +static std::string getDeletedInstanceSignal(const std::string &name, + const bool isAction) +{ + std::string signal = name; + replaceProblematicChars(signal); + signal += isAction ? "_action" : "_condition"; + signal += "_deleted_instance"; + return signal; +} + void ScriptHandler::RegisterScriptAction(void *, calldata_t *data) { const char *actionName; @@ -177,14 +232,19 @@ void ScriptHandler::RegisterScriptAction(void *, calldata_t *data) auto triggerSignalName = getTriggerSignal(actionName, true); auto completionSignalName = getCompletionSignal(actionName, true); auto propertiesSignalName = getPropertiesSignal(actionName, true); + auto newInstanceSignalName = getNewInstanceSignal(actionName, true); + auto deletedInstanceSignalName = + getDeletedInstanceSignal(actionName, true); const auto createScriptAction = [id, defaultSettings, propertiesSignalName, triggerSignalName, - completionSignalName]( + completionSignalName, newInstanceSignalName, + deletedInstanceSignalName]( Macro *m) -> std::shared_ptr { return std::make_shared( m, id, defaultSettings, propertiesSignalName, - triggerSignalName, completionSignalName); + triggerSignalName, completionSignalName, + newInstanceSignalName, deletedInstanceSignalName); }; if (!MacroActionFactory::Register(id, {createScriptAction, MacroSegmentScriptEdit::Create, @@ -202,9 +262,15 @@ void ScriptHandler::RegisterScriptAction(void *, calldata_t *data) triggerSignalName.c_str()); calldata_set_string(data, propertiesSignalParam.data(), propertiesSignalName.c_str()); + calldata_set_string(data, newInstanceSignalNameParam.data(), + newInstanceSignalName.c_str()); + calldata_set_string(data, deletedInstanceSignalNameParam.data(), + deletedInstanceSignalName.c_str()); _actions.emplace(id, ScriptSegmentType(id, propertiesSignalName, triggerSignalName, - completionSignalName)); + completionSignalName, + newInstanceSignalName, + deletedInstanceSignalName)); RETURN_SUCCESS(); } @@ -279,14 +345,19 @@ void ScriptHandler::RegisterScriptCondition(void *, calldata_t *data) auto triggerSignalName = getTriggerSignal(conditionName, false); auto completionSignalName = getCompletionSignal(conditionName, false); auto propertiesSignalName = getPropertiesSignal(conditionName, false); + auto newInstanceSignalName = getNewInstanceSignal(conditionName, false); + auto deletedInstanceSignalName = + getDeletedInstanceSignal(conditionName, false); const auto createScriptCondition = [id, defaultSettings, propertiesSignalName, triggerSignalName, - completionSignalName]( + completionSignalName, newInstanceSignalName, + deletedInstanceSignalName]( Macro *m) -> std::shared_ptr { return std::make_shared( m, id, defaultSettings, propertiesSignalName, - triggerSignalName, completionSignalName); + triggerSignalName, completionSignalName, + newInstanceSignalName, deletedInstanceSignalName); }; if (!MacroConditionFactory::Register( id, {createScriptCondition, MacroSegmentScriptEdit::Create, @@ -304,9 +375,15 @@ void ScriptHandler::RegisterScriptCondition(void *, calldata_t *data) triggerSignalName.c_str()); calldata_set_string(data, propertiesSignalParam.data(), propertiesSignalName.c_str()); + calldata_set_string(data, newInstanceSignalNameParam.data(), + newInstanceSignalName.c_str()); + calldata_set_string(data, deletedInstanceSignalNameParam.data(), + deletedInstanceSignalName.c_str()); _conditions.emplace(id, ScriptSegmentType(id, propertiesSignalName, triggerSignalName, - completionSignalName)); + completionSignalName, + newInstanceSignalName, + deletedInstanceSignalName)); RETURN_SUCCESS(); } @@ -399,6 +476,92 @@ void ScriptHandler::SetVariableValue(void *, calldata_t *data) RETURN_SUCCESS(); } +void ScriptHandler::RegisterTempVar(void *, calldata_t *data) +{ + const char *variableId; + if (!calldata_get_string(data, tempVarIdParam.data(), &variableId) || + strlen(variableId) == 0) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + registerTempVarFuncName.data(), tempVarIdParam.data()); + RETURN_FAILURE(); + } + const char *name; + if (!calldata_get_string(data, tempVarNameParam.data(), &name) || + strlen(name) == 0) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + registerTempVarFuncName.data(), tempVarNameParam.data()); + RETURN_FAILURE(); + } + const char *helpText; + if (!calldata_get_string(data, tempVarHelpParam.data(), &helpText)) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + registerTempVarFuncName.data(), tempVarHelpParam.data()); + RETURN_FAILURE(); + } + long long instanceId; + if (!calldata_get_int(data, GetInstanceIdParamName().data(), + &instanceId)) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + registerTempVarFuncName.data(), + GetInstanceIdParamName().data()); + RETURN_FAILURE(); + } + + std::lock_guard lock(_mutex); + MacroSegmentScript::RegisterTempVar(variableId, name, helpText, + instanceId); + RETURN_SUCCESS(); +} + +void ScriptHandler::DeregisterAllTempVars(void *, calldata_t *data) +{ + long long instanceId; + if (!calldata_get_int(data, GetInstanceIdParamName().data(), + &instanceId)) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + deregisterAllTempVarsFuncName.data(), + GetInstanceIdParamName().data()); + RETURN_FAILURE(); + } + + std::lock_guard lock(_mutex); + MacroSegmentScript::DeregisterAllTempVars(instanceId); + RETURN_SUCCESS(); +} + +void ScriptHandler::SetTempVarValue(void *, calldata_t *data) +{ + const char *variableId; + if (!calldata_get_string(data, tempVarIdParam.data(), &variableId) || + strlen(variableId) == 0) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + setTempVarValueFuncName.data(), tempVarIdParam.data()); + RETURN_FAILURE(); + } + + const char *variableValue; + if (!calldata_get_string(data, valueParam.data(), &variableValue) || + strlen(variableValue) == 0) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + setTempVarValueFuncName.data(), valueParam.data()); + RETURN_FAILURE(); + } + + long long instanceId; + if (!calldata_get_int(data, GetInstanceIdParamName().data(), + &instanceId)) { + blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!", + setTempVarValueFuncName.data(), + GetInstanceIdParamName().data()); + RETURN_FAILURE(); + } + + std::lock_guard lock(_mutex); + MacroSegmentScript::SetTempVarValue(variableId, variableValue, + instanceId); + RETURN_SUCCESS(); +} + bool ScriptHandler::ActionIdIsValid(const std::string &id) { std::lock_guard lock(_mutex); @@ -427,21 +590,36 @@ static std::string signalNameToCompletionSignalDecl(const std::string &name) GetCompletionIdParamName().data() + ")"; } -ScriptSegmentType::ScriptSegmentType(const std::string &id, - const std::string &propertiesSignal, - const std::string &triggerSignal, - const std::string &completionSignal) +static std::string signalNameToInstanceSignalDecl(const std::string &name) +{ + return std::string("void ") + name + "(out int " + + GetInstanceIdParamName().data() + ")"; +} + +ScriptSegmentType::ScriptSegmentType( + const std::string &id, const std::string &propertiesSignalName, + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName) : _id(id) { + auto sh = obs_get_signal_handler(); + signal_handler_add( - obs_get_signal_handler(), - signalNameToPropertiesSignalDecl(propertiesSignal).c_str()); + sh, + signalNameToPropertiesSignalDecl(propertiesSignalName).c_str()); signal_handler_add( - obs_get_signal_handler(), - signalNameToTriggerSignalDecl(triggerSignal).c_str()); + sh, signalNameToTriggerSignalDecl(triggerSignalName).c_str()); signal_handler_add( - obs_get_signal_handler(), - signalNameToCompletionSignalDecl(completionSignal).c_str()); + sh, + signalNameToCompletionSignalDecl(completionSignalName).c_str()); + signal_handler_add( + sh, + signalNameToInstanceSignalDecl(newInstanceSignalName).c_str()); + signal_handler_add( + sh, signalNameToInstanceSignalDecl(deletedInstanceSignalName) + .c_str()); } } // namespace advss diff --git a/lib/macro/macro-script-handler.hpp b/lib/macro/macro-script-handler.hpp index 558466f9..d9b2846f 100644 --- a/lib/macro/macro-script-handler.hpp +++ b/lib/macro/macro-script-handler.hpp @@ -10,9 +10,11 @@ class ScriptSegmentType { public: ScriptSegmentType() = delete; ScriptSegmentType(const std::string &id, - const std::string &propertiesSignal, - const std::string &triggerSignal, - const std::string &completionSignal); + const std::string &propertiesSignalName, + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName); private: std::string _id; @@ -26,6 +28,9 @@ public: static void RegisterScriptCondition(void *ctx, calldata_t *data); static void DeregisterScriptCondition(void *ctx, calldata_t *data); static void GetVariableValue(void *ctx, calldata_t *data); + static void RegisterTempVar(void *ctx, calldata_t *data); + static void DeregisterAllTempVars(void *ctx, calldata_t *data); + static void SetTempVarValue(void *ctx, calldata_t *data); static void SetVariableValue(void *ctx, calldata_t *data); static bool ActionIdIsValid(const std::string &id); static bool ConditionIdIsValid(const std::string &id); @@ -56,4 +61,9 @@ static constexpr std::string_view GetResultSignalParamName() return "result"; } +static constexpr std::string_view GetInstanceIdParamName() +{ + return "instance_id"; +} + } // namespace advss diff --git a/lib/macro/macro-segment-script.cpp b/lib/macro/macro-segment-script.cpp index 9cf55c7d..7bec1b51 100644 --- a/lib/macro/macro-segment-script.cpp +++ b/lib/macro/macro-segment-script.cpp @@ -11,33 +11,106 @@ namespace advss { static std::atomic_int completionIdCounter = 0; +static std::atomic_int instanceIdCounter = 0; +static std::mutex instanceMtx; +static std::vector instances{}; -MacroSegmentScript::MacroSegmentScript(obs_data_t *defaultSettings, - const std::string &propertiesSignalName, - const std::string &triggerSignal, - const std::string &completionSignal) +MacroSegmentScript::MacroSegmentScript( + obs_data_t *defaultSettings, const std::string &propertiesSignalName, + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName) : _settings(obs_data_get_defaults(defaultSettings)), _propertiesSignal(propertiesSignalName), - _triggerSignal(triggerSignal), - _completionSignal(completionSignal) + _triggerSignal(triggerSignalName), + _completionSignal(completionSignalName), + _newInstanceSignal(newInstanceSignalName), + _deletedInstanceSignal(deletedInstanceSignalName), + _instanceId(++instanceIdCounter) { signal_handler_connect(obs_get_signal_handler(), - completionSignal.c_str(), + completionSignalName.c_str(), &MacroSegmentScript::CompletionSignalReceived, this); + + std::lock_guard lock(instanceMtx); + instances.emplace_back(this); + + SignalNewInstance(); } MacroSegmentScript::MacroSegmentScript(const MacroSegmentScript &other) : _settings(obs_data_create()), _propertiesSignal(other._propertiesSignal), _triggerSignal(other._triggerSignal), - _completionSignal(other._completionSignal) + _completionSignal(other._completionSignal), + _newInstanceSignal(other._newInstanceSignal), + _deletedInstanceSignal(other._deletedInstanceSignal), + _instanceId(++instanceIdCounter) { signal_handler_connect(obs_get_signal_handler(), _completionSignal.c_str(), &MacroSegmentScript::CompletionSignalReceived, this); obs_data_apply(_settings.Get(), other._settings.Get()); + + std::lock_guard lock(instanceMtx); + instances.emplace_back(this); + + SignalNewInstance(); +} + +MacroSegmentScript::~MacroSegmentScript() +{ + auto data = calldata_create(); + calldata_set_int(data, GetInstanceIdParamName().data(), _instanceId); + signal_handler_signal(obs_get_signal_handler(), + _deletedInstanceSignal.c_str(), data); + calldata_destroy(data); + + std::lock_guard lock(instanceMtx); + instances.erase(std::remove(instances.begin(), instances.end(), this), + instances.end()); +} + +void MacroSegmentScript::RegisterTempVar(const std::string &variableId, + const std::string &name, + const std::string &helpText, + int instanceId) +{ + std::lock_guard lock(instanceMtx); + for (auto instance : instances) { + if (instance->_instanceId != instanceId) { + continue; + } + instance->RegisterTempVarHelper(variableId, name, helpText); + break; + } +} + +void MacroSegmentScript::DeregisterAllTempVars(int instanceId) +{ + std::lock_guard lock(instanceMtx); + for (auto instance : instances) { + if (instance->_instanceId != instanceId) { + continue; + } + instance->DeregisterAllTempVarsHelper(); + } +} + +void MacroSegmentScript::SetTempVarValue(const std::string &variableId, + const std::string &value, + int instanceId) +{ + std::lock_guard lock(instanceMtx); + for (auto instance : instances) { + if (instance->_instanceId != instanceId) { + continue; + } + instance->SetTempVarValueHelper(variableId, value); + } } bool MacroSegmentScript::Save(obs_data_t *obj) const @@ -88,6 +161,7 @@ bool MacroSegmentScript::SendTriggerSignal() calldata_set_int(data, GetCompletionIdParamName().data(), _completionId); calldata_set_string(data, "settings", obs_data_get_json(GetSettings())); + calldata_set_int(data, GetInstanceIdParamName().data(), _instanceId); signal_handler_signal(obs_get_signal_handler(), _triggerSignal.c_str(), data); calldata_destroy(data); @@ -123,6 +197,19 @@ void MacroSegmentScript::CompletionSignalReceived(void *param, calldata_t *data) segment->_triggerResult = result; } +void MacroSegmentScript::SignalNewInstance() const +{ + std::thread signalNewInstanceThread([this]() { + auto data = calldata_create(); + calldata_set_int(data, GetInstanceIdParamName().data(), + _instanceId); + signal_handler_signal(obs_get_signal_handler(), + _newInstanceSignal.c_str(), data); + calldata_destroy(data); + }); + signalNewInstanceThread.detach(); +} + obs_properties_t *MacroSegmentScriptEdit::GetProperties(void *obj) { auto segmentEdit = reinterpret_cast(obj); diff --git a/lib/macro/macro-segment-script.hpp b/lib/macro/macro-segment-script.hpp index 0bf9dda5..8c9a2796 100644 --- a/lib/macro/macro-segment-script.hpp +++ b/lib/macro/macro-segment-script.hpp @@ -15,9 +15,20 @@ class MacroSegmentScript { public: MacroSegmentScript(obs_data_t *defaultSettings, const std::string &propertiesSignalName, - const std::string &triggerSignal, - const std::string &completionSignal); + const std::string &triggerSignalName, + const std::string &completionSignalName, + const std::string &newInstanceSignalName, + const std::string &deletedInstanceSignalName); MacroSegmentScript(const advss::MacroSegmentScript &); + virtual ~MacroSegmentScript(); + + static void RegisterTempVar(const std::string &variableId, + const std::string &name, + const std::string &helpText, + int instanceId); + static void DeregisterAllTempVars(int instanceId); + static void SetTempVarValue(const std::string &variableId, + const std::string &value, int instanceId); protected: bool Save(obs_data_t *obj) const; @@ -31,15 +42,27 @@ protected: double GetTimeoutSeconds() const { return _timeout.Seconds(); }; bool TriggerIsCompleted() const { return _triggerIsComplete; } + virtual void RegisterTempVarHelper(const std::string &variableId, + const std::string &name, + const std::string &helpText) = 0; + virtual void DeregisterAllTempVarsHelper() = 0; + virtual void SetTempVarValueHelper(const std::string &variableId, + const std::string &value) = 0; + + const int64_t _instanceId; + private: virtual void WaitForCompletion() const = 0; static void CompletionSignalReceived(void *param, calldata_t *data); + void SignalNewInstance() const; OBSDataAutoRelease _settings; std::string _propertiesSignal = ""; std::string _triggerSignal = ""; std::string _completionSignal = ""; + std::string _newInstanceSignal = ""; + std::string _deletedInstanceSignal = ""; std::atomic_bool _triggerIsComplete = {false}; bool _triggerResult = false; int64_t _completionId = 0;