/****************************************************************************** Copyright (C) 2023 by Lain Bailey Zachary Lund Philippe Groarke This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ******************************************************************************/ #include "OBSBasic.hpp" #include #include #include #define REPLAY_BUFFER_START "==== Replay Buffer Start ===========================================" #define REPLAY_BUFFER_STOP "==== Replay Buffer Stop ============================================" void OBSBasic::ReplayBufferActionTriggered() { if (outputHandler->ReplayBufferActive()) StopReplayBuffer(); else StartReplayBuffer(); }; void OBSBasic::ShowReplayBufferPauseWarning() { auto msgBox = []() { QMessageBox msgbox(App()->GetMainWindow()); msgbox.setWindowTitle(QTStr("Output.ReplayBuffer." "PauseWarning.Title")); msgbox.setText(QTStr("Output.ReplayBuffer." "PauseWarning.Text")); msgbox.setIcon(QMessageBox::Icon::Information); msgbox.addButton(QMessageBox::Ok); QCheckBox *cb = new QCheckBox(QTStr("DoNotShowAgain")); msgbox.setCheckBox(cb); msgbox.exec(); if (cb->isChecked()) { config_set_bool(App()->GetUserConfig(), "General", "WarnedAboutReplayBufferPausing", true); config_save_safe(App()->GetUserConfig(), "tmp", nullptr); } }; bool warned = config_get_bool(App()->GetUserConfig(), "General", "WarnedAboutReplayBufferPausing"); if (!warned) { QMetaObject::invokeMethod(App(), "Exec", Qt::QueuedConnection, Q_ARG(VoidFunc, msgBox)); } } void OBSBasic::StartReplayBuffer() { if (!outputHandler || !outputHandler->replayBuffer) return; if (outputHandler->ReplayBufferActive()) return; if (disableOutputsRef) return; if (!UIValidation::NoSourcesConfirmation(this)) return; if (!OutputPathValid()) { OutputPathInvalidMessage(); return; } if (LowDiskSpace()) { DiskSpaceMessage(); return; } OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING); SaveProject(); if (outputHandler->StartReplayBuffer() && os_atomic_load_bool(&recording_paused)) { ShowReplayBufferPauseWarning(); } } void OBSBasic::ReplayBufferStopping() { if (!outputHandler || !outputHandler->replayBuffer) return; emit ReplayBufStopping(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText(QTStr("Basic.Main.StoppingReplayBuffer")); replayBufferStopping = true; OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPING); } void OBSBasic::StopReplayBuffer() { if (!outputHandler || !outputHandler->replayBuffer) return; SaveProject(); if (outputHandler->ReplayBufferActive()) outputHandler->StopReplayBuffer(replayBufferStopping); OnDeactivate(); } void OBSBasic::ReplayBufferStart() { if (!outputHandler || !outputHandler->replayBuffer) return; emit ReplayBufStarted(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText(QTStr("Basic.Main.StopReplayBuffer")); replayBufferStopping = false; OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED); OnActivate(); blog(LOG_INFO, REPLAY_BUFFER_START); } void OBSBasic::ReplayBufferSave() { if (!outputHandler || !outputHandler->replayBuffer) return; if (!outputHandler->ReplayBufferActive()) return; calldata_t cd = {0}; proc_handler_t *ph = obs_output_get_proc_handler(outputHandler->replayBuffer); proc_handler_call(ph, "save", &cd); calldata_free(&cd); } void OBSBasic::ReplayBufferSaved() { if (!outputHandler || !outputHandler->replayBuffer) return; if (!outputHandler->ReplayBufferActive()) return; calldata_t cd = {0}; proc_handler_t *ph = obs_output_get_proc_handler(outputHandler->replayBuffer); proc_handler_call(ph, "get_last_replay", &cd); std::string path = calldata_string(&cd, "path"); QString msg = QTStr("Basic.StatusBar.ReplayBufferSavedTo").arg(QT_UTF8(path.c_str())); ShowStatusBarMessage(msg); lastReplay = path; calldata_free(&cd); OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED); AutoRemux(QT_UTF8(path.c_str())); } void OBSBasic::ReplayBufferStop(int code) { if (!outputHandler || !outputHandler->replayBuffer) return; emit ReplayBufStopped(); if (sysTrayReplayBuffer) sysTrayReplayBuffer->setText(QTStr("Basic.Main.StartReplayBuffer")); blog(LOG_INFO, REPLAY_BUFFER_STOP); if (code == OBS_OUTPUT_UNSUPPORTED && isVisible()) { OBSMessageBox::critical(this, QTStr("Output.RecordFail.Title"), QTStr("Output.RecordFail.Unsupported")); } else if (code == OBS_OUTPUT_NO_SPACE && isVisible()) { OBSMessageBox::warning(this, QTStr("Output.RecordNoSpace.Title"), QTStr("Output.RecordNoSpace.Msg")); } else if (code != OBS_OUTPUT_SUCCESS && isVisible()) { OBSMessageBox::critical(this, QTStr("Output.RecordError.Title"), QTStr("Output.RecordError.Msg")); } else if (code == OBS_OUTPUT_UNSUPPORTED && !isVisible()) { SysTrayNotify(QTStr("Output.RecordFail.Unsupported"), QSystemTrayIcon::Warning); } else if (code == OBS_OUTPUT_NO_SPACE && !isVisible()) { SysTrayNotify(QTStr("Output.RecordNoSpace.Msg"), QSystemTrayIcon::Warning); } else if (code != OBS_OUTPUT_SUCCESS && !isVisible()) { SysTrayNotify(QTStr("Output.RecordError.Msg"), QSystemTrayIcon::Warning); } OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED); OnDeactivate(); } bool OBSBasic::ReplayBufferActive() { if (!outputHandler) return false; return outputHandler->ReplayBufferActive(); }