mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
1 Commits
now-playin
...
flatpak
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2ad1ced77 |
@@ -904,19 +904,9 @@ 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"
|
||||
AdvSceneSwitcher.condition.nowPlaying="Now Playing"
|
||||
AdvSceneSwitcher.condition.nowPlaying.checkType.playbackState="Playback state"
|
||||
AdvSceneSwitcher.condition.nowPlaying.checkType.title="Title"
|
||||
AdvSceneSwitcher.condition.nowPlaying.checkType.artist="Artist"
|
||||
AdvSceneSwitcher.condition.nowPlaying.checkType.album="Album"
|
||||
AdvSceneSwitcher.condition.nowPlaying.checkType.appName="App name"
|
||||
AdvSceneSwitcher.condition.nowPlaying.playbackState.playing="Playing"
|
||||
AdvSceneSwitcher.condition.nowPlaying.playbackState.paused="Paused"
|
||||
AdvSceneSwitcher.condition.nowPlaying.playbackState.stopped="Stopped"
|
||||
AdvSceneSwitcher.condition.nowPlaying.playbackState.opening="Opening"
|
||||
AdvSceneSwitcher.condition.nowPlaying.playbackState.changing="Changing"
|
||||
AdvSceneSwitcher.condition.mqtt="MQTT"
|
||||
AdvSceneSwitcher.condition.mqtt.layout.match="Message was received from{{connection}} which matches{{regex}}:"
|
||||
AdvSceneSwitcher.condition.mqtt.layout.listen="Set message selection to incoming message:{{listenButton}}"
|
||||
@@ -2609,12 +2599,6 @@ AdvSceneSwitcher.tempVar.gameCapture.class.description="Window class of the appl
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable="Executable"
|
||||
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
||||
|
||||
AdvSceneSwitcher.tempVar.nowPlaying.title="Title"
|
||||
AdvSceneSwitcher.tempVar.nowPlaying.artist="Artist"
|
||||
AdvSceneSwitcher.tempVar.nowPlaying.album="Album"
|
||||
AdvSceneSwitcher.tempVar.nowPlaying.appName="App name"
|
||||
AdvSceneSwitcher.tempVar.nowPlaying.playbackStatus="Playback status"
|
||||
|
||||
AdvSceneSwitcher.tempVar.http.status="Status code"
|
||||
AdvSceneSwitcher.tempVar.http.error="Error"
|
||||
AdvSceneSwitcher.tempVar.http.error.description="Empty when no error occurred.\nOther possible values:\n\n * Could not establish connection\n * Failed to bind IP address\n * Failed to read connection\n * Failed to write connection\n * Maximum redirect count exceeded\n * Connection handling canceled\n * SSL connection failed\n * SSL certificate loading failed\n * SSL server verification failed\n * Unsupported HTTP multipart boundary characters\n * Compression failed\n * Connection timed out\n * Proxy connection failed\n * Unknown"
|
||||
@@ -3123,3 +3107,4 @@ AdvSceneSwitcher.sceneGroupTab.defaultname="Scene Group %1"
|
||||
AdvSceneSwitcher.sceneGroupTab.exists="Scene Group or Scene name exists already"
|
||||
AdvSceneSwitcher.sceneGroupTab.help="Scene Groups can be selected as a target just like a regular scene.\n\nAs the name suggests a scene group is a collection of multiple scenes.\nThe scene group will advance through the list of its assigned scenes depending on the configured settings, which can be found on the right side.\n\nYou can configure the scene group to advance to the next scene in the list:\nAfter a number of times the scene group is selected as a target.\nAfter a certain amount of time has passed.\nOr randomly.\n\nFor example, a scene group containing the scenes ...\nScene 1\nScene 2\nScene 3 \n... will activate \"Scene 1\" the first time it is selected as a target.\nThe second time it will activate \"Scene 2\".\nThe remaining times \"Scene 3\" will be activated.\n\nClick the highlighted plus symbol below to add a new scene group."
|
||||
AdvSceneSwitcher.sceneGroupTab.scenes.help="Select the scene group you want to modify on the left.\n\nSelect a scene to add to this scene group by selecting the scene above and clicking the plus symbol below.\n\nA scene can be added multiple times to the same scene group."
|
||||
AdvSceneSwitcher.kwin.flatpakPermissionWarning="Window detection via KWin is unavailable.\nThe OBS Studio Flatpak requires additional permissions to enable this feature.\nSee the Advanced Scene Switcher wiki for details."
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#include "platform-funcs.hpp"
|
||||
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "plugin-state-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
@@ -628,27 +632,39 @@ int ignoreXerror(Display *d, XErrorEvent *e)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handleKWinInitFailure(bool kwinAvailable)
|
||||
{
|
||||
blog(LOG_INFO, "not using KWin compat");
|
||||
const bool onKDE = qEnvironmentVariable("XDG_CURRENT_DESKTOP")
|
||||
.contains("KDE", Qt::CaseInsensitive);
|
||||
const bool inFlatpak = qEnvironmentVariableIsSet("FLATPAK_ID");
|
||||
if (!kwinAvailable && onKDE && inFlatpak)
|
||||
AddFinishedLoadingStep([]() {
|
||||
DisplayTrayMessage(
|
||||
obs_module_text("AdvSceneSwitcher.pluginName"),
|
||||
obs_module_text("AdvSceneSwitcher.kwin.flatpakPermissionWarning"));
|
||||
});
|
||||
}
|
||||
|
||||
void PlatformInit()
|
||||
{
|
||||
const bool kwinAvailable = isKWinAvailable();
|
||||
KWin = kwinAvailable && registerKWinDBusListener(¬ifier) &&
|
||||
startKWinScript(KWinScriptObjectPath);
|
||||
if (KWin)
|
||||
blog(LOG_INFO, "using KWin compat");
|
||||
else
|
||||
handleKWinInitFailure(kwinAvailable);
|
||||
|
||||
initProcps();
|
||||
initProc2();
|
||||
|
||||
auto display = disp();
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
|
||||
KWin = isKWinAvailable();
|
||||
if (!(KWin && startKWinScript(KWinScriptObjectPath) &&
|
||||
registerKWinDBusListener(¬ifier))) {
|
||||
// something bad happened while trying to initialize
|
||||
// the KWin script/dbus so disable it
|
||||
KWin = false;
|
||||
blog(LOG_INFO, "not using KWin compat");
|
||||
} else {
|
||||
blog(LOG_INFO, "using KWin compat");
|
||||
}
|
||||
|
||||
initXss();
|
||||
initProcps();
|
||||
initProc2();
|
||||
XSetErrorHandler(ignoreXerror);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileDevice>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextStream>
|
||||
#include <QtDBus/QDBusConnectionInterface>
|
||||
#include <QtDBus/QDBusInterface>
|
||||
@@ -97,11 +98,13 @@ bool isKWinAvailable()
|
||||
bool startKWinScript(QString &scriptObjectPath)
|
||||
{
|
||||
const QString scriptPath =
|
||||
"/tmp/AdvancedSceneSwitcher/KWinFocusNotifier.js";
|
||||
QStandardPaths::writableLocation(
|
||||
QStandardPaths::RuntimeLocation) +
|
||||
"/AdvancedSceneSwitcher/KWinFocusNotifier.js";
|
||||
|
||||
const QString script =
|
||||
R"(var adss = "com.github.AdvancedSceneSwitcher";
|
||||
var adssPath = "/com/github/AdvancedSceneSwitcher";
|
||||
R"(var adss = "com.obsproject.Studio.Plugin.SceneSwitcher";
|
||||
var adssPath = "/com/obsproject/Studio/Plugin/SceneSwitcher";
|
||||
|
||||
function trackWindow(window) {
|
||||
var id = window.internalId.toString();
|
||||
@@ -129,7 +132,8 @@ workspace.windowActivated.connect(function(client) {
|
||||
}))";
|
||||
|
||||
if (const QDir dir; !dir.mkpath(QFileInfo(scriptPath).absolutePath())) {
|
||||
blog(LOG_ERROR, "error creating /tmp/AdvancedSceneSwitcher");
|
||||
blog(LOG_ERROR,
|
||||
"error creating KWinFocusNotifier script directory");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -198,8 +202,8 @@ bool stopKWinScript(const QString &scriptObjectPath)
|
||||
|
||||
bool registerKWinDBusListener(FocusNotifier *notifier)
|
||||
{
|
||||
static const QString serviceName = "com.github.AdvancedSceneSwitcher";
|
||||
static const QString objectPath = "/com/github/AdvancedSceneSwitcher";
|
||||
static const QString serviceName = "com.obsproject.Studio.Plugin.SceneSwitcher";
|
||||
static const QString objectPath = "/com/obsproject/Studio/Plugin/SceneSwitcher";
|
||||
auto bus = QDBusConnection::sessionBus();
|
||||
|
||||
if (bus.objectRegisteredAt(objectPath)) {
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace advss {
|
||||
|
||||
class FocusNotifier final : public QObject {
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "com.github.AdvancedSceneSwitcher")
|
||||
Q_CLASSINFO("D-Bus Interface", "com.obsproject.Studio.Plugin.SceneSwitcher")
|
||||
|
||||
static std::mutex _mutex;
|
||||
static int activePID;
|
||||
|
||||
@@ -42,7 +42,6 @@ add_plugin(twitch)
|
||||
add_plugin(usb)
|
||||
add_plugin(video)
|
||||
add_plugin(speech)
|
||||
add_plugin(now-playing)
|
||||
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(advanced-scene-switcher-now-playing)
|
||||
|
||||
if(NOT WIN32)
|
||||
message(WARNING "Now playing condition is only supported on Windows.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE)
|
||||
target_sources(${PROJECT_NAME} PRIVATE macro-condition-now-playing.cpp
|
||||
macro-condition-now-playing.hpp)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE windowsapp)
|
||||
|
||||
setup_advss_plugin(${PROJECT_NAME})
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
|
||||
install_advss_plugin(${PROJECT_NAME})
|
||||
@@ -1,338 +0,0 @@
|
||||
#include "macro-condition-now-playing.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "sync-helpers.hpp"
|
||||
|
||||
#include <util/base.h>
|
||||
|
||||
#include <roapi.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Media.Control.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
using namespace winrt::Windows::Media::Control;
|
||||
|
||||
const std::string MacroConditionNowPlaying::id = "now_playing";
|
||||
|
||||
bool MacroConditionNowPlaying::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionNowPlaying::id,
|
||||
{MacroConditionNowPlaying::Create, MacroConditionNowPlayingEdit::Create,
|
||||
"AdvSceneSwitcher.condition.nowPlaying"});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
struct SessionInfo {
|
||||
bool hasSession = false;
|
||||
std::string title;
|
||||
std::string artist;
|
||||
std::string album;
|
||||
std::string appName;
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus playbackStatus =
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus::Closed;
|
||||
};
|
||||
|
||||
static bool initWinRT()
|
||||
{
|
||||
HRESULT hr = RoInitialize(RO_INIT_MULTITHREADED);
|
||||
// S_OK: initialized, S_FALSE: already initialized with same type,
|
||||
// RPC_E_CHANGED_MODE: thread is STA (OBS UI thread) - WinRT still usable
|
||||
return SUCCEEDED(hr) || hr == RPC_E_CHANGED_MODE;
|
||||
}
|
||||
|
||||
static SessionInfo getCurrentSessionInfo()
|
||||
{
|
||||
thread_local bool initialized = initWinRT();
|
||||
(void)initialized;
|
||||
|
||||
SessionInfo info;
|
||||
|
||||
try {
|
||||
auto manager =
|
||||
GlobalSystemMediaTransportControlsSessionManager::
|
||||
RequestAsync()
|
||||
.get();
|
||||
auto session = manager.GetCurrentSession();
|
||||
if (!session) {
|
||||
return info;
|
||||
}
|
||||
|
||||
info.hasSession = true;
|
||||
info.appName = winrt::to_string(session.SourceAppUserModelId());
|
||||
|
||||
auto playbackInfo = session.GetPlaybackInfo();
|
||||
info.playbackStatus = playbackInfo.PlaybackStatus();
|
||||
|
||||
auto props = session.TryGetMediaPropertiesAsync().get();
|
||||
if (props) {
|
||||
info.title = winrt::to_string(props.Title());
|
||||
info.artist = winrt::to_string(props.Artist());
|
||||
info.album = winrt::to_string(props.AlbumTitle());
|
||||
}
|
||||
} catch (const winrt::hresult_error &e) {
|
||||
blog(LOG_WARNING, "now playing: WinRT error 0x%08X",
|
||||
static_cast<uint32_t>(e.code()));
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static std::string PlaybackStatusToString(
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus status)
|
||||
{
|
||||
switch (status) {
|
||||
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Playing:
|
||||
return "Playing";
|
||||
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Paused:
|
||||
return "Paused";
|
||||
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Stopped:
|
||||
return "Stopped";
|
||||
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Opened:
|
||||
return "Opening";
|
||||
case GlobalSystemMediaTransportControlsSessionPlaybackStatus::Changing:
|
||||
return "Changing";
|
||||
default:
|
||||
return "Closed";
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool MacroConditionNowPlaying::CheckCondition()
|
||||
{
|
||||
const auto info = getCurrentSessionInfo();
|
||||
|
||||
SetTempVarValue("title", info.title);
|
||||
SetTempVarValue("artist", info.artist);
|
||||
SetTempVarValue("album", info.album);
|
||||
SetTempVarValue("appName", info.appName);
|
||||
SetTempVarValue("playbackStatus",
|
||||
PlaybackStatusToString(info.playbackStatus));
|
||||
|
||||
if (!info.hasSession) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto textMatches = [this](const std::string &field) -> bool {
|
||||
const QString pattern = QString::fromStdString(_matchText);
|
||||
const QString value = QString::fromStdString(field);
|
||||
if (_regex.Enabled()) {
|
||||
return _regex.Matches(value, pattern);
|
||||
}
|
||||
return value == pattern;
|
||||
};
|
||||
|
||||
switch (_checkType) {
|
||||
case CheckType::PLAYBACK_STATE: {
|
||||
using S =
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus;
|
||||
switch (_playbackState) {
|
||||
case PlaybackState::PLAYING:
|
||||
return info.playbackStatus == S::Playing;
|
||||
case PlaybackState::PAUSED:
|
||||
return info.playbackStatus == S::Paused;
|
||||
case PlaybackState::STOPPED:
|
||||
return info.playbackStatus == S::Stopped;
|
||||
case PlaybackState::OPENING:
|
||||
return info.playbackStatus == S::Opened;
|
||||
case PlaybackState::CHANGING:
|
||||
return info.playbackStatus == S::Changing;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CheckType::TITLE:
|
||||
return textMatches(info.title);
|
||||
case CheckType::ARTIST:
|
||||
return textMatches(info.artist);
|
||||
case CheckType::ALBUM:
|
||||
return textMatches(info.album);
|
||||
case CheckType::APP_NAME:
|
||||
return textMatches(info.appName);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionNowPlaying::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "checkType", static_cast<int>(_checkType));
|
||||
obs_data_set_int(obj, "playbackState",
|
||||
static_cast<int>(_playbackState));
|
||||
_matchText.Save(obj, "matchText");
|
||||
_regex.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionNowPlaying::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_checkType = static_cast<CheckType>(obs_data_get_int(obj, "checkType"));
|
||||
_playbackState = static_cast<PlaybackState>(
|
||||
obs_data_get_int(obj, "playbackState"));
|
||||
_matchText.Load(obj, "matchText");
|
||||
_regex.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroConditionNowPlaying::SetupTempVars()
|
||||
{
|
||||
AddTempvar(
|
||||
"title",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.nowPlaying.title"));
|
||||
AddTempvar(
|
||||
"artist",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.nowPlaying.artist"));
|
||||
AddTempvar(
|
||||
"album",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.nowPlaying.album"));
|
||||
AddTempvar(
|
||||
"appName",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.nowPlaying.appName"));
|
||||
AddTempvar(
|
||||
"playbackStatus",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.nowPlaying.playbackStatus"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void populateCheckTypeSelection(QComboBox *list)
|
||||
{
|
||||
static const std::map<MacroConditionNowPlaying::CheckType, std::string> checkTypes = {
|
||||
{MacroConditionNowPlaying::CheckType::PLAYBACK_STATE,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.checkType.playbackState"},
|
||||
{MacroConditionNowPlaying::CheckType::TITLE,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.checkType.title"},
|
||||
{MacroConditionNowPlaying::CheckType::ARTIST,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.checkType.artist"},
|
||||
{MacroConditionNowPlaying::CheckType::ALBUM,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.checkType.album"},
|
||||
{MacroConditionNowPlaying::CheckType::APP_NAME,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.checkType.appName"},
|
||||
};
|
||||
|
||||
for (const auto &[type, name] : checkTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(type));
|
||||
}
|
||||
}
|
||||
|
||||
static void populatePlaybackStateSelection(QComboBox *list)
|
||||
{
|
||||
static const std::map<MacroConditionNowPlaying::PlaybackState, std::string> playbackStates = {
|
||||
{MacroConditionNowPlaying::PlaybackState::PLAYING,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.playbackState.playing"},
|
||||
{MacroConditionNowPlaying::PlaybackState::PAUSED,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.playbackState.paused"},
|
||||
{MacroConditionNowPlaying::PlaybackState::STOPPED,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.playbackState.stopped"},
|
||||
{MacroConditionNowPlaying::PlaybackState::OPENING,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.playbackState.opening"},
|
||||
{MacroConditionNowPlaying::PlaybackState::CHANGING,
|
||||
"AdvSceneSwitcher.condition.nowPlaying.playbackState.changing"},
|
||||
};
|
||||
|
||||
for (const auto &[state, name] : playbackStates) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(state));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionNowPlayingEdit::MacroConditionNowPlayingEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionNowPlaying> entryData)
|
||||
: QWidget(parent),
|
||||
_checkType(new QComboBox(this)),
|
||||
_playbackState(new QComboBox(this)),
|
||||
_matchText(new VariableLineEdit(this)),
|
||||
_regex(new RegexConfigWidget(this))
|
||||
{
|
||||
populateCheckTypeSelection(_checkType);
|
||||
populatePlaybackStateSelection(_playbackState);
|
||||
|
||||
connect(_checkType, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &MacroConditionNowPlayingEdit::CheckTypeChanged);
|
||||
connect(_playbackState,
|
||||
QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
||||
&MacroConditionNowPlayingEdit::PlaybackStateChanged);
|
||||
connect(_matchText, &VariableLineEdit::textEdited, this,
|
||||
&MacroConditionNowPlayingEdit::MatchTextChanged);
|
||||
connect(_regex, &RegexConfigWidget::RegexConfigChanged, this,
|
||||
&MacroConditionNowPlayingEdit::RegexChanged);
|
||||
|
||||
_layout = new QHBoxLayout();
|
||||
_layout->addWidget(_checkType);
|
||||
_layout->addWidget(_playbackState);
|
||||
_layout->addWidget(_matchText);
|
||||
_layout->addWidget(_regex);
|
||||
setLayout(_layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_checkType->setCurrentIndex(
|
||||
_checkType->findData(static_cast<int>(_entryData->_checkType)));
|
||||
_playbackState->setCurrentIndex(_playbackState->findData(
|
||||
static_cast<int>(_entryData->_playbackState)));
|
||||
_matchText->setText(QString::fromStdString(_entryData->_matchText));
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::CheckTypeChanged(int)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_checkType =
|
||||
static_cast<MacroConditionNowPlaying::CheckType>(
|
||||
_checkType->currentData().toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::PlaybackStateChanged(int)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_playbackState =
|
||||
static_cast<MacroConditionNowPlaying::PlaybackState>(
|
||||
_playbackState->currentData().toInt());
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::MatchTextChanged(const QString &text)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_matchText = text.toStdString();
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::RegexChanged(const RegexConfig ®ex)
|
||||
{
|
||||
GUARD_LOADING_AND_LOCK();
|
||||
_entryData->_regex = regex;
|
||||
}
|
||||
|
||||
void MacroConditionNowPlayingEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool isStateCheck =
|
||||
_entryData->_checkType ==
|
||||
MacroConditionNowPlaying::CheckType::PLAYBACK_STATE;
|
||||
_playbackState->setVisible(isStateCheck);
|
||||
_matchText->setVisible(!isStateCheck);
|
||||
_regex->setVisible(!isStateCheck);
|
||||
|
||||
if (isStateCheck) {
|
||||
AddStretchIfNecessary(_layout);
|
||||
} else {
|
||||
RemoveStretchIfPresent(_layout);
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
@@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroConditionNowPlaying : public MacroCondition {
|
||||
public:
|
||||
enum class CheckType {
|
||||
PLAYBACK_STATE,
|
||||
TITLE,
|
||||
ARTIST,
|
||||
ALBUM,
|
||||
APP_NAME,
|
||||
};
|
||||
|
||||
enum class PlaybackState {
|
||||
PLAYING,
|
||||
PAUSED,
|
||||
STOPPED,
|
||||
OPENING,
|
||||
CHANGING,
|
||||
};
|
||||
|
||||
MacroConditionNowPlaying(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<MacroConditionNowPlaying>(m);
|
||||
}
|
||||
|
||||
CheckType _checkType = CheckType::PLAYBACK_STATE;
|
||||
PlaybackState _playbackState = PlaybackState::PLAYING;
|
||||
StringVariable _matchText;
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionNowPlayingEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionNowPlayingEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionNowPlaying> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionNowPlayingEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionNowPlaying>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void CheckTypeChanged(int);
|
||||
void PlaybackStateChanged(int);
|
||||
void MatchTextChanged(const QString &);
|
||||
void RegexChanged(const RegexConfig &);
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QHBoxLayout *_layout;
|
||||
QComboBox *_checkType;
|
||||
QComboBox *_playbackState;
|
||||
VariableLineEdit *_matchText;
|
||||
RegexConfigWidget *_regex;
|
||||
|
||||
std::shared_ptr<MacroConditionNowPlaying> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
Reference in New Issue
Block a user