mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Add game capture condition
This commit is contained in:
parent
ef5cf41d34
commit
4e51b56b9b
|
|
@ -769,6 +769,8 @@ AdvSceneSwitcher.condition.streamDeck.checkData="Check data field"
|
|||
AdvSceneSwitcher.condition.streamDeck.startListen="Start listening"
|
||||
AdvSceneSwitcher.condition.streamDeck.stopListen="Stop listening"
|
||||
AdvSceneSwitcher.condition.streamDeck.pluginDownload="<html><head/><body><p>The Stream Deck plugin can be found <a href=\"https://github.com/WarmUpTill/advanced-scene-switcher-streamdeck-plugin/releases\"><span style=\" text-decoration: underline; color:#268bd2;\">here on GitHub</span></a>.</p></body></html>"
|
||||
AdvSceneSwitcher.condition.gameCapture="Game capture"
|
||||
AdvSceneSwitcher.condition.gameCapture.entry="{{sources}}hooked a game."
|
||||
|
||||
AdvSceneSwitcher.condition.screenshot="Screenshot"
|
||||
AdvSceneSwitcher.condition.screenshot.entry="A screenshot was taken"
|
||||
|
|
@ -1980,6 +1982,13 @@ AdvSceneSwitcher.tempVar.queue.running.description="Returns \"true\" if the queu
|
|||
AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath="Last screenshot path"
|
||||
AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath.description="The filesystem path to the last screenshot taken."
|
||||
|
||||
AdvSceneSwitcher.tempVar.gameCapture.title="Title"
|
||||
AdvSceneSwitcher.tempVar.gameCapture.title.description="Window title of the application captured by the source."
|
||||
AdvSceneSwitcher.tempVar.gameCapture.class="Class"
|
||||
AdvSceneSwitcher.tempVar.gameCapture.class.description="Window class of the application captured by the source."
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable="Executable"
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ target_sources(
|
|||
macro-condition-filter.hpp
|
||||
macro-condition-folder.cpp
|
||||
macro-condition-folder.hpp
|
||||
macro-condition-game-capture.cpp
|
||||
macro-condition-game-capture.hpp
|
||||
macro-condition-hotkey.cpp
|
||||
macro-condition-hotkey.hpp
|
||||
macro-condition-idle.cpp
|
||||
|
|
|
|||
197
plugins/base/macro-condition-game-capture.cpp
Normal file
197
plugins/base/macro-condition-game-capture.cpp
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
#include "macro-condition-game-capture.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroConditionGameCapture::id = "game_capture";
|
||||
|
||||
#ifdef _WIN32
|
||||
bool MacroConditionGameCapture::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionGameCapture::id,
|
||||
{MacroConditionGameCapture::Create,
|
||||
MacroConditionGameCaptureEdit::Create,
|
||||
"AdvSceneSwitcher.condition.gameCapture"});
|
||||
#else
|
||||
bool MacroConditionGameCapture::_registered =
|
||||
false; // For now the 'game_capture' source only exists on Windows
|
||||
#endif
|
||||
|
||||
bool MacroConditionGameCapture::CheckCondition()
|
||||
{
|
||||
auto source = OBSGetStrongRef(_source.GetSource());
|
||||
if (source != _lastSource) {
|
||||
SetupSignalHandler(source);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(_mtx);
|
||||
if (_hooked) {
|
||||
SetTempVarValue("title", _title);
|
||||
SetTempVarValue("class", _class);
|
||||
SetTempVarValue("executable", _executable);
|
||||
}
|
||||
|
||||
return _hooked;
|
||||
}
|
||||
|
||||
bool MacroConditionGameCapture::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_source.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionGameCapture::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_source.Load(obj);
|
||||
SetupSignalHandler(OBSGetStrongRef(_source.GetSource()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::GetCalldataInfo(calldata_t *cd)
|
||||
{
|
||||
const char *title = "";
|
||||
if (!calldata_get_string(cd, "title", &title)) {
|
||||
blog(LOG_WARNING, "%s failed to get title", __func__);
|
||||
}
|
||||
_title = title;
|
||||
const char *className = "";
|
||||
if (!calldata_get_string(cd, "class", &className)) {
|
||||
blog(LOG_WARNING, "%s failed to get class", __func__);
|
||||
}
|
||||
_class = className;
|
||||
const char *executable = "";
|
||||
if (!calldata_get_string(cd, "executable", &executable)) {
|
||||
blog(LOG_WARNING, "%s failed to get executable", __func__);
|
||||
}
|
||||
_executable = executable;
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::HookedSignalReceived(void *data, calldata_t *cd)
|
||||
{
|
||||
auto condition = static_cast<MacroConditionGameCapture *>(data);
|
||||
std::lock_guard<std::mutex> lock(condition->_mtx);
|
||||
condition->GetCalldataInfo(cd);
|
||||
condition->_hooked = true;
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::UnhookedSignalReceived(void *data, calldata_t *)
|
||||
{
|
||||
auto condition = static_cast<MacroConditionGameCapture *>(data);
|
||||
std::lock_guard<std::mutex> lock(condition->_mtx);
|
||||
condition->_hooked = false;
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
AddTempvar(
|
||||
"title",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.gameCapture.title"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.gameCapture.title.description"));
|
||||
AddTempvar(
|
||||
"class",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.gameCapture.class"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.gameCapture.class.description"));
|
||||
AddTempvar(
|
||||
"executable",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.gameCapture.executable"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.gameCapture.executable.description"));
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::SetupSignalHandler(obs_source_t *source)
|
||||
{
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(source);
|
||||
_hookSignal = OBSSignal(sh, "hooked", HookedSignalReceived, this);
|
||||
_unhookSignal = OBSSignal(sh, "unhooked", UnhookedSignalReceived, this);
|
||||
_lastSource = source;
|
||||
|
||||
SetupInitialState(source);
|
||||
}
|
||||
|
||||
void MacroConditionGameCapture::SetupInitialState(obs_source_t *source)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mtx);
|
||||
|
||||
_hooked = false;
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
calldata_t cd;
|
||||
calldata_init(&cd);
|
||||
auto ph = obs_source_get_proc_handler(source);
|
||||
if (!proc_handler_call(ph, "get_hooked", &cd)) {
|
||||
blog(LOG_WARNING,
|
||||
"%s failed to call proc_handler for 'get_hooked'",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!calldata_get_bool(&cd, "hooked", &_hooked)) {
|
||||
blog(LOG_WARNING, "%s failed to get hooked state", __func__);
|
||||
}
|
||||
GetCalldataInfo(&cd);
|
||||
|
||||
calldata_free(&cd);
|
||||
}
|
||||
|
||||
static QStringList getGameCaptureSourceNames()
|
||||
{
|
||||
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
||||
{
|
||||
QStringList *list = reinterpret_cast<QStringList *>(param);
|
||||
|
||||
if (strcmp(obs_source_get_unversioned_id(source),
|
||||
"game_capture") == 0) {
|
||||
*list << obs_source_get_name(source);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
QStringList list;
|
||||
obs_enum_sources(sourceEnum, &list);
|
||||
return list;
|
||||
}
|
||||
|
||||
MacroConditionGameCaptureEdit::MacroConditionGameCaptureEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionGameCapture> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true))
|
||||
{
|
||||
auto sources = getGameCaptureSourceNames();
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.gameCapture.entry"),
|
||||
layout, {{"{{sources}}", _sources}});
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionGameCaptureEdit::SourceChanged(const SourceSelection &source)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_source = source;
|
||||
}
|
||||
|
||||
void MacroConditionGameCaptureEdit::UpdateEntryData()
|
||||
{
|
||||
_sources->SetSource(_entryData->_source);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
74
plugins/base/macro-condition-game-capture.hpp
Normal file
74
plugins/base/macro-condition-game-capture.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroConditionGameCapture : public MacroCondition {
|
||||
public:
|
||||
MacroConditionGameCapture(Macro *m) : MacroCondition(m) {}
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroConditionGameCapture>(m);
|
||||
}
|
||||
|
||||
SourceSelection _source;
|
||||
|
||||
private:
|
||||
static void HookedSignalReceived(void *data, calldata_t *);
|
||||
static void UnhookedSignalReceived(void *data, calldata_t *);
|
||||
|
||||
void SetupTempVars();
|
||||
void SetupSignalHandler(obs_source_t *source);
|
||||
void SetupInitialState(obs_source_t *source);
|
||||
void GetCalldataInfo(calldata_t *cd);
|
||||
|
||||
obs_source_t *_lastSource = nullptr;
|
||||
OBSSignal _hookSignal;
|
||||
OBSSignal _unhookSignal;
|
||||
|
||||
bool _hooked = false;
|
||||
std::string _title = "";
|
||||
std::string _class = "";
|
||||
std::string _executable = "";
|
||||
std::mutex _mtx;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionGameCaptureEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionGameCaptureEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionGameCapture> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionGameCaptureEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionGameCapture>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
|
||||
private:
|
||||
SourceSelectionWidget *_sources;
|
||||
std::shared_ptr<MacroConditionGameCapture> _entryData;
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
Loading…
Reference in New Issue
Block a user