From 7690ae8684e88258e6b64e00605e32b2dbbc965f Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 13 Jan 2024 10:45:01 +0100 Subject: [PATCH] Add option to perform media actions on scene items --- data/locale/en-US.ini | 4 +- src/macro-core/macro-action-media.cpp | 134 ++++++++++++++++++++++---- src/macro-core/macro-action-media.hpp | 14 +++ 3 files changed, 134 insertions(+), 18 deletions(-) diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 0e61474b..40371f9d 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -673,7 +673,9 @@ AdvSceneSwitcher.action.media.type.next="Next" AdvSceneSwitcher.action.media.type.previous="Previous" AdvSceneSwitcher.action.media.type.seek.duration="Seek to duration" AdvSceneSwitcher.action.media.type.seek.percentage="Seek to percentage" -AdvSceneSwitcher.action.media.entry="{{actions}}{{seekDuration}}{{seekPercentage}}{{mediaSources}}" +AdvSceneSwitcher.action.media.selectionType.source="Source" +AdvSceneSwitcher.action.media.selectionType.sceneItem="Scene item" +AdvSceneSwitcher.action.media.entry="{{actions}}{{seekDuration}}{{seekPercentage}}{{selectionTypes}}{{mediaSources}}{{scenes}}{{sceneItems}}" AdvSceneSwitcher.action.media.seek.percentage.label="Percentage of total duration of the media" AdvSceneSwitcher.action.macro="Macro" AdvSceneSwitcher.action.macro.type.pause="Pause" diff --git a/src/macro-core/macro-action-media.cpp b/src/macro-core/macro-action-media.cpp index 2a515898..ef43a7c1 100644 --- a/src/macro-core/macro-action-media.cpp +++ b/src/macro-core/macro-action-media.cpp @@ -10,7 +10,7 @@ bool MacroActionMedia::_registered = MacroActionFactory::Register( {MacroActionMedia::Create, MacroActionMediaEdit::Create, "AdvSceneSwitcher.action.media"}); -const static std::map actionTypes = { +static const std::map actionTypes = { {MacroActionMedia::Action::PLAY, "AdvSceneSwitcher.action.media.type.play"}, {MacroActionMedia::Action::PAUSE, @@ -29,9 +29,20 @@ const static std::map actionTypes = { "AdvSceneSwitcher.action.media.type.seek.percentage"}, }; +static const std::map + selectionTypes = { + {MacroActionMedia::SelectionType::SOURCE, + "AdvSceneSwitcher.action.media.selectionType.source"}, + {MacroActionMedia::SelectionType::SCENE_ITEM, + "AdvSceneSwitcher.action.media.selectionType.sceneItem"}, +}; + std::string MacroActionMedia::GetShortDesc() const { - return _mediaSource.ToString(); + if (_selection == SelectionType::SOURCE) { + return _mediaSource.ToString(); + } + return _scene.ToString() + " - " + _sceneItem.ToString(); } void MacroActionMedia::SeekToPercentage(obs_source_t *source) const @@ -42,9 +53,8 @@ void MacroActionMedia::SeekToPercentage(obs_source_t *source) const obs_source_media_set_time(source, percentageTimeMs); } -bool MacroActionMedia::PerformAction() +void MacroActionMedia::PerformActionHelper(obs_source_t *source) const { - auto source = obs_weak_source_get_source(_mediaSource.GetSource()); obs_media_state state = obs_source_media_get_state(source); switch (_action) { @@ -80,8 +90,20 @@ bool MacroActionMedia::PerformAction() default: break; } +} - obs_source_release(source); +bool MacroActionMedia::PerformAction() +{ + if (_selection == SelectionType::SOURCE) { + OBSSourceAutoRelease source = + obs_weak_source_get_source(_mediaSource.GetSource()); + PerformActionHelper(source); + } else { + const auto items = _sceneItem.GetSceneItems(_scene); + for (const auto &item : items) { + PerformActionHelper(obs_sceneitem_get_source(item)); + } + } return true; } @@ -90,7 +112,10 @@ void MacroActionMedia::LogAction() const auto it = actionTypes.find(_action); if (it != actionTypes.end()) { vblog(LOG_INFO, "performed action \"%s\" for source \"%s\"", - it->second.c_str(), _mediaSource.ToString(true).c_str()); + it->second.c_str(), + _selection == SelectionType::SOURCE + ? _mediaSource.ToString(true).c_str() + : _sceneItem.ToString().c_str()); } else { blog(LOG_WARNING, "ignored unknown media action %d", static_cast(_action)); @@ -101,10 +126,12 @@ bool MacroActionMedia::Save(obs_data_t *obj) const { MacroAction::Save(obj); obs_data_set_int(obj, "action", static_cast(_action)); + obs_data_set_int(obj, "selectionType", static_cast(_selection)); _seekDuration.Save(obj); _seekPercentage.Save(obj, "seekPercentage"); _mediaSource.Save(obj, "mediaSource"); - + _scene.Save(obj); + _sceneItem.Save(obj); return true; } @@ -112,10 +139,13 @@ bool MacroActionMedia::Load(obs_data_t *obj) { MacroAction::Load(obj); _action = static_cast(obs_data_get_int(obj, "action")); + _selection = static_cast( + obs_data_get_int(obj, "selectionType")); _seekDuration.Load(obj); _seekPercentage.Load(obj, "seekPercentage"); _mediaSource.Load(obj, "mediaSource"); - + _scene.Load(obj); + _sceneItem.Load(obj); return true; } @@ -126,24 +156,37 @@ static inline void populateActionSelection(QComboBox *list) } } +static inline void populateSelectionTypeSelection(QComboBox *list) +{ + for (const auto &[_, name] : selectionTypes) { + list->addItem(obs_module_text(name.c_str())); + } +} + MacroActionMediaEdit::MacroActionMediaEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), _actions(new QComboBox()), + _selectionTypes(new QComboBox()), _seekDuration(new DurationSelection()), _seekPercentage(new SliderSpinBox( 0, 100, obs_module_text( "AdvSceneSwitcher.action.media.seek.percentage.label"))), - _sources(new SourceSelectionWidget(this, QStringList(), true)) + _sources(new SourceSelectionWidget(this, QStringList(), true)), + _sceneItems(new SceneItemSelectionWidget(parent, false)), + _scenes(new SceneSelectionWidget(this, true, false, true, true, true)) { populateActionSelection(_actions); + populateSelectionTypeSelection(_selectionTypes); auto sources = GetMediaSourceNames(); sources.sort(); _sources->SetSourceNameList(sources); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); + QWidget::connect(_selectionTypes, SIGNAL(currentIndexChanged(int)), + this, SLOT(SelectionTypeChanged(int))); QWidget::connect(_seekDuration, SIGNAL(DurationChanged(const Duration &)), this, SLOT(SeekDurationChanged(const Duration &))); @@ -155,16 +198,25 @@ MacroActionMediaEdit::MacroActionMediaEdit( QWidget::connect(_sources, SIGNAL(SourceChanged(const SourceSelection &)), this, SLOT(SourceChanged(const SourceSelection &))); + QWidget::connect(_sceneItems, + SIGNAL(SceneItemChanged(const SceneItemSelection &)), + this, SLOT(SourceChanged(const SceneItemSelection &))); + QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), + _sceneItems, + SLOT(SceneChanged(const SceneSelection &))); + QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)), + this, SLOT(SceneChanged(const SceneSelection &))); auto layout = new QHBoxLayout; - std::unordered_map widgetPlaceholders = { - {"{{actions}}", _actions}, - {"{{seekDuration}}", _seekDuration}, - {"{{seekPercentage}}", _seekPercentage}, - {"{{mediaSources}}", _sources}, - }; PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"), - layout, widgetPlaceholders); + layout, + {{"{{actions}}", _actions}, + {"{{selectionTypes}}", _selectionTypes}, + {"{{seekDuration}}", _seekDuration}, + {"{{seekPercentage}}", _seekPercentage}, + {"{{mediaSources}}", _sources}, + {"{{scenes}}", _scenes}, + {"{{sceneItems}}", _sceneItems}}); setLayout(layout); _entryData = entryData; @@ -180,7 +232,18 @@ void MacroActionMediaEdit::ActionChanged(int value) auto lock = LockContext(); _entryData->_action = static_cast(value); + SetWidgetVisibility(); +} +void MacroActionMediaEdit::SelectionTypeChanged(int value) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_selection = + static_cast(value); SetWidgetVisibility(); } @@ -217,18 +280,52 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source) QString::fromStdString(_entryData->GetShortDesc())); } +void MacroActionMediaEdit::SourceChanged(const SceneItemSelection &item) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_sceneItem = item; + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); + adjustSize(); + updateGeometry(); +} + +void MacroActionMediaEdit::SceneChanged(const SceneSelection &scene) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_scene = scene; + emit HeaderInfoChanged( + QString::fromStdString(_entryData->GetShortDesc())); +} + void MacroActionMediaEdit::SetWidgetVisibility() { if (!_entryData) { return; } + _sources->setVisible(_entryData->_selection == + MacroActionMedia::SelectionType::SOURCE); + _scenes->setVisible(_entryData->_selection == + MacroActionMedia::SelectionType::SCENE_ITEM); + _sceneItems->setVisible(_entryData->_selection == + MacroActionMedia::SelectionType::SCENE_ITEM); + _seekDuration->setVisible(_entryData->_action == MacroActionMedia::Action::SEEK_DURATION); _seekPercentage->setVisible(_entryData->_action == MacroActionMedia::Action::SEEK_PERCENTAGE); adjustSize(); + updateGeometry(); } void MacroActionMediaEdit::UpdateEntryData() @@ -238,10 +335,13 @@ void MacroActionMediaEdit::UpdateEntryData() } _actions->setCurrentIndex(static_cast(_entryData->_action)); + _selectionTypes->setCurrentIndex( + static_cast(_entryData->_selection)); _seekDuration->SetDuration(_entryData->_seekDuration); _seekPercentage->SetDoubleValue(_entryData->_seekPercentage); _sources->SetSource(_entryData->_mediaSource); - + _scenes->SetScene(_entryData->_scene); + _sceneItems->SetSceneItem((_entryData->_sceneItem)); SetWidgetVisibility(); } diff --git a/src/macro-core/macro-action-media.hpp b/src/macro-core/macro-action-media.hpp index 8675aced..f4bd5183 100644 --- a/src/macro-core/macro-action-media.hpp +++ b/src/macro-core/macro-action-media.hpp @@ -3,6 +3,8 @@ #include "duration-control.hpp" #include "slider-spinbox.hpp" #include "source-selection.hpp" +#include "scene-selection.hpp" +#include "scene-item-selection.hpp" namespace advss { @@ -32,12 +34,18 @@ public: SEEK_PERCENTAGE, }; + enum class SelectionType { SOURCE, SCENE_ITEM }; + Action _action = Action::PLAY; + SelectionType _selection = SelectionType::SOURCE; Duration _seekDuration; DoubleVariable _seekPercentage = 50; SourceSelection _mediaSource; + SceneItemSelection _sceneItem; + SceneSelection _scene; private: + void PerformActionHelper(obs_source_t *) const; void SeekToPercentage(obs_source_t *source) const; static bool _registered; @@ -62,10 +70,13 @@ public: private slots: void ActionChanged(int value); + void SelectionTypeChanged(int value); void SeekDurationChanged(const Duration &seekDuration); void SeekPercentageChanged(const NumberVariable &seekPercentage); void SourceChanged(const SourceSelection &source); + void SourceChanged(const SceneItemSelection &); + void SceneChanged(const SceneSelection &); signals: void HeaderInfoChanged(const QString &); @@ -74,9 +85,12 @@ private: void SetWidgetVisibility(); QComboBox *_actions; + QComboBox *_selectionTypes; DurationSelection *_seekDuration; SliderSpinBox *_seekPercentage; SourceSelectionWidget *_sources; + SceneSelectionWidget *_scenes; + SceneItemSelectionWidget *_sceneItems; std::shared_ptr _entryData; bool _loading = true;