mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-03-02 13:27:14 -05:00
UI: Add pause support
Adds support for pausing recordings. When settings are eligible for recordings, a pause button will appear next to the recording button. If the settings are not eligible, it will warn the user in the output settings that they cannot pause recordings if those settings are used.
This commit is contained in:
@@ -2112,6 +2112,17 @@ void OBSBasic::CreateHotkeys()
|
||||
LoadHotkeyPair(recordingHotkeys, "OBSBasic.StartRecording",
|
||||
"OBSBasic.StopRecording");
|
||||
|
||||
pauseHotkeys = obs_hotkey_pair_register_frontend(
|
||||
"OBSBasic.PauseRecording", Str("Basic.Main.PauseRecording"),
|
||||
"OBSBasic.UnpauseRecording", Str("Basic.Main.UnpauseRecording"),
|
||||
MAKE_CALLBACK(basic.pause && !basic.pause->isChecked(),
|
||||
basic.PauseRecording, "Pausing recording"),
|
||||
MAKE_CALLBACK(basic.pause && basic.pause->isChecked(),
|
||||
basic.UnpauseRecording, "Unpausing recording"),
|
||||
this, this);
|
||||
LoadHotkeyPair(pauseHotkeys, "OBSBasic.PauseRecording",
|
||||
"OBSBasic.UnpauseRecording");
|
||||
|
||||
replayBufHotkeys = obs_hotkey_pair_register_frontend(
|
||||
"OBSBasic.StartReplayBuffer",
|
||||
Str("Basic.Main.StartReplayBuffer"),
|
||||
@@ -2169,6 +2180,7 @@ void OBSBasic::ClearHotkeys()
|
||||
{
|
||||
obs_hotkey_pair_unregister(streamingHotkeys);
|
||||
obs_hotkey_pair_unregister(recordingHotkeys);
|
||||
obs_hotkey_pair_unregister(pauseHotkeys);
|
||||
obs_hotkey_pair_unregister(replayBufHotkeys);
|
||||
obs_hotkey_pair_unregister(togglePreviewHotkeys);
|
||||
obs_hotkey_unregister(forceStreamingStopHotkey);
|
||||
@@ -5319,6 +5331,7 @@ void OBSBasic::RecordingStart()
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STARTED);
|
||||
|
||||
OnActivate();
|
||||
UpdatePause();
|
||||
|
||||
blog(LOG_INFO, RECORDING_START);
|
||||
}
|
||||
@@ -5385,11 +5398,46 @@ void OBSBasic::RecordingStop(int code, QString last_error)
|
||||
AutoRemux();
|
||||
|
||||
OnDeactivate();
|
||||
UpdatePause(false);
|
||||
}
|
||||
|
||||
#define RP_NO_HOTKEY_TITLE QTStr("Output.ReplayBuffer.NoHotkey.Title")
|
||||
#define RP_NO_HOTKEY_TEXT QTStr("Output.ReplayBuffer.NoHotkey.Msg")
|
||||
|
||||
extern volatile bool recording_paused;
|
||||
extern volatile bool replaybuf_active;
|
||||
|
||||
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()->GlobalConfig(), "General",
|
||||
"WarnedAboutReplayBufferPausing", true);
|
||||
config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
bool warned = config_get_bool(App()->GlobalConfig(), "General",
|
||||
"WarnedAboutReplayBufferPausing");
|
||||
if (!warned) {
|
||||
QMetaObject::invokeMethod(App(), "Exec", Qt::QueuedConnection,
|
||||
Q_ARG(VoidFunc, msgBox));
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::StartReplayBuffer()
|
||||
{
|
||||
if (!outputHandler || !outputHandler->replayBuffer)
|
||||
@@ -5423,8 +5471,12 @@ void OBSBasic::StartReplayBuffer()
|
||||
api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTING);
|
||||
|
||||
SaveProject();
|
||||
if (!outputHandler->StartReplayBuffer())
|
||||
|
||||
if (!outputHandler->StartReplayBuffer()) {
|
||||
replayBufferButton->setChecked(false);
|
||||
} else if (os_atomic_load_bool(&recording_paused)) {
|
||||
ShowReplayBufferPauseWarning();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::ReplayBufferStopping()
|
||||
@@ -7295,3 +7347,106 @@ void OBSBasic::UpdatePatronJson(const QString &text, const QString &error)
|
||||
|
||||
patronJson = QT_TO_UTF8(text);
|
||||
}
|
||||
|
||||
void OBSBasic::PauseRecording()
|
||||
{
|
||||
if (!pause || !outputHandler || !outputHandler->fileOutput)
|
||||
return;
|
||||
|
||||
obs_output_t *output = outputHandler->fileOutput;
|
||||
|
||||
if (obs_output_pause(output, true)) {
|
||||
pause->setChecked(true);
|
||||
os_atomic_set_bool(&recording_paused, true);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_PAUSED);
|
||||
|
||||
if (os_atomic_load_bool(&replaybuf_active))
|
||||
ShowReplayBufferPauseWarning();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::UnpauseRecording()
|
||||
{
|
||||
if (!pause || !outputHandler || !outputHandler->fileOutput)
|
||||
return;
|
||||
|
||||
obs_output_t *output = outputHandler->fileOutput;
|
||||
|
||||
if (obs_output_pause(output, false)) {
|
||||
pause->setChecked(false);
|
||||
os_atomic_set_bool(&recording_paused, false);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_RECORDING_UNPAUSED);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::PauseToggled()
|
||||
{
|
||||
if (!pause || !outputHandler || !outputHandler->fileOutput)
|
||||
return;
|
||||
|
||||
obs_output_t *output = outputHandler->fileOutput;
|
||||
bool enable = !obs_output_paused(output);
|
||||
|
||||
if (obs_output_pause(output, enable)) {
|
||||
os_atomic_set_bool(&recording_paused, enable);
|
||||
|
||||
if (api)
|
||||
api->on_event(
|
||||
enable ? OBS_FRONTEND_EVENT_RECORDING_PAUSED
|
||||
: OBS_FRONTEND_EVENT_RECORDING_UNPAUSED);
|
||||
|
||||
if (enable && os_atomic_load_bool(&replaybuf_active))
|
||||
ShowReplayBufferPauseWarning();
|
||||
} else {
|
||||
pause->setChecked(!enable);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasic::UpdatePause(bool activate)
|
||||
{
|
||||
if (!activate || !outputHandler || !outputHandler->RecordingActive()) {
|
||||
pause.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const char *mode = config_get_string(basicConfig, "Output", "Mode");
|
||||
bool adv = astrcmpi(mode, "Advanced") == 0;
|
||||
bool shared;
|
||||
|
||||
if (adv) {
|
||||
const char *recType =
|
||||
config_get_string(basicConfig, "AdvOut", "RecType");
|
||||
|
||||
if (astrcmpi(recType, "FFmpeg") == 0) {
|
||||
shared = config_get_bool(basicConfig, "AdvOut",
|
||||
"FFOutputToFile");
|
||||
} else {
|
||||
const char *recordEncoder = config_get_string(
|
||||
basicConfig, "AdvOut", "RecEncoder");
|
||||
shared = astrcmpi(recordEncoder, "none") == 0;
|
||||
}
|
||||
} else {
|
||||
const char *quality = config_get_string(
|
||||
basicConfig, "SimpleOutput", "RecQuality");
|
||||
shared = strcmp(quality, "Stream") == 0;
|
||||
}
|
||||
|
||||
if (!shared) {
|
||||
pause.reset(new QPushButton());
|
||||
pause->setAccessibleName(QTStr("Basic.Main.PauseRecording"));
|
||||
pause->setToolTip(QTStr("Basic.Main.PauseRecording"));
|
||||
pause->setCheckable(true);
|
||||
pause->setChecked(false);
|
||||
pause->setProperty("themeID",
|
||||
QVariant(QStringLiteral("pauseIconSmall")));
|
||||
connect(pause.data(), &QAbstractButton::clicked, this,
|
||||
&OBSBasic::PauseToggled);
|
||||
ui->recordingLayout->addWidget(pause.data());
|
||||
} else {
|
||||
pause.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user