aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO13
-rw-r--r--gsr-window-name/main.c190
-rw-r--r--include/Config.hpp2
-rw-r--r--include/gui/SettingsPage.hpp4
-rw-r--r--meson.build8
-rw-r--r--project.conf2
-rwxr-xr-xscripts/save-video-in-game-folder.sh25
-rw-r--r--src/Config.cpp2
-rw-r--r--src/Overlay.cpp60
-rw-r--r--src/gui/ScrollablePage.cpp1
-rw-r--r--src/gui/SettingsPage.cpp23
11 files changed, 293 insertions, 37 deletions
diff --git a/TODO b/TODO
index 41e57d4..a9c216c 100644
--- a/TODO
+++ b/TODO
@@ -24,21 +24,10 @@ Add support for window selection in capture.
Add option to record the focused monitor. This works on wayland too when using kms capture since we can get cursor position without root and see which monitor (crtc) the cursor is on.
-For system startup dont allow default output/input audio, as that can change after startup. For example if default output is a bluetooth devices that gets connected after startup.
-
Make hotkeys configurable.
-Move hotkey to gsr-ui-daemon which should execute gpu-screen-recorder --info on start, write that output to /tmp/blabla (or $XDG_RUNTIME_DIR) and gsr-ui
- should read that tmp file. gsr-ui should remove show/hide functions for overlay and run show on startup.
-
-Combobox shouldn't show all items if its the combobox at the bottom and scrolling is needed to show them all.
-
Filechooser should have the option to select list view, search bar and common folders/mounted drives on the left side for quick navigation. Also a button to create a new directory.
-Start recording/replay/streaming with correct data from settings.
-Save recording/replay/streaming status to file.
-Save gsr info data to file to quick re-open.
-
Support wayland (excluding gnome, or force xwayland on gnome).
Restart replay on system start if monitor resolution changes.
@@ -61,3 +50,5 @@ Add global setting. In that setting there should be an option to enable/disable
Add profiles and hotkey to switch between profiles (show notification when switching profile).
Fix first frame being black.
+
+Add support for systray.
diff --git a/gsr-window-name/main.c b/gsr-window-name/main.c
new file mode 100644
index 0000000..a46aff2
--- /dev/null
+++ b/gsr-window-name/main.c
@@ -0,0 +1,190 @@
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef enum {
+ CAPTURE_TYPE_FOCUSED,
+ CAPTURE_TYPE_CURSOR
+} capture_type;
+
+static bool window_has_atom(Display *dpy, Window window, Atom atom) {
+ Atom type;
+ unsigned long len, bytes_left;
+ int format;
+ unsigned char *properties = NULL;
+ if(XGetWindowProperty(dpy, window, atom, 0, 1024, False, AnyPropertyType, &type, &format, &len, &bytes_left, &properties) < Success)
+ return false;
+
+ if(properties)
+ XFree(properties);
+
+ return type != None;
+}
+
+static bool window_is_user_program(Display *dpy, Window window) {
+ const Atom net_wm_state_atom = XInternAtom(dpy, "_NET_WM_STATE", False);
+ const Atom wm_state_atom = XInternAtom(dpy, "WM_STATE", False);
+ return window_has_atom(dpy, window, net_wm_state_atom) || window_has_atom(dpy, window, wm_state_atom);
+}
+
+static Window get_window_at_cursor_position(Display *dpy) {
+ Window root_window = None;
+ Window window = None;
+ int dummy_i;
+ unsigned int dummy_u;
+ int cursor_pos_x = 0;
+ int cursor_pos_y = 0;
+ XQueryPointer(dpy, DefaultRootWindow(dpy), &root_window, &window, &dummy_i, &dummy_i, &cursor_pos_x, &cursor_pos_y, &dummy_u);
+ return window;
+}
+
+static Window get_focused_window(Display *dpy, capture_type cap_type) {
+ const Atom net_active_window_atom = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ Window focused_window = None;
+
+ if(cap_type == CAPTURE_TYPE_FOCUSED) {
+ Atom type = None;
+ int format = 0;
+ unsigned long num_items = 0;
+ unsigned long bytes_left = 0;
+ unsigned char *data = NULL;
+ XGetWindowProperty(dpy, DefaultRootWindow(dpy), net_active_window_atom, 0, 1, False, XA_WINDOW, &type, &format, &num_items, &bytes_left, &data);
+
+ if(type == XA_WINDOW && num_items == 1 && data)
+ return *(Window*)data;
+
+ int revert_to = 0;
+ XGetInputFocus(dpy, &focused_window, &revert_to);
+ if(focused_window && focused_window != DefaultRootWindow(dpy) && window_is_user_program(dpy, focused_window))
+ return focused_window;
+ }
+
+ focused_window = get_window_at_cursor_position(dpy);
+ if(focused_window && focused_window != DefaultRootWindow(dpy) && window_is_user_program(dpy, focused_window))
+ return focused_window;
+
+ return None;
+}
+
+static char* get_window_title(Display *dpy, Window window) {
+ const Atom net_wm_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False);
+ const Atom wm_name_atom = XInternAtom(dpy, "_NET_WM_NAME", False);
+ const Atom utf8_string_atom = XInternAtom(dpy, "UTF8_STRING", False);
+
+ Atom type = None;
+ int format = 0;
+ unsigned long num_items = 0;
+ unsigned long bytes_left = 0;
+ unsigned char *data = NULL;
+ XGetWindowProperty(dpy, window, net_wm_name_atom, 0, 1024, False, utf8_string_atom, &type, &format, &num_items, &bytes_left, &data);
+
+ if(type == utf8_string_atom && format == 8 && data)
+ return (char*)data;
+
+ type = None;
+ format = 0;
+ num_items = 0;
+ bytes_left = 0;
+ data = NULL;
+ XGetWindowProperty(dpy, window, wm_name_atom, 0, 1024, False, 0, &type, &format, &num_items, &bytes_left, &data);
+
+ if((type == XA_STRING || type == utf8_string_atom) && data)
+ return (char*)data;
+
+ return NULL;
+}
+
+static bool is_steam_game(Display *dpy, Window window) {
+ return window_has_atom(dpy, window, XInternAtom(dpy, "STEAM_GAME", False));
+}
+
+static const char* strip(const char *str, int *len) {
+ int str_len = strlen(str);
+ for(int i = 0; i < str_len; ++i) {
+ if(str[i] != ' ') {
+ str += i;
+ str_len -= i;
+ break;
+ }
+ }
+
+ for(int i = str_len - 1; i >= 0; --i) {
+ if(str[i] != ' ') {
+ str_len = i + 1;
+ break;
+ }
+ }
+
+ *len = str_len;
+ return str;
+}
+
+static void print_str_strip(const char *str) {
+ int len = 0;
+ str = strip(str, &len);
+ printf("%.*s", len, str);
+}
+
+static int x11_ignore_error(Display *dpy, XErrorEvent *error_event) {
+ (void)dpy;
+ (void)error_event;
+ return 0;
+}
+
+static void usage(void) {
+ fprintf(stderr, "usage: gsr-window-name <focused|cursor>\n");
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " focused The class/name of the focused window is returned. If no window is focused then the window beneath the cursor is returned instead\n");
+ fprintf(stderr, " cursor The class/name of the window beneath the cursor is returned\n");
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ if(argc != 2)
+ usage();
+
+ const char *cap_type_str = argv[1];
+ capture_type cap_type = CAPTURE_TYPE_FOCUSED;
+ if(strcmp(cap_type_str, "focused") == 0) {
+ cap_type = CAPTURE_TYPE_FOCUSED;
+ } else if(strcmp(cap_type_str, "cursor") == 0) {
+ cap_type = CAPTURE_TYPE_CURSOR;
+ } else {
+ fprintf(stderr, "error: invalid option '%s', expected either 'focused' or 'cursor'\n", cap_type_str);
+ usage();
+ }
+
+ Display *dpy = XOpenDisplay(NULL);
+ if(!dpy) {
+ fprintf(stderr, "Error: failed to connect to the X11 server\n");
+ exit(1);
+ }
+
+ XSetErrorHandler(x11_ignore_error);
+
+ const Window focused_window = get_focused_window(dpy, cap_type);
+ if(focused_window == None)
+ exit(2);
+
+ if(!is_steam_game(dpy, focused_window)) {
+ XClassHint class_hint = {0};
+ XGetClassHint(dpy, focused_window, &class_hint);
+ if(class_hint.res_class) {
+ print_str_strip(class_hint.res_class);
+ exit(0);
+ }
+ }
+
+ char *window_title = get_window_title(dpy, focused_window);
+ if(window_title) {
+ print_str_strip(window_title);
+ exit(0);
+ }
+
+ return 2;
+}
diff --git a/include/Config.hpp b/include/Config.hpp
index dc508cc..575f303 100644
--- a/include/Config.hpp
+++ b/include/Config.hpp
@@ -67,6 +67,7 @@ namespace gsr {
struct RecordConfig {
RecordOptions record_options;
+ bool save_video_in_game_folder = false;
bool show_recording_started_notifications = true;
bool show_video_saved_notifications = true;
std::string save_directory;
@@ -78,6 +79,7 @@ namespace gsr {
struct ReplayConfig {
RecordOptions record_options;
bool start_replay_automatically = false;
+ bool save_video_in_game_folder = false;
bool show_replay_started_notifications = true;
bool show_replay_stopped_notifications = true;
bool show_replay_saved_notifications = true;
diff --git a/include/gui/SettingsPage.hpp b/include/gui/SettingsPage.hpp
index 4c5388d..a0bc518 100644
--- a/include/gui/SettingsPage.hpp
+++ b/include/gui/SettingsPage.hpp
@@ -82,6 +82,8 @@ namespace gsr {
std::unique_ptr<Entry> create_replay_time_entry();
std::unique_ptr<List> create_replay_time();
std::unique_ptr<CheckBox> create_start_replay_on_startup();
+ std::unique_ptr<CheckBox> create_save_replay_in_game_folder();
+ std::unique_ptr<CheckBox> create_save_recording_in_game_folder();
void add_replay_widgets();
void add_record_widgets();
@@ -144,9 +146,11 @@ namespace gsr {
List *stream_url_list_ptr = nullptr;
List *container_list_ptr = nullptr;
CheckBox *start_replay_automatically_ptr = nullptr;
+ CheckBox *save_replay_in_game_folder_ptr = nullptr;
CheckBox *show_replay_started_notification_checkbox_ptr = nullptr;
CheckBox *show_replay_stopped_notification_checkbox_ptr = nullptr;
CheckBox *show_replay_saved_notification_checkbox_ptr = nullptr;
+ CheckBox *save_recording_in_game_folder_ptr = nullptr;
CheckBox *show_recording_started_notification_checkbox_ptr = nullptr;
CheckBox *show_video_saved_notification_checkbox_ptr = nullptr;
CheckBox *show_streaming_started_notification_checkbox_ptr = nullptr;
diff --git a/meson.build b/meson.build
index edd90b8..e64b9dc 100644
--- a/meson.build
+++ b/meson.build
@@ -57,8 +57,16 @@ executable(
cpp_args : '-DGSR_UI_RESOURCES_PATH="' + gsr_ui_resources_path + '"',
)
+executable(
+ 'gsr-window-name',
+ ['gsr-window-name/main.c'],
+ install : true,
+ dependencies : [dependency('x11')],
+)
+
install_subdir('images', install_dir : gsr_ui_resources_path)
install_subdir('fonts', install_dir : gsr_ui_resources_path)
+install_subdir('scripts', install_dir : gsr_ui_resources_path, install_mode : 'rwxr-xr-x')
if get_option('systemd') == true
install_data(files('extra/gpu-screen-recorder-ui.service'), install_dir : 'lib/systemd/user')
diff --git a/project.conf b/project.conf
index cf3c0e4..0cc523a 100644
--- a/project.conf
+++ b/project.conf
@@ -8,7 +8,7 @@ platforms = ["posix"]
version = "c++17"
[config]
-ignore_dirs = ["build", "gsr-ui-daemon"]
+ignore_dirs = ["build", "gsr-window-name"]
[dependencies]
xcomposite = ">=0" \ No newline at end of file
diff --git a/scripts/save-video-in-game-folder.sh b/scripts/save-video-in-game-folder.sh
new file mode 100755
index 0000000..4dafa03
--- /dev/null
+++ b/scripts/save-video-in-game-folder.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+filepath="$1"
+type="$2"
+
+file_name="$(basename "$filepath")"
+file_dir="$(dirname "$filepath")"
+
+game_name=$(gsr-window-name focused || echo "Game")
+target_dir="$file_dir/$game_name"
+new_filepath="$target_dir/$file_name"
+
+mkdir -p "$target_dir"
+mv "$filepath" "$new_filepath"
+
+[ "$GSR_SHOW_SAVED_NOTIFICATION" != "1" ] && exit 0
+
+case "$type" in
+ "regular")
+ gsr-notify --text "Saved recording to a folder called '$game_name'" --timeout 3.0 --icon record --bg-color "$GSR_NOTIFY_BG_COLOR"
+ ;;
+ "replay")
+ gsr-notify --text "Saved replay to a folder called '$game_name'" --timeout 3.0 --icon replay --bg-color "$GSR_NOTIFY_BG_COLOR"
+ ;;
+esac \ No newline at end of file
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<mgl::Window>();
- 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<CheckBox> SettingsPage::create_save_replay_in_game_folder() {
+ auto checkbox = std::make_unique<CheckBox>(&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>(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<Subsection>("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>(List::Orientation::HORIZONTAL);
+ auto general_list = std::make_unique<List>(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<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL);
@@ -576,12 +583,22 @@ namespace gsr {
view_radio_button_ptr->on_selection_changed("Simple", "simple");
}
+ std::unique_ptr<CheckBox> SettingsPage::create_save_recording_in_game_folder() {
+ auto checkbox = std::make_unique<CheckBox>(&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>(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<Subsection>("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>(List::Orientation::VERTICAL);
+ general_list->add_widget(create_save_recording_in_game_folder());
+ settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
+
auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL);
auto show_recording_started_notification_checkbox = std::make_unique<CheckBox>(&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();