diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini index f18b4d2c..7817db87 100644 --- a/data/locale/de-DE.ini +++ b/data/locale/de-DE.ini @@ -428,7 +428,7 @@ AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren" AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen" AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann" AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!" -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="Replay Buffer" AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!" AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen" diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index c41a1101..b4bb893c 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -463,9 +463,11 @@ AdvSceneSwitcher.action.recording.type.start="Start recording" AdvSceneSwitcher.action.recording.type.pause="Pause recording" AdvSceneSwitcher.action.recording.type.unpause="Unpause recording" AdvSceneSwitcher.action.recording.type.split="Split recording file" +AdvSceneSwitcher.action.recording.type.changeOutputFolder="Change output folder" +AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Change filename formatting" AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording" AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!" -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="Replay buffer" AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!" AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer" diff --git a/data/locale/es-ES.ini b/data/locale/es-ES.ini index 220fe614..88c13a16 100644 --- a/data/locale/es-ES.ini +++ b/data/locale/es-ES.ini @@ -350,7 +350,7 @@ AdvSceneSwitcher.action.recording.type.start="Iniciar grabación" AdvSceneSwitcher.action.recording.type.pause="Pausar grabación" AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación" AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación" -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="Búfer de reproducción" AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!" AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción" diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini index 32e83cf8..09acf888 100644 --- a/data/locale/ru-RU.ini +++ b/data/locale/ru-RU.ini @@ -135,7 +135,7 @@ AdvSceneSwitcher.action.recording.type.start="Начать запись" AdvSceneSwitcher.action.recording.type.pause="Пауза записи" AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы" AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись" -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="Буфер воспроизведения" AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения" AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера" diff --git a/data/locale/tr-TR.ini b/data/locale/tr-TR.ini index 365095c6..0580805d 100644 --- a/data/locale/tr-TR.ini +++ b/data/locale/tr-TR.ini @@ -281,7 +281,7 @@ AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat" AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat" AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma" AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın." -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="Tekrar arabelleği" AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur" AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat" diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini index b5f604d2..21afd752 100644 --- a/data/locale/zh-CN.ini +++ b/data/locale/zh-CN.ini @@ -393,7 +393,7 @@ AdvSceneSwitcher.action.recording.type.unpause="取消录制暂停" AdvSceneSwitcher.action.recording.type.split="分割录制文件" AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制" AdvSceneSwitcher.action.recording.split.hint="确保先在OBS设置中启用自动分割文件!" -AdvSceneSwitcher.action.recording.entry="{{actions}}{{pauseHint}}{{splitHint}}" +AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.replay="回放缓冲区" AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致重播缓冲区实际上未保存!" AdvSceneSwitcher.action.replay.type.stop="停止回放缓冲区" diff --git a/src/macro-core/macro-action-recording.cpp b/src/macro-core/macro-action-recording.cpp index 04f50780..4ebecb00 100644 --- a/src/macro-core/macro-action-recording.cpp +++ b/src/macro-core/macro-action-recording.cpp @@ -2,6 +2,8 @@ #include "advanced-scene-switcher.hpp" #include "utility.hpp" +#include + namespace advss { const std::string MacroActionRecord::id = "recording"; @@ -11,45 +13,80 @@ bool MacroActionRecord::_registered = MacroActionFactory::Register( {MacroActionRecord::Create, MacroActionRecordEdit::Create, "AdvSceneSwitcher.action.recording"}); -const static std::map actionTypes = { - {RecordAction::STOP, "AdvSceneSwitcher.action.recording.type.stop"}, - {RecordAction::START, "AdvSceneSwitcher.action.recording.type.start"}, - {RecordAction::PAUSE, "AdvSceneSwitcher.action.recording.type.pause"}, - {RecordAction::UNPAUSE, +const static std::map actionTypes = { + {MacroActionRecord::Action::STOP, + "AdvSceneSwitcher.action.recording.type.stop"}, + {MacroActionRecord::Action::START, + "AdvSceneSwitcher.action.recording.type.start"}, + {MacroActionRecord::Action::PAUSE, + "AdvSceneSwitcher.action.recording.type.pause"}, + {MacroActionRecord::Action::UNPAUSE, "AdvSceneSwitcher.action.recording.type.unpause"}, - {RecordAction::SPLIT, "AdvSceneSwitcher.action.recording.type.split"}, + {MacroActionRecord::Action::SPLIT, + "AdvSceneSwitcher.action.recording.type.split"}, + {MacroActionRecord::Action::FOLDER, + "AdvSceneSwitcher.action.recording.type.changeOutputFolder"}, + {MacroActionRecord::Action::FILE_FORMAT, + "AdvSceneSwitcher.action.recording.type.changeOutputFileFormat"}, }; bool MacroActionRecord::PerformAction() { switch (_action) { - case RecordAction::STOP: + case Action::STOP: if (obs_frontend_recording_active()) { obs_frontend_recording_stop(); } break; - case RecordAction::START: + case Action::START: if (!obs_frontend_recording_active()) { obs_frontend_recording_start(); } break; - case RecordAction::PAUSE: + case Action::PAUSE: if (obs_frontend_recording_active() && !obs_frontend_recording_paused()) { obs_frontend_recording_pause(true); } break; - case RecordAction::UNPAUSE: + case Action::UNPAUSE: if (obs_frontend_recording_active() && obs_frontend_recording_paused()) { obs_frontend_recording_pause(false); } break; #if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(28, 0, 0) - case RecordAction::SPLIT: + case Action::SPLIT: obs_frontend_recording_split_file(); break; #endif + case Action::FOLDER: { + std::string folder = _folder; // Trigger variable resolve + + auto conf = obs_frontend_get_profile_config(); + config_set_string(conf, "SimpleOutput", "FilePath", + folder.c_str()); + config_set_string(conf, "AdvOut", "FFFilePath", folder.c_str()); + config_set_string(conf, "AdvOut", "RecFilePath", + folder.c_str()); + if (config_save(conf) != CONFIG_SUCCESS) { + blog(LOG_WARNING, + "failed to set recoding output folder"); + } + break; + } + case Action::FILE_FORMAT: { + std::string format = _fileFormat; // Trigger variable resolve + + auto conf = obs_frontend_get_profile_config(); + config_set_string(conf, "Output", "FilenameFormatting", + format.c_str()); + if (config_save(conf) != CONFIG_SUCCESS) { + blog(LOG_WARNING, + "failed to set recoding file format string"); + } + break; + } default: break; } @@ -71,13 +108,17 @@ bool MacroActionRecord::Save(obs_data_t *obj) const { MacroAction::Save(obj); obs_data_set_int(obj, "action", static_cast(_action)); + _folder.Save(obj, "folder"); + _fileFormat.Save(obj, "format"); return true; } bool MacroActionRecord::Load(obs_data_t *obj) { MacroAction::Load(obj); - _action = static_cast(obs_data_get_int(obj, "action")); + _action = static_cast(obs_data_get_int(obj, "action")); + _folder.Load(obj, "folder"); + _fileFormat.Load(obj, "format"); return true; } @@ -95,21 +136,27 @@ MacroActionRecordEdit::MacroActionRecordEdit( _pauseHint(new QLabel(obs_module_text( "AdvSceneSwitcher.action.recording.pause.hint"))), _splitHint(new QLabel(obs_module_text( - "AdvSceneSwitcher.action.recording.split.hint"))) + "AdvSceneSwitcher.action.recording.split.hint"))), + _recordFolder(new FileSelection(FileSelection::Type::FOLDER, this)), + _recordFileFormat(new VariableLineEdit(this)) { populateActionSelection(_actions); QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, SLOT(ActionChanged(int))); + QWidget::connect(_recordFolder, SIGNAL(PathChanged(const QString &)), + this, SLOT(FolderChanged(const QString &))); + QWidget::connect(_recordFileFormat, SIGNAL(editingFinished()), this, + SLOT(FormatStringChanged())); - QHBoxLayout *mainLayout = new QHBoxLayout; - std::unordered_map widgetPlaceholders = { - {"{{actions}}", _actions}, - {"{{pauseHint}}", _pauseHint}, - {"{{splitHint}}", _splitHint}, - }; + auto mainLayout = new QHBoxLayout; placeWidgets(obs_module_text("AdvSceneSwitcher.action.recording.entry"), - mainLayout, widgetPlaceholders); + mainLayout, + {{"{{actions}}", _actions}, + {"{{pauseHint}}", _pauseHint}, + {"{{splitHint}}", _splitHint}, + {"{{recordFolder}}", _recordFolder}, + {"{{recordFileFormat}}", _recordFileFormat}}); setLayout(mainLayout); _entryData = entryData; @@ -123,18 +170,46 @@ void MacroActionRecordEdit::UpdateEntryData() return; } _actions->setCurrentIndex(static_cast(_entryData->_action)); - SetLabelVisibility(); + _recordFolder->SetPath(_entryData->_folder); + _recordFileFormat->setText(_entryData->_fileFormat); + SetWidgetVisibility(); } -bool isPauseAction(RecordAction a) +static bool isPauseAction(MacroActionRecord::Action a) { - return a == RecordAction::PAUSE || a == RecordAction::UNPAUSE; + return a == MacroActionRecord::Action::PAUSE || + a == MacroActionRecord::Action::UNPAUSE; } -void MacroActionRecordEdit::SetLabelVisibility() +void MacroActionRecordEdit::FolderChanged(const QString &folder) +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_folder = folder.toStdString(); +} + +void MacroActionRecordEdit::FormatStringChanged() +{ + if (_loading || !_entryData) { + return; + } + + std::lock_guard lock(switcher->m); + _entryData->_fileFormat = _recordFileFormat->text().toStdString(); +} + +void MacroActionRecordEdit::SetWidgetVisibility() { _pauseHint->setVisible(isPauseAction(_entryData->_action)); - _splitHint->setVisible(_entryData->_action == RecordAction::SPLIT); + _splitHint->setVisible(_entryData->_action == + MacroActionRecord::Action::SPLIT); + _recordFolder->setVisible(_entryData->_action == + MacroActionRecord::Action::FOLDER); + _recordFileFormat->setVisible(_entryData->_action == + MacroActionRecord::Action::FILE_FORMAT); } void MacroActionRecordEdit::ActionChanged(int value) @@ -144,8 +219,8 @@ void MacroActionRecordEdit::ActionChanged(int value) } std::lock_guard lock(switcher->m); - _entryData->_action = static_cast(value); - SetLabelVisibility(); + _entryData->_action = static_cast(value); + SetWidgetVisibility(); } } // namespace advss diff --git a/src/macro-core/macro-action-recording.hpp b/src/macro-core/macro-action-recording.hpp index adb2567d..3af471f7 100644 --- a/src/macro-core/macro-action-recording.hpp +++ b/src/macro-core/macro-action-recording.hpp @@ -1,19 +1,14 @@ #pragma once #include "macro-action-edit.hpp" +#include "file-selection.hpp" +#include "variable-line-edit.hpp" +#include #include #include namespace advss { -enum class RecordAction { - STOP, - START, - PAUSE, - UNPAUSE, - SPLIT, -}; - class MacroActionRecord : public MacroAction { public: MacroActionRecord(Macro *m) : MacroAction(m) {} @@ -27,7 +22,19 @@ public: return std::make_shared(m); } - RecordAction _action = RecordAction::STOP; + enum class Action { + STOP, + START, + PAUSE, + UNPAUSE, + SPLIT, + FOLDER, + FILE_FORMAT, + }; + Action _action = Action::STOP; + + StringVariable _folder = QDir::homePath().toStdString() + "/Videos"; + StringVariable _fileFormat = "%CCYY-%MM-%DD %hh-%mm-%ss"; private: static bool _registered; @@ -52,15 +59,19 @@ public: private slots: void ActionChanged(int value); + void FolderChanged(const QString &); + void FormatStringChanged(); protected: QComboBox *_actions; QLabel *_pauseHint; QLabel *_splitHint; + FileSelection *_recordFolder; + VariableLineEdit *_recordFileFormat; std::shared_ptr _entryData; private: - void SetLabelVisibility(); + void SetWidgetVisibility(); QHBoxLayout *_mainLayout; bool _loading = true;