aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cli/ipc.c57
-rw-r--r--src/cli/main.c12
-rw-r--r--src/recorder/recorder.c9
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);
}