UI: Add replay buffer options to simple output mode

This commit is contained in:
jp9000 2016-12-07 05:21:44 -08:00
parent 47fe89b964
commit 752c118f2e
8 changed files with 400 additions and 158 deletions

View File

@ -58,6 +58,7 @@ Hours="Hours"
Minutes="Minutes"
Seconds="Seconds"
Deprecated="Deprecated"
ReplayBuffer="Replay Buffer"
# quick transitions
QuickTransitions.SwapScenes="Swap Preview/Output Scenes After Transitioning"
@ -123,6 +124,8 @@ Output.RecordNoSpace.Title="Insufficient disk space"
Output.RecordNoSpace.Msg="There is not sufficient disk space to continue recording."
Output.RecordError.Title="Recording error"
Output.RecordError.Msg="An unspecified error occurred while recording."
Output.ReplayBuffer.NoHotkey.Title="No hotkey set!"
Output.ReplayBuffer.NoHotkey.Msg="No hotkey set for replay buffer. Please set a hotkey to use for saving replay recordings."
# output recording messages
Output.BadPath.Title="Bad File Path"
@ -304,9 +307,12 @@ Basic.Main.Scenes="Scenes"
Basic.Main.Sources="Sources"
Basic.Main.Connecting="Connecting..."
Basic.Main.StartRecording="Start Recording"
Basic.Main.StartReplayBuffer="Start Replay Buffer"
Basic.Main.StartStreaming="Start Streaming"
Basic.Main.StopRecording="Stop Recording"
Basic.Main.StoppingRecording="Stopping Recording..."
Basic.Main.StopReplayBuffer="Stop Replay Buffer"
Basic.Main.StoppingReplayBuffer="Stopping Replay Buffer..."
Basic.Main.StopStreaming="Stop Streaming"
Basic.Main.StoppingStreaming="Stopping Stream..."
Basic.Main.ForceStopStreaming="Stop Streaming (discard delay)"
@ -414,6 +420,12 @@ Basic.Settings.Output.Mode="Output Mode"
Basic.Settings.Output.Mode.Simple="Simple"
Basic.Settings.Output.Mode.Adv="Advanced"
Basic.Settings.Output.Mode.FFmpeg="FFmpeg Output"
Basic.Settings.Output.UseReplayBuffer="Replay Buffer Mode"
Basic.Settings.Output.ReplayBuffer.SecondsMax="Maximum Replay Time (Seconds)"
Basic.Settings.Output.ReplayBuffer.MegabytesMax="Maximum Memory (Megabytes)"
Basic.Settings.Output.ReplayBuffer.Estimate="Estimated memory usage: %1 MB"
Basic.Settings.Output.ReplayBuffer.EstimateUnknown="Cannot estimate memory usage. Please set maximum memory limit."
Basic.Settings.Output.ReplayBuffer.HotkeyMessage="(Note: Make sure to set a hotkey for the replay buffer in the hotkeys section)"
Basic.Settings.Output.Simple.SavePath="Recording Path"
Basic.Settings.Output.Simple.RecordingQuality="Recording Quality"
Basic.Settings.Output.Simple.RecordingQuality.Stream="Same as stream"
@ -562,8 +574,8 @@ Basic.Settings.Hotkeys.Pair="Key combinations shared with '%1' act as toggles"
# basic mode hotkeys
Basic.Hotkeys.StartStreaming="Start Streaming"
Basic.Hotkeys.StopStreaming="Stop Streaming"
Basic.Hotkeys.StartRecording="Start Recording"
Basic.Hotkeys.StopRecording="Stop Recording"
Basic.Hotkeys.StartRecording="Start Recording/Replay Buffer"
Basic.Hotkeys.StopRecording="Stop Recording/Replay Buffer"
Basic.Hotkeys.SelectScene="Switch to scene"
# system tray

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>981</width>
<height>667</height>
<height>720</height>
</rect>
</property>
<property name="sizePolicy">
@ -739,6 +739,25 @@
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_18">
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Basic.Settings.Output.Simple.SavePath</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>simpleOutputPath</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
@ -760,25 +779,6 @@
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_18">
<property name="minimumSize">
<size>
<width>170</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Basic.Settings.Output.Simple.SavePath</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>simpleOutputPath</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="simpleNoSpace">
<property name="text">
@ -789,6 +789,29 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Basic.Settings.Output.Simple.RecordingQuality</string>
</property>
<property name="buddy">
<cstring>simpleOutRecQuality</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="simpleOutRecQuality"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="simpleOutRecFormatLabel">
<property name="text">
<string>Basic.Settings.Output.Format</string>
</property>
<property name="buddy">
<cstring>simpleOutRecFormat</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="simpleOutRecFormat">
<item>
@ -823,32 +846,6 @@
</item>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="simpleOutRecFormatLabel">
<property name="text">
<string>Basic.Settings.Output.Format</string>
</property>
<property name="buddy">
<cstring>simpleOutRecFormat</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="simpleOutRecQuality"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Basic.Settings.Output.Simple.RecordingQuality</string>
</property>
<property name="buddy">
<cstring>simpleOutRecQuality</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="simpleOutRecEncoder"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="simpleOutRecEncoderLabel">
<property name="text">
@ -859,6 +856,9 @@
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="simpleOutRecEncoder"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_420">
<property name="text">
@ -872,6 +872,91 @@
<item row="5" column="1">
<widget class="QLineEdit" name="simpleOutMuxCustom"/>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="simpleReplayBuf">
<property name="text">
<string>Basic.Settings.Output.UseReplayBuffer</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="replayBufferGroupBox">
<property name="title">
<string>ReplayBuffer</string>
</property>
<layout class="QFormLayout" name="formLayout_24">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_35">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.SecondsMax</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="simpleRBSecMax">
<property name="suffix">
<string notr="true"> sec</string>
</property>
<property name="minimum">
<number>5</number>
</property>
<property name="maximum">
<number>21600</number>
</property>
<property name="value">
<number>15</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="simpleRBMegsMaxLabel">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.MegabytesMax</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="simpleRBMegsMax">
<property name="suffix">
<string notr="true"> MB</string>
</property>
<property name="minimum">
<number>20</number>
</property>
<property name="maximum">
<number>8192</number>
</property>
<property name="value">
<number>512</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="simpleRBEstimate">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_45">
<property name="text">
<string>Basic.Settings.Output.ReplayBuffer.HotkeyMessage</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -2545,8 +2630,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>80</width>
<height>16</height>
<width>98</width>
<height>28</height>
</rect>
</property>
</widget>
@ -3384,12 +3469,12 @@
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>310</x>
<y>29</y>
<x>159</x>
<y>30</y>
</hint>
<hint type="destinationlabel">
<x>241</x>
<y>34</y>
<y>30</y>
</hint>
</hints>
</connection>
@ -3400,12 +3485,12 @@
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>586</x>
<y>38</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>401</x>
<y>102</y>
</hint>
</hints>
</connection>
@ -3416,12 +3501,12 @@
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>180</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>229</y>
</hint>
</hints>
</connection>
@ -3432,12 +3517,12 @@
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>180</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>383</x>
<y>229</y>
</hint>
</hints>
</connection>
@ -3448,12 +3533,12 @@
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>180</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>255</y>
</hint>
</hints>
</connection>
@ -3464,12 +3549,12 @@
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>180</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>383</x>
<y>255</y>
</hint>
</hints>
</connection>
@ -3480,12 +3565,12 @@
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>48</y>
<x>232</x>
<y>71</y>
</hint>
<hint type="destinationlabel">
<x>241</x>
<y>30</y>
<y>83</y>
</hint>
</hints>
</connection>
@ -3496,12 +3581,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>60</y>
<x>168</x>
<y>97</y>
</hint>
<hint type="destinationlabel">
<x>228</x>
<y>50</y>
<x>250</x>
<y>97</y>
</hint>
</hints>
</connection>
@ -3512,12 +3597,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>39</y>
<x>168</x>
<y>82</y>
</hint>
<hint type="destinationlabel">
<x>228</x>
<y>29</y>
<x>232</x>
<y>82</y>
</hint>
</hints>
</connection>
@ -3528,12 +3613,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>60</y>
<x>168</x>
<y>86</y>
</hint>
<hint type="destinationlabel">
<x>228</x>
<y>50</y>
<x>232</x>
<y>86</y>
</hint>
</hints>
</connection>
@ -3544,12 +3629,12 @@
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>60</y>
<x>250</x>
<y>80</y>
</hint>
<hint type="destinationlabel">
<x>259</x>
<y>60</y>
<x>250</x>
<y>82</y>
</hint>
</hints>
</connection>
@ -3560,12 +3645,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>653</x>
<y>408</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>397</x>
<y>434</y>
</hint>
</hints>
</connection>
@ -3576,12 +3661,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>653</x>
<y>408</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>653</x>
<y>457</y>
</hint>
</hints>
</connection>
@ -3592,12 +3677,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>653</x>
<y>408</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>653</x>
<y>434</y>
</hint>
</hints>
</connection>
@ -3608,12 +3693,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>513</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>332</x>
<y>539</y>
</hint>
</hints>
</connection>
@ -3624,12 +3709,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>513</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>539</y>
</hint>
</hints>
</connection>
@ -3640,12 +3725,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>513</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>332</x>
<y>565</y>
</hint>
</hints>
</connection>
@ -3656,12 +3741,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>513</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>588</x>
<y>565</y>
</hint>
</hints>
</connection>
@ -3672,12 +3757,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>720</x>
<y>280</y>
<x>951</x>
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>346</x>
<y>306</y>
<y>375</y>
</hint>
</hints>
</connection>
@ -3688,12 +3773,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>761</x>
<y>280</y>
<x>951</x>
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>778</x>
<y>306</y>
<x>951</x>
<y>375</y>
</hint>
</hints>
</connection>
@ -3704,12 +3789,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>820</x>
<y>280</y>
<x>951</x>
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>810</x>
<y>329</y>
<x>951</x>
<y>398</y>
</hint>
</hints>
</connection>
@ -3720,12 +3805,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>862</x>
<y>280</y>
<x>951</x>
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>859</x>
<y>352</y>
<x>951</x>
<y>421</y>
</hint>
</hints>
</connection>
@ -3736,12 +3821,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>866</x>
<y>280</y>
<x>951</x>
<y>349</y>
</hint>
<hint type="destinationlabel">
<x>866</x>
<y>375</y>
<x>951</x>
<y>444</y>
</hint>
</hints>
</connection>
@ -3752,12 +3837,12 @@
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>180</y>
</hint>
<hint type="destinationlabel">
<x>250</x>
<y>39</y>
<x>640</x>
<y>203</y>
</hint>
</hints>
</connection>
@ -3768,12 +3853,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>404</x>
<y>193</y>
<x>705</x>
<y>225</y>
</hint>
<hint type="destinationlabel">
<x>404</x>
<y>219</y>
<x>705</x>
<y>248</y>
</hint>
</hints>
</connection>
@ -3784,12 +3869,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>404</x>
<y>245</y>
<x>705</x>
<y>271</y>
</hint>
<hint type="destinationlabel">
<x>404</x>
<y>271</y>
<x>705</x>
<y>294</y>
</hint>
</hints>
</connection>

View File

@ -306,8 +306,21 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
LoadRecordingPreset();
if (!ffmpegOutput) {
fileOutput = obs_output_create("ffmpeg_muxer",
"simple_file_output", nullptr, nullptr);
replayBuffer = config_get_bool(main->Config(),
"SimpleOutput", "RecRB");
if (replayBuffer) {
const char *str = config_get_string(main->Config(),
"Hotkeys", "ReplayBuffer");
obs_data_t *hotkey = obs_data_create_from_json(str);
fileOutput = obs_output_create("replay_buffer",
Str("ReplayBuffer"), nullptr, hotkey);
obs_data_release(hotkey);
} else {
fileOutput = obs_output_create("ffmpeg_muxer",
"simple_file_output", nullptr, nullptr);
}
if (!fileOutput)
throw "Failed to create recording output "
"(simple output)";
@ -660,6 +673,10 @@ bool SimpleOutput::StartRecording()
"FilenameFormatting");
bool overwriteIfExists = config_get_bool(main->Config(), "Output",
"OverwriteIfExists");
int rbTime = config_get_int(main->Config(), "SimpleOutput",
"RecRBTime");
int rbSize = config_get_int(main->Config(), "SimpleOutput",
"RecRBSize");
os_dir_t *dir = path ? os_opendir(path) : nullptr;
@ -695,8 +712,17 @@ bool SimpleOutput::StartRecording()
}
obs_data_t *settings = obs_data_create();
obs_data_set_string(settings, ffmpegOutput ? "url" : "path",
strPath.c_str());
if (replayBuffer) {
obs_data_set_string(settings, "directory", path);
obs_data_set_string(settings, "format", filenameFormat);
obs_data_set_string(settings, "extension", format);
obs_data_set_int(settings, "max_time_sec", rbTime);
obs_data_set_int(settings, "max_size_mb",
usingRecordingPreset ? rbSize : 0);
} else {
obs_data_set_string(settings, ffmpegOutput ? "url" : "path",
strPath.c_str());
}
obs_data_set_string(settings, "muxer_settings", mux);
obs_output_update(fileOutput, settings);

View File

@ -8,6 +8,7 @@ struct BasicOutputHandler {
bool streamingActive = false;
bool recordingActive = false;
bool delayActive = false;
bool replayBuffer = false;
OBSBasic *main;
OBSSignal startRecording;

View File

@ -847,6 +847,9 @@ bool OBSBasic::InitBasicConfigDefaults()
"Stream");
config_set_default_string(basicConfig, "SimpleOutput", "RecEncoder",
SIMPLE_ENCODER_X264);
config_set_default_bool(basicConfig, "SimpleOutput", "RecRB", false);
config_set_default_int(basicConfig, "SimpleOutput", "RecRBTime", 20);
config_set_default_int(basicConfig, "SimpleOutput", "RecRBSize", 512);
config_set_default_bool (basicConfig, "AdvOut", "ApplyServiceSettings",
true);
@ -1041,6 +1044,16 @@ void OBSBasic::ResetOutputs()
outputHandler.reset(advOut ?
CreateAdvancedOutputHandler(this) :
CreateSimpleOutputHandler(this));
if (outputHandler->replayBuffer)
ui->recordButton->setText(
QTStr("Basic.Main.StartReplayBuffer"));
else
ui->recordButton->setText(
QTStr("Basic.Main.StartRecording"));
if (sysTrayRecord)
sysTrayRecord->setText(ui->recordButton->text());
} else {
outputHandler->Update();
}
@ -3905,11 +3918,31 @@ void OBSBasic::StreamingStop(int code)
}
}
#define RP_NO_HOTKEY_TITLE QTStr("Output.ReplayBuffer.NoHotkey.Title")
#define RP_NO_HOTKEY_TEXT QTStr("Output.ReplayBuffer.NoHotkey.Msg")
void OBSBasic::StartRecording()
{
if (outputHandler->RecordingActive())
return;
if (outputHandler->replayBuffer) {
obs_output_t *output = outputHandler->fileOutput;
obs_data_t *hotkeys = obs_hotkeys_save_output(output);
obs_data_array_t *bindings = obs_data_get_array(hotkeys,
"ReplayBuffer.Save");
size_t count = obs_data_array_count(bindings);
obs_data_array_release(bindings);
obs_data_release(hotkeys);
if (!count) {
QMessageBox::information(this,
RP_NO_HOTKEY_TITLE,
RP_NO_HOTKEY_TEXT);
return;
}
}
if (api)
api->on_event(OBS_FRONTEND_EVENT_RECORDING_STARTING);
@ -3919,7 +3952,10 @@ void OBSBasic::StartRecording()
void OBSBasic::RecordStopping()
{
ui->recordButton->setText(QTStr("Basic.Main.StoppingRecording"));
if (outputHandler->replayBuffer)
ui->recordButton->setText(QTStr("Basic.Main.StoppingReplayBuffer"));
else
ui->recordButton->setText(QTStr("Basic.Main.StoppingRecording"));
if (sysTrayRecord)
sysTrayRecord->setText(ui->recordButton->text());
@ -3942,7 +3978,11 @@ void OBSBasic::StopRecording()
void OBSBasic::RecordingStart()
{
ui->statusbar->RecordingStarted(outputHandler->fileOutput);
ui->recordButton->setText(QTStr("Basic.Main.StopRecording"));
if (outputHandler->replayBuffer)
ui->recordButton->setText(QTStr("Basic.Main.StopReplayBuffer"));
else
ui->recordButton->setText(QTStr("Basic.Main.StopRecording"));
if (sysTrayRecord)
sysTrayRecord->setText(ui->recordButton->text());
@ -3959,7 +3999,11 @@ void OBSBasic::RecordingStart()
void OBSBasic::RecordingStop(int code)
{
ui->statusbar->RecordingStopped();
ui->recordButton->setText(QTStr("Basic.Main.StartRecording"));
if (outputHandler->replayBuffer)
ui->recordButton->setText(QTStr("Basic.Main.StartReplayBuffer"));
else
ui->recordButton->setText(QTStr("Basic.Main.StartRecording"));
if (sysTrayRecord)
sysTrayRecord->setText(ui->recordButton->text());
@ -4696,6 +4740,8 @@ void OBSBasic::SystemTrayInit()
exit = new QAction(QTStr("Exit"),
trayIcon);
sysTrayRecord->setText(ui->recordButton->text());
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this,
SLOT(IconActivated(QSystemTrayIcon::ActivationReason)));

View File

@ -86,6 +86,7 @@ class OBSBasic : public OBSMainWindow {
friend class OBSBasicPreview;
friend class OBSBasicStatusBar;
friend class OBSBasicSourceSelect;
friend class OBSBasicSettings;
friend struct OBSStudioAPI;
enum class MoveDir {

View File

@ -44,6 +44,7 @@
#include "qt-wrappers.hpp"
#include "window-basic-main.hpp"
#include "window-basic-settings.hpp"
#include "window-basic-main-outputs.hpp"
#include <util/platform.h>
@ -299,6 +300,9 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->simpleOutRecQuality, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutRecEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleOutMuxCustom, EDIT_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleReplayBuf, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleRBSecMax, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->simpleRBMegsMax, SCROLL_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutEncoder, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutUseRescale, CHECK_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->advOutRescale, CBEDIT_CHANGED, OUTPUTS_CHANGED);
@ -525,6 +529,14 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
this, SLOT(SimpleRecordingEncoderChanged()));
connect(ui->simpleOutEnforce, SIGNAL(toggled(bool)),
this, SLOT(SimpleRecordingEncoderChanged()));
connect(ui->simpleReplayBuf, SIGNAL(toggled(bool)),
this, SLOT(SimpleReplayBufferChanged()));
connect(ui->simpleOutputVBitrate, SIGNAL(valueChanged(int)),
this, SLOT(SimpleReplayBufferChanged()));
connect(ui->simpleOutputABitrate, SIGNAL(currentIndexChanged(int)),
this, SLOT(SimpleReplayBufferChanged()));
connect(ui->simpleRBSecMax, SIGNAL(valueChanged(int)),
this, SLOT(SimpleReplayBufferChanged()));
connect(ui->listWidget, SIGNAL(currentRowChanged(int)),
this, SLOT(SimpleRecordingEncoderChanged()));
@ -1216,6 +1228,12 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
"RecEncoder");
const char *muxCustom = config_get_string(main->Config(),
"SimpleOutput", "MuxerCustom");
bool replayBuf = config_get_bool(main->Config(), "SimpleOutput",
"RecRB");
int rbTime = config_get_int(main->Config(), "SimpleOutput",
"RecRBTime");
int rbSize = config_get_int(main->Config(), "SimpleOutput",
"RecRBSize");
curPreset = preset;
curQSVPreset = qsvPreset;
@ -1252,6 +1270,10 @@ void OBSBasicSettings::LoadSimpleOutputSettings()
ui->simpleOutMuxCustom->setText(muxCustom);
ui->simpleReplayBuf->setChecked(replayBuf);
ui->simpleRBSecMax->setValue(rbTime);
ui->simpleRBMegsMax->setValue(rbSize);
SimpleStreamingEncoderChanged();
}
@ -1555,6 +1577,7 @@ void OBSBasicSettings::LoadOutputSettings()
ui->outputMode->setEnabled(false);
ui->outputModeLabel->setEnabled(false);
ui->simpleRecordingGroupBox->setEnabled(false);
ui->replayBufferGroupBox->setEnabled(false);
ui->advOutTopContainer->setEnabled(false);
ui->advOutRecTopContainer->setEnabled(false);
ui->advOutRecTypeContainer->setEnabled(false);
@ -2489,6 +2512,9 @@ void OBSBasicSettings::SaveOutputSettings()
SaveComboData(ui->simpleOutRecQuality, "SimpleOutput", "RecQuality");
SaveComboData(ui->simpleOutRecEncoder, "SimpleOutput", "RecEncoder");
SaveEdit(ui->simpleOutMuxCustom, "SimpleOutput", "MuxerCustom");
SaveCheckBox(ui->simpleReplayBuf, "SimpleOutput", "RecRB");
SaveSpinBox(ui->simpleRBSecMax, "SimpleOutput", "RecRBTime");
SaveSpinBox(ui->simpleRBMegsMax, "SimpleOutput", "RecRBSize");
curAdvStreamEncoder = GetComboData(ui->advOutEncoder);
@ -2636,6 +2662,15 @@ void OBSBasicSettings::SaveHotkeySettings()
obs_data_release(data);
obs_data_array_release(array);
}
const char *id = obs_obj_get_id(main->outputHandler->fileOutput);
if (strcmp(id, "replay_buffer") == 0) {
obs_data_t *hotkeys = obs_hotkeys_save_output(
main->outputHandler->fileOutput);
config_set_string(config, "Hotkeys", "ReplayBuffer",
obs_data_get_json(hotkeys));
obs_data_release(hotkeys);
}
}
#define MINOR_SEPARATOR \
@ -3292,6 +3327,7 @@ void OBSBasicSettings::SimpleRecordingQualityChanged()
ui->simpleOutRecFormatLabel->setVisible(!losslessQuality);
SimpleRecordingEncoderChanged();
SimpleReplayBufferChanged();
}
void OBSBasicSettings::SimpleStreamingEncoderChanged()
@ -3364,6 +3400,39 @@ void OBSBasicSettings::SimpleStreamingEncoderChanged()
ui->simpleOutPreset->setCurrentIndex(idx);
}
#define ESTIMATE_STR "Basic.Settings.Output.ReplayBuffer.Estimate"
#define ESTIMATE_UNKNOWN_STR \
"Basic.Settings.Output.ReplayBuffer.EstimateUnknown"
void OBSBasicSettings::SimpleReplayBufferChanged()
{
QString qual = ui->simpleOutRecQuality->currentData().toString();
bool replayBufferEnabled = ui->simpleReplayBuf->isChecked();
bool lossless = qual == "Lossless";
bool streamQuality = qual == "Stream";
ui->simpleRBMegsMax->setVisible(!streamQuality);
ui->simpleRBMegsMaxLabel->setVisible(!streamQuality);
int vbitrate = ui->simpleOutputVBitrate->value();
int abitrate = ui->simpleOutputABitrate->currentText().toInt();
int seconds = ui->simpleRBSecMax->value();
int64_t memMB = int64_t(seconds) * int64_t(vbitrate + abitrate) *
1000 / 8 / 1024 / 1024;
if (memMB < 1) memMB = 1;
if (streamQuality)
ui->simpleRBEstimate->setText(
QTStr(ESTIMATE_STR).arg(
QString::number(int(memMB))));
else
ui->simpleRBEstimate->setText(QTStr(ESTIMATE_UNKNOWN_STR));
ui->replayBufferGroupBox->setVisible(!lossless && replayBufferEnabled);
ui->simpleReplayBuf->setVisible(!lossless);
}
#define SIMPLE_OUTPUT_WARNING(str) \
QTStr("Basic.Settings.Output.Simple.Warn." str)

View File

@ -290,6 +290,8 @@ private slots:
void SimpleRecordingEncoderChanged();
void SimpleRecordingQualityLosslessWarning(int idx);
void SimpleReplayBufferChanged();
void SimpleStreamingEncoderChanged();
protected: