diff --git a/docs/sphinx/reference-frontend-api.rst b/docs/sphinx/reference-frontend-api.rst index 6ef7854d12fa78..b4983669bc2d74 100644 --- a/docs/sphinx/reference-frontend-api.rst +++ b/docs/sphinx/reference-frontend-api.rst @@ -150,6 +150,10 @@ Structures/Enumerations Triggered when the replay buffer has fully stopped. + - **OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING** + + Triggered when the replay buffer is saving. + - **OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED** Triggered when the replay buffer has been saved. diff --git a/frontend/api/obs-frontend-api.h b/frontend/api/obs-frontend-api.h index 54cc6bf5669dbf..d5c34ee2aa1c7d 100644 --- a/frontend/api/obs-frontend-api.h +++ b/frontend/api/obs-frontend-api.h @@ -65,6 +65,8 @@ enum obs_frontend_event { OBS_FRONTEND_EVENT_CANVAS_ADDED, OBS_FRONTEND_EVENT_CANVAS_REMOVED, + + OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING, }; /* ------------------------------------------------------------------------- */ diff --git a/frontend/widgets/OBSBasic.hpp b/frontend/widgets/OBSBasic.hpp index 18ccb370a041e9..4b550f8ba72320 100644 --- a/frontend/widgets/OBSBasic.hpp +++ b/frontend/widgets/OBSBasic.hpp @@ -492,7 +492,7 @@ private slots: obs_hotkey_pair_id streamingHotkeys, recordingHotkeys, pauseHotkeys, replayBufHotkeys, vcamHotkeys, togglePreviewHotkeys, contextBarHotkeys; - obs_hotkey_id forceStreamingStopHotkey, splitFileHotkey, addChapterHotkey; + obs_hotkey_id forceStreamingStopHotkey, splitFileHotkey, addChapterHotkey, replayBufSaveHotkey; void InitHotkeys(); void CreateHotkeys(); diff --git a/frontend/widgets/OBSBasic_Hotkeys.cpp b/frontend/widgets/OBSBasic_Hotkeys.cpp index 3be00aeeed9169..f635ae5fa39b6a 100644 --- a/frontend/widgets/OBSBasic_Hotkeys.cpp +++ b/frontend/widgets/OBSBasic_Hotkeys.cpp @@ -206,6 +206,30 @@ void OBSBasic::CreateHotkeys() this, this); LoadHotkeyPair(replayBufHotkeys, "OBSBasic.StartReplayBuffer", "OBSBasic.StopReplayBuffer"); + auto replayBufferCallback = [](void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed) { + OBSBasic *basic = static_cast(data); + if (basic->outputHandler->ReplayBufferActive() && pressed) { + blog(LOG_INFO, "Saving replay buffer due to hotkey"); + basic->ReplayBufferSave(); + } + }; + + replayBufSaveHotkey = obs_hotkey_register_frontend("OBSBasic.SaveReplayBuffer", Str("Basic.Main.SaveReplay"), + replayBufferCallback, this); + + const char *exists = config_get_string(activeConfiguration, "Hotkeys", "OBSBasic.SaveReplayBuffer"); + if (exists) { + LoadHotkey(replayBufSaveHotkey, "OBSBasic.SaveReplayBuffer"); + } else { + OBSDataArrayAutoRelease array = obs_data_get_array(LoadHotkeyData("ReplayBuffer"), "ReplayBuffer.Save"); + obs_hotkey_load(replayBufSaveHotkey, array); + + OBSDataAutoRelease newData = obs_data_create(); + obs_data_set_array(newData, "bindings", array); + config_set_string(activeConfiguration, "Hotkeys", "OBSBasic.SaveReplayBuffer", + obs_data_get_json(newData)); + } + if (vcamEnabled) { vcamHotkeys = obs_hotkey_pair_register_frontend( "OBSBasic.StartVirtualCam", Str("Basic.Main.StartVirtualCam"), "OBSBasic.StopVirtualCam", diff --git a/frontend/widgets/OBSBasic_ReplayBuffer.cpp b/frontend/widgets/OBSBasic_ReplayBuffer.cpp index 8d95f2210677ba..12dc179f8c4ac3 100644 --- a/frontend/widgets/OBSBasic_ReplayBuffer.cpp +++ b/frontend/widgets/OBSBasic_ReplayBuffer.cpp @@ -147,6 +147,8 @@ void OBSBasic::ReplayBufferSave() if (!outputHandler->ReplayBufferActive()) return; + OnEvent(OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVING); + calldata_t cd = {0}; proc_handler_t *ph = obs_output_get_proc_handler(outputHandler->replayBuffer); proc_handler_call(ph, "save", &cd); diff --git a/plugins/obs-ffmpeg/data/locale/en-US.ini b/plugins/obs-ffmpeg/data/locale/en-US.ini index 2331d1e4917b1b..d74426cabb3a4c 100644 --- a/plugins/obs-ffmpeg/data/locale/en-US.ini +++ b/plugins/obs-ffmpeg/data/locale/en-US.ini @@ -100,7 +100,6 @@ MediaFileFilter.AudioFiles="Audio Files" MediaFileFilter.AllFiles="All Files" ReplayBuffer="Replay Buffer" -ReplayBuffer.Save="Save Replay" HelperProcessFailed="Unable to start the recording helper process. Check that OBS files have not been blocked or removed by any 3rd party antivirus / security software." UnableToWritePath="Unable to write to %1. Make sure you're using a recording path which your user account is allowed to write to and that there is sufficient disk space." diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-mux.c b/plugins/obs-ffmpeg/obs-ffmpeg-mux.c index f152b2849e3e1a..b0f3072309ef24 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-mux.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-mux.c @@ -914,30 +914,20 @@ static const char *replay_buffer_getname(void *type) return obs_module_text("ReplayBuffer"); } -static void replay_buffer_hotkey(void *data, obs_hotkey_id id, obs_hotkey_t *hotkey, bool pressed) +static void save_replay_proc(void *data, calldata_t *cd) { - UNUSED_PARAMETER(id); - UNUSED_PARAMETER(hotkey); - - if (!pressed) - return; struct ffmpeg_muxer *stream = data; if (os_atomic_load_bool(&stream->active)) { obs_encoder_t *vencoder = obs_output_get_video_encoder(stream->output); if (obs_encoder_paused(vencoder)) { - info("Could not save buffer because encoders paused"); + info("Could not save buffer because the encoder is paused"); return; } stream->save_ts = os_gettime_ns() / 1000LL; } -} - -static void save_replay_proc(void *data, calldata_t *cd) -{ - replay_buffer_hotkey(data, 0, NULL, true); UNUSED_PARAMETER(cd); } @@ -954,24 +944,19 @@ static void *replay_buffer_create(obs_data_t *settings, obs_output_t *output) struct ffmpeg_muxer *stream = bzalloc(sizeof(*stream)); stream->output = output; - stream->hotkey = obs_hotkey_register_output(output, "ReplayBuffer.Save", obs_module_text("ReplayBuffer.Save"), - replay_buffer_hotkey, stream); - proc_handler_t *ph = obs_output_get_proc_handler(output); proc_handler_add(ph, "void save()", save_replay_proc, stream); proc_handler_add(ph, "void get_last_replay(out string path)", get_last_replay, stream); signal_handler_t *sh = obs_output_get_signal_handler(output); signal_handler_add(sh, "void saved()"); + signal_handler_add(sh, "void saving(ptr output)"); return stream; } static void replay_buffer_destroy(void *data) { - struct ffmpeg_muxer *stream = data; - if (stream->hotkey) - obs_hotkey_unregister(stream->hotkey); ffmpeg_mux_destroy(data); } @@ -1154,6 +1139,12 @@ static void replay_buffer_save(struct ffmpeg_muxer *stream) int64_t audio_offsets[MAX_AUDIO_MIXES] = {0}; int64_t audio_dts_offsets[MAX_AUDIO_MIXES] = {0}; + calldata_t cd = {0}; + calldata_set_ptr(&cd, "output", stream->output); + signal_handler_t *sh = obs_output_get_signal_handler(stream->output); + signal_handler_signal(sh, "saving", &cd); + calldata_free(&cd); + for (size_t i = 0; i < num_packets; i++) { struct encoder_packet *pkt; pkt = deque_data(&stream->packets, i * size);