diff options
-rw-r--r-- | README.md | 14 | ||||
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | com.dec05eba.gpu_screen_recorder.appdata.xml | 72 | ||||
-rw-r--r-- | meson.build | 20 | ||||
-rw-r--r-- | project.conf | 2 | ||||
-rw-r--r-- | src/config.hpp | 12 | ||||
-rw-r--r-- | src/main.cpp | 275 |
7 files changed, 309 insertions, 89 deletions
@@ -1,14 +1,8 @@ ![](https://dec05eba.com/images/gpu_screen_recorder_logo_small.png) -GTK frontend for [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/about/). - -This is a screen recorder that has minimal impact on system performance by recording your monitor using the GPU only, -similar to shadowplay on windows. This is the fastest screen recording tool for Linux. - -This screen recorder can be used for recording your desktop offline, for live streaming and for nvidia shadowplay-like instant replay, -where only the last few minutes are saved. - -More info at [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/about/). +# GPU Screen Recorder GTK +GTK frontend for [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/about/).\ +There is a new alternative UI for GPU Screen Recorder in the style of ShadowPlay available here: [GPU Screen Recorder UI](https://git.dec05eba.com/gpu-screen-recorder-ui/). # Installation This program depends on [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/) which needs to be installed first.\ @@ -28,7 +22,7 @@ These are the dependencies needed to build GPU Screen Recorder GTK: ## Runtime dependencies There are also additional dependencies needed at runtime: -* [gpu-screen-recorder](https://git.dec05eba.com/gpu-screen-recorder/) +* [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/) # Screenshots ![](https://www.dec05eba.com/images/gpu-screen-recorder.png) @@ -4,7 +4,6 @@ Add list of windows to select from. This makes it easier to select another windo Disable overclocking and show some kind of sign that overclocking is not possible (if coolbits not set). Button (in the field) to remove hotkey. Error if polkit agent is not running (pkexec --help may work but the agent might not be running anyways). -Fix gui crash on stop recording on sway. Re-enable wlroots based capture when it's fixed. Add translation support (using gettext, which uses .mo files and _ macro). It should be easy for non-devs to contribute. But how? maybe have a page that links to the english translation files (or translation directory) in git and give instructions, @@ -62,4 +61,4 @@ Start recording after showing start recording notification has disappeared, not Use modprobe command. modprobe on system startup in modprobe.d directory is only available for udev, other systems need to add it to linux kernel boot parameters (is this also needed for nvidia open kernel module driver?). -Save gpu screen recorder status in $XDG_RUNTIME_DIR. +Save gpu screen recorder status in $XDG_RUNTIME_DIR.
\ No newline at end of file diff --git a/com.dec05eba.gpu_screen_recorder.appdata.xml b/com.dec05eba.gpu_screen_recorder.appdata.xml index 694f3f8..e4d821c 100644 --- a/com.dec05eba.gpu_screen_recorder.appdata.xml +++ b/com.dec05eba.gpu_screen_recorder.appdata.xml @@ -7,7 +7,7 @@ <metadata_license>CC0-1.0</metadata_license> <project_license>GPL-3.0</project_license> <url type="homepage">https://git.dec05eba.com/gpu-screen-recorder/about/</url> - <url type="bugtracker">https://github.com/dec05eba/gpu-screen-recorder-issues/issues</url> + <url type="bugtracker">https://github.com/dec05eba/gpu-screen-recorder-issues</url> <url type="contribute">https://git.dec05eba.com/?p=about</url> <url type="donation">https://git.dec05eba.com/?p=about</url> @@ -37,7 +37,7 @@ <li>AAC</li> </ul> <p> - Recording a monitor requires (restricted) root access which means that you have to install GPU Screen Recorder system-wide: "flatpak install flathub --system com.dec05eba.gpu_screen_recorder" + Recording a monitor requires (restricted) root access which means that you have to install GPU Screen Recorder system-wide: "flatpak install --system com.dec05eba.gpu_screen_recorder" and pkexec needs to be installed on the system and a polkit agent needs to be running. Note that this only applies to when recording a monitor on AMD/Intel or when recording on Wayland without using the desktop portal option. </p> @@ -80,6 +80,74 @@ </screenshots> <releases> + <release version="4.2.6" date="2024-11-05"> + <description> + <ul> + <li>Add option to change video resolution</li> + <li>Change quality parameters, file size was too large by default</li> + </ul> + </description> + </release> + <release version="4.2.5" date="2024-11-04"> + <description> + <ul> + <li>Add option to change video resolution</li> + <li>Fix bitrate calculation being incorrect (it was too low)</li> + </ul> + </description> + </release> + <release version="4.2.4" date="2024-10-22"> + <description> + <ul> + <li>Fix capture not working if one of the audio inputs is a virtual audio device with forward slash in its name, for example if NoiseTorch is used</li> + </ul> + </description> + </release> + <release version="4.2.2" date="2024-10-15"> + <description> + <ul> + <li>Enable amd low latency mode (only available since mesa 24.1.4, released in july 17, 2024). This reduces stutter in video in some cases but increases power usage when idle</li> + </ul> + </description> + </release> + <release version="4.2.1" date="2024-10-12"> + <description> + <ul> + <li>Better frame timing when hardware is too slow to record at the desired framerate</li> + </ul> + </description> + </release> + <release version="4.2.0" date="2024-10-11"> + <description> + <ul> + <li>Better frame timing for smoother video, especially when recording a game that runs at the same fps as the recording or lower.</li> + <li>Add constant bitrate option, for better live streaming experience and for lower file size at the cost of quality.</li> + </ul> + </description> + </release> + <release version="4.1.11" date="2024-09-21"> + <description> + <ul> + <li>Fix recording not working on some amd systems</li> + </ul> + </description> + </release> + <release version="4.1.10" date="2024-09-21"> + <description> + <ul> + <li>Revert frame timing change as it badly affected slower devices</li> + </ul> + </description> + </release> + <release version="4.1.9" date="2024-09-20"> + <description> + <ul> + <li>Improve frame timing for smoother video</li> + <li>Improve screen recording performance on AMD when the system usage is very high</li> + <li>Fix recording not working on old nvidia gpus (that are stuck on nvidia driver version 470)</li> + </ul> + </description> + </release> <release version="4.1.8" date="2024-09-17"> <description> <ul> diff --git a/meson.build b/meson.build index ae1208e..5277b5c 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('gpu-screen-recorder-gtk', ['c', 'cpp'], version : '4.1.8', default_options : ['warning_level=2']) +project('gpu-screen-recorder-gtk', ['c', 'cpp'], version : '4.2.6', default_options : ['warning_level=2']) add_project_arguments('-Wshadow', language : ['c', 'cpp']) if get_option('buildtype') == 'debug' @@ -18,15 +18,23 @@ dep = [ dependency('ayatana-appindicator3-0.1'), ] -add_project_arguments('-DGSR_VERSION="' + meson.project_version() + '"', language: ['c', 'cpp']) - -executable('gpu-screen-recorder-gtk', src, dependencies : dep, install : true) - prefix = get_option('prefix') datadir = get_option('datadir') +icons_path = join_paths(prefix, datadir, 'icons') + +executable('gpu-screen-recorder-gtk', + src, + dependencies : dep, + install : true, + cpp_args : [ + '-DGSR_ICONS_PATH="' + icons_path + '"', + '-DGSR_VERSION="' + meson.project_version() + '"' + ] +) + install_data(files('com.dec05eba.gpu_screen_recorder.desktop'), install_dir : join_paths(prefix, datadir, 'applications')) install_data(files('com.dec05eba.gpu_screen_recorder.appdata.xml'), install_dir : join_paths(prefix, datadir, 'metainfo')) -install_subdir('icons/hicolor', install_dir : join_paths(prefix, datadir, 'icons')) +install_subdir('icons/hicolor', install_dir : icons_path) gnome = import('gnome') gnome.post_install(gtk_update_icon_cache : true, update_desktop_database : true) diff --git a/project.conf b/project.conf index 9f754d7..518649a 100644 --- a/project.conf +++ b/project.conf @@ -1,7 +1,7 @@ [package] name = "gpu-screen-recorder-gtk" type = "executable" -version = "4.1.8" +version = "4.2.6" platforms = ["posix"] [config] diff --git a/src/config.hpp b/src/config.hpp index 4e01b6b..0ab8af2 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -23,8 +23,12 @@ struct MainConfig { std::string record_area_option; int32_t record_area_width = 0; int32_t record_area_height = 0; + int32_t video_width = 0; + int32_t video_height = 0; int32_t fps = 60; + int32_t video_bitrate = 15000; bool merge_audio_tracks = true; + bool change_video_resolution = false; std::vector<std::string> audio_input; std::string color_range; std::string quality; @@ -40,6 +44,8 @@ struct MainConfig { bool hide_window_when_recording = false; bool software_encoding_warning_shown = false; bool steam_deck_warning_shown = false; + bool hevc_amd_bug_warning_shown = false; + bool av1_amd_bug_warning_shown = false; bool restore_portal_session = true; }; @@ -302,8 +308,12 @@ static std::map<std::string, ConfigValue> get_config_options(Config &config) { {"main.record_area_option", {CONFIG_TYPE_STRING, &config.main_config.record_area_option}}, {"main.record_area_width", {CONFIG_TYPE_I32, &config.main_config.record_area_width}}, {"main.record_area_height", {CONFIG_TYPE_I32, &config.main_config.record_area_height}}, + {"main.video_width", {CONFIG_TYPE_I32, &config.main_config.video_width}}, + {"main.video_height", {CONFIG_TYPE_I32, &config.main_config.video_height}}, {"main.fps", {CONFIG_TYPE_I32, &config.main_config.fps}}, + {"main.video_bitrate", {CONFIG_TYPE_I32, &config.main_config.video_bitrate}}, {"main.merge_audio_tracks", {CONFIG_TYPE_BOOL, &config.main_config.merge_audio_tracks}}, + {"main.change_video_resolution", {CONFIG_TYPE_BOOL, &config.main_config.change_video_resolution}}, {"main.audio_input", {CONFIG_TYPE_STRING_ARRAY, &config.main_config.audio_input}}, {"main.color_range", {CONFIG_TYPE_STRING, &config.main_config.color_range}}, {"main.quality", {CONFIG_TYPE_STRING, &config.main_config.quality}}, @@ -319,6 +329,8 @@ static std::map<std::string, ConfigValue> get_config_options(Config &config) { {"main.hide_window_when_recording", {CONFIG_TYPE_BOOL, &config.main_config.hide_window_when_recording}}, {"main.software_encoding_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.software_encoding_warning_shown}}, {"main.steam_deck_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.steam_deck_warning_shown}}, + {"main.hevc_amd_bug_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.hevc_amd_bug_warning_shown}}, + {"main.av1_amd_bug_warning_shown", {CONFIG_TYPE_BOOL, &config.main_config.av1_amd_bug_warning_shown}}, {"main.restore_portal_session", {CONFIG_TYPE_BOOL, &config.main_config.restore_portal_session}}, {"streaming.service", {CONFIG_TYPE_STRING, &config.streaming_config.streaming_service}}, diff --git a/src/main.cpp b/src/main.cpp index 2b6cac9..a8a3295 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,10 +51,14 @@ static SelectWindowUserdata select_window_userdata; static PageNavigationUserdata page_navigation_userdata; static Cursor crosshair_cursor; static GtkSpinButton *fps_entry; -static GtkLabel *area_size_label; +static GtkSpinButton *video_bitrate_entry; static GtkGrid *area_size_grid; +static GtkWidget *change_video_resolution_button; +static GtkGrid *video_resolution_grid; static GtkSpinButton *area_width_entry; static GtkSpinButton *area_height_entry; +static GtkSpinButton *video_width_entry; +static GtkSpinButton *video_height_entry; static GtkComboBox *record_area_selection_menu; static GtkTreeModel *record_area_selection_model; static GtkComboBoxText *quality_input_menu; @@ -103,6 +107,7 @@ static GtkGrid *video_codec_grid; static GtkGrid *audio_codec_grid; static GtkGrid *color_range_grid; static GtkGrid *framerate_mode_grid; +static GtkGrid *video_bitrate_grid; static GtkComboBoxText *view_combo_box; static GtkGrid *overclock_grid; static GtkWidget *overclock_button; @@ -853,8 +858,12 @@ static void save_configs() { config.main_config.record_area_width = gtk_spin_button_get_value_as_int(area_width_entry); config.main_config.record_area_height = gtk_spin_button_get_value_as_int(area_height_entry); } + config.main_config.video_width = gtk_spin_button_get_value_as_int(video_width_entry); + config.main_config.video_height = gtk_spin_button_get_value_as_int(video_height_entry); config.main_config.fps = gtk_spin_button_get_value_as_int(fps_entry); + config.main_config.video_bitrate = gtk_spin_button_get_value_as_int(video_bitrate_entry); config.main_config.merge_audio_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button)); + config.main_config.change_video_resolution = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(change_video_resolution_button)); config.main_config.audio_input.clear(); for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [](const AudioRow *audio_row) { @@ -910,8 +919,7 @@ static void show_notification(GtkApplication *app, const char *title, const char // KDE doesn't show notifications when using desktop portal capture unless either DoNotDisturb.WhenScreenSharing kde config // has been changed by the user or if the priority for the notification is set as urgent - const std::string recording_window = record_area_selection_menu_get_active_id(); - if((recording || replaying || streaming) && wayland_compositor == WaylandCompositor::KDE && recording_window == "portal") + if((recording || replaying || streaming) && wayland_compositor == WaylandCompositor::KDE) priority = G_NOTIFICATION_PRIORITY_URGENT; fprintf(stderr, "Notification: title: %s, body: %s\n", title, body); @@ -979,7 +987,6 @@ static Window window_get_target_window_child(Display *display, Window _window) { return found_window; } -/* TODO: Look at xwininfo source to figure out how to make this work for different types of window managers */ static GdkFilterReturn filter_callback(GdkXEvent *xevent, GdkEvent*, gpointer userdata) { SelectWindowUserdata *_select_window_userdata = (SelectWindowUserdata*)userdata; XEvent *ev = (XEvent*)xevent; @@ -1065,6 +1072,13 @@ static gboolean on_select_window_button_click(GtkButton *button, gpointer) { return true; } +static gboolean on_change_video_resolution_button_click(GtkButton *button, gpointer) { + const bool clicked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); + const std::string window_str = record_area_selection_menu_get_active_id(); + gtk_widget_set_visible(GTK_WIDGET(video_resolution_grid), clicked && window_str != "focused"); + return true; +} + static bool key_is_modifier(KeySym key_sym) { return key_sym >= XK_Shift_L && key_sym <= XK_Super_R && key_sym != XK_Caps_Lock && key_sym != XK_Shift_Lock; } @@ -1345,13 +1359,13 @@ static bool show_pkexec_flatpak_error_if_needed() { if(gsr_info.system_info.display_server == DisplayServer::WAYLAND) { GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "GPU Screen Recorder needs to be installed system-wide to record your monitor on Wayland when not using the portal option. To install GPU Screen recorder system-wide, you can run this command:\n" - "flatpak install flathub --system com.dec05eba.gpu_screen_recorder\n"); + "flatpak install --system com.dec05eba.gpu_screen_recorder\n"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } else { GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "GPU Screen Recorder needs to be installed system-wide to record your monitor on AMD/Intel when not using the portal option. To install GPU Screen recorder system-wide, you can run this command:\n" - "flatpak install flathub --system com.dec05eba.gpu_screen_recorder\n" + "flatpak install --system com.dec05eba.gpu_screen_recorder\n" "Alternatively, record a single window which doesn't have this restriction."); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); @@ -1362,10 +1376,36 @@ static bool show_pkexec_flatpak_error_if_needed() { return false; } +static void show_bugged_driver_warning() { + if(gsr_info.gpu_info.vendor != GpuVendor::AMD) + return; + + const std::string video_codec = video_codec_selection_menu_get_active_id(); + if((video_codec == "hevc" || video_codec == "hevc_10bit" || video_codec == "hevc_hdr") && !config.main_config.hevc_amd_bug_warning_shown) { + GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + "There is an AMD driver bug and FFmpeg bug that causes black bars to appear on the sides of the video at certain resolutions when using HEVC codec.\n" + "Select H264 video codec instead if this is an issue for you."); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + config.main_config.hevc_amd_bug_warning_shown = true; + } + + if((video_codec == "av1" || video_codec == "av1_10bit" || video_codec == "av1_hdr") && !config.main_config.av1_amd_bug_warning_shown) { + GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, + "There is an AMD hardware bug that causes black bars to appear on the sides of the video at certain resolutions when using AV1 codec.\n" + "Select H264 video codec instead if this is an issue for you."); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + config.main_config.av1_amd_bug_warning_shown = true; + } +} + static gboolean on_start_replay_click(GtkButton*, gpointer userdata) { if(show_pkexec_flatpak_error_if_needed()) return true; + show_bugged_driver_warning(); + PageNavigationUserdata *_page_navigation_userdata = (PageNavigationUserdata*)userdata; gtk_stack_set_visible_child(_page_navigation_userdata->stack, _page_navigation_userdata->replay_page); app_indicator_set_menu(app_indicator, GTK_MENU(create_systray_menu(_page_navigation_userdata->app, SystrayPage::REPLAY))); @@ -1380,6 +1420,8 @@ static gboolean on_start_recording_click(GtkButton*, gpointer userdata) { if(show_pkexec_flatpak_error_if_needed()) return true; + show_bugged_driver_warning(); + PageNavigationUserdata *_page_navigation_userdata = (PageNavigationUserdata*)userdata; gtk_stack_set_visible_child(_page_navigation_userdata->stack, _page_navigation_userdata->recording_page); app_indicator_set_menu(app_indicator, GTK_MENU(create_systray_menu(_page_navigation_userdata->app, SystrayPage::RECORDING))); @@ -1400,6 +1442,8 @@ static gboolean on_start_streaming_click(GtkButton*, gpointer userdata) { if(show_pkexec_flatpak_error_if_needed()) return true; + show_bugged_driver_warning(); + int num_audio_tracks = 0; for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&num_audio_tracks](const AudioRow*) { ++num_audio_tracks; @@ -1541,6 +1585,18 @@ static bool switch_video_codec_to_usable_hardware_encoder(std::string &video_cod return false; } +static void add_quality_command_line_args(std::vector<const char*> &args, const char *quality_input_str, const char *video_bitrate_str) { + if(strcmp(quality_input_str, "custom") == 0) { + args.push_back("-bm"); + args.push_back("cbr"); + args.push_back("-q"); + args.push_back(video_bitrate_str); + } else { + args.push_back("-q"); + args.push_back(quality_input_str); + } +} + static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdata) { GtkApplication *app = (GtkApplication*)userdata; const gchar *dir = gtk_button_get_label(replay_file_chooser_button); @@ -1583,10 +1639,8 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat save_configs(); - int fps = gtk_spin_button_get_value_as_int(fps_entry); - int replay_time = gtk_spin_button_get_value_as_int(replay_time_entry); - int record_width = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_width_entry); - int record_height = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_height_entry); + const int fps = gtk_spin_button_get_value_as_int(fps_entry); + const int replay_time = gtk_spin_button_get_value_as_int(replay_time_entry); char dir_tmp[PATH_MAX]; strcpy(dir_tmp, dir); @@ -1607,8 +1661,9 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat } else if(window_str == "focused") { follow_focused = true; } - std::string fps_str = std::to_string(fps); - std::string replay_time_str = std::to_string(replay_time); + const std::string fps_str = std::to_string(fps); + const std::string replay_time_str = std::to_string(replay_time); + const bool change_video_resolution = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(change_video_resolution_button)); const gchar* container_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(replay_container)); const gchar* color_range_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(color_range_input_menu)); @@ -1617,6 +1672,10 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); const bool record_cursor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(record_cursor_button)); const bool restore_portal_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(restore_portal_session_button)); + const std::string video_bitrate_str = std::to_string(gtk_spin_button_get_value_as_int(video_bitrate_entry)); + + const int record_width = follow_focused ? gtk_spin_button_get_value_as_int(area_width_entry) : gtk_spin_button_get_value_as_int(video_width_entry); + const int record_height = follow_focused ? gtk_spin_button_get_value_as_int(area_height_entry) : gtk_spin_button_get_value_as_int(video_height_entry); const char *encoder = "gpu"; std::string video_codec_input_str = video_codec_selection_menu_get_active_id(); @@ -1636,9 +1695,11 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat snprintf(area, sizeof(area), "%dx%d", record_width, record_height); std::vector<const char*> args = { - "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-q", quality_input_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-r", replay_time_str.c_str(), "-encoder", encoder, "-o", dir + "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-r", replay_time_str.c_str(), "-encoder", encoder, "-o", dir }; + add_quality_command_line_args(args, quality_input_str, video_bitrate_str.c_str()); + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); @@ -1648,7 +1709,7 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat std::string merge_audio_tracks_arg_value; add_audio_command_line_args(args, merge_audio_tracks_arg_value); - if(follow_focused) + if(follow_focused || change_video_resolution) args.insert(args.end(), { "-s", area }); args.push_back(NULL); @@ -1769,7 +1830,7 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user } else if(exit_status == 60) { // Canceled by the user } else if(!exit_success || (already_dead && exit_status != 0)) { - show_notification(app, "GPU Screen Recorder", "Failed to save video. Either your graphics card doesn't support GPU Screen Recorder with the settings you used or you don't have enough disk space to record a video. Run GPU Screen Recorder from the terminal to see more information when this failure happens", G_NOTIFICATION_PRIORITY_URGENT); + show_notification(app, "GPU Screen Recorder", "Failed to save video. Either your graphics card doesn't support GPU Screen Recorder with the settings you used or you don't have enough disk space to record a video. Start this GPU Screen Recorder GUI application from the terminal to see more information when this failure happens", G_NOTIFICATION_PRIORITY_URGENT); } else if(exit_success) { if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(show_recording_saved_notification_button))) { const std::string notification_body = std::string("The recording was saved to ") + record_file_current_filename; @@ -1781,9 +1842,7 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user save_configs(); - int fps = gtk_spin_button_get_value_as_int(fps_entry); - int record_width = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_width_entry); - int record_height = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_height_entry); + const int fps = gtk_spin_button_get_value_as_int(fps_entry); bool follow_focused = false; std::string window_str = record_area_selection_menu_get_active_id(); @@ -1797,7 +1856,8 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user follow_focused = true; } - std::string fps_str = std::to_string(fps); + const std::string fps_str = std::to_string(fps); + const bool change_video_resolution = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(change_video_resolution_button)); const gchar* container_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(record_container)); const gchar* container_name = gtk_combo_box_text_get_active_text(record_container); @@ -1807,6 +1867,10 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); const bool record_cursor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(record_cursor_button)); const bool restore_portal_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(restore_portal_session_button)); + const std::string video_bitrate_str = std::to_string(gtk_spin_button_get_value_as_int(video_bitrate_entry)); + + const int record_width = follow_focused ? gtk_spin_button_get_value_as_int(area_width_entry) : gtk_spin_button_get_value_as_int(video_width_entry); + const int record_height = follow_focused ? gtk_spin_button_get_value_as_int(area_height_entry) : gtk_spin_button_get_value_as_int(video_height_entry); const char *encoder = "gpu"; std::string video_codec_input_str = video_codec_selection_menu_get_active_id(); @@ -1836,9 +1900,11 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user snprintf(area, sizeof(area), "%dx%d", record_width, record_height); std::vector<const char*> args = { - "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-q", quality_input_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-encoder", encoder, "-o", record_file_current_filename.c_str() + "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-encoder", encoder, "-o", record_file_current_filename.c_str() }; + add_quality_command_line_args(args, quality_input_str, video_bitrate_str.c_str()); + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); @@ -1848,7 +1914,7 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user std::string merge_audio_tracks_arg_value; add_audio_command_line_args(args, merge_audio_tracks_arg_value); - if(follow_focused) + if(follow_focused || change_video_resolution) args.insert(args.end(), { "-s", area }); args.push_back(NULL); @@ -1936,9 +2002,7 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user save_configs(); - int fps = gtk_spin_button_get_value_as_int(fps_entry); - int record_width = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_width_entry); - int record_height = gsr_info.system_info.display_server == DisplayServer::WAYLAND ? 0 : gtk_spin_button_get_value_as_int(area_height_entry); + const int fps = gtk_spin_button_get_value_as_int(fps_entry); bool follow_focused = false; std::string window_str = record_area_selection_menu_get_active_id(); @@ -1951,7 +2015,8 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user } else if(window_str == "focused") { follow_focused = true; } - std::string fps_str = std::to_string(fps); + const std::string fps_str = std::to_string(fps); + const bool change_video_resolution = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(change_video_resolution_button)); std::string stream_url; const gchar *container_str = "flv"; @@ -1991,6 +2056,10 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); const bool record_cursor = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(record_cursor_button)); const bool restore_portal_session = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(restore_portal_session_button)); + const std::string video_bitrate_str = std::to_string(gtk_spin_button_get_value_as_int(video_bitrate_entry)); + + const int record_width = follow_focused ? gtk_spin_button_get_value_as_int(area_width_entry) : gtk_spin_button_get_value_as_int(video_width_entry); + const int record_height = follow_focused ? gtk_spin_button_get_value_as_int(area_height_entry) : gtk_spin_button_get_value_as_int(video_height_entry); const char *encoder = "gpu"; std::string video_codec_input_str = video_codec_selection_menu_get_active_id(); @@ -2010,9 +2079,11 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user snprintf(area, sizeof(area), "%dx%d", record_width, record_height); std::vector<const char*> args = { - "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-q", quality_input_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-encoder", encoder, "-o", stream_url.c_str() + "gpu-screen-recorder", "-w", window_str.c_str(), "-c", container_str, "-k", video_codec_input_str.c_str(), "-ac", audio_codec_input_str, "-f", fps_str.c_str(), "-cursor", record_cursor ? "yes" : "no", "-restore-portal-session", restore_portal_session ? "yes" : "no", "-cr", color_range_input_str, "-encoder", encoder, "-o", stream_url.c_str() }; + add_quality_command_line_args(args, quality_input_str, video_bitrate_str.c_str()); + if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); @@ -2022,7 +2093,7 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user std::string merge_audio_tracks_arg_value; add_audio_command_line_args(args, merge_audio_tracks_arg_value); - if(follow_focused) + if(follow_focused || change_video_resolution) args.insert(args.end(), { "-s", area }); args.push_back(NULL); @@ -2102,9 +2173,10 @@ static void record_area_item_change_callback(GtkComboBox *widget, gpointer userd (void)userdata; const std::string selected_window_area = record_area_selection_menu_get_active_id(); gtk_widget_set_visible(GTK_WIDGET(select_window_button), strcmp(selected_window_area.c_str(), "window") == 0); - gtk_widget_set_visible(GTK_WIDGET(area_size_label), strcmp(selected_window_area.c_str(), "focused") == 0); gtk_widget_set_visible(GTK_WIDGET(area_size_grid), strcmp(selected_window_area.c_str(), "focused") == 0); gtk_widget_set_visible(GTK_WIDGET(restore_portal_session_button), strcmp(selected_window_area.c_str(), "portal") == 0); + gtk_widget_set_visible(GTK_WIDGET(change_video_resolution_button), strcmp(selected_window_area.c_str(), "focused") != 0); + on_change_video_resolution_button_click(GTK_BUTTON(change_video_resolution_button), nullptr); enable_stream_record_button_if_info_filled(); } @@ -2122,6 +2194,13 @@ static void view_combo_box_change_callback(GtkComboBox *widget, gpointer userdat gtk_widget_set_visible(GTK_WIDGET(show_recording_saved_notification_button), advanced_view); } +static void quality_combo_box_change_callback(GtkComboBox *widget, gpointer userdata) { + (void)userdata; + const gchar *selected_view = gtk_combo_box_get_active_id(widget); + const bool custom_selected = strcmp(selected_view, "custom") == 0; + gtk_widget_set_visible(GTK_WIDGET(video_bitrate_grid), custom_selected); +} + static void stream_service_item_change_callback(GtkComboBox *widget, gpointer userdata) { (void)userdata; @@ -2629,7 +2708,7 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a if(gsr_info.system_info.display_server == DisplayServer::WAYLAND) { gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, 0, gsr_info.supported_capture_options.portal ? "Desktop portal (Experimental, HDR not supported)" : "Desktop portal (Not available on your system)", -1); + gtk_list_store_set(store, &iter, 0, gsr_info.supported_capture_options.portal ? "Desktop portal (HDR not supported)" : "Desktop portal (Not available on your system)", -1); gtk_list_store_set(store, &iter, 1, "portal", -1); } else { gtk_list_store_append(store, &iter); @@ -2656,24 +2735,55 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a g_signal_connect(select_window_button, "clicked", G_CALLBACK(on_select_window_button_click), app); gtk_grid_attach(record_area_grid, GTK_WIDGET(select_window_button), 0, record_area_row++, 3, 1); - area_size_label = GTK_LABEL(gtk_label_new("Area size: ")); - gtk_label_set_xalign(area_size_label, 0.0f); - gtk_grid_attach(record_area_grid, GTK_WIDGET(area_size_label), 0, record_area_row++, 2, 1); + change_video_resolution_button = gtk_check_button_new_with_label("Change video resolution"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(change_video_resolution_button), false); + gtk_widget_set_halign(change_video_resolution_button, GTK_ALIGN_START); + g_signal_connect(change_video_resolution_button, "clicked", G_CALLBACK(on_change_video_resolution_button_click), app); + gtk_grid_attach(record_area_grid, change_video_resolution_button, 0, record_area_row++, 3, 1); + + { + area_size_grid = GTK_GRID(gtk_grid_new()); + gtk_grid_set_row_spacing(area_size_grid, 10); + gtk_grid_attach(record_area_grid, GTK_WIDGET(area_size_grid), 0, record_area_row++, 3, 1); + + GtkLabel *video_resolution_label = GTK_LABEL(gtk_label_new("Video resolution limit: ")); + gtk_label_set_xalign(video_resolution_label, 0.0f); + gtk_grid_attach(area_size_grid, GTK_WIDGET(video_resolution_label), 0, 0, 3, 1); + + area_width_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); + gtk_spin_button_set_value(area_width_entry, 1920.0); + gtk_widget_set_hexpand(GTK_WIDGET(area_width_entry), true); + gtk_grid_attach(area_size_grid, GTK_WIDGET(area_width_entry), 0, 1, 1, 1); + + gtk_grid_attach(area_size_grid, gtk_label_new("x"), 1, 1, 1, 1); - area_size_grid = GTK_GRID(gtk_grid_new()); - gtk_grid_attach(record_area_grid, GTK_WIDGET(area_size_grid), 0, record_area_row++, 3, 1); + area_height_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); + gtk_spin_button_set_value(area_height_entry, 1080.0); + gtk_widget_set_hexpand(GTK_WIDGET(area_height_entry), true); + gtk_grid_attach(area_size_grid, GTK_WIDGET(area_height_entry), 2, 1, 1, 1); + } + + { + video_resolution_grid = GTK_GRID(gtk_grid_new()); + gtk_grid_set_row_spacing(video_resolution_grid, 10); + gtk_grid_attach(record_area_grid, GTK_WIDGET(video_resolution_grid), 0, record_area_row++, 3, 1); - area_width_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); - gtk_spin_button_set_value(area_width_entry, 1920.0); - gtk_widget_set_hexpand(GTK_WIDGET(area_width_entry), true); - gtk_grid_attach(area_size_grid, GTK_WIDGET(area_width_entry), 0, 0, 1, 1); + GtkLabel *video_resolution_label = GTK_LABEL(gtk_label_new("Video resolution: ")); + gtk_label_set_xalign(video_resolution_label, 0.0f); + gtk_grid_attach(video_resolution_grid, GTK_WIDGET(video_resolution_label), 0, 0, 3, 1); - gtk_grid_attach(area_size_grid, gtk_label_new("x"), 1, 0, 1, 1); + video_width_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); + gtk_spin_button_set_value(video_width_entry, 1920.0); + gtk_widget_set_hexpand(GTK_WIDGET(video_width_entry), true); + gtk_grid_attach(video_resolution_grid, GTK_WIDGET(video_width_entry), 0, 1, 1, 1); - area_height_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); - gtk_spin_button_set_value(area_height_entry, 1080.0); - gtk_widget_set_hexpand(GTK_WIDGET(area_height_entry), true); - gtk_grid_attach(area_size_grid, GTK_WIDGET(area_height_entry), 2, 0, 1, 1); + gtk_grid_attach(video_resolution_grid, gtk_label_new("x"), 1, 1, 1, 1); + + video_height_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(5.0, 10000.0, 1.0)); + gtk_spin_button_set_value(video_height_entry, 1080.0); + gtk_widget_set_hexpand(GTK_WIDGET(video_height_entry), true); + gtk_grid_attach(video_resolution_grid, GTK_WIDGET(video_height_entry), 2, 1, 1, 1); + } restore_portal_session_button = gtk_check_button_new_with_label("Restore portal session"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(restore_portal_session_button), true); @@ -2733,17 +2843,27 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a gtk_grid_attach(color_range_grid, GTK_WIDGET(color_range_input_menu), 1, 0, 1, 1); gtk_combo_box_set_active(GTK_COMBO_BOX(color_range_input_menu), 0); - GtkGrid *quality_grid = GTK_GRID(gtk_grid_new()); - gtk_grid_attach(grid, GTK_WIDGET(quality_grid), 0, grid_row++, 2, 1); - gtk_grid_attach(quality_grid, gtk_label_new("Video quality: "), 0, 0, 1, 1); + GtkGrid *video_quality_grid = GTK_GRID(gtk_grid_new()); + gtk_grid_attach(grid, GTK_WIDGET(video_quality_grid), 0, grid_row++, 2, 1); + gtk_grid_attach(video_quality_grid, gtk_label_new("Video quality: "), 0, 0, 1, 1); quality_input_menu = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new()); + gtk_combo_box_text_append(quality_input_menu, "custom", "Constant bitrate (Recommended for live streaming and replay)"); gtk_combo_box_text_append(quality_input_menu, "medium", "Medium"); - gtk_combo_box_text_append(quality_input_menu, "high", "High (Recommended for live streaming)"); - gtk_combo_box_text_append(quality_input_menu, "very_high", "Very High (Recommended)"); + gtk_combo_box_text_append(quality_input_menu, "high", "High"); + gtk_combo_box_text_append(quality_input_menu, "very_high", "Very High (Recommended for recording)"); gtk_combo_box_text_append(quality_input_menu, "ultra", "Ultra"); gtk_widget_set_hexpand(GTK_WIDGET(quality_input_menu), true); - gtk_grid_attach(quality_grid, GTK_WIDGET(quality_input_menu), 1, 0, 1, 1); + gtk_grid_attach(video_quality_grid, GTK_WIDGET(quality_input_menu), 1, 0, 1, 1); gtk_combo_box_set_active(GTK_COMBO_BOX(quality_input_menu), 0); + g_signal_connect(quality_input_menu, "changed", G_CALLBACK(quality_combo_box_change_callback), quality_input_menu); + + video_bitrate_grid = GTK_GRID(gtk_grid_new()); + gtk_grid_attach(grid, GTK_WIDGET(video_bitrate_grid), 0, grid_row++, 2, 1); + gtk_grid_attach(video_bitrate_grid, gtk_label_new("Video bitrate (kbps): "), 0, 0, 1, 1); + video_bitrate_entry = GTK_SPIN_BUTTON(gtk_spin_button_new_with_range(1.0, 500000.0, 1.0)); + gtk_spin_button_set_value(video_bitrate_entry, 15000.0); + gtk_widget_set_hexpand(GTK_WIDGET(video_bitrate_entry), true); + gtk_grid_attach(video_bitrate_grid, GTK_WIDGET(video_bitrate_entry), 1, 0, 1, 1); video_codec_grid = GTK_GRID(gtk_grid_new()); gtk_grid_attach(grid, GTK_WIDGET(video_codec_grid), 0, grid_row++, 2, 1); @@ -3622,8 +3742,7 @@ static void load_config() { } gtk_widget_set_visible(GTK_WIDGET(select_window_button), strcmp(config.main_config.record_area_option.c_str(), "window") == 0); - gtk_widget_set_visible(GTK_WIDGET(area_size_label), strcmp(config.main_config.record_area_option.c_str(), "focused") == 0); - gtk_widget_set_visible(GTK_WIDGET(area_size_grid), strcmp(config.main_config.record_area_option.c_str(), "focused") == 0); + //gtk_widget_set_visible(GTK_WIDGET(area_size_grid), strcmp(config.main_config.record_area_option.c_str(), "focused") == 0); gtk_widget_set_visible(GTK_WIDGET(restore_portal_session_button), strcmp(config.main_config.record_area_option.c_str(), "portal") == 0); if(config.main_config.record_area_width == 0) @@ -3632,6 +3751,12 @@ static void load_config() { if(config.main_config.record_area_height == 0) config.main_config.record_area_height = 1080; + if(config.main_config.video_width == 0) + config.main_config.video_width = 1920; + + if(config.main_config.video_height == 0) + config.main_config.video_height = 1080; + if(config.main_config.fps == 0) config.main_config.fps = 60; else if(config.main_config.fps < 1) @@ -3642,7 +3767,7 @@ static void load_config() { if(config.main_config.color_range != "limited" && config.main_config.color_range != "full") config.main_config.color_range = "limited"; - if(config.main_config.quality != "medium" && config.main_config.quality != "high" && config.main_config.quality != "very_high" && config.main_config.quality != "ultra") + if(config.main_config.quality != "custom" && config.main_config.quality != "medium" && config.main_config.quality != "high" && config.main_config.quality != "very_high" && config.main_config.quality != "ultra") config.main_config.quality = "very_high"; if(config.main_config.audio_codec != "opus" && config.main_config.audio_codec != "aac") @@ -3670,8 +3795,12 @@ static void load_config() { gtk_spin_button_set_value(area_width_entry, config.main_config.record_area_width); gtk_spin_button_set_value(area_height_entry, config.main_config.record_area_height); } + gtk_spin_button_set_value(video_width_entry, config.main_config.video_width); + gtk_spin_button_set_value(video_height_entry, config.main_config.video_height); gtk_spin_button_set_value(fps_entry, config.main_config.fps); + gtk_spin_button_set_value(video_bitrate_entry, config.main_config.video_bitrate); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button), config.main_config.merge_audio_tracks); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(change_video_resolution_button), config.main_config.change_video_resolution); for(const std::string &audio_input : config.main_config.audio_input) { add_audio_input_track(audio_input.c_str()); @@ -3710,6 +3839,7 @@ static void load_config() { gtk_combo_box_set_active_id(GTK_COMBO_BOX(view_combo_box), config.main_config.advanced_view ? "advanced" : "simple"); view_combo_box_change_callback(GTK_COMBO_BOX(view_combo_box), view_combo_box); + quality_combo_box_change_callback(GTK_COMBO_BOX(quality_input_menu), quality_input_menu); if(gsr_info.system_info.display_server != DisplayServer::WAYLAND) { if(!config_empty) { for(int i = 0; i < num_hotkeys; ++i) { @@ -3723,9 +3853,11 @@ static void load_config() { gtk_widget_set_visible(streaming_start_stop_hotkey.hotkey_active_label, false); gtk_widget_set_visible(replay_start_stop_hotkey.hotkey_active_label, false); } - enable_stream_record_button_if_info_filled(); + record_area_item_change_callback(nullptr, nullptr); stream_service_item_change_callback(GTK_COMBO_BOX(stream_service_input_menu), nullptr); + on_change_video_resolution_button_click(GTK_BUTTON(change_video_resolution_button), nullptr); + std::string dummy; if(!config.main_config.software_encoding_warning_shown && !switch_video_codec_to_usable_hardware_encoder(dummy)) { GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, @@ -3737,6 +3869,9 @@ static void load_config() { gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); config.main_config.software_encoding_warning_shown = true; + video_codec_selection_menu_set_active_id("h264_software"); + config.main_config.advanced_view = true; + gtk_combo_box_set_active_id(GTK_COMBO_BOX(view_combo_box), "advanced"); } if(gsr_info.system_info.is_steam_deck && !config.main_config.steam_deck_warning_shown) { @@ -3869,6 +4004,21 @@ static void activate(GtkApplication *app, gpointer) { gtk_window_set_title(GTK_WINDOW(window), window_title.c_str()); gtk_window_set_resizable(GTK_WINDOW(window), false); + GtkIconTheme *icon_theme = gtk_icon_theme_get_default(); +#ifdef GSR_ICONS_PATH + const char *icon_path = GSR_ICONS_PATH; +#else + const char *icon_path = "/usr/share/icons"; +#endif + gtk_icon_theme_set_search_path(icon_theme, &icon_path, 1); + + const char *icon_name = "com.dec05eba.gpu_screen_recorder"; + if(!gtk_icon_theme_has_icon(icon_theme, icon_name)) + fprintf(stderr, "Error: failed to find icon %s in %s\n", icon_name, icon_path); + + gtk_window_set_default_icon_name(icon_name); + gtk_window_set_icon_name(GTK_WINDOW(window), icon_name); + select_window_userdata.app = app; audio_inputs = get_audio_devices(); @@ -3946,20 +4096,6 @@ static void activate(GtkApplication *app, gpointer) { int main(int argc, char **argv) { setlocale(LC_ALL, "C"); - // Stop nvidia driver from buffering frames - setenv("__GL_MaxFramesAllowed", "1", true); - // If this is set to 1 then cuGraphicsGLRegisterImage will fail for egl context with error: invalid OpenGL or DirectX context, - // so we overwrite it - setenv("__GL_THREADED_OPTIMIZATIONS", "0", true); - // Some people set this to nvidia (for nvdec) or vdpau (for nvidia vdpau), which breaks gpu screen recorder since - // nvidia doesn't support vaapi and nvidia-vaapi-driver doesn't support encoding yet. - // Let vaapi find the match vaapi driver instead of forcing a specific one. - unsetenv("LIBVA_DRIVER_NAME"); - // Some people set this to force all applications to vsync on nvidia, but this makes eglSwapBuffers never return. - unsetenv("__GL_SYNC_TO_VBLANK"); - // Same as above, but for amd/intel - unsetenv("vblank_mode"); - dpy = XOpenDisplay(NULL); gsr_info_exit_status = get_gpu_screen_recorder_info(&gsr_info); @@ -3971,7 +4107,10 @@ int main(int argc, char **argv) { } } - GtkApplication *app = gtk_application_new("com.dec05eba.gpu_screen_recorder", G_APPLICATION_NON_UNIQUE); + char app_id[] = "com.dec05eba.gpu_screen_recorder"; + argv[0] = app_id; + + GtkApplication *app = gtk_application_new(app_id, G_APPLICATION_NON_UNIQUE); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); int status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); |