mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-05-09 04:32:13 -05:00
Merge 6d7e23c88f into 873e073eb6
This commit is contained in:
commit
3a135de1b5
|
|
@ -99,7 +99,6 @@ AdvSceneSwitcher.macroList.deleted="gelöscht"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" ist bereits ausgewählt!"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Eintrag ignorieren"
|
||||
AdvSceneSwitcher.logic.and="Und"
|
||||
AdvSceneSwitcher.logic.or="Oder"
|
||||
AdvSceneSwitcher.logic.andNot="Und nicht"
|
||||
|
|
|
|||
|
|
@ -306,7 +306,6 @@ AdvSceneSwitcher.macroList.deleted="deleted"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" is alreay selected!"
|
||||
|
||||
# Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Ignore entry"
|
||||
AdvSceneSwitcher.logic.and="And"
|
||||
AdvSceneSwitcher.logic.or="Or"
|
||||
AdvSceneSwitcher.logic.andNot="And not"
|
||||
|
|
@ -1076,8 +1075,8 @@ AdvSceneSwitcher.action.macro.type.runActions="Run macro actions"
|
|||
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Do not consider condition state"
|
||||
AdvSceneSwitcher.action.macro.type.run.conditions.true="Only if conditions evaluate to true"
|
||||
AdvSceneSwitcher.action.macro.type.run.conditions.false="Only if conditions evaluate to false"
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Reevaluate the condition state before executing this action"
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nCheck this option if you want those side effects to be taken into account when evaluating the condition state."
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Check conditions now, even if macro is paused"
|
||||
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nAdditionally, paused macros are assumed to not match their conditions.\nCheck this option to force a fresh condition evaluation before running this action, regardless of whether the macro is paused."
|
||||
AdvSceneSwitcher.action.macro.type.run.actionType.regular="actions"
|
||||
AdvSceneSwitcher.action.macro.type.run.actionType.else="else-actions"
|
||||
AdvSceneSwitcher.action.macro.type.run.skipWhenPaused="Skip execution when macro is paused"
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la ma
|
|||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente"
|
||||
|
||||
; Lógica de macros
|
||||
AdvSceneSwitcher.logic.none="Omitir entrada"
|
||||
AdvSceneSwitcher.logic.and="Y"
|
||||
AdvSceneSwitcher.logic.or="O"
|
||||
AdvSceneSwitcher.logic.andNot="Y no"
|
||||
|
|
|
|||
|
|
@ -131,7 +131,6 @@ AdvSceneSwitcher.macroList.deleted="supprimé"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" est déjà sélectionné !"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Ignorer l'entrée"
|
||||
AdvSceneSwitcher.logic.and="Et"
|
||||
AdvSceneSwitcher.logic.or="Ou"
|
||||
AdvSceneSwitcher.logic.andNot="Et pas"
|
||||
|
|
|
|||
|
|
@ -275,7 +275,6 @@ AdvSceneSwitcher.macroList.deleted="削除"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" はすでに選択されています!"
|
||||
|
||||
# Macro Logic
|
||||
AdvSceneSwitcher.logic.none="入力無視"
|
||||
; AdvSceneSwitcher.logic.and="And"
|
||||
; AdvSceneSwitcher.logic.or="Or"
|
||||
; AdvSceneSwitcher.logic.andNot="And not"
|
||||
|
|
|
|||
|
|
@ -239,7 +239,6 @@ AdvSceneSwitcher.macroList.deleted="excluída"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" já está selecionada!"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Ignorar entrada"
|
||||
AdvSceneSwitcher.logic.and="E"
|
||||
AdvSceneSwitcher.logic.or="Ou"
|
||||
AdvSceneSwitcher.logic.andNot="E não"
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ AdvSceneSwitcher.macroTab.name="Имя:"
|
|||
AdvSceneSwitcher.macroTab.defaultname="Макрос %1"
|
||||
AdvSceneSwitcher.macroTab.copy="Создать копию"
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Игнорировать вход"
|
||||
AdvSceneSwitcher.logic.and="И"
|
||||
AdvSceneSwitcher.logic.or="Или"
|
||||
AdvSceneSwitcher.logic.andNot="И не"
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@ AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
|
|||
AdvSceneSwitcher.macroTab.collapseAll="Hepsini Küçült"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="Girişi yoksay"
|
||||
AdvSceneSwitcher.logic.and="Ve"
|
||||
AdvSceneSwitcher.logic.or="Ya da"
|
||||
AdvSceneSwitcher.logic.andNot="ve değil"
|
||||
|
|
|
|||
|
|
@ -259,7 +259,6 @@ AdvSceneSwitcher.macroList.deleted="删除"
|
|||
AdvSceneSwitcher.macroList.duplicate="\"%1\" 已选择!"
|
||||
|
||||
; Macro Logic
|
||||
AdvSceneSwitcher.logic.none="忽略条件"
|
||||
AdvSceneSwitcher.logic.and="且"
|
||||
AdvSceneSwitcher.logic.or="或"
|
||||
AdvSceneSwitcher.logic.andNot="且不"
|
||||
|
|
|
|||
|
|
@ -506,6 +506,8 @@ bool SwitcherData::AnySceneTransitionStarted()
|
|||
******************************************************************************/
|
||||
extern "C" EXPORT void FreeSceneSwitcher()
|
||||
{
|
||||
switcher->Stop();
|
||||
|
||||
PlatformCleanup();
|
||||
RunPluginCleanupSteps();
|
||||
|
||||
|
|
|
|||
|
|
@ -871,6 +871,8 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||
} else {
|
||||
_noConditionsWarning->setVisible(false);
|
||||
}
|
||||
_runMacroHelp->setVisible(action ==
|
||||
MacroActionMacro::Action::RUN_MACRO);
|
||||
|
||||
_nestedMacro->setVisible(action ==
|
||||
MacroActionMacro::Action::NESTED_MACRO);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "path-helpers.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "section.hpp"
|
||||
#include "switch-button.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
|
|
@ -102,12 +103,15 @@ MacroConditionEdit::MacroConditionEdit(
|
|||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||
bool isRootCondition)
|
||||
: MacroSegmentEdit(parent),
|
||||
_enable(new SwitchButton()),
|
||||
_logicSelection(new QComboBox()),
|
||||
_conditionSelection(new FilterComboBox()),
|
||||
_dur(new DurationModifierEdit()),
|
||||
_entryData(entryData),
|
||||
_isRoot(isRootCondition)
|
||||
{
|
||||
QWidget::connect(_enable, SIGNAL(checked(bool)), this,
|
||||
SLOT(ConditionEnableChanged(bool)));
|
||||
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(LogicSelectionChanged(int)));
|
||||
QWidget::connect(_conditionSelection,
|
||||
|
|
@ -122,6 +126,7 @@ MacroConditionEdit::MacroConditionEdit(
|
|||
Logic::PopulateLogicTypeSelection(_logicSelection, isRootCondition);
|
||||
populateConditionSelection(_conditionSelection);
|
||||
|
||||
_section->AddHeaderWidget(_enable);
|
||||
_section->AddHeaderWidget(_logicSelection);
|
||||
_section->AddHeaderWidget(_conditionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
|
|
@ -154,8 +159,17 @@ void MacroConditionEdit::LogicSelectionChanged(int idx)
|
|||
const auto logic = static_cast<Logic::Type>(
|
||||
_logicSelection->itemData(idx).toInt());
|
||||
(*_entryData)->SetLogicType(logic);
|
||||
}
|
||||
|
||||
SetEnableAppearance(logic != Logic::Type::NONE);
|
||||
void MacroConditionEdit::ConditionEnableChanged(bool value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
(*_entryData)->SetEnabled(value);
|
||||
SetDisableEffect(!value);
|
||||
}
|
||||
|
||||
bool MacroConditionEdit::IsRootNode() const
|
||||
|
|
@ -168,7 +182,9 @@ void MacroConditionEdit::SetLogicSelection()
|
|||
const auto logic = (*_entryData)->GetLogicType();
|
||||
_logicSelection->setCurrentIndex(
|
||||
_logicSelection->findData(static_cast<int>(logic)));
|
||||
SetEnableAppearance(logic != Logic::Type::NONE);
|
||||
const bool enabled = (*_entryData)->Enabled();
|
||||
_enable->setChecked(enabled);
|
||||
SetEnableAppearance(enabled);
|
||||
}
|
||||
|
||||
void MacroConditionEdit::SetRootNode(bool root)
|
||||
|
|
@ -239,10 +255,12 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||
{
|
||||
auto lock = LockContext();
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
const bool enabled = (*_entryData)->Enabled();
|
||||
_entryData->reset();
|
||||
*_entryData = MacroConditionFactory::Create(id, macro);
|
||||
(*_entryData)->SetIndex(idx);
|
||||
(*_entryData)->SetLogicType(logic);
|
||||
(*_entryData)->SetEnabled(enabled);
|
||||
(*_entryData)->PostLoad();
|
||||
RunAndClearPostLoadSteps();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
namespace advss {
|
||||
|
||||
class SwitchButton;
|
||||
|
||||
class DurationModifierEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
@ -47,11 +49,13 @@ private slots:
|
|||
void ConditionSelectionChanged(const QString &text);
|
||||
void DurationChanged(const Duration &value);
|
||||
void DurationModifierChanged(DurationModifier::Type m);
|
||||
void ConditionEnableChanged(bool);
|
||||
|
||||
private:
|
||||
void SetLogicSelection();
|
||||
std::shared_ptr<MacroSegment> Data() const;
|
||||
|
||||
SwitchButton *_enable;
|
||||
QComboBox *_logicSelection;
|
||||
FilterComboBox *_conditionSelection;
|
||||
DurationModifierEdit *_dur;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ bool MacroCondition::Load(obs_data_t *obj)
|
|||
{
|
||||
MacroSegment::Load(obj);
|
||||
_logic.Load(obj, "logic");
|
||||
if (_logic.GetType() == Logic::Type::NONE) {
|
||||
SetEnabled(false);
|
||||
_logic.SetType(Logic::Type::AND);
|
||||
}
|
||||
_durationModifier.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -50,7 +54,8 @@ void MacroCondition::ValidateLogicSelection(bool isRootCondition,
|
|||
return;
|
||||
}
|
||||
|
||||
_logic.SetType(Logic::Type::NONE);
|
||||
_logic.SetType(Logic::Type::AND);
|
||||
SetEnabled(false);
|
||||
blog(LOG_WARNING,
|
||||
"setting invalid logic selection to 'ignore' for macro %s",
|
||||
context);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ bool MacroSegment::Save(obs_data_t *obj) const
|
|||
obs_data_set_bool(data, "useCustomLabel", _useCustomLabel);
|
||||
obs_data_set_string(data, "customLabel", _customLabel.c_str());
|
||||
obs_data_set_bool(data, "enabled", _enabled);
|
||||
obs_data_set_int(data, "version", 1);
|
||||
obs_data_set_int(data, "version", 2);
|
||||
|
||||
OBSDataArrayAutoRelease mappingsArray = obs_data_array_create();
|
||||
for (const auto &mapping : _varMappings) {
|
||||
|
|
@ -112,6 +112,12 @@ bool MacroSegment::Load(obs_data_t *obj)
|
|||
_enabled = obs_data_get_bool(obj, "enabled");
|
||||
}
|
||||
|
||||
// Reset the previously unused "enabled" value for conditions to "true"
|
||||
if (obs_data_get_int(data, "version") < 2 &&
|
||||
obs_data_has_user_value(obj, "logic")) {
|
||||
_enabled = true;
|
||||
}
|
||||
|
||||
_varMappings.clear();
|
||||
OBSDataArrayAutoRelease mappingsArray =
|
||||
obs_data_get_array(data, "varMappings");
|
||||
|
|
|
|||
|
|
@ -557,6 +557,10 @@ void AdvSceneSwitcher::HighlightOnChange() const
|
|||
return;
|
||||
}
|
||||
|
||||
if (macro->Paused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (macro->ActionTriggerModePreventedActionsSince(
|
||||
lastOnChangeHighlightCheckTime)) {
|
||||
HighlightWidget(ui->actionTriggerMode, Qt::yellow,
|
||||
|
|
|
|||
|
|
@ -157,6 +157,15 @@ bool Macro::CheckConditionHelper(
|
|||
return conditionMatched;
|
||||
};
|
||||
|
||||
if (!condition->Enabled()) {
|
||||
vblog(LOG_INFO, "ignoring condition '%s' for '%s'",
|
||||
condition->GetId().c_str(), _name.c_str());
|
||||
if (!_useShortCircuitEvaluation) {
|
||||
(void)evaluateCondition();
|
||||
}
|
||||
return _matched;
|
||||
}
|
||||
|
||||
const auto logicType = condition->GetLogicType();
|
||||
if (logicType == Logic::Type::NONE) {
|
||||
vblog(LOG_INFO, "ignoring condition '%s' for '%s'",
|
||||
|
|
@ -281,7 +290,7 @@ bool Macro::CheckConditions(bool ignorePause)
|
|||
|
||||
const bool hasActionsToExecute = _matched ? (_actions.size() > 0)
|
||||
: (_elseActions.size() > 0);
|
||||
if (!_actionModeMatch && hasActionsToExecute) {
|
||||
if (!_actionModeMatch && hasActionsToExecute && !_paused) {
|
||||
_lastActionRunModePreventTime =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
|
@ -380,7 +389,7 @@ bool Macro::ShouldRunActions() const
|
|||
!_paused && (_matched || _elseActions.size() > 0) &&
|
||||
_actionModeMatch;
|
||||
|
||||
if (VerboseLoggingEnabled() && !_actionModeMatch) {
|
||||
if (VerboseLoggingEnabled() && !_actionModeMatch && !_paused) {
|
||||
if (_matched && _actions.size() > 0) {
|
||||
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
namespace advss {
|
||||
|
||||
const std::map<Logic::Type, const char *> Logic::localeMap = {
|
||||
{Logic::Type::NONE, {"AdvSceneSwitcher.logic.none"}},
|
||||
{Logic::Type::AND, {"AdvSceneSwitcher.logic.and"}},
|
||||
{Logic::Type::OR, {"AdvSceneSwitcher.logic.or"}},
|
||||
{Logic::Type::AND_NOT, {"AdvSceneSwitcher.logic.andNot"}},
|
||||
|
|
@ -67,7 +66,7 @@ void Logic::PopulateLogicTypeSelection(QComboBox *list, bool isRootCondition)
|
|||
return typeValue < rootOffset;
|
||||
}}
|
||||
: std::function<bool(int)>{[](int typeValue) {
|
||||
return typeValue >= rootOffset;
|
||||
return typeValue > rootOffset;
|
||||
}};
|
||||
for (const auto &[type, name] : localeMap) {
|
||||
const int typeValue = static_cast<int>(type);
|
||||
|
|
|
|||
|
|
@ -75,6 +75,18 @@ static std::vector<std::function<void()>> &getStopSteps()
|
|||
return steps;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void(obs_data_t *)>> &getEarlySaveSteps()
|
||||
{
|
||||
static std::vector<std::function<void(obs_data_t *)>> steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void(obs_data_t *)>> &getEarlyLoadSteps()
|
||||
{
|
||||
static std::vector<std::function<void(obs_data_t *)>> steps;
|
||||
return steps;
|
||||
}
|
||||
|
||||
static std::vector<std::function<void(obs_data_t *)>> &getSaveSteps()
|
||||
{
|
||||
static std::vector<std::function<void(obs_data_t *)>> steps;
|
||||
|
|
@ -109,6 +121,18 @@ void LoadPluginSettings(obs_data_t *obj)
|
|||
GetSwitcher()->LoadSettings(obj);
|
||||
}
|
||||
|
||||
void AddEarlySaveStep(std::function<void(obs_data_t *)> step)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
getEarlySaveSteps().emplace_back(step);
|
||||
}
|
||||
|
||||
void AddEarlyLoadStep(std::function<void(obs_data_t *)> step)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
getEarlyLoadSteps().emplace_back(step);
|
||||
}
|
||||
|
||||
void AddSaveStep(std::function<void(obs_data_t *)> step)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
|
@ -136,6 +160,9 @@ void AddIntervalResetStep(std::function<void()> step)
|
|||
void RunSaveSteps(obs_data_t *obj)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
for (const auto &func : getEarlySaveSteps()) {
|
||||
func(obj);
|
||||
}
|
||||
for (const auto &func : getSaveSteps()) {
|
||||
func(obj);
|
||||
}
|
||||
|
|
@ -144,6 +171,9 @@ void RunSaveSteps(obs_data_t *obj)
|
|||
void RunLoadSteps(obs_data_t *obj)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
for (const auto &func : getEarlyLoadSteps()) {
|
||||
func(obj);
|
||||
}
|
||||
for (const auto &func : getLoadSteps()) {
|
||||
func(obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ namespace advss {
|
|||
void SavePluginSettings(obs_data_t *);
|
||||
EXPORT void LoadPluginSettings(obs_data_t *);
|
||||
|
||||
void AddEarlySaveStep(std::function<void(obs_data_t *)>);
|
||||
void AddEarlyLoadStep(std::function<void(obs_data_t *)>);
|
||||
EXPORT void AddSaveStep(std::function<void(obs_data_t *)>);
|
||||
EXPORT void AddLoadStep(std::function<void(obs_data_t *)>);
|
||||
EXPORT void AddPostLoadStep(std::function<void()>);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ static void load(obs_data_t *data)
|
|||
{
|
||||
tabSettings.Load(data, "tabSettings");
|
||||
dockSettings.Load(data, "dockSettings");
|
||||
|
||||
enableDock(obs_data_get_bool(data, "addVariablesDock"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ static std::chrono::high_resolution_clock::time_point lastVariableChange{};
|
|||
|
||||
static bool setup()
|
||||
{
|
||||
AddSaveStep(SaveVariables);
|
||||
AddLoadStep(LoadVariables);
|
||||
AddEarlySaveStep(SaveVariables);
|
||||
AddEarlyLoadStep(LoadVariables);
|
||||
AddPluginCleanupStep([]() { variables.clear(); });
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
#include "platform-funcs.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
|
||||
#include <windows.h>
|
||||
#include <UIAutomation.h>
|
||||
#include <util/platform.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <Psapi.h>
|
||||
#include <memory>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <string>
|
||||
|
|
@ -16,6 +18,9 @@
|
|||
#include <QWidget>
|
||||
#include <mutex>
|
||||
|
||||
#define ADVSS_WIDEN_(x) L##x
|
||||
#define ADVSS_WIDEN(x) ADVSS_WIDEN_(x)
|
||||
|
||||
namespace advss {
|
||||
|
||||
#define MAX_SEARCH 1000
|
||||
|
|
@ -500,9 +505,86 @@ int SecondsSinceLastInput()
|
|||
return (getTime() - getLastInputTime()) / 1000;
|
||||
}
|
||||
|
||||
static void addPluginFolderToSymbolPath()
|
||||
{
|
||||
// This runs after OBS_FRONTEND_EVENT_FINISHED_LOADING, which fires after
|
||||
// obs_load_all_modules() completes. By that point OBS has already called
|
||||
// reset_win32_symbol_paths() -> SymInitializeW(), so DbgHelp is
|
||||
// initialized and we can append our plugins subfolder (where the PDB
|
||||
// files live) to the existing search path.
|
||||
HMODULE dbghelp = LoadLibraryW(L"DbgHelp");
|
||||
if (!dbghelp) {
|
||||
return;
|
||||
}
|
||||
|
||||
typedef BOOL(WINAPI * SymGetSearchPathW_t)(HANDLE, PWSTR, DWORD);
|
||||
typedef BOOL(WINAPI * SymSetSearchPathW_t)(HANDLE, PCWSTR);
|
||||
typedef BOOL(WINAPI * SymRefreshModuleList_t)(HANDLE);
|
||||
|
||||
auto symGetSearchPathW = reinterpret_cast<SymGetSearchPathW_t>(
|
||||
GetProcAddress(dbghelp, "SymGetSearchPathW"));
|
||||
auto symSetSearchPathW = reinterpret_cast<SymSetSearchPathW_t>(
|
||||
GetProcAddress(dbghelp, "SymSetSearchPathW"));
|
||||
auto symRefreshModuleList = reinterpret_cast<SymRefreshModuleList_t>(
|
||||
GetProcAddress(dbghelp, "SymRefreshModuleList"));
|
||||
|
||||
if (!symGetSearchPathW || !symSetSearchPathW || !symRefreshModuleList) {
|
||||
FreeLibrary(dbghelp);
|
||||
return;
|
||||
}
|
||||
|
||||
HMODULE hModule = NULL;
|
||||
if (!GetModuleHandleExW(
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
|
||||
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
reinterpret_cast<LPCWSTR>(addPluginFolderToSymbolPath),
|
||||
&hModule)) {
|
||||
FreeLibrary(dbghelp);
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t dllDir[MAX_PATH];
|
||||
if (!GetModuleFileNameW(hModule, dllDir, MAX_PATH)) {
|
||||
FreeLibrary(dbghelp);
|
||||
return;
|
||||
}
|
||||
|
||||
wchar_t *lastSep = wcsrchr(dllDir, L'\\');
|
||||
if (!lastSep) {
|
||||
FreeLibrary(dbghelp);
|
||||
return;
|
||||
}
|
||||
*lastSep = L'\0';
|
||||
|
||||
wchar_t pluginsPath[MAX_PATH];
|
||||
wcsncpy_s(pluginsPath, MAX_PATH, dllDir, _TRUNCATE);
|
||||
wcsncat_s(pluginsPath, MAX_PATH, L"\\" ADVSS_WIDEN(ADVSS_PLUGIN_FOLDER),
|
||||
_TRUNCATE);
|
||||
|
||||
constexpr DWORD currentPathLen = 4096;
|
||||
constexpr DWORD newPathLen = 8192;
|
||||
auto currentPath = std::make_unique<wchar_t[]>(currentPathLen);
|
||||
auto newPath = std::make_unique<wchar_t[]>(newPathLen);
|
||||
|
||||
symGetSearchPathW(GetCurrentProcess(), currentPath.get(),
|
||||
currentPathLen);
|
||||
|
||||
if (currentPath[0] != L'\0') {
|
||||
_snwprintf_s(newPath.get(), newPathLen, _TRUNCATE, L"%s;%s",
|
||||
currentPath.get(), pluginsPath);
|
||||
} else {
|
||||
wcsncpy_s(newPath.get(), newPathLen, pluginsPath, _TRUNCATE);
|
||||
}
|
||||
|
||||
symSetSearchPathW(GetCurrentProcess(), newPath.get());
|
||||
symRefreshModuleList(GetCurrentProcess());
|
||||
FreeLibrary(dbghelp);
|
||||
}
|
||||
|
||||
void PlatformInit()
|
||||
{
|
||||
CoInitialize(NULL);
|
||||
AddFinishedLoadingStep(addPluginFolderToSymbolPath);
|
||||
}
|
||||
|
||||
void PlatformCleanup()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ namespace advss {
|
|||
|
||||
void SavePluginSettings(obs_data_t *) {}
|
||||
void LoadPluginSettings(obs_data_t *) {}
|
||||
void AddEarlySaveStep(std::function<void(obs_data_t *)>) {}
|
||||
void AddEarlyLoadStep(std::function<void(obs_data_t *)>) {}
|
||||
void AddSaveStep(std::function<void(obs_data_t *)>) {}
|
||||
void AddLoadStep(std::function<void(obs_data_t *)>) {}
|
||||
void AddPostLoadStep(std::function<void()>) {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user