From 449daa80ccb6c52a675735786b13b645c28bed9b Mon Sep 17 00:00:00 2001 From: Przemek Pawlas <3606072+Destroy666x@users.noreply.github.com> Date: Thu, 16 Nov 2023 02:23:18 +0100 Subject: [PATCH] Add media seek to percentage action + cleanup --- data/locale/de-DE.ini | 5 +- data/locale/en-US.ini | 6 +- data/locale/es-ES.ini | 81 ++++++------ data/locale/fr-FR.ini | 2 +- data/locale/tr-TR.ini | 1 - data/locale/zh-CN.ini | 3 +- src/macro-core/macro-action-media.cpp | 182 +++++++++++++++++--------- src/macro-core/macro-action-media.hpp | 67 +++++----- 8 files changed, 203 insertions(+), 144 deletions(-) diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index 095febf7..5c8299a4 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -470,8 +470,7 @@ AdvSceneSwitcher.action.media.type.stop="Stoppen" AdvSceneSwitcher.action.media.type.restart="Neu starten" AdvSceneSwitcher.action.media.type.next="Nächste" AdvSceneSwitcher.action.media.type.previous="Vorherige" -AdvSceneSwitcher.action.media.type.seek="Suche nach" -AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}" +AdvSceneSwitcher.action.media.type.seek.duration="Suche nach" AdvSceneSwitcher.action.macro="Makro" AdvSceneSwitcher.action.macro.type.pause="Pausieren" AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren" @@ -715,7 +714,7 @@ AdvSceneSwitcher.sceneSequenceTab.loadFail="Laden der Einstellungen ist fehlgesc AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!" AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)" AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden" -AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen" +AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen" AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}" AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern" AdvSceneSwitcher.sceneSequenceTab.extendEntry="Nach {{delay}} wechsle zu {{scenes}} mit {{transitions}}" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 3ae20062..2b3c7d01 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -650,8 +650,10 @@ 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.type.seek="Seek to" -AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}" +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.seek.percentage.label="Percentage of total duration of the media" AdvSceneSwitcher.action.macro="Macro" AdvSceneSwitcher.action.macro.type.pause="Pause" AdvSceneSwitcher.action.macro.type.unpause="Unpause" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index dbff47f5..a196924f 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -41,17 +41,17 @@ AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="Exportar los a AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="Importar los ajustes para Advanced Scene Switcher ..." AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="Archivos de texto (*.txt)" AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="La importacion la configuracion de escenas fallo" -AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Configuración de escenas importada correctamente" -AdvSceneSwitcher.generalTab.priority.fileContent="Contenido del archivo" -AdvSceneSwitcher.generalTab.priority.sceneSequence="Secuencia de escenas" -AdvSceneSwitcher.generalTab.priority.idleDetection="Detección de inactivos" -AdvSceneSwitcher.generalTab.priority.executable="Ejecutable" -AdvSceneSwitcher.generalTab.priority.screenRegion="Región de pantalla" -AdvSceneSwitcher.generalTab.priority.windowTitle="Título de la ventana" -AdvSceneSwitcher.generalTab.priority.media="Medios" -AdvSceneSwitcher.generalTab.priority.time="Tiempo" -AdvSceneSwitcher.generalTab.priority.audio="Audio" -AdvSceneSwitcher.generalTab.priority.video="Video" +AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Configuración de escenas importada correctamente" +AdvSceneSwitcher.generalTab.priority.fileContent="Contenido del archivo" +AdvSceneSwitcher.generalTab.priority.sceneSequence="Secuencia de escenas" +AdvSceneSwitcher.generalTab.priority.idleDetection="Detección de inactivos" +AdvSceneSwitcher.generalTab.priority.executable="Ejecutable" +AdvSceneSwitcher.generalTab.priority.screenRegion="Región de pantalla" +AdvSceneSwitcher.generalTab.priority.windowTitle="Título de la ventana" +AdvSceneSwitcher.generalTab.priority.media="Medios" +AdvSceneSwitcher.generalTab.priority.time="Tiempo" +AdvSceneSwitcher.generalTab.priority.audio="Audio" +AdvSceneSwitcher.generalTab.priority.video="Video" AdvSceneSwitcher.generalTab.priority.macro="Macro" AdvSceneSwitcher.generalTab.setTransitionBy="Al cambiar las transiciones:" AdvSceneSwitcher.generalTab.transitionOverride="Establecer anulaciones de transición" @@ -61,38 +61,38 @@ AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Al menos una opci ; Macro Tab AdvSceneSwitcher.macroTab.title="Macro" AdvSceneSwitcher.macroTab.macros="Macros" -AdvSceneSwitcher.macroTab.priorityWarning="Nota: Se recomienda configurar las macros para que sean la funcionalidad de máxima prioridad.\nEsta configuración se puede cambiar en la ficha General." -AdvSceneSwitcher.macroTab.help="Las macros le permiten ejecutar una cadena de acciones en función de varias condiciones.\n\nHaga clic en el símbolo más resaltado para agregar una nueva macro." -AdvSceneSwitcher.macroTab.editConditionHelp="Esta sección le permite definir las condiciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva condición." +AdvSceneSwitcher.macroTab.priorityWarning="Nota: Se recomienda configurar las macros para que sean la funcionalidad de máxima prioridad.\nEsta configuración se puede cambiar en la ficha General." +AdvSceneSwitcher.macroTab.help="Las macros le permiten ejecutar una cadena de acciones en función de varias condiciones.\n\nHaga clic en el símbolo más resaltado para agregar una nueva macro." +AdvSceneSwitcher.macroTab.editConditionHelp="Esta sección le permite definir las condiciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva condición." AdvSceneSwitcher.macroTab.editActionHelp="Esta sección le permite definir acciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva acción" AdvSceneSwitcher.macroTab.edit="Editar macro" -AdvSceneSwitcher.macroTab.edit.logic="Tipo de lógica:" -AdvSceneSwitcher.macroTab.edit.condition="Tipo de condición:" +AdvSceneSwitcher.macroTab.edit.logic="Tipo de lógica:" +AdvSceneSwitcher.macroTab.edit.condition="Tipo de condición:" AdvSceneSwitcher.macroTab.edit.action="Tipo de acción:" -AdvSceneSwitcher.macroTab.add="Agregar nueva macro" -AdvSceneSwitcher.macroTab.name="Nombre:" -AdvSceneSwitcher.macroTab.run="Ejecutar macro" -AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando." -AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros" -AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición" -AdvSceneSwitcher.macroTab.defaultname="Macro %1" -AdvSceneSwitcher.macroTab.exists="El nombre de la macro ya existe" -AdvSceneSwitcher.macroTab.copy="Crear copia" -AdvSceneSwitcher.macroTab.expandAll="Expandir todo" -AdvSceneSwitcher.macroTab.collapseAll="Contraer todo" -AdvSceneSwitcher.macroTab.maximize="Maximizar" +AdvSceneSwitcher.macroTab.add="Agregar nueva macro" +AdvSceneSwitcher.macroTab.name="Nombre:" +AdvSceneSwitcher.macroTab.run="Ejecutar macro" +AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando." +AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros" +AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición" +AdvSceneSwitcher.macroTab.defaultname="Macro %1" +AdvSceneSwitcher.macroTab.exists="El nombre de la macro ya existe" +AdvSceneSwitcher.macroTab.copy="Crear copia" +AdvSceneSwitcher.macroTab.expandAll="Expandir todo" +AdvSceneSwitcher.macroTab.collapseAll="Contraer todo" +AdvSceneSwitcher.macroTab.maximize="Maximizar" AdvSceneSwitcher.macroTab.minimize="Minimizar" -AdvSceneSwitcher.macroTab.highlightExecutedMacros="Resaltar macros ejecutadas recientemente" -AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la macro seleccionada, que se evaluaron como verdaderas recientemente" -AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente" +AdvSceneSwitcher.macroTab.highlightExecutedMacros="Resaltar macros ejecutadas recientemente" +AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la macro seleccionada, que se evaluaron como verdaderas recientemente" +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" -AdvSceneSwitcher.logic.orNot="O no" -AdvSceneSwitcher.logic.rootNone="Si" +; Lógica de macros +AdvSceneSwitcher.logic.none="Omitir entrada" +AdvSceneSwitcher.logic.and="Y" +AdvSceneSwitcher.logic.or="O" +AdvSceneSwitcher.logic.andNot="Y no" +AdvSceneSwitcher.logic.orNot="O no" +AdvSceneSwitcher.logic.rootNone="Si" AdvSceneSwitcher.logic.not="Si no" ; Macro Conditions @@ -388,8 +388,7 @@ AdvSceneSwitcher.action.media.type.stop="Detener" AdvSceneSwitcher.action.media.type.restart="Reiniciar" AdvSceneSwitcher.action.media.type.next="Siguiente" AdvSceneSwitcher.action.media.type.previous="Anterior" -AdvSceneSwitcher.action.media.type.seek="Buscar" -AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}" +AdvSceneSwitcher.action.media.type.seek.duration="Buscar" AdvSceneSwitcher.action.macro="Macro" AdvSceneSwitcher.action.macro.type.pause="Pausa" AdvSceneSwitcher.action.macro.type.unpause="Reanudar" @@ -568,7 +567,7 @@ AdvSceneSwitcher.fileTab.help="Esta pestaña te permitirá cambiar escenas autom ; Random Tab AdvSceneSwitcher.randomTab.title="Aleatorio" AdvSceneSwitcher.randomTab.randomDisabledWarning="Funcionalidad deshabilitada - para activarla, selecciona \"Si no se cumple ninguna condición de cambio, cambiar a cualquier escena en la pestaña Aleatorio\" en la pestaña General" -AdvSceneSwitcher.randomTab.entry="Si no se cumple ninguna condición de cambio, cambiar a {{scenes}} usando {{transitions}} después de {{delay}}" +AdvSceneSwitcher.randomTab.entry="Si no se cumple ninguna condición de cambio, cambiar a {{scenes}} usando {{transitions}} después de {{delay}}" AdvSceneSwitcher.randomTab.help="El selector de escenas elegirá aleatoriamente una entrada en esta pestaña para cambiar durante el tiempo configurado.\nTen en cuenta que la misma entrada no se elegirá dos veces seguidas.\n\nHaz clic en el símbolo más resaltado para continuar." ; Time Tab diff --git a/data/locale/fr-FR.ini b/data/locale/fr-FR.ini index 127e1fa8..26d20542 100644 --- a/data/locale/fr-FR.ini +++ b/data/locale/fr-FR.ini @@ -558,7 +558,7 @@ AdvSceneSwitcher.action.media.type.stop="Arrêt" AdvSceneSwitcher.action.media.type.restart="Redémarrage" AdvSceneSwitcher.action.media.type.next="Suivant" AdvSceneSwitcher.action.media.type.previous="Précédent" -AdvSceneSwitcher.action.media.type.seek="Recherche vers" +AdvSceneSwitcher.action.media.type.seek.duration="Recherche vers" AdvSceneSwitcher.action.macro="Macro" AdvSceneSwitcher.action.macro.type.pause="Pause" AdvSceneSwitcher.action.macro.type.unpause="Reprendre" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 564bab78..0414cc4e 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -318,7 +318,6 @@ AdvSceneSwitcher.action.media.type.stop="Dur" AdvSceneSwitcher.action.media.type.restart="Yeniden Başlat" AdvSceneSwitcher.action.media.type.next="Sonraki" AdvSceneSwitcher.action.media.type.previous="Önceki" -AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}" AdvSceneSwitcher.action.macro="Makro" AdvSceneSwitcher.action.macro.type.pause="Duraklat" AdvSceneSwitcher.action.macro.type.unpause="Duraklatma" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index f5a408c9..92b85adc 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -529,8 +529,7 @@ AdvSceneSwitcher.action.media.type.stop="停止" AdvSceneSwitcher.action.media.type.restart="重新启动" AdvSceneSwitcher.action.media.type.next="下一个" AdvSceneSwitcher.action.media.type.previous="上一个" -AdvSceneSwitcher.action.media.type.seek="时间轴定位" -AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}" +AdvSceneSwitcher.action.media.type.seek.duration="时间轴定位" AdvSceneSwitcher.action.macro="宏" AdvSceneSwitcher.action.macro.type.pause="暂停" AdvSceneSwitcher.action.macro.type.unpause="取消暂停" diff --git a/src/macro-core/macro-action-media.cpp b/src/macro-core/macro-action-media.cpp index fe00bdfe..2a515898 100644 --- a/src/macro-core/macro-action-media.cpp +++ b/src/macro-core/macro-action-media.cpp @@ -10,22 +10,45 @@ bool MacroActionMedia::_registered = MacroActionFactory::Register( {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"}, - {MediaAction::SEEK, "AdvSceneSwitcher.action.media.type.seek"}, +const static std::map actionTypes = { + {MacroActionMedia::Action::PLAY, + "AdvSceneSwitcher.action.media.type.play"}, + {MacroActionMedia::Action::PAUSE, + "AdvSceneSwitcher.action.media.type.pause"}, + {MacroActionMedia::Action::STOP, + "AdvSceneSwitcher.action.media.type.stop"}, + {MacroActionMedia::Action::RESTART, + "AdvSceneSwitcher.action.media.type.restart"}, + {MacroActionMedia::Action::NEXT, + "AdvSceneSwitcher.action.media.type.next"}, + {MacroActionMedia::Action::PREVIOUS, + "AdvSceneSwitcher.action.media.type.previous"}, + {MacroActionMedia::Action::SEEK_DURATION, + "AdvSceneSwitcher.action.media.type.seek.duration"}, + {MacroActionMedia::Action::SEEK_PERCENTAGE, + "AdvSceneSwitcher.action.media.type.seek.percentage"}, }; +std::string MacroActionMedia::GetShortDesc() const +{ + return _mediaSource.ToString(); +} + +void MacroActionMedia::SeekToPercentage(obs_source_t *source) const +{ + auto totalTimeMs = obs_source_media_get_duration(source); + auto percentageTimeMs = round(totalTimeMs * _seekPercentage / 100); + + obs_source_media_set_time(source, percentageTimeMs); +} + bool MacroActionMedia::PerformAction() { auto source = obs_weak_source_get_source(_mediaSource.GetSource()); obs_media_state state = obs_source_media_get_state(source); + switch (_action) { - case MediaAction::PLAY: + case Action::PLAY: if (state == OBS_MEDIA_STATE_STOPPED || state == OBS_MEDIA_STATE_ENDED) { obs_source_media_restart(source); @@ -33,27 +56,31 @@ bool MacroActionMedia::PerformAction() obs_source_media_play_pause(source, false); } break; - case MediaAction::PAUSE: + case Action::PAUSE: obs_source_media_play_pause(source, true); break; - case MediaAction::STOP: + case Action::STOP: obs_source_media_stop(source); break; - case MediaAction::RESTART: + case Action::RESTART: obs_source_media_restart(source); break; - case MediaAction::NEXT: + case Action::NEXT: obs_source_media_next(source); break; - case MediaAction::PREVIOUS: + case Action::PREVIOUS: obs_source_media_previous(source); break; - case MediaAction::SEEK: - obs_source_media_set_time(source, _seek.Milliseconds()); + case Action::SEEK_DURATION: + obs_source_media_set_time(source, _seekDuration.Milliseconds()); + break; + case Action::SEEK_PERCENTAGE: + SeekToPercentage(source); break; default: break; } + obs_source_release(source); return true; } @@ -73,39 +100,42 @@ void MacroActionMedia::LogAction() const bool MacroActionMedia::Save(obs_data_t *obj) const { MacroAction::Save(obj); - _mediaSource.Save(obj, "mediaSource"); obs_data_set_int(obj, "action", static_cast(_action)); - _seek.Save(obj); + _seekDuration.Save(obj); + _seekPercentage.Save(obj, "seekPercentage"); + _mediaSource.Save(obj, "mediaSource"); + return true; } bool MacroActionMedia::Load(obs_data_t *obj) { MacroAction::Load(obj); + _action = static_cast(obs_data_get_int(obj, "action")); + _seekDuration.Load(obj); + _seekPercentage.Load(obj, "seekPercentage"); _mediaSource.Load(obj, "mediaSource"); - _action = static_cast(obs_data_get_int(obj, "action")); - _seek.Load(obj); - return true; -} -std::string MacroActionMedia::GetShortDesc() const -{ - return _mediaSource.ToString(); + return true; } static inline void populateActionSelection(QComboBox *list) { - for (auto entry : actionTypes) { - list->addItem(obs_module_text(entry.second.c_str())); + for (const auto &[_, name] : actionTypes) { + list->addItem(obs_module_text(name.c_str())); } } MacroActionMediaEdit::MacroActionMediaEdit( QWidget *parent, std::shared_ptr entryData) : QWidget(parent), - _sources(new SourceSelectionWidget(this, QStringList(), true)), _actions(new QComboBox()), - _seek(new DurationSelection()) + _seekDuration(new DurationSelection()), + _seekPercentage(new SliderSpinBox( + 0, 100, + obs_module_text( + "AdvSceneSwitcher.action.media.seek.percentage.label"))), + _sources(new SourceSelectionWidget(this, QStringList(), true)) { populateActionSelection(_actions); auto sources = GetMediaSourceNames(); @@ -114,39 +144,67 @@ MacroActionMediaEdit::MacroActionMediaEdit( QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); + QWidget::connect(_seekDuration, + SIGNAL(DurationChanged(const Duration &)), this, + SLOT(SeekDurationChanged(const Duration &))); + QWidget::connect( + _seekPercentage, + SIGNAL(DoubleValueChanged(const NumberVariable &)), + this, + SLOT(SeekPercentageChanged(const NumberVariable &))); QWidget::connect(_sources, SIGNAL(SourceChanged(const SourceSelection &)), this, SLOT(SourceChanged(const SourceSelection &))); - QWidget::connect(_seek, SIGNAL(DurationChanged(const Duration &)), this, - SLOT(DurationChanged(const Duration &))); - QHBoxLayout *mainLayout = new QHBoxLayout; + auto layout = new QHBoxLayout; std::unordered_map widgetPlaceholders = { - {"{{mediaSources}}", _sources}, {"{{actions}}", _actions}, - {"{{duration}}", _seek}, + {"{{seekDuration}}", _seekDuration}, + {"{{seekPercentage}}", _seekPercentage}, + {"{{mediaSources}}", _sources}, }; PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"), - mainLayout, widgetPlaceholders); - setLayout(mainLayout); + layout, widgetPlaceholders); + setLayout(layout); _entryData = entryData; UpdateEntryData(); _loading = false; } -void MacroActionMediaEdit::UpdateEntryData() +void MacroActionMediaEdit::ActionChanged(int value) { - if (!_entryData) { + if (_loading || !_entryData) { return; } - _sources->SetSource(_entryData->_mediaSource); - _actions->setCurrentIndex(static_cast(_entryData->_action)); - _seek->SetDuration(_entryData->_seek); + auto lock = LockContext(); + _entryData->_action = static_cast(value); + SetWidgetVisibility(); } +void MacroActionMediaEdit::SeekDurationChanged(const Duration &seekDuration) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_seekDuration = seekDuration; +} + +void MacroActionMediaEdit::SeekPercentageChanged( + const NumberVariable &seekPercentage) +{ + if (_loading || !_entryData) { + return; + } + + auto lock = LockContext(); + _entryData->_seekPercentage = seekPercentage; +} + void MacroActionMediaEdit::SourceChanged(const SourceSelection &source) { if (_loading || !_entryData) { @@ -159,34 +217,32 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source) QString::fromStdString(_entryData->GetShortDesc())); } -void MacroActionMediaEdit::ActionChanged(int value) -{ - if (_loading || !_entryData) { - return; - } - - auto lock = LockContext(); - _entryData->_action = static_cast(value); - SetWidgetVisibility(); -} - -void MacroActionMediaEdit::DurationChanged(const Duration &dur) -{ - if (_loading || !_entryData) { - return; - } - - auto lock = LockContext(); - _entryData->_seek = dur; -} - void MacroActionMediaEdit::SetWidgetVisibility() { if (!_entryData) { return; } - _seek->setVisible(_entryData->_action == MediaAction::SEEK); + + _seekDuration->setVisible(_entryData->_action == + MacroActionMedia::Action::SEEK_DURATION); + _seekPercentage->setVisible(_entryData->_action == + MacroActionMedia::Action::SEEK_PERCENTAGE); + adjustSize(); } +void MacroActionMediaEdit::UpdateEntryData() +{ + if (!_entryData) { + return; + } + + _actions->setCurrentIndex(static_cast(_entryData->_action)); + _seekDuration->SetDuration(_entryData->_seekDuration); + _seekPercentage->SetDoubleValue(_entryData->_seekPercentage); + _sources->SetSource(_entryData->_mediaSource); + + SetWidgetVisibility(); +} + } // namespace advss diff --git a/src/macro-core/macro-action-media.hpp b/src/macro-core/macro-action-media.hpp index 8e63520a..8675aced 100644 --- a/src/macro-core/macro-action-media.hpp +++ b/src/macro-core/macro-action-media.hpp @@ -1,42 +1,45 @@ #pragma once #include "macro-action-edit.hpp" #include "duration-control.hpp" +#include "slider-spinbox.hpp" #include "source-selection.hpp" -#include -#include - namespace advss { -enum class MediaAction { - PLAY, - PAUSE, - STOP, - RESTART, - NEXT, - PREVIOUS, - SEEK, -}; - class MacroActionMedia : public MacroAction { public: MacroActionMedia(Macro *m) : MacroAction(m) {} - bool PerformAction(); - void LogAction() const; - bool Save(obs_data_t *obj) const; - bool Load(obs_data_t *obj); - std::string GetShortDesc() const; - std::string GetId() const { return id; }; static std::shared_ptr Create(Macro *m) { return std::make_shared(m); } + std::string GetId() const { return id; }; + std::string GetShortDesc() const; + bool PerformAction(); + void LogAction() const; + bool Save(obs_data_t *obj) const; + bool Load(obs_data_t *obj); + + enum class Action { + PLAY, + PAUSE, + STOP, + RESTART, + NEXT, + PREVIOUS, + SEEK_DURATION, + SEEK_PERCENTAGE, + }; + + Action _action = Action::PLAY; + Duration _seekDuration; + DoubleVariable _seekPercentage = 50; SourceSelection _mediaSource; - MediaAction _action = MediaAction::PLAY; - Duration _seek; private: + void SeekToPercentage(obs_source_t *source) const; + static bool _registered; static const std::string id; }; @@ -48,7 +51,6 @@ public: MacroActionMediaEdit( QWidget *parent, std::shared_ptr entryData = nullptr); - void UpdateEntryData(); static QWidget *Create(QWidget *parent, std::shared_ptr action) { @@ -56,24 +58,27 @@ public: parent, std::dynamic_pointer_cast(action)); } + void UpdateEntryData(); private slots: - void SourceChanged(const SourceSelection &); void ActionChanged(int value); - void DurationChanged(const Duration &value); + void SeekDurationChanged(const Duration &seekDuration); + void + SeekPercentageChanged(const NumberVariable &seekPercentage); + void SourceChanged(const SourceSelection &source); + signals: void HeaderInfoChanged(const QString &); -protected: - SourceSelectionWidget *_sources; - QComboBox *_actions; - DurationSelection *_seek; - std::shared_ptr _entryData; - private: void SetWidgetVisibility(); - QHBoxLayout *_mainLayout; + QComboBox *_actions; + DurationSelection *_seekDuration; + SliderSpinBox *_seekPercentage; + SourceSelectionWidget *_sources; + + std::shared_ptr _entryData; bool _loading = true; };