diff options
| author | dec05eba <dec05eba@protonmail.com> | 2026-08-05 15:26:36 +0200 |
|---|---|---|
| committer | dec05eba <dec05eba@protonmail.com> | 2026-08-05 15:26:36 +0200 |
| commit | 3a1ce0e17f209702095aaa86fedeb74400b3d039 (patch) | |
| tree | d16516e0876361da09c4ff6f05be5f190d0891a1 /src | |
| parent | f17157274d02ddf88af7af95ad6353b231983f5a (diff) | |
ipc: save-replay: add restart-replay option
Diffstat (limited to 'src')
| -rw-r--r-- | src/cli/ipc.c | 57 | ||||
| -rw-r--r-- | src/cli/main.c | 12 | ||||
| -rw-r--r-- | src/recorder/recorder.c | 9 |
3 files changed, 65 insertions, 13 deletions
diff --git a/src/cli/ipc.c b/src/cli/ipc.c index ff4b852..2fb3000 100644 --- a/src/cli/ipc.c +++ b/src/cli/ipc.c @@ -37,6 +37,7 @@ typedef struct { char name[GSR_IPC_MAX_REQUEST_NAME_SIZE]; sj_Value data; bool has_data; + const char *request_end; } gsr_ipc_request; typedef struct { @@ -269,6 +270,7 @@ static bool ipc_client_send_reply(gsr_ipc *self, gsr_ipc_client *client, int64_t static bool ipc_request_parse(char *data, size_t size, gsr_ipc_request *request, char *error_message, size_t error_message_size) { memset(request, 0, sizeof(*request)); + request->request_end = data + size; sj_Reader reader = sj_reader(data, size); const sj_Value root = sj_read(&reader); @@ -326,18 +328,57 @@ static bool ipc_request_parse(char *data, size_t size, gsr_ipc_request *request, return true; } -static bool ipc_request_get_save_replay_seconds(const gsr_ipc_request *request, int *seconds, char *error_message, size_t error_message_size) { +static bool json_value_to_save_replay_seconds(const sj_Value *value, int *seconds, char *error_message, size_t error_message_size) { + int64_t data_seconds = 0; + if(!gsr_json_number_to_int64(value, &data_seconds) || data_seconds <= 0 || data_seconds > INT_MAX) { + snprintf(error_message, error_message_size, "expected the number of seconds to save to be larger than 0"); + return false; + } + + *seconds = data_seconds; + return true; +} + +static bool ipc_request_get_save_replay_options(const gsr_ipc_request *request, int *seconds, bool *has_restart_replay, bool *restart_replay, char *error_message, size_t error_message_size) { *seconds = GSR_SAVE_REPLAY_SECONDS_FULL; + *has_restart_replay = false; + *restart_replay = false; if(!request->has_data || request->data.type == SJ_NULL) return true; - int64_t data_seconds = 0; - if(!gsr_json_number_to_int64(&request->data, &data_seconds) || data_seconds <= 0 || data_seconds > INT_MAX) { - snprintf(error_message, error_message_size, "expected 'data' to be the number of seconds to save, which has to be larger than 0"); + if(request->data.type != SJ_OBJECT) { + snprintf(error_message, error_message_size, "expected 'data' to be an object with the optional fields 'seconds' and 'restart-replay'"); + return false; + } + + sj_Reader reader = sj_reader(request->data.start, request->request_end - request->data.start); + const sj_Value data = sj_read(&reader); + + sj_Value key; + sj_Value value; + while(sj_iter_object(&reader, data, &key, &value)) { + if(gsr_json_string_equals(&key, "seconds")) { + if(value.type == SJ_NULL) + continue; + + if(!json_value_to_save_replay_seconds(&value, seconds, error_message, error_message_size)) + return false; + } else if(gsr_json_string_equals(&key, "restart-replay")) { + if(value.type != SJ_BOOL) { + snprintf(error_message, error_message_size, "expected 'restart-replay' to be true or false"); + return false; + } + + *has_restart_replay = true; + *restart_replay = gsr_json_string_equals(&value, "true"); + } + } + + if(reader.error) { + snprintf(error_message, error_message_size, "failed to parse 'data': %s", reader.error); return false; } - *seconds = data_seconds; return true; } @@ -437,10 +478,12 @@ static bool ipc_handle_request(gsr_ipc *self, const gsr_ipc_request *request, ch if(strcmp(request->name, "save-replay") == 0) { int seconds = GSR_SAVE_REPLAY_SECONDS_FULL; - if(!ipc_request_get_save_replay_seconds(request, &seconds, error_message, error_message_size)) + bool has_restart_replay = false; + bool restart_replay = false; + if(!ipc_request_get_save_replay_options(request, &seconds, &has_restart_replay, &restart_replay, error_message, error_message_size)) return false; - return self->handlers.save_replay(seconds, error_message, error_message_size, self->handlers.userdata); + return self->handlers.save_replay(seconds, has_restart_replay, restart_replay, error_message, error_message_size, self->handlers.userdata); } snprintf(error_message, error_message_size, "unknown request name '%s'", request->name); diff --git a/src/cli/main.c b/src/cli/main.c index de014a7..ac7de24 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -59,7 +59,7 @@ static void toggle_replay_recording_handler(int signal_value) { static void save_replay_seconds_handler(gsr_recorder *rec, int seconds) { if(rec) - gsr_recorder_save_replay(rec, seconds); + gsr_recorder_save_replay(rec, seconds, GSR_RESTART_REPLAY_USE_OPTION); else pending_save_replay_seconds = seconds; } @@ -78,7 +78,7 @@ static void apply_pending_signals(gsr_recorder *rec) { if(pending_save_replay_seconds != 0) { const int seconds = pending_save_replay_seconds; pending_save_replay_seconds = 0; - gsr_recorder_save_replay(rec, seconds); + gsr_recorder_save_replay(rec, seconds, GSR_RESTART_REPLAY_USE_OPTION); } } @@ -186,14 +186,18 @@ static bool ipc_stop_replay_recording_handler(char *error_message, size_t error_ return true; } -static bool ipc_save_replay_handler(int seconds, char *error_message, size_t error_message_size, void *userdata) { +static bool ipc_save_replay_handler(int seconds, bool has_restart_replay, bool restart_replay, char *error_message, size_t error_message_size, void *userdata) { const gsr_recorder_settings *settings = userdata; if(!settings->is_replaying) { snprintf(error_message, error_message_size, "option -r is required to save a replay"); return false; } - gsr_recorder_save_replay(recorder, seconds); + int restart_replay_request = GSR_RESTART_REPLAY_USE_OPTION; + if(has_restart_replay) + restart_replay_request = restart_replay ? GSR_RESTART_REPLAY_ENABLE : GSR_RESTART_REPLAY_DISABLE; + + gsr_recorder_save_replay(recorder, seconds, restart_replay_request); return true; } diff --git a/src/recorder/recorder.c b/src/recorder/recorder.c index fc0ccf0..3f1331f 100644 --- a/src/recorder/recorder.c +++ b/src/recorder/recorder.c @@ -101,6 +101,7 @@ struct gsr_recorder { atomic_int replay_recording_request; atomic_int replay_recording_state; atomic_int save_replay_seconds; + atomic_int save_replay_restart_replay; bool should_stop_error; bool force_iframe_frame; int audio_max_frame_size; @@ -418,6 +419,7 @@ gsr_recorder* gsr_recorder_create(const gsr_recorder_params *params, const gsr_r atomic_init(&self->replay_recording_request, GSR_REPLAY_RECORDING_REQUEST_NONE); atomic_init(&self->replay_recording_state, 0); atomic_init(&self->save_replay_seconds, 0); + atomic_init(&self->save_replay_restart_replay, GSR_RESTART_REPLAY_USE_OPTION); self->audio_max_frame_size = 1024; int error_code = GSR_ERROR_GENERIC; self->hdr = video_codec_is_hdr(params->settings->video_codec); @@ -748,11 +750,13 @@ static void recorder_poll_replay_save(gsr_recorder *self) { current_save_replay_seconds += self->settings.keyint; atomic_store(&self->save_replay_seconds, 0); + const int restart_replay_request = atomic_exchange(&self->save_replay_restart_replay, GSR_RESTART_REPLAY_USE_OPTION); + const bool restart_replay = restart_replay_request == GSR_RESTART_REPLAY_USE_OPTION ? self->settings.restart_replay_on_save : restart_replay_request == GSR_RESTART_REPLAY_ENABLE; const bool replay_start_result = gsr_replay_save_start(&self->replay_save, self->video_codec_context, GSR_VIDEO_STREAM_INDEX, &self->audio_capture, &self->encoder, &self->settings, self->file_extension, self->hdr, self->video_sources, current_save_replay_seconds); if(!replay_start_result && self->callbacks.replay_saved) self->callbacks.replay_saved(NULL, self->callbacks.userdata); - if(self->settings.restart_replay_on_save && current_save_replay_seconds == GSR_SAVE_REPLAY_SECONDS_FULL) { + if(restart_replay && current_save_replay_seconds == GSR_SAVE_REPLAY_SECONDS_FULL) { pthread_mutex_lock(&self->encoder.replay_mutex); gsr_replay_buffer_clear(self->encoder.replay_buffer); pthread_mutex_unlock(&self->encoder.replay_mutex); @@ -959,6 +963,7 @@ bool gsr_recorder_is_replay_recording(const gsr_recorder *self) { return atomic_load(&self->replay_recording_state) == 1; } -void gsr_recorder_save_replay(gsr_recorder *self, int seconds) { +void gsr_recorder_save_replay(gsr_recorder *self, int seconds, int restart_replay) { + atomic_store(&self->save_replay_restart_replay, restart_replay); atomic_store(&self->save_replay_seconds, seconds); } |
