From 26a9e750dc6f1313413524cd97e60a94e25a56ec Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 4 Nov 2024 20:37:26 +0100 Subject: Add option to save replay/recording to a folder with the name of the game --- src/Config.cpp | 2 ++ src/Overlay.cpp | 60 +++++++++++++++++++++++++++------------------- src/gui/ScrollablePage.cpp | 1 + src/gui/SettingsPage.cpp | 23 +++++++++++++++++- 4 files changed, 61 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/Config.cpp b/src/Config.cpp index 95949e8..4bf9101 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -93,6 +93,7 @@ namespace gsr { {"record.record_options.overclock", &config.record_config.record_options.overclock}, {"record.record_options.record_cursor", &config.record_config.record_options.record_cursor}, {"record.record_options.restore_portal_session", &config.record_config.record_options.restore_portal_session}, + {"record.save_video_in_game_folder", &config.record_config.save_video_in_game_folder}, {"record.show_recording_started_notifications", &config.record_config.show_recording_started_notifications}, {"record.show_video_saved_notifications", &config.record_config.show_video_saved_notifications}, {"record.save_directory", &config.record_config.save_directory}, @@ -120,6 +121,7 @@ namespace gsr { {"replay.record_options.record_cursor", &config.replay_config.record_options.record_cursor}, {"replay.record_options.restore_portal_session", &config.replay_config.record_options.restore_portal_session}, {"replay.start_replay_automatically", &config.replay_config.start_replay_automatically}, + {"replay.save_video_in_game_folder", &config.replay_config.save_video_in_game_folder}, {"replay.show_replay_started_notifications", &config.replay_config.show_replay_started_notifications}, {"replay.show_replay_stopped_notifications", &config.replay_config.show_replay_stopped_notifications}, {"replay.show_replay_saved_notifications", &config.replay_config.show_replay_saved_notifications}, diff --git a/src/Overlay.cpp b/src/Overlay.cpp index 9f87326..7526b2b 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -134,12 +134,8 @@ namespace gsr { #define _NET_WM_STATE_ADD 1 #define _NET_WM_STATE_TOGGLE 2 - static Bool set_window_wm_state(Display *display, Window window, Atom atom) { - Atom net_wm_state_atom = XInternAtom(display, "_NET_WM_STATE", False); - if(!net_wm_state_atom) { - fprintf(stderr, "Error: failed to find atom _NET_WM_STATE\n"); - return False; - } + static Bool set_window_wm_state(Display *dpy, Window window, Atom atom) { + const Atom net_wm_state_atom = XInternAtom(dpy, "_NET_WM_STATE", False); XClientMessageEvent xclient; memset(&xclient, 0, sizeof(xclient)); @@ -154,19 +150,17 @@ namespace gsr { xclient.data.l[3] = 0; xclient.data.l[4] = 0; - XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xclient); - XFlush(display); + XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xclient); + XFlush(dpy); return True; } - static Bool make_window_sticky(Display* display, Window window) { - Atom net_wm_state_sticky_atom = XInternAtom(display, "_NET_WM_STATE_STICKY", False); - if(!net_wm_state_sticky_atom) { - fprintf(stderr, "Error: failed to find atom _NET_WM_STATE_STICKY\n"); - return False; - } - - return set_window_wm_state(display, window, net_wm_state_sticky_atom); + static Bool make_window_sticky(Display *dpy, Window window) { + return set_window_wm_state(dpy, window, XInternAtom(dpy, "_NET_WM_STATE_STICKY", False)); + } + + static Bool hide_window_from_taskbar(Display *dpy, Window window) { + return set_window_wm_state(dpy, window, XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False)); } // Returns the first monitor if not found. Assumes there is at least one monitor connected. @@ -212,7 +206,10 @@ namespace gsr { if(new_config) config = std::move(new_config.value()); - gsr::init_color_theme(gsr_info); + init_color_theme(gsr_info); + // These environment variable are used by files in scripts/ folder + const std::string notify_bg_color_str = color_to_hex_str(get_color_theme().tint_color); + setenv("GSR_NOTIFY_BG_COLOR", notify_bg_color_str.c_str(), true); if(config.replay_config.start_replay_automatically) on_press_start_replay(true); @@ -241,7 +238,7 @@ namespace gsr { gpu_screen_recorder_process = -1; // TODO: Show this with a slight delay to make sure it doesn't show up in the video - if(recording_status == RecordingStatus::RECORD && config.record_config.show_video_saved_notifications) + if(recording_status == RecordingStatus::RECORD && config.record_config.show_video_saved_notifications && !config.record_config.save_video_in_game_folder) show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); } } @@ -326,7 +323,7 @@ namespace gsr { void Overlay::show() { window.reset(); window = std::make_unique(); - gsr::deinit_theme(); + deinit_theme(); mgl::vec2i window_size = { 1280, 720 }; mgl::vec2i window_pos = { 0, 0 }; @@ -355,7 +352,7 @@ namespace gsr { data = 1; XChangeProperty(display, window->get_system_handle(), XInternAtom(display, "GAMESCOPE_EXTERNAL_OVERLAY", False), XA_CARDINAL, 32, PropModeReplace, &data, 1); - if(!gsr::init_theme(resources_path)) { + if(!init_theme(resources_path)) { fprintf(stderr, "Error: failed to load theme\n"); exit(1); } @@ -508,6 +505,7 @@ namespace gsr { window->set_fullscreen(true); window->set_visible(true); make_window_sticky(display, window->get_system_handle()); + hide_window_from_taskbar(display, window->get_system_handle()); if(default_cursor) { XFreeCursor(display, default_cursor); @@ -588,7 +586,7 @@ namespace gsr { window.reset(); } - gsr::deinit_theme(); + deinit_theme(); } void Overlay::toggle_show() { @@ -730,7 +728,7 @@ namespace gsr { case RecordingStatus::RECORD: { update_ui_recording_stopped(); if(exit_code == 0) { - if(config.record_config.show_video_saved_notifications) + if(config.record_config.show_video_saved_notifications && !config.record_config.save_video_in_game_folder) show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); } else { fprintf(stderr, "Warning: gpu-screen-recorder (%d) exited with exit status %d\n", (int)gpu_screen_recorder_process, exit_code); @@ -871,7 +869,7 @@ namespace gsr { return; kill(gpu_screen_recorder_process, SIGUSR1); - if(config.replay_config.show_replay_saved_notifications) + if(config.replay_config.show_replay_saved_notifications && !config.replay_config.save_video_in_game_folder) show_notification("Replay saved", 3.0, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY); } @@ -973,6 +971,13 @@ namespace gsr { } } + setenv("GSR_SHOW_SAVED_NOTIFICATION", config.replay_config.show_replay_saved_notifications ? "1" : "0", true); + const std::string save_video_in_game_folder = resources_path + "scripts/save-video-in-game-folder.sh"; + if(config.replay_config.save_video_in_game_folder) { + args.push_back("-sc"); + args.push_back(save_video_in_game_folder.c_str()); + } + args.push_back(nullptr); gpu_screen_recorder_process = exec_program(args.data()); @@ -1030,7 +1035,7 @@ namespace gsr { update_ui_recording_stopped(); // TODO: Show this with a slight delay to make sure it doesn't show up in the video - if(config.record_config.show_video_saved_notifications) + if(config.record_config.show_video_saved_notifications && !config.record_config.save_video_in_game_folder) show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); return; } @@ -1095,6 +1100,13 @@ namespace gsr { } } + setenv("GSR_SHOW_SAVED_NOTIFICATION", config.record_config.show_video_saved_notifications ? "1" : "0", true); + const std::string save_video_in_game_folder = resources_path + "scripts/save-video-in-game-folder.sh"; + if(config.record_config.save_video_in_game_folder) { + args.push_back("-sc"); + args.push_back(save_video_in_game_folder.c_str()); + } + args.push_back(nullptr); gpu_screen_recorder_process = exec_program(args.data()); diff --git a/src/gui/ScrollablePage.cpp b/src/gui/ScrollablePage.cpp index 09439e9..74dd715 100644 --- a/src/gui/ScrollablePage.cpp +++ b/src/gui/ScrollablePage.cpp @@ -93,6 +93,7 @@ namespace gsr { for(size_t i = 0; i < widgets.size(); ++i) { auto &widget = widgets[i]; if(widget.get() != selected_widget) { + // TODO: Do not draw if scrolled out of view widget->draw(window, offset); // TODO: Create a widget function to get the render area instead, which each widget should set (position + offset as start, and position + offset + size as end), this has to be done in the widgets to ensure that recursive rendering has correct position. diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp index bf68500..7a27b00 100644 --- a/src/gui/SettingsPage.cpp +++ b/src/gui/SettingsPage.cpp @@ -531,6 +531,12 @@ namespace gsr { return checkbox; } + std::unique_ptr SettingsPage::create_save_replay_in_game_folder() { + auto checkbox = std::make_unique(&get_theme().body_font, "Save video in a folder with the name of the game"); + save_replay_in_game_folder_ptr = checkbox.get(); + return checkbox; + } + void SettingsPage::add_replay_widgets() { auto file_info_list = std::make_unique(List::Orientation::HORIZONTAL); file_info_list->add_widget(create_save_directory("Directory to save replays:")); @@ -538,8 +544,9 @@ namespace gsr { file_info_list->add_widget(create_replay_time()); settings_list_ptr->add_widget(std::make_unique("File info", std::move(file_info_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); - auto general_list = std::make_unique(List::Orientation::HORIZONTAL); + auto general_list = std::make_unique(List::Orientation::VERTICAL); general_list->add_widget(create_start_replay_on_startup()); + general_list->add_widget(create_save_replay_in_game_folder()); settings_list_ptr->add_widget(std::make_unique("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); auto checkboxes_list = std::make_unique(List::Orientation::VERTICAL); @@ -576,12 +583,22 @@ namespace gsr { view_radio_button_ptr->on_selection_changed("Simple", "simple"); } + std::unique_ptr SettingsPage::create_save_recording_in_game_folder() { + auto checkbox = std::make_unique(&get_theme().body_font, "Save video in a folder with the name of the game"); + save_recording_in_game_folder_ptr = checkbox.get(); + return checkbox; + } + void SettingsPage::add_record_widgets() { auto file_list = std::make_unique(List::Orientation::HORIZONTAL); file_list->add_widget(create_save_directory("Directory to save the video:")); file_list->add_widget(create_container_section()); settings_list_ptr->add_widget(std::make_unique("File info", std::move(file_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); + auto general_list = std::make_unique(List::Orientation::VERTICAL); + general_list->add_widget(create_save_recording_in_game_folder()); + settings_list_ptr->add_widget(std::make_unique("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); + auto checkboxes_list = std::make_unique(List::Orientation::VERTICAL); auto show_recording_started_notification_checkbox = std::make_unique(&get_theme().body_font, "Show recording started notification"); @@ -823,6 +840,7 @@ namespace gsr { void SettingsPage::load_replay() { load_common(config.replay_config.record_options); start_replay_automatically_ptr->set_checked(config.replay_config.start_replay_automatically); + save_replay_in_game_folder_ptr->set_checked(config.replay_config.save_video_in_game_folder); show_replay_started_notification_checkbox_ptr->set_checked(config.replay_config.show_replay_started_notifications); show_replay_stopped_notification_checkbox_ptr->set_checked(config.replay_config.show_replay_stopped_notifications); show_replay_saved_notification_checkbox_ptr->set_checked(config.replay_config.show_replay_saved_notifications); @@ -836,6 +854,7 @@ namespace gsr { void SettingsPage::load_record() { load_common(config.record_config.record_options); + save_recording_in_game_folder_ptr->set_checked(config.record_config.save_video_in_game_folder); show_recording_started_notification_checkbox_ptr->set_checked(config.record_config.show_recording_started_notifications); show_video_saved_notification_checkbox_ptr->set_checked(config.record_config.show_video_saved_notifications); save_directory_button_ptr->set_text(config.record_config.save_directory); @@ -931,6 +950,7 @@ namespace gsr { void SettingsPage::save_replay() { save_common(config.replay_config.record_options); config.replay_config.start_replay_automatically = start_replay_automatically_ptr->is_checked(); + config.replay_config.save_video_in_game_folder = save_replay_in_game_folder_ptr->is_checked(); config.replay_config.show_replay_started_notifications = show_replay_started_notification_checkbox_ptr->is_checked(); config.replay_config.show_replay_stopped_notifications = show_replay_stopped_notification_checkbox_ptr->is_checked(); config.replay_config.show_replay_saved_notifications = show_replay_saved_notification_checkbox_ptr->is_checked(); @@ -946,6 +966,7 @@ namespace gsr { void SettingsPage::save_record() { save_common(config.record_config.record_options); + config.record_config.save_video_in_game_folder = save_recording_in_game_folder_ptr->is_checked(); config.record_config.show_recording_started_notifications = show_recording_started_notification_checkbox_ptr->is_checked(); config.record_config.show_video_saved_notifications = show_video_saved_notification_checkbox_ptr->is_checked(); config.record_config.save_directory = save_directory_button_ptr->get_text(); -- cgit v1.2.3