From e4b060976bb610714860160b5162a3ed2e7743a4 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 22 May 2021 12:44:40 +0200 Subject: [PATCH] Add macro action "media" --- CMakeLists.txt | 6 +- data/locale/en-US.ini | 10 ++ src/headers/macro-action-media.hpp | 62 ++++++++++++ src/macro-action-media.cpp | 153 +++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 src/headers/macro-action-media.hpp create mode 100644 src/macro-action-media.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 01435fd8..def9a5e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,9 @@ set(advanced-scene-switcher_HEADERS src/headers/switch-video.hpp src/headers/switch-generic.hpp src/headers/macro-action-edit.hpp - src/headers/macro-action-filter.hpp src/headers/macro-action-audio.hpp + src/headers/macro-action-filter.hpp + src/headers/macro-action-media.hpp src/headers/macro-action-recording.hpp src/headers/macro-action-replay-buffer.hpp src/headers/macro-action-run.hpp @@ -141,8 +142,9 @@ set(advanced-scene-switcher_SOURCES src/switch-video.cpp src/switch-generic.cpp src/macro-action-edit.cpp - src/macro-action-filter.cpp src/macro-action-audio.cpp + src/macro-action-filter.cpp + src/macro-action-media.cpp src/macro-action-recording.cpp src/macro-action-replay-buffer.cpp src/macro-action-run.cpp diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 8324233a..4c6a443b 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -68,6 +68,7 @@ AdvSceneSwitcher.macroTab.name="Name:" AdvSceneSwitcher.macroTab.defaultname="Macro %1" AdvSceneSwitcher.macroTab.exists="Macro name exists already" AdvSceneSwitcher.macroTab.copy="Create copy" + ; Macro Logic AdvSceneSwitcher.logic.none="Ignore entry" AdvSceneSwitcher.logic.and="And" @@ -76,6 +77,7 @@ AdvSceneSwitcher.logic.andNot="And not" AdvSceneSwitcher.logic.orNot="Or not" AdvSceneSwitcher.logic.rootNone="If" AdvSceneSwitcher.logic.not="If not" + ; Macro Conditions AdvSceneSwitcher.condition.audio="Audio" AdvSceneSwitcher.ondition.audio.state.below="Below" @@ -169,6 +171,14 @@ AdvSceneSwitcher.action.source="Source" AdvSceneSwitcher.action.source.type.enable="Enable" AdvSceneSwitcher.action.source.type.disable="Disable" AdvSceneSwitcher.action.source.entry="{{actions}} {{sources}}" +AdvSceneSwitcher.action.media="Media" +AdvSceneSwitcher.action.media.type.play="Play" +AdvSceneSwitcher.action.media.type.pause="Pause" +AdvSceneSwitcher.action.media.type.stop="Stop" +AdvSceneSwitcher.action.media.type.restart="Restart" +AdvSceneSwitcher.action.media.type.next="Next" +AdvSceneSwitcher.action.media.type.previous="Previous" +AdvSceneSwitcher.action.media.entry="{{actions}} {{mediaSources}}" ; Transition Tab diff --git a/src/headers/macro-action-media.hpp b/src/headers/macro-action-media.hpp new file mode 100644 index 00000000..1ba797c1 --- /dev/null +++ b/src/headers/macro-action-media.hpp @@ -0,0 +1,62 @@ +#pragma once +#include +#include "macro-action-edit.hpp" + +enum class MediaAction { + PLAY, + PAUSE, + STOP, + RESTART, + NEXT, + PREVIOUS, +}; + +class MacroActionMedia : public MacroAction { +public: + bool PerformAction(); + void LogAction(); + bool Save(obs_data_t *obj); + bool Load(obs_data_t *obj); + std::string GetId() { return id; }; + static std::shared_ptr Create() + { + return std::make_shared(); + } + + OBSWeakSource _mediaSource; + MediaAction _action = MediaAction::PLAY; + +private: + static bool _registered; + static const std::string id; +}; + +class MacroActionMediaEdit : public QWidget { + Q_OBJECT + +public: + MacroActionMediaEdit( + QWidget *parent, + std::shared_ptr entryData = nullptr); + void UpdateEntryData(); + static QWidget *Create(QWidget *parent, + std::shared_ptr action) + { + return new MacroActionMediaEdit( + parent, + std::dynamic_pointer_cast(action)); + } + +private slots: + void SourceChanged(const QString &text); + void ActionChanged(int value); + +protected: + QComboBox *_mediaSources; + QComboBox *_actions; + std::shared_ptr _entryData; + +private: + QHBoxLayout *_mainLayout; + bool _loading = true; +}; diff --git a/src/macro-action-media.cpp b/src/macro-action-media.cpp new file mode 100644 index 00000000..827bc583 --- /dev/null +++ b/src/macro-action-media.cpp @@ -0,0 +1,153 @@ +#include "headers/macro-action-media.hpp" +#include "headers/advanced-scene-switcher.hpp" +#include "headers/utility.hpp" + +const std::string MacroActionMedia::id = "media"; + +bool MacroActionMedia::_registered = MacroActionFactory::Register( + MacroActionMedia::id, + {MacroActionMedia::Create, MacroActionMediaEdit::Create, + "AdvSceneSwitcher.action.media"}); + +const static std::map actionTypes = { + {MediaAction::PLAY, "AdvSceneSwitcher.action.media.type.play"}, + {MediaAction::PAUSE, "AdvSceneSwitcher.action.media.type.pause"}, + {MediaAction::STOP, "AdvSceneSwitcher.action.media.type.stop"}, + {MediaAction::RESTART, "AdvSceneSwitcher.action.media.type.restart"}, + {MediaAction::NEXT, "AdvSceneSwitcher.action.media.type.next"}, + {MediaAction::PREVIOUS, "AdvSceneSwitcher.action.media.type.previous"}, +}; + +bool MacroActionMedia::PerformAction() +{ + auto source = obs_weak_source_get_source(_mediaSource); + obs_media_state state = obs_source_media_get_state(source); + switch (_action) { + case MediaAction::PLAY: + if (state == OBS_MEDIA_STATE_STOPPED || + state == OBS_MEDIA_STATE_ENDED) { + obs_source_media_restart(source); + } else { + obs_source_media_play_pause(source, false); + } + break; + case MediaAction::PAUSE: + obs_source_media_play_pause(source, true); + break; + case MediaAction::STOP: + obs_source_media_stop(source); + break; + case MediaAction::RESTART: + obs_source_media_restart(source); + break; + case MediaAction::NEXT: + obs_source_media_next(source); + break; + case MediaAction::PREVIOUS: + obs_source_media_previous(source); + break; + default: + break; + } + obs_source_release(source); + return true; +} + +void MacroActionMedia::LogAction() +{ + auto it = actionTypes.find(_action); + if (it != actionTypes.end()) { + vblog(LOG_INFO, "performed action \"%s\" for source \"%s\"", + it->second.c_str(), + GetWeakSourceName(_mediaSource).c_str()); + } else { + blog(LOG_WARNING, "ignored unknown media action %d", + static_cast(_action)); + } +} + +bool MacroActionMedia::Save(obs_data_t *obj) +{ + MacroAction::Save(obj); + obs_data_set_string(obj, "mediaSource", + GetWeakSourceName(_mediaSource).c_str()); + obs_data_set_int(obj, "action", static_cast(_action)); + return true; +} + +bool MacroActionMedia::Load(obs_data_t *obj) +{ + MacroAction::Load(obj); + const char *MediaSourceName = obs_data_get_string(obj, "mediaSource"); + _mediaSource = GetWeakSourceByName(MediaSourceName); + _action = static_cast(obs_data_get_int(obj, "action")); + return true; +} + +static inline void populateActionSelection(QComboBox *list) +{ + for (auto entry : actionTypes) { + list->addItem(obs_module_text(entry.second.c_str())); + } +} + +MacroActionMediaEdit::MacroActionMediaEdit( + QWidget *parent, std::shared_ptr entryData) + : QWidget(parent) +{ + _mediaSources = new QComboBox(); + _actions = new QComboBox(); + + populateActionSelection(_actions); + AdvSceneSwitcher::populateMediaSelection(_mediaSources); + + QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, + SLOT(ActionChanged(int))); + QWidget::connect(_mediaSources, + SIGNAL(currentTextChanged(const QString &)), this, + SLOT(SourceChanged(const QString &))); + + QHBoxLayout *mainLayout = new QHBoxLayout; + std::unordered_map widgetPlaceholders = { + {"{{mediaSources}}", _mediaSources}, + {"{{actions}}", _actions}, + }; + placeWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"), + mainLayout, widgetPlaceholders); + setLayout(mainLayout); + + _entryData = entryData; + UpdateEntryData(); + _loading = false; +} + +void MacroActionMediaEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _mediaSources->setCurrentText( + GetWeakSourceName(_entryData->_mediaSource).c_str()); + _actions->setCurrentIndex(static_cast(_entryData->_action)); +} + +void MacroActionMediaEdit::SourceChanged(const QString &text) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_mediaSource = GetWeakSourceByQString(text); +} + +void MacroActionMediaEdit::ActionChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_action = static_cast(value); +}