diff options
| author | Trung Lê <8@tle.id.au> | 2026-02-22 11:29:18 +1100 |
|---|---|---|
| committer | Trung Lê <8@tle.id.au> | 2026-02-22 11:29:18 +1100 |
| commit | 9690617ae3855ab9f58e5bce0f55b4842b9832e5 (patch) | |
| tree | 22fb5532cbaf4a6f0c4b1714f563aebf68b52918 /src | |
| parent | 442c8be65ac2ba1fdcbcfa8204adec5fecb2c474 (diff) | |
Prepare 1.0.0: fix memory leaks, use-after-free bugs, and code quality issues
- Version 6.0.0 → 1.0.0, C standard gnu17 → gnu23
- Fix desktop file path (was referencing parent directory)
- global_shortcuts.c: fix systematic GVariant/GDBusProxy leaks, guint64-to-gchar*
type mismatch, buffer overflow risk, missing malloc NULL checks, debug artifacts
- gsr-window.c: fix notification timeout use-after-free, menu object leak in
finalize, localtime NULL check, extract active_mode_to_string helper
- gsr-stream-page.c, gsr-record-page.c, gsr-replay-page.c: fix timer source
leak in finalize (use-after-free if destroyed while timer running)
- gsr-shortcut-accel-dialog.c: fix Pango markup injection via shortcut titles
- gsr-info.c: fix pclose UB, replace fprintf with g_warning
- gsr-config.c: include errno in fopen failure warning
- Remove unused include, stale Phase 5 comments
Diffstat (limited to 'src')
| -rw-r--r-- | src/global_shortcuts.c | 91 | ||||
| -rw-r--r-- | src/gsr-config.c | 2 | ||||
| -rw-r--r-- | src/gsr-info.c | 4 | ||||
| -rw-r--r-- | src/gsr-record-page.c | 7 | ||||
| -rw-r--r-- | src/gsr-record-page.h | 2 | ||||
| -rw-r--r-- | src/gsr-replay-page.c | 6 | ||||
| -rw-r--r-- | src/gsr-replay-page.h | 2 | ||||
| -rw-r--r-- | src/gsr-shortcut-accel-dialog.c | 12 | ||||
| -rw-r--r-- | src/gsr-stream-page.c | 8 | ||||
| -rw-r--r-- | src/gsr-stream-page.h | 2 | ||||
| -rw-r--r-- | src/gsr-window.c | 57 |
11 files changed, 135 insertions, 58 deletions
diff --git a/src/global_shortcuts.c b/src/global_shortcuts.c index a7540f0..794de04 100644 --- a/src/global_shortcuts.c +++ b/src/global_shortcuts.c @@ -5,14 +5,9 @@ #include <sys/random.h> #include <gio/gio.h> -/* TODO: Remove G_DBUS_CALL_FLAGS_NO_AUTO_START and G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START? also in gpu screen recorder equivalent */ -/* TODO: More error handling and clean up resources after done */ -/* TODO: Use GArray instead of GVariant where possible */ - static bool generate_random_characters(char *buffer, int buffer_size, const char *alphabet, size_t alphabet_size) { - /* TODO: Use other functions on other platforms than linux */ if(getrandom(buffer, buffer_size, 0) < buffer_size) { - fprintf(stderr, "gsr error: generate_random_characters: failed to get random bytes, error: %s\n", strerror(errno)); + g_warning("generate_random_characters: failed to get random bytes: %s", strerror(errno)); return false; } @@ -35,11 +30,11 @@ static void handle_shortcuts_data(GVariant *shortcuts, gsr_shortcut_callback cal GVariant *shortcut_values = NULL; g_variant_get_child(shortcuts, i, "(s@a{sv})", &shortcut_id, &shortcut_values); - if(!shortcut_id || !shortcut_values) + if(!shortcut_id || !shortcut_values) { + g_free(shortcut_id); + if(shortcut_values) g_variant_unref(shortcut_values); continue; - - // gchar *description = NULL; - // g_variant_lookup(shortcut_values, "description", "s", &description); + } gchar *trigger_description = NULL; g_variant_lookup(shortcut_values, "trigger_description", "s", &trigger_description); @@ -48,6 +43,10 @@ static void handle_shortcuts_data(GVariant *shortcuts, gsr_shortcut_callback cal shortcut.id = shortcut_id; shortcut.trigger_description = trigger_description ? trigger_description : ""; callback(shortcut, userdata); + + g_free(shortcut_id); + g_free(trigger_description); + g_variant_unref(shortcut_values); } } @@ -67,14 +66,20 @@ static void dbus_signal_list_bind(GDBusProxy *proxy, gchar *sender_name, gchar * GVariant *results = NULL; g_variant_get(parameters, "(u@a{sv})", &response, &results); - if(response != 0 || !results) + if(response != 0 || !results) { + if(results) g_variant_unref(results); goto done; + } GVariant *shortcuts = g_variant_lookup_value(results, "shortcuts", G_VARIANT_TYPE("a(sa{sv})")); - if(!shortcuts) + if(!shortcuts) { + g_variant_unref(results); goto done; + } handle_shortcuts_data(shortcuts, userdata->callback, userdata->userdata); + g_variant_unref(shortcuts); + g_variant_unref(results); done: free(userdata); @@ -107,12 +112,16 @@ static void signal_callback(GDBusConnection *connection, if(strcmp(signal_name, "Deactivated") == 0) { gchar *session_handle = NULL; gchar *shortcut_id = NULL; - gchar *timestamp = NULL; + guint64 timestamp = 0; GVariant *options = NULL; g_variant_get(parameters, "(ost@a{sv})", &session_handle, &shortcut_id, ×tamp, &options); if(session_handle && shortcut_id && strcmp(session_handle, cu->self->session_handle) == 0) cu->deactivated_callback(shortcut_id, cu->userdata); + + g_free(session_handle); + g_free(shortcut_id); + if(options) g_variant_unref(options); } else if(strcmp(signal_name, "ShortcutsChanged") == 0) { gchar *session_handle = NULL; GVariant *shortcuts = NULL; @@ -120,6 +129,9 @@ static void signal_callback(GDBusConnection *connection, if(session_handle && shortcuts && strcmp(session_handle, cu->self->session_handle) == 0) handle_shortcuts_data(shortcuts, cu->shortcut_changed_callback, cu->userdata); + + g_free(session_handle); + if(shortcuts) g_variant_unref(shortcuts); } } @@ -141,6 +153,7 @@ static void dbus_signal_create_session(GDBusProxy *proxy, gchar *sender_name, gc if(response != 0 || !results) { cu->callback(false, cu->userdata); + if(results) g_variant_unref(results); goto done; } @@ -149,18 +162,22 @@ static void dbus_signal_create_session(GDBusProxy *proxy, gchar *sender_name, gc cu->self->session_handle = strdup(session_handle); cu->self->session_created = true; cu->callback(true, cu->userdata); + g_free(session_handle); + } else { + cu->callback(false, cu->userdata); } + g_variant_unref(results); done: free(cu); } static bool gsr_global_shortcuts_create_session(gsr_global_shortcuts *self, gsr_init_callback callback, void *userdata) { - char handle_token[64]; + char handle_token[128]; gsr_dbus_portal_get_unique_handle_token(self, handle_token, sizeof(handle_token)); - char session_handle_token[64]; - snprintf(session_handle_token, sizeof(session_handle_token), "gpu_screen_recorder_adwaita"); + char session_handle_token[128]; + snprintf(session_handle_token, sizeof(session_handle_token), "gpu_screen_recorder_adwaita_%s", self->random_str); GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); @@ -173,16 +190,21 @@ static bool gsr_global_shortcuts_create_session(gsr_global_shortcuts *self, gsr_ if(ret) { const gchar *val = NULL; g_variant_get(ret, "(&o)", &val); - if(!val) + if(!val) { + g_variant_unref(ret); return false; - //g_variant_unref(ret); + } GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, "org.freedesktop.portal.Desktop", val, "org.freedesktop.portal.Request", NULL, NULL); + g_variant_unref(ret); if(!proxy) return false; - //g_object_unref(proxy); signal_create_session_userdata *cu = malloc(sizeof(signal_create_session_userdata)); + if(!cu) { + g_object_unref(proxy); + return false; + } cu->self = self; cu->callback = callback; cu->userdata = userdata; @@ -198,13 +220,13 @@ bool gsr_global_shortcuts_init(gsr_global_shortcuts *self, gsr_init_callback cal self->random_str[DBUS_RANDOM_STR_SIZE] = '\0'; if(!generate_random_characters(self->random_str, DBUS_RANDOM_STR_SIZE, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62)) { - fprintf(stderr, "gsr error: gsr_global_shortcuts_init: failed to generate random string\n"); + g_warning("gsr_global_shortcuts_init: failed to generate random string"); return false; } self->gdbus_con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); if(!self->gdbus_con) { - fprintf(stderr, "gsr error: gsr_global_shortcuts_init: g_bus_get_sync failed\n"); + g_warning("gsr_global_shortcuts_init: g_bus_get_sync failed"); return false; } @@ -218,8 +240,7 @@ bool gsr_global_shortcuts_init(gsr_global_shortcuts *self, gsr_init_callback cal void gsr_global_shortcuts_deinit(gsr_global_shortcuts *self) { if(self->gdbus_con) { - /* TODO: Re-add this. Right now it causes errors as the connection is already closed, but checking if it's already closed here has no effect */ - //g_dbus_connection_close(self->gdbus_con, NULL, NULL, NULL); + g_object_unref(self->gdbus_con); self->gdbus_con = NULL; } @@ -233,7 +254,7 @@ bool gsr_global_shortcuts_list_shortcuts(gsr_global_shortcuts *self, gsr_shortcu if(!self->session_created) return false; - char handle_token[64]; + char handle_token[128]; gsr_dbus_portal_get_unique_handle_token(self, handle_token, sizeof(handle_token)); GVariant *session_handle_obj = g_variant_new_object_path(self->session_handle); @@ -249,15 +270,21 @@ bool gsr_global_shortcuts_list_shortcuts(gsr_global_shortcuts *self, gsr_shortcu if(ret) { const gchar *val = NULL; g_variant_get(ret, "(&o)", &val); - if(!val) + if(!val) { + g_variant_unref(ret); return false; + } GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, "org.freedesktop.portal.Desktop", val, "org.freedesktop.portal.Request", NULL, NULL); + g_variant_unref(ret); if(!proxy) return false; - //g_object_unref(proxy); signal_list_bind_userdata *cu = malloc(sizeof(signal_list_bind_userdata)); + if(!cu) { + g_object_unref(proxy); + return false; + } cu->self = self; cu->callback = callback; cu->userdata = userdata; @@ -272,7 +299,7 @@ bool gsr_global_shortcuts_bind_shortcuts(gsr_global_shortcuts *self, const gsr_b if(!self->session_created) return false; - char handle_token[64]; + char handle_token[128]; gsr_dbus_portal_get_unique_handle_token(self, handle_token, sizeof(handle_token)); GVariant *session_handle_obj = g_variant_new_object_path(self->session_handle); @@ -303,15 +330,21 @@ bool gsr_global_shortcuts_bind_shortcuts(gsr_global_shortcuts *self, const gsr_b if(ret) { const gchar *val = NULL; g_variant_get(ret, "(&o)", &val); - if(!val) + if(!val) { + g_variant_unref(ret); return false; + } GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, NULL, "org.freedesktop.portal.Desktop", val, "org.freedesktop.portal.Request", NULL, NULL); + g_variant_unref(ret); if(!proxy) return false; - //g_object_unref(proxy); signal_list_bind_userdata *cu = malloc(sizeof(signal_list_bind_userdata)); + if(!cu) { + g_object_unref(proxy); + return false; + } cu->self = self; cu->callback = callback; cu->userdata = userdata; diff --git a/src/gsr-config.c b/src/gsr-config.c index 21405ea..e9de887 100644 --- a/src/gsr-config.c +++ b/src/gsr-config.c @@ -389,7 +389,7 @@ gsr_config_save(const GsrConfig *config) FILE *file = fopen(config_path, "wb"); if (!file) { - g_warning("Failed to create config file: %s", config_path); + g_warning("Failed to create config file: %s: %s", config_path, g_strerror(errno)); g_free(config_path); return; } diff --git a/src/gsr-info.c b/src/gsr-info.c index 04da95c..4187aed 100644 --- a/src/gsr-info.c +++ b/src/gsr-info.c @@ -32,7 +32,7 @@ read_command_output(const char *cmd, int *exit_code) int status = pclose(f); if (exit_code) { - if (WIFEXITED(status)) + if (status >= 0 && WIFEXITED(status)) *exit_code = WEXITSTATUS(status); else *exit_code = -1; @@ -223,7 +223,7 @@ gsr_info_load(GsrInfo *info) int exit_code = -1; char *output = read_command_output("gpu-screen-recorder --info", &exit_code); if (!output) { - fprintf(stderr, "error: 'gpu-screen-recorder --info' failed to run\n"); + g_warning("'gpu-screen-recorder --info' failed to run"); return GSR_INFO_EXIT_FAILED_TO_RUN; } diff --git a/src/gsr-record-page.c b/src/gsr-record-page.c index a9575c4..de4781e 100644 --- a/src/gsr-record-page.c +++ b/src/gsr-record-page.c @@ -3,7 +3,6 @@ #include "gsr-shortcut-accel-dialog.h" #endif #include "gsr-window.h" -#include <glib/gi18n.h> #include <signal.h> #include <time.h> @@ -503,6 +502,12 @@ static void gsr_record_page_finalize(GObject *object) { GsrRecordPage *self = GSR_RECORD_PAGE(object); + + if (self->timer_source_id) { + g_source_remove(self->timer_source_id); + self->timer_source_id = 0; + } + g_free(self->save_directory); #ifdef HAVE_X11 g_free(self->x11_start_stop_accel); diff --git a/src/gsr-record-page.h b/src/gsr-record-page.h index 94acaf4..ee5f4f5 100644 --- a/src/gsr-record-page.h +++ b/src/gsr-record-page.h @@ -15,7 +15,7 @@ void gsr_record_page_apply_config (GsrRecordPage *self, void gsr_record_page_read_config (GsrRecordPage *self, GsrConfig *config); -/* Process management API (Phase 5) */ +/* Process management API */ void gsr_record_page_set_active (GsrRecordPage *self, gboolean active); void gsr_record_page_set_paused (GsrRecordPage *self, diff --git a/src/gsr-replay-page.c b/src/gsr-replay-page.c index 67c7c9a..4dcbc81 100644 --- a/src/gsr-replay-page.c +++ b/src/gsr-replay-page.c @@ -490,6 +490,12 @@ static void gsr_replay_page_finalize(GObject *object) { GsrReplayPage *self = GSR_REPLAY_PAGE(object); + + if (self->timer_source_id) { + g_source_remove(self->timer_source_id); + self->timer_source_id = 0; + } + g_free(self->save_directory); #ifdef HAVE_X11 g_free(self->x11_start_stop_accel); diff --git a/src/gsr-replay-page.h b/src/gsr-replay-page.h index 697cba2..d703d93 100644 --- a/src/gsr-replay-page.h +++ b/src/gsr-replay-page.h @@ -15,7 +15,7 @@ void gsr_replay_page_apply_config (GsrReplayPage *self, void gsr_replay_page_read_config (GsrReplayPage *self, GsrConfig *config); -/* Process management API (Phase 5) */ +/* Process management API */ void gsr_replay_page_set_active (GsrReplayPage *self, gboolean active); void gsr_replay_page_update_timer (GsrReplayPage *self, diff --git a/src/gsr-shortcut-accel-dialog.c b/src/gsr-shortcut-accel-dialog.c index bf5b0e9..37e90c6 100644 --- a/src/gsr-shortcut-accel-dialog.c +++ b/src/gsr-shortcut-accel-dialog.c @@ -280,9 +280,11 @@ build_dialog_ui(GsrShortcutAccelDialog *self) gtk_widget_add_css_class(GTK_WIDGET(keyboard_icon), "dim-label"); gtk_box_append(capture_box, GTK_WIDGET(keyboard_icon)); + char *escaped_title = g_markup_escape_text( + self->shortcut_title ? self->shortcut_title : "Shortcut", -1); char *label_text = g_strdup_printf( - "Enter new shortcut for\n<b>%s</b>", - self->shortcut_title ? self->shortcut_title : "Shortcut"); + "Enter new shortcut for\n<b>%s</b>", escaped_title); + g_free(escaped_title); self->capture_label = GTK_LABEL(gtk_label_new(NULL)); gtk_label_set_markup(self->capture_label, label_text); gtk_label_set_justify(self->capture_label, GTK_JUSTIFY_CENTER); @@ -309,9 +311,11 @@ build_dialog_ui(GsrShortcutAccelDialog *self) gtk_widget_set_margin_bottom(GTK_WIDGET(display_box), 24); GtkLabel *display_title = GTK_LABEL(gtk_label_new(NULL)); + char *escaped_display_title = g_markup_escape_text( + self->shortcut_title ? self->shortcut_title : "Shortcut", -1); char *display_text = g_strdup_printf( - "Shortcut for <b>%s</b>", - self->shortcut_title ? self->shortcut_title : "Shortcut"); + "Shortcut for <b>%s</b>", escaped_display_title); + g_free(escaped_display_title); gtk_label_set_markup(display_title, display_text); gtk_label_set_justify(display_title, GTK_JUSTIFY_CENTER); gtk_label_set_wrap(display_title, TRUE); diff --git a/src/gsr-stream-page.c b/src/gsr-stream-page.c index fceef37..e3ec495 100644 --- a/src/gsr-stream-page.c +++ b/src/gsr-stream-page.c @@ -413,8 +413,14 @@ build_status_group(GsrStreamPage *self) static void gsr_stream_page_finalize(GObject *object) { -#ifdef HAVE_X11 GsrStreamPage *self = GSR_STREAM_PAGE(object); + + if (self->timer_source_id) { + g_source_remove(self->timer_source_id); + self->timer_source_id = 0; + } + +#ifdef HAVE_X11 g_free(self->x11_start_stop_accel); #endif G_OBJECT_CLASS(gsr_stream_page_parent_class)->finalize(object); diff --git a/src/gsr-stream-page.h b/src/gsr-stream-page.h index af63bc6..798e2f4 100644 --- a/src/gsr-stream-page.h +++ b/src/gsr-stream-page.h @@ -15,7 +15,7 @@ void gsr_stream_page_apply_config (GsrStreamPage *self, void gsr_stream_page_read_config (GsrStreamPage *self, GsrConfig *config); -/* Process management API (Phase 5) */ +/* Process management API */ void gsr_stream_page_set_active (GsrStreamPage *self, gboolean active); void gsr_stream_page_update_timer (GsrStreamPage *self, diff --git a/src/gsr-window.c b/src/gsr-window.c index 19b5f1a..28091f9 100644 --- a/src/gsr-window.c +++ b/src/gsr-window.c @@ -66,6 +66,7 @@ struct _GsrWindow { /* ── Desktop notifications ─── */ gboolean showing_notification; + guint notification_timeout_id; /* auto-withdraw timer */ gboolean is_kde; /* KDE workaround */ /* ── Startup error state ─── */ @@ -80,6 +81,19 @@ static void handle_child_death(GsrWindow *self, int exit_status); static void send_notification(GsrWindow *self, const char *title, const char *body, GNotificationPriority priority); +/* ── Mode-to-string helper ───────────────────────────────────────── */ + +static const char * +active_mode_to_string(GsrActiveMode mode) +{ + switch (mode) { + case GSR_ACTIVE_MODE_STREAM: return "streaming"; + case GSR_ACTIVE_MODE_RECORD: return "recording"; + case GSR_ACTIVE_MODE_REPLAY: return "replay"; + default: return "unknown"; + } +} + /* ── Desktop notification helpers ────────────────────────────────── */ /** @@ -91,6 +105,8 @@ on_notification_withdraw(gpointer user_data) { GsrWindow *self = GSR_WINDOW(user_data); + self->notification_timeout_id = 0; /* source is being removed */ + if (self->showing_notification) { GtkApplication *app = GTK_APPLICATION( gtk_window_get_application(GTK_WINDOW(self))); @@ -146,8 +162,12 @@ send_notification(GsrWindow *self, const char *title, g_object_unref(notif); /* Auto-withdraw after timeout */ + if (self->notification_timeout_id) { + g_source_remove(self->notification_timeout_id); + self->notification_timeout_id = 0; + } guint timeout_ms = (effective >= G_NOTIFICATION_PRIORITY_URGENT) ? 10000 : 3000; - g_timeout_add(timeout_ms, on_notification_withdraw, self); + self->notification_timeout_id = g_timeout_add(timeout_ms, on_notification_withdraw, self); /* ── In-app toast ── */ AdwToast *toast = adw_toast_new(body); @@ -211,6 +231,9 @@ build_record_filename(const char *dir, const char *container_display) { time_t now = time(NULL); struct tm *tm = localtime(&now); + if (!tm) { + return g_strdup_printf("%s/Video.%s", dir, container_display); + } char date_buf[64]; strftime(date_buf, sizeof(date_buf), "%Y-%m-%d_%H-%M-%S", tm); return g_strdup_printf("%s/Video_%s.%s", dir, date_buf, container_display); @@ -540,9 +563,7 @@ handle_child_death(GsrWindow *self, int exit_status) g_free(msg); } } else if (gsr_config_page_get_notify_stopped(self->config_page)) { - const char *mode_str = - mode == GSR_ACTIVE_MODE_STREAM ? "streaming" : - mode == GSR_ACTIVE_MODE_REPLAY ? "replay" : "recording"; + const char *mode_str = active_mode_to_string(mode); char *msg = g_strdup_printf("Stopped %s", mode_str); send_notification(self, "GPU Screen Recorder", msg, G_NOTIFICATION_PRIORITY_NORMAL); @@ -638,7 +659,11 @@ on_close_request(GtkWindow *window, gpointer user_data G_GNUC_UNUSED) self->hotkeys = NULL; } - /* Withdraw any pending desktop notification */ + /* Withdraw any pending desktop notification and cancel its timer */ + if (self->notification_timeout_id) { + g_source_remove(self->notification_timeout_id); + self->notification_timeout_id = 0; + } if (self->showing_notification) { GtkApplication *app = GTK_APPLICATION( gtk_window_get_application(GTK_WINDOW(self))); @@ -982,12 +1007,19 @@ gsr_window_finalize(GObject *object) self->poll_timer_id = 0; } + if (self->notification_timeout_id) { + g_source_remove(self->notification_timeout_id); + self->notification_timeout_id = 0; + } + if (self->hotkeys) { gsr_hotkeys_free(self->hotkeys); self->hotkeys = NULL; } g_free(self->record_filename); + g_clear_object(&self->primary_menu); + g_clear_object(&self->view_section); gsr_config_clear(&self->config); gsr_info_clear(&self->info); G_OBJECT_CLASS(gsr_window_parent_class)->finalize(object); @@ -1046,10 +1078,7 @@ gsr_window_start_process(GsrWindow *self, GsrActiveMode mode) g_ptr_array_unref(args); if (!ok) { - const char *mode_str = - mode == GSR_ACTIVE_MODE_STREAM ? "streaming" : - mode == GSR_ACTIVE_MODE_RECORD ? "recording" : - mode == GSR_ACTIVE_MODE_REPLAY ? "replay" : "unknown"; + const char *mode_str = active_mode_to_string(mode); char *msg = g_strdup_printf("Failed to start %s (failed to fork)", mode_str); send_notification(self, "GPU Screen Recorder", msg, G_NOTIFICATION_PRIORITY_URGENT); @@ -1065,10 +1094,7 @@ gsr_window_start_process(GsrWindow *self, GsrActiveMode mode) /* Show "started" notification */ if (gsr_config_page_get_notify_started(self->config_page)) { - const char *mode_str = - mode == GSR_ACTIVE_MODE_STREAM ? "streaming" : - mode == GSR_ACTIVE_MODE_RECORD ? "recording" : - mode == GSR_ACTIVE_MODE_REPLAY ? "replay" : "unknown"; + const char *mode_str = active_mode_to_string(mode); char *msg = g_strdup_printf("Started %s", mode_str); send_notification(self, "GPU Screen Recorder", msg, G_NOTIFICATION_PRIORITY_NORMAL); @@ -1112,10 +1138,7 @@ gsr_window_stop_process(GsrWindow *self, gboolean *already_dead) g_free(msg); } } else if (gsr_config_page_get_notify_stopped(self->config_page)) { - const char *mode_str = - mode == GSR_ACTIVE_MODE_STREAM ? "streaming" : - mode == GSR_ACTIVE_MODE_RECORD ? "recording" : - mode == GSR_ACTIVE_MODE_REPLAY ? "replay" : "unknown"; + const char *mode_str = active_mode_to_string(mode); char *msg = g_strdup_printf("Stopped %s", mode_str); send_notification(self, "GPU Screen Recorder", msg, G_NOTIFICATION_PRIORITY_NORMAL); |
