Allow recording while using replay/streaming and option to save 1 min or 10 min

This commit is contained in:
dec05eba
2025-04-23 00:59:17 +02:00
parent 719236d4f4
commit 736f2f3095
9 changed files with 275 additions and 72 deletions

2
TODO
View File

@@ -14,8 +14,6 @@ Add nvidia overclock option.
Add support for window selection in capture. 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. Or use create_window_get_center_position.
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. 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.
Restart replay on system start if monitor resolution changes. Restart replay on system start if monitor resolution changes.

View File

@@ -119,6 +119,8 @@ namespace gsr {
int32_t replay_time = 60; int32_t replay_time = 60;
ConfigHotkey start_stop_hotkey; ConfigHotkey start_stop_hotkey;
ConfigHotkey save_hotkey; ConfigHotkey save_hotkey;
ConfigHotkey save_1_min_hotkey;
ConfigHotkey save_10_min_hotkey;
}; };
struct ScreenshotConfig { struct ScreenshotConfig {

View File

@@ -59,6 +59,8 @@ namespace gsr {
void toggle_stream(); void toggle_stream();
void toggle_replay(); void toggle_replay();
void save_replay(); void save_replay();
void save_replay_1_min();
void save_replay_10_min();
void take_screenshot(); void take_screenshot();
void take_screenshot_region(); void take_screenshot_region();
void show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type, const char *capture_target = nullptr); void show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type, const char *capture_target = nullptr);
@@ -87,7 +89,7 @@ namespace gsr {
void update_notification_process_status(); void update_notification_process_status();
void save_video_in_current_game_directory(const char *video_filepath, NotificationType notification_type); void save_video_in_current_game_directory(const char *video_filepath, NotificationType notification_type);
void on_replay_saved(const char *replay_saved_filepath); void on_replay_saved(const char *replay_saved_filepath);
void update_gsr_replay_save(); void process_gsr_output();
void update_gsr_process_status(); void update_gsr_process_status();
void update_gsr_screenshot_process_status(); void update_gsr_screenshot_process_status();
@@ -96,7 +98,7 @@ namespace gsr {
void update_power_supply_status(); void update_power_supply_status();
void update_system_startup_status(); void update_system_startup_status();
void on_stop_recording(int exit_code); void on_stop_recording(int exit_code, const std::string &video_filepath);
void update_ui_recording_paused(); void update_ui_recording_paused();
void update_ui_recording_unpaused(); void update_ui_recording_unpaused();
@@ -110,7 +112,10 @@ namespace gsr {
void update_ui_replay_started(); void update_ui_replay_started();
void update_ui_replay_stopped(); void update_ui_replay_stopped();
void prepare_gsr_output_for_reading();
void on_press_save_replay(); void on_press_save_replay();
void on_press_save_replay_1_min_replay();
void on_press_save_replay_10_min_replay();
bool on_press_start_replay(bool disable_notification, bool finished_region_selection); bool on_press_start_replay(bool disable_notification, bool finished_region_selection);
void on_press_start_record(bool finished_region_selection); void on_press_start_record(bool finished_region_selection);
void on_press_start_stream(bool finished_region_selection); void on_press_start_stream(bool finished_region_selection);
@@ -211,7 +216,6 @@ namespace gsr {
std::function<void()> on_region_selected; std::function<void()> on_region_selected;
std::string recording_capture_target; std::string recording_capture_target;
std::string replay_capture_target;
std::string screenshot_capture_target; std::string screenshot_capture_target;
std::unique_ptr<CursorTracker> cursor_tracker; std::unique_ptr<CursorTracker> cursor_tracker;

View File

@@ -22,6 +22,8 @@ namespace gsr {
NONE, NONE,
REPLAY_START_STOP, REPLAY_START_STOP,
REPLAY_SAVE, REPLAY_SAVE,
REPLAY_SAVE_1_MIN,
REPLAY_SAVE_10_MIN,
RECORD_START_STOP, RECORD_START_STOP,
RECORD_PAUSE_UNPAUSE, RECORD_PAUSE_UNPAUSE,
STREAM_START_STOP, STREAM_START_STOP,
@@ -56,6 +58,7 @@ namespace gsr {
std::unique_ptr<RadioButton> create_enable_joystick_hotkeys_button(); std::unique_ptr<RadioButton> create_enable_joystick_hotkeys_button();
std::unique_ptr<List> create_show_hide_hotkey_options(); std::unique_ptr<List> create_show_hide_hotkey_options();
std::unique_ptr<List> create_replay_hotkey_options(); std::unique_ptr<List> create_replay_hotkey_options();
std::unique_ptr<List> create_replay_partial_save_hotkey_options();
std::unique_ptr<List> create_record_hotkey_options(); std::unique_ptr<List> create_record_hotkey_options();
std::unique_ptr<List> create_stream_hotkey_options(); std::unique_ptr<List> create_stream_hotkey_options();
std::unique_ptr<List> create_screenshot_hotkey_options(); std::unique_ptr<List> create_screenshot_hotkey_options();
@@ -89,6 +92,8 @@ namespace gsr {
Button *turn_replay_on_off_button_ptr = nullptr; Button *turn_replay_on_off_button_ptr = nullptr;
Button *save_replay_button_ptr = nullptr; Button *save_replay_button_ptr = nullptr;
Button *save_replay_1_min_button_ptr = nullptr;
Button *save_replay_10_min_button_ptr = nullptr;
Button *start_stop_recording_button_ptr = nullptr; Button *start_stop_recording_button_ptr = nullptr;
Button *pause_unpause_recording_button_ptr = nullptr; Button *pause_unpause_recording_button_ptr = nullptr;
Button *start_stop_streaming_button_ptr = nullptr; Button *start_stop_streaming_button_ptr = nullptr;

View File

@@ -84,8 +84,8 @@ namespace gsr {
modifier_str = mgl::Keyboard::key_to_string(modifier_key); modifier_str = mgl::Keyboard::key_to_string(modifier_key);
if(!modifier_side) { if(!modifier_side) {
string_remove_all(modifier_str, "Left"); string_remove_all(modifier_str, "Left ");
string_remove_all(modifier_str, "Right"); string_remove_all(modifier_str, "Right ");
} }
result += modifier_str; result += modifier_str;
} }
@@ -148,6 +148,8 @@ namespace gsr {
replay_config.start_stop_hotkey = {mgl::Keyboard::F10, HOTKEY_MOD_LALT | HOTKEY_MOD_LSHIFT}; replay_config.start_stop_hotkey = {mgl::Keyboard::F10, HOTKEY_MOD_LALT | HOTKEY_MOD_LSHIFT};
replay_config.save_hotkey = {mgl::Keyboard::F10, HOTKEY_MOD_LALT}; replay_config.save_hotkey = {mgl::Keyboard::F10, HOTKEY_MOD_LALT};
replay_config.save_1_min_hotkey = {mgl::Keyboard::F11, HOTKEY_MOD_LALT};
replay_config.save_10_min_hotkey = {mgl::Keyboard::F12, HOTKEY_MOD_LALT};
screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Printscreen, 0}; screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Printscreen, 0};
screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Printscreen, HOTKEY_MOD_LCTRL}; screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Printscreen, HOTKEY_MOD_LCTRL};
@@ -264,6 +266,8 @@ namespace gsr {
{"replay.time", &config.replay_config.replay_time}, {"replay.time", &config.replay_config.replay_time},
{"replay.start_stop_hotkey", &config.replay_config.start_stop_hotkey}, {"replay.start_stop_hotkey", &config.replay_config.start_stop_hotkey},
{"replay.save_hotkey", &config.replay_config.save_hotkey}, {"replay.save_hotkey", &config.replay_config.save_hotkey},
{"replay.save_1_min_hotkey", &config.replay_config.save_1_min_hotkey},
{"replay.save_10_min_hotkey", &config.replay_config.save_10_min_hotkey},
{"screenshot.record_area_option", &config.screenshot_config.record_area_option}, {"screenshot.record_area_option", &config.screenshot_config.record_area_option},
{"screenshot.image_width", &config.screenshot_config.image_width}, {"screenshot.image_width", &config.screenshot_config.image_width},

View File

@@ -47,7 +47,7 @@ namespace gsr {
static const double force_window_on_top_timeout_seconds = 1.0; static const double force_window_on_top_timeout_seconds = 1.0;
static const double replay_status_update_check_timeout_seconds = 1.5; static const double replay_status_update_check_timeout_seconds = 1.5;
static const double replay_saving_notification_timeout_seconds = 0.5; static const double replay_saving_notification_timeout_seconds = 0.5;
static const double notification_timeout_seconds = 2.0; static const double notification_timeout_seconds = 2.5;
static const double notification_error_timeout_seconds = 5.0; static const double notification_error_timeout_seconds = 5.0;
static const double cursor_tracker_update_timeout_sec = 0.1; static const double cursor_tracker_update_timeout_sec = 0.1;
@@ -325,6 +325,20 @@ namespace gsr {
overlay->save_replay(); overlay->save_replay();
}); });
global_hotkeys->bind_key_press(
config_hotkey_to_hotkey(overlay->get_config().replay_config.save_1_min_hotkey),
"replay_save_1_min", [overlay](const std::string &id) {
fprintf(stderr, "pressed %s\n", id.c_str());
overlay->save_replay_1_min();
});
global_hotkeys->bind_key_press(
config_hotkey_to_hotkey(overlay->get_config().replay_config.save_10_min_hotkey),
"replay_save_10_min", [overlay](const std::string &id) {
fprintf(stderr, "pressed %s\n", id.c_str());
overlay->save_replay_10_min();
});
global_hotkeys->bind_key_press( global_hotkeys->bind_key_press(
config_hotkey_to_hotkey(overlay->get_config().screenshot_config.take_screenshot_hotkey), config_hotkey_to_hotkey(overlay->get_config().screenshot_config.take_screenshot_hotkey),
"take_screenshot", [overlay](const std::string &id) { "take_screenshot", [overlay](const std::string &id) {
@@ -688,7 +702,7 @@ namespace gsr {
remove_widgets_to_be_removed(); remove_widgets_to_be_removed();
update_notification_process_status(); update_notification_process_status();
update_gsr_replay_save(); process_gsr_output();
update_gsr_process_status(); update_gsr_process_status();
update_gsr_screenshot_process_status(); update_gsr_screenshot_process_status();
replay_status_update_status(); replay_status_update_status();
@@ -697,7 +711,7 @@ namespace gsr {
start_region_capture = false; start_region_capture = false;
hide(); hide();
if(!region_selector.start(get_color_theme().tint_color)) { if(!region_selector.start(get_color_theme().tint_color)) {
show_notification("Failed to start region capture", notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::NONE); show_notification("Failed to start region capture", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::NONE);
on_region_selected = nullptr; on_region_selected = nullptr;
} }
} }
@@ -1051,9 +1065,15 @@ namespace gsr {
replay_dropdown_button_ptr = button.get(); replay_dropdown_button_ptr = button.get();
button->add_item("Turn on", "start", config.replay_config.start_stop_hotkey.to_string(false, false)); button->add_item("Turn on", "start", config.replay_config.start_stop_hotkey.to_string(false, false));
button->add_item("Save", "save", config.replay_config.save_hotkey.to_string(false, false)); button->add_item("Save", "save", config.replay_config.save_hotkey.to_string(false, false));
if(gsr_info.system_info.gsr_version >= GsrVersion{5, 4, 0}) {
button->add_item("Save 1 min", "save_1_min", config.replay_config.save_1_min_hotkey.to_string(false, false));
button->add_item("Save 10 min", "save_10_min", config.replay_config.save_10_min_hotkey.to_string(false, false));
}
button->add_item("Settings", "settings"); button->add_item("Settings", "settings");
button->set_item_icon("start", &get_theme().play_texture); button->set_item_icon("start", &get_theme().play_texture);
button->set_item_icon("save", &get_theme().save_texture); button->set_item_icon("save", &get_theme().save_texture);
button->set_item_icon("save_1_min", &get_theme().save_texture);
button->set_item_icon("save_10_min", &get_theme().save_texture);
button->set_item_icon("settings", &get_theme().settings_small_texture); button->set_item_icon("settings", &get_theme().settings_small_texture);
button->on_click = [this](const std::string &id) { button->on_click = [this](const std::string &id) {
if(id == "settings") { if(id == "settings") {
@@ -1066,11 +1086,17 @@ namespace gsr {
page_stack.push(std::move(replay_settings_page)); page_stack.push(std::move(replay_settings_page));
} else if(id == "save") { } else if(id == "save") {
on_press_save_replay(); on_press_save_replay();
} else if(id == "save_1_min") {
on_press_save_replay_1_min_replay();
} else if(id == "save_10_min") {
on_press_save_replay_10_min_replay();
} else if(id == "start") { } else if(id == "start") {
on_press_start_replay(false, false); on_press_start_replay(false, false);
} }
}; };
button->set_item_enabled("save", false); button->set_item_enabled("save", false);
button->set_item_enabled("save_1_min", false);
button->set_item_enabled("save_10_min", false);
main_buttons_list->add_widget(std::move(button)); main_buttons_list->add_widget(std::move(button));
} }
{ {
@@ -1370,6 +1396,14 @@ namespace gsr {
on_press_save_replay(); on_press_save_replay();
} }
void Overlay::save_replay_1_min() {
on_press_save_replay_1_min_replay();
}
void Overlay::save_replay_10_min() {
on_press_save_replay_10_min_replay();
}
void Overlay::take_screenshot() { void Overlay::take_screenshot() {
on_press_take_screenshot(false, false); on_press_take_screenshot(false, false);
} }
@@ -1596,12 +1630,12 @@ namespace gsr {
if(!config.replay_config.show_replay_saved_notifications) if(!config.replay_config.show_replay_saved_notifications)
return; return;
if(is_capture_target_monitor(replay_capture_target.c_str())) if(is_capture_target_monitor(recording_capture_target.c_str()))
snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str()); snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str());
else else
snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str()); snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
capture_target = replay_capture_target.c_str(); capture_target = recording_capture_target.c_str();
break; break;
} }
case NotificationType::SCREENSHOT: { case NotificationType::SCREENSHOT: {
@@ -1623,6 +1657,16 @@ namespace gsr {
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type, capture_target); show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type, capture_target);
} }
static NotificationType recording_status_to_notification_type(RecordingStatus recording_status) {
switch(recording_status) {
case RecordingStatus::NONE: return NotificationType::NONE;
case RecordingStatus::REPLAY: return NotificationType::REPLAY;
case RecordingStatus::RECORD: return NotificationType::RECORD;
case RecordingStatus::STREAM: return NotificationType::STREAM;
}
return NotificationType::NONE;
}
void Overlay::on_replay_saved(const char *replay_saved_filepath) { void Overlay::on_replay_saved(const char *replay_saved_filepath) {
replay_save_show_notification = false; replay_save_show_notification = false;
if(config.replay_config.save_video_in_game_folder) { if(config.replay_config.save_video_in_game_folder) {
@@ -1630,15 +1674,15 @@ namespace gsr {
} else { } else {
const std::string filename = filepath_get_filename(replay_saved_filepath); const std::string filename = filepath_get_filename(replay_saved_filepath);
char msg[512]; char msg[512];
if(is_capture_target_monitor(replay_capture_target.c_str())) if(is_capture_target_monitor(recording_capture_target.c_str()))
snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str()); snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str());
else else
snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str()); snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", recording_capture_target.c_str(), filename.c_str());
show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY, replay_capture_target.c_str()); show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY, recording_capture_target.c_str());
} }
} }
void Overlay::update_gsr_replay_save() { void Overlay::process_gsr_output() {
if(replay_save_show_notification && replay_save_clock.get_elapsed_time_seconds() >= replay_saving_notification_timeout_seconds) { if(replay_save_show_notification && replay_save_clock.get_elapsed_time_seconds() >= replay_saving_notification_timeout_seconds) {
replay_save_show_notification = false; replay_save_show_notification = false;
show_notification("Saving replay, this might take some time", notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY); show_notification("Saving replay, this might take some time", notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY);
@@ -1646,15 +1690,36 @@ namespace gsr {
if(gpu_screen_recorder_process_output_file) { if(gpu_screen_recorder_process_output_file) {
char buffer[1024]; char buffer[1024];
char *replay_saved_filepath = fgets(buffer, sizeof(buffer), gpu_screen_recorder_process_output_file); char *line = fgets(buffer, sizeof(buffer), gpu_screen_recorder_process_output_file);
if(!replay_saved_filepath || replay_saved_filepath[0] == '\0') if(!line || line[0] == '\0')
return; return;
const int line_len = strlen(replay_saved_filepath); const int line_len = strlen(line);
if(replay_saved_filepath[line_len - 1] == '\n') if(line[line_len - 1] == '\n')
replay_saved_filepath[line_len - 1] = '\0'; line[line_len - 1] = '\0';
on_replay_saved(replay_saved_filepath); if(starts_with({line, (size_t)line_len}, "Error: ")) {
show_notification(line + 7, notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), recording_status_to_notification_type(recording_status));
return;
}
const std::string video_filepath = filepath_get_filename(line);
if(starts_with(video_filepath, "Video_")) {
on_stop_recording(0, video_filepath);
return;
}
switch(recording_status) {
case RecordingStatus::NONE:
break;
case RecordingStatus::REPLAY:
on_replay_saved(line);
break;
case RecordingStatus::RECORD:
break;
case RecordingStatus::STREAM:
break;
}
} else if(gpu_screen_recorder_process_output_fd > 0) { } else if(gpu_screen_recorder_process_output_fd > 0) {
char buffer[1024]; char buffer[1024];
read(gpu_screen_recorder_process_output_fd, buffer, sizeof(buffer)); read(gpu_screen_recorder_process_output_fd, buffer, sizeof(buffer));
@@ -1693,7 +1758,7 @@ namespace gsr {
} }
case RecordingStatus::RECORD: { case RecordingStatus::RECORD: {
update_ui_recording_stopped(); update_ui_recording_stopped();
on_stop_recording(exit_code); on_stop_recording(exit_code, record_filepath);
break; break;
} }
case RecordingStatus::STREAM: { case RecordingStatus::STREAM: {
@@ -1829,12 +1894,12 @@ namespace gsr {
on_press_start_replay(true, false); on_press_start_replay(true, false);
} }
void Overlay::on_stop_recording(int exit_code) { void Overlay::on_stop_recording(int exit_code, const std::string &video_filepath) {
if(exit_code == 0) { if(exit_code == 0) {
if(config.record_config.save_video_in_game_folder) { if(config.record_config.save_video_in_game_folder) {
save_video_in_current_game_directory(record_filepath.c_str(), NotificationType::RECORD); save_video_in_current_game_directory(video_filepath.c_str(), NotificationType::RECORD);
} else { } else {
const std::string filename = filepath_get_filename(record_filepath.c_str()); const std::string filename = filepath_get_filename(video_filepath.c_str());
char msg[512]; char msg[512];
if(is_capture_target_monitor(recording_capture_target.c_str())) if(is_capture_target_monitor(recording_capture_target.c_str()))
snprintf(msg, sizeof(msg), "Saved a recording of this monitor to '%s'", filename.c_str()); snprintf(msg, sizeof(msg), "Saved a recording of this monitor to '%s'", filename.c_str());
@@ -1846,6 +1911,7 @@ namespace gsr {
fprintf(stderr, "Warning: gpu-screen-recorder (%d) exited with exit status %d\n", (int)gpu_screen_recorder_process, exit_code); fprintf(stderr, "Warning: gpu-screen-recorder (%d) exited with exit status %d\n", (int)gpu_screen_recorder_process, exit_code);
show_notification("Failed to start/save recording. Verify if settings are correct", notification_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD); show_notification("Failed to start/save recording. Verify if settings are correct", notification_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD);
} }
update_ui_recording_stopped();
} }
void Overlay::update_ui_recording_paused() { void Overlay::update_ui_recording_paused() {
@@ -1874,7 +1940,7 @@ namespace gsr {
record_dropdown_button_ptr->set_activated(true); record_dropdown_button_ptr->set_activated(true);
record_dropdown_button_ptr->set_description("Recording"); record_dropdown_button_ptr->set_description("Recording");
record_dropdown_button_ptr->set_item_icon("start", &get_theme().stop_texture); record_dropdown_button_ptr->set_item_icon("start", &get_theme().stop_texture);
record_dropdown_button_ptr->set_item_enabled("pause", true); record_dropdown_button_ptr->set_item_enabled("pause", recording_status == RecordingStatus::RECORD);
} }
void Overlay::update_ui_recording_stopped() { void Overlay::update_ui_recording_stopped() {
@@ -1910,6 +1976,7 @@ namespace gsr {
stream_dropdown_button_ptr->set_activated(false); stream_dropdown_button_ptr->set_activated(false);
stream_dropdown_button_ptr->set_description("Not streaming"); stream_dropdown_button_ptr->set_description("Not streaming");
stream_dropdown_button_ptr->set_item_icon("start", &get_theme().play_texture); stream_dropdown_button_ptr->set_item_icon("start", &get_theme().play_texture);
update_ui_recording_stopped();
} }
void Overlay::update_ui_replay_started() { void Overlay::update_ui_replay_started() {
@@ -1921,6 +1988,8 @@ namespace gsr {
replay_dropdown_button_ptr->set_description("On"); replay_dropdown_button_ptr->set_description("On");
replay_dropdown_button_ptr->set_item_icon("start", &get_theme().stop_texture); replay_dropdown_button_ptr->set_item_icon("start", &get_theme().stop_texture);
replay_dropdown_button_ptr->set_item_enabled("save", true); replay_dropdown_button_ptr->set_item_enabled("save", true);
replay_dropdown_button_ptr->set_item_enabled("save_1_min", true);
replay_dropdown_button_ptr->set_item_enabled("save_10_min", true);
} }
void Overlay::update_ui_replay_stopped() { void Overlay::update_ui_replay_stopped() {
@@ -1932,6 +2001,9 @@ namespace gsr {
replay_dropdown_button_ptr->set_description("Off"); replay_dropdown_button_ptr->set_description("Off");
replay_dropdown_button_ptr->set_item_icon("start", &get_theme().play_texture); replay_dropdown_button_ptr->set_item_icon("start", &get_theme().play_texture);
replay_dropdown_button_ptr->set_item_enabled("save", false); replay_dropdown_button_ptr->set_item_enabled("save", false);
replay_dropdown_button_ptr->set_item_enabled("save_1_min", false);
replay_dropdown_button_ptr->set_item_enabled("save_10_min", false);
update_ui_recording_stopped();
} }
static std::string get_date_str() { static std::string get_date_str() {
@@ -2060,6 +2132,17 @@ namespace gsr {
} }
} }
void Overlay::prepare_gsr_output_for_reading() {
if(gpu_screen_recorder_process_output_fd <= 0)
return;
const int fdl = fcntl(gpu_screen_recorder_process_output_fd, F_GETFL);
fcntl(gpu_screen_recorder_process_output_fd, F_SETFL, fdl | O_NONBLOCK);
gpu_screen_recorder_process_output_file = fdopen(gpu_screen_recorder_process_output_fd, "r");
if(gpu_screen_recorder_process_output_file)
gpu_screen_recorder_process_output_fd = -1;
}
void Overlay::on_press_save_replay() { void Overlay::on_press_save_replay() {
if(recording_status != RecordingStatus::REPLAY || gpu_screen_recorder_process <= 0) if(recording_status != RecordingStatus::REPLAY || gpu_screen_recorder_process <= 0)
return; return;
@@ -2069,6 +2152,24 @@ namespace gsr {
kill(gpu_screen_recorder_process, SIGUSR1); kill(gpu_screen_recorder_process, SIGUSR1);
} }
void Overlay::on_press_save_replay_1_min_replay() {
if(recording_status != RecordingStatus::REPLAY || gpu_screen_recorder_process <= 0)
return;
replay_save_show_notification = true;
replay_save_clock.restart();
kill(gpu_screen_recorder_process, SIGRTMIN+3);
}
void Overlay::on_press_save_replay_10_min_replay() {
if(recording_status != RecordingStatus::REPLAY || gpu_screen_recorder_process <= 0)
return;
replay_save_show_notification = true;
replay_save_clock.restart();
kill(gpu_screen_recorder_process, SIGRTMIN+5);
}
bool Overlay::on_press_start_replay(bool disable_notification, bool finished_region_selection) { bool Overlay::on_press_start_replay(bool disable_notification, bool finished_region_selection) {
if(region_selector.is_started()) if(region_selector.is_started())
return false; return false;
@@ -2078,10 +2179,10 @@ namespace gsr {
case RecordingStatus::REPLAY: case RecordingStatus::REPLAY:
break; break;
case RecordingStatus::RECORD: case RecordingStatus::RECORD:
show_notification("Unable to start replay when recording.\nStop recording before starting replay.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); show_notification("Unable to start replay when recording.\nStop recording before starting replay.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD);
return false; return false;
case RecordingStatus::STREAM: case RecordingStatus::STREAM:
show_notification("Unable to start replay when streaming.\nStop streaming before starting replay.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::STREAM); show_notification("Unable to start replay when streaming.\nStop streaming before starting replay.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::STREAM);
return false; return false;
} }
@@ -2089,9 +2190,6 @@ namespace gsr {
replay_save_show_notification = false; replay_save_show_notification = false;
try_replay_startup = false; try_replay_startup = false;
// window->close();
// usleep(1000 * 50); // 50 milliseconds
close_gpu_screen_recorder_output(); close_gpu_screen_recorder_output();
if(gpu_screen_recorder_process > 0) { if(gpu_screen_recorder_process > 0) {
@@ -2114,11 +2212,11 @@ namespace gsr {
} }
const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info);
replay_capture_target = get_capture_target(config.replay_config.record_options.record_area_option, capture_options); recording_capture_target = get_capture_target(config.replay_config.record_options.record_area_option, capture_options);
if(!validate_capture_target(replay_capture_target, capture_options)) { if(!validate_capture_target(recording_capture_target, capture_options)) {
char err_msg[256]; char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Failed to start replay, capture target \"%s\" is invalid. Please change capture target in settings", replay_capture_target.c_str()); snprintf(err_msg, sizeof(err_msg), "Failed to start replay, capture target \"%s\" is invalid. Please change capture target in settings", recording_capture_target.c_str());
show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::REPLAY); show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::REPLAY);
return false; return false;
} }
@@ -2153,7 +2251,7 @@ namespace gsr {
snprintf(size, sizeof(size), "%dx%d", (int)config.replay_config.record_options.video_width, (int)config.replay_config.record_options.video_height); snprintf(size, sizeof(size), "%dx%d", (int)config.replay_config.record_options.video_width, (int)config.replay_config.record_options.video_height);
std::vector<const char*> args = { std::vector<const char*> args = {
"gpu-screen-recorder", "-w", replay_capture_target.c_str(), "gpu-screen-recorder", "-w", recording_capture_target.c_str(),
"-c", config.replay_config.container.c_str(), "-c", config.replay_config.container.c_str(),
"-ac", config.replay_config.record_options.audio_codec.c_str(), "-ac", config.replay_config.record_options.audio_codec.c_str(),
"-cursor", config.replay_config.record_options.record_cursor ? "yes" : "no", "-cursor", config.replay_config.record_options.record_cursor ? "yes" : "no",
@@ -2175,21 +2273,23 @@ namespace gsr {
char region_str[128]; char region_str[128];
add_common_gpu_screen_recorder_args(args, config.replay_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector); add_common_gpu_screen_recorder_args(args, config.replay_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector);
if(gsr_info.system_info.gsr_version >= GsrVersion{5, 4, 0}) {
args.push_back("-ro");
args.push_back(config.record_config.save_directory.c_str());
}
args.push_back(nullptr); args.push_back(nullptr);
gpu_screen_recorder_process = exec_program(args.data(), &gpu_screen_recorder_process_output_fd); gpu_screen_recorder_process = exec_program(args.data(), &gpu_screen_recorder_process_output_fd);
if(gpu_screen_recorder_process == -1) { if(gpu_screen_recorder_process == -1) {
// TODO: Show notification failed to start show_notification("Failed to launch gpu-screen-recorder to start replay", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::REPLAY);
return false;
} else { } else {
recording_status = RecordingStatus::REPLAY; recording_status = RecordingStatus::REPLAY;
update_ui_replay_started(); update_ui_replay_started();
} }
const int fdl = fcntl(gpu_screen_recorder_process_output_fd, F_GETFL); prepare_gsr_output_for_reading();
fcntl(gpu_screen_recorder_process_output_fd, F_SETFL, fdl | O_NONBLOCK);
gpu_screen_recorder_process_output_file = fdopen(gpu_screen_recorder_process_output_fd, "r");
if(gpu_screen_recorder_process_output_file)
gpu_screen_recorder_process_output_fd = -1;
// TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video. // TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video.
// Make clear to the user that the recording starts after the notification is gone. // Make clear to the user that the recording starts after the notification is gone.
@@ -2202,11 +2302,11 @@ namespace gsr {
// to see when the program has exit. // to see when the program has exit.
if(!disable_notification && config.replay_config.show_replay_started_notifications) { if(!disable_notification && config.replay_config.show_replay_started_notifications) {
char msg[256]; char msg[256];
if(is_capture_target_monitor(replay_capture_target.c_str())) if(is_capture_target_monitor(recording_capture_target.c_str()))
snprintf(msg, sizeof(msg), "Started replaying this monitor"); snprintf(msg, sizeof(msg), "Started replaying this monitor");
else else
snprintf(msg, sizeof(msg), "Started replaying %s", replay_capture_target.c_str()); snprintf(msg, sizeof(msg), "Started replaying %s", recording_capture_target.c_str());
show_notification(msg, notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::REPLAY, replay_capture_target.c_str()); show_notification(msg, notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::REPLAY, recording_capture_target.c_str());
} }
return true; return true;
@@ -2220,18 +2320,37 @@ namespace gsr {
case RecordingStatus::NONE: case RecordingStatus::NONE:
case RecordingStatus::RECORD: case RecordingStatus::RECORD:
break; break;
case RecordingStatus::REPLAY: case RecordingStatus::REPLAY: {
show_notification("Unable to start recording when replay is turned on.\nTurn off replay before starting recording.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY); if(gsr_info.system_info.gsr_version >= GsrVersion{5, 4, 0}) {
if(gpu_screen_recorder_process > 0) {
if(config.record_config.show_recording_started_notifications)
show_notification("Started recording in the replay session", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::RECORD);
update_ui_recording_started();
kill(gpu_screen_recorder_process, SIGRTMIN);
}
} else {
show_notification("Unable to start recording when replay is turned on.\nTurn off replay before starting recording.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), get_color_theme().tint_color, NotificationType::REPLAY);
}
return; return;
case RecordingStatus::STREAM: }
show_notification("Unable to start recording when streaming.\nStop streaming before starting recording.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::STREAM); case RecordingStatus::STREAM: {
if(gsr_info.system_info.gsr_version >= GsrVersion{5, 4, 0}) {
if(gpu_screen_recorder_process > 0) {
if(config.record_config.show_recording_started_notifications)
show_notification("Started recording in the streaming session", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::RECORD);
update_ui_recording_started();
kill(gpu_screen_recorder_process, SIGRTMIN);
}
} else {
show_notification("Unable to start recording when streaming.\nStop streaming before starting recording.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), get_color_theme().tint_color, NotificationType::STREAM);
}
return; return;
}
} }
paused = false; paused = false;
// window->close(); close_gpu_screen_recorder_output();
// usleep(1000 * 50); // 50 milliseconds
if(gpu_screen_recorder_process > 0) { if(gpu_screen_recorder_process > 0) {
kill(gpu_screen_recorder_process, SIGINT); kill(gpu_screen_recorder_process, SIGINT);
@@ -2243,7 +2362,7 @@ namespace gsr {
int exit_code = -1; int exit_code = -1;
if(WIFEXITED(status)) if(WIFEXITED(status))
exit_code = WEXITSTATUS(status); exit_code = WEXITSTATUS(status);
on_stop_recording(exit_code); on_stop_recording(exit_code, record_filepath);
} }
gpu_screen_recorder_process = -1; gpu_screen_recorder_process = -1;
@@ -2258,7 +2377,7 @@ namespace gsr {
if(!validate_capture_target(config.record_config.record_options.record_area_option, capture_options)) { if(!validate_capture_target(config.record_config.record_options.record_area_option, capture_options)) {
char err_msg[256]; char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Failed to start recording, capture target \"%s\" is invalid. Please change capture target in settings", recording_capture_target.c_str()); snprintf(err_msg, sizeof(err_msg), "Failed to start recording, capture target \"%s\" is invalid. Please change capture target in settings", recording_capture_target.c_str());
show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::RECORD); show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD);
return; return;
} }
@@ -2313,14 +2432,17 @@ namespace gsr {
args.push_back(nullptr); args.push_back(nullptr);
record_filepath = output_file; record_filepath = output_file;
gpu_screen_recorder_process = exec_program(args.data(), nullptr); gpu_screen_recorder_process = exec_program(args.data(), &gpu_screen_recorder_process_output_fd);
if(gpu_screen_recorder_process == -1) { if(gpu_screen_recorder_process == -1) {
// TODO: Show notification failed to start show_notification("Failed to launch gpu-screen-recorder to start recording", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD);
return;
} else { } else {
recording_status = RecordingStatus::RECORD; recording_status = RecordingStatus::RECORD;
update_ui_recording_started(); update_ui_recording_started();
} }
prepare_gsr_output_for_reading();
// TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video. // TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video.
// Make clear to the user that the recording starts after the notification is gone. // Make clear to the user that the recording starts after the notification is gone.
// Maybe have the option in notification to show timer until its getting hidden, then the notification can say: // Maybe have the option in notification to show timer until its getting hidden, then the notification can say:
@@ -2378,17 +2500,16 @@ namespace gsr {
case RecordingStatus::STREAM: case RecordingStatus::STREAM:
break; break;
case RecordingStatus::REPLAY: case RecordingStatus::REPLAY:
show_notification("Unable to start streaming when replay is turned on.\nTurn off replay before starting streaming.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY); show_notification("Unable to start streaming when replay is turned on.\nTurn off replay before starting streaming.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::REPLAY);
return; return;
case RecordingStatus::RECORD: case RecordingStatus::RECORD:
show_notification("Unable to start streaming when recording.\nStop recording before starting streaming.", notification_error_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); show_notification("Unable to start streaming when recording.\nStop recording before starting streaming.", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD);
return; return;
} }
paused = false; paused = false;
// window->close(); close_gpu_screen_recorder_output();
// usleep(1000 * 50); // 50 milliseconds
if(gpu_screen_recorder_process > 0) { if(gpu_screen_recorder_process > 0) {
kill(gpu_screen_recorder_process, SIGINT); kill(gpu_screen_recorder_process, SIGINT);
@@ -2409,11 +2530,11 @@ namespace gsr {
} }
const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info);
const std::string capture_target = get_capture_target(config.streaming_config.record_options.record_area_option, capture_options); recording_capture_target = get_capture_target(config.streaming_config.record_options.record_area_option, capture_options);
if(!validate_capture_target(config.streaming_config.record_options.record_area_option, capture_options)) { if(!validate_capture_target(config.streaming_config.record_options.record_area_option, capture_options)) {
char err_msg[256]; char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Failed to start streaming, capture target \"%s\" is invalid. Please change capture target in settings", capture_target.c_str()); snprintf(err_msg, sizeof(err_msg), "Failed to start streaming, capture target \"%s\" is invalid. Please change capture target in settings", recording_capture_target.c_str());
show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::STREAM); show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::STREAM);
return; return;
} }
@@ -2456,7 +2577,7 @@ namespace gsr {
snprintf(size, sizeof(size), "%dx%d", (int)config.streaming_config.record_options.video_width, (int)config.streaming_config.record_options.video_height); snprintf(size, sizeof(size), "%dx%d", (int)config.streaming_config.record_options.video_width, (int)config.streaming_config.record_options.video_height);
std::vector<const char*> args = { std::vector<const char*> args = {
"gpu-screen-recorder", "-w", capture_target.c_str(), "gpu-screen-recorder", "-w", recording_capture_target.c_str(),
"-c", container.c_str(), "-c", container.c_str(),
"-ac", config.streaming_config.record_options.audio_codec.c_str(), "-ac", config.streaming_config.record_options.audio_codec.c_str(),
"-cursor", config.streaming_config.record_options.record_cursor ? "yes" : "no", "-cursor", config.streaming_config.record_options.record_cursor ? "yes" : "no",
@@ -2471,16 +2592,24 @@ namespace gsr {
char region_str[128]; char region_str[128];
add_common_gpu_screen_recorder_args(args, config.streaming_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector); add_common_gpu_screen_recorder_args(args, config.streaming_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector);
if(gsr_info.system_info.gsr_version >= GsrVersion{5, 4, 0}) {
args.push_back("-ro");
args.push_back(config.record_config.save_directory.c_str());
}
args.push_back(nullptr); args.push_back(nullptr);
gpu_screen_recorder_process = exec_program(args.data(), nullptr); gpu_screen_recorder_process = exec_program(args.data(), &gpu_screen_recorder_process_output_fd);
if(gpu_screen_recorder_process == -1) { if(gpu_screen_recorder_process == -1) {
// TODO: Show notification failed to start show_notification("Failed to launch gpu-screen-recorder to start streaming", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::STREAM);
return;
} else { } else {
recording_status = RecordingStatus::STREAM; recording_status = RecordingStatus::STREAM;
update_ui_streaming_started(); update_ui_streaming_started();
} }
prepare_gsr_output_for_reading();
// TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video. // TODO: Start recording after this notification has disappeared to make sure it doesn't show up in the video.
// Make clear to the user that the recording starts after the notification is gone. // Make clear to the user that the recording starts after the notification is gone.
// Maybe have the option in notification to show timer until its getting hidden, then the notification can say: // Maybe have the option in notification to show timer until its getting hidden, then the notification can say:
@@ -2492,11 +2621,11 @@ namespace gsr {
// to see when the program has exit. // to see when the program has exit.
if(config.streaming_config.show_streaming_started_notifications) { if(config.streaming_config.show_streaming_started_notifications) {
char msg[256]; char msg[256];
if(is_capture_target_monitor(capture_target.c_str())) if(is_capture_target_monitor(recording_capture_target.c_str()))
snprintf(msg, sizeof(msg), "Started streaming this monitor"); snprintf(msg, sizeof(msg), "Started streaming this monitor");
else else
snprintf(msg, sizeof(msg), "Started streaming %s", capture_target.c_str()); snprintf(msg, sizeof(msg), "Started streaming %s", recording_capture_target.c_str());
show_notification(msg, notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::STREAM, capture_target.c_str()); show_notification(msg, notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::STREAM, recording_capture_target.c_str());
} }
} }
@@ -2516,7 +2645,7 @@ namespace gsr {
if(!validate_capture_target(record_area_option, capture_options)) { if(!validate_capture_target(record_area_option, capture_options)) {
char err_msg[256]; char err_msg[256];
snprintf(err_msg, sizeof(err_msg), "Failed to take a screenshot, capture target \"%s\" is invalid. Please change capture target in settings", screenshot_capture_target.c_str()); snprintf(err_msg, sizeof(err_msg), "Failed to take a screenshot, capture target \"%s\" is invalid. Please change capture target in settings", screenshot_capture_target.c_str());
show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::SCREENSHOT); show_notification(err_msg, notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::SCREENSHOT);
return; return;
} }
@@ -2562,7 +2691,7 @@ namespace gsr {
screenshot_filepath = output_file; screenshot_filepath = output_file;
gpu_screen_recorder_screenshot_process = exec_program(args.data(), nullptr); gpu_screen_recorder_screenshot_process = exec_program(args.data(), nullptr);
if(gpu_screen_recorder_screenshot_process == -1) { if(gpu_screen_recorder_screenshot_process == -1) {
// TODO: Show notification failed to start show_notification("Failed to launch gpu-screen-recorder to take a screenshot", notification_error_timeout_seconds, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::SCREENSHOT);
} }
} }

View File

@@ -181,6 +181,10 @@ namespace gsr {
} }
void DropdownButton::add_item(const std::string &text, const std::string &id, const std::string &description) { void DropdownButton::add_item(const std::string &text, const std::string &id, const std::string &description) {
for(auto &item : items) {
if(item.id == id)
return;
}
items.push_back({mgl::Text(text, *title_font), mgl::Text(description, *description_font), nullptr, id}); items.push_back({mgl::Text(text, *title_font), mgl::Text(description, *description_font), nullptr, id});
dirty = true; dirty = true;
} }

View File

@@ -256,6 +256,30 @@ namespace gsr {
return list; return list;
} }
std::unique_ptr<List> GlobalSettingsPage::create_replay_partial_save_hotkey_options() {
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Save 1 minute replay:", get_color_theme().text_color));
auto save_replay_1_min_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
save_replay_1_min_button_ptr = save_replay_1_min_button.get();
list->add_widget(std::move(save_replay_1_min_button));
list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Save 10 minute replay:", get_color_theme().text_color));
auto save_replay_10_min_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
save_replay_10_min_button_ptr = save_replay_10_min_button.get();
list->add_widget(std::move(save_replay_10_min_button));
save_replay_1_min_button_ptr->on_click = [this] {
configure_hotkey_start(ConfigureHotkeyType::REPLAY_SAVE_1_MIN);
};
save_replay_10_min_button_ptr->on_click = [this] {
configure_hotkey_start(ConfigureHotkeyType::REPLAY_SAVE_10_MIN);
};
return list;
}
std::unique_ptr<List> GlobalSettingsPage::create_record_hotkey_options() { std::unique_ptr<List> GlobalSettingsPage::create_record_hotkey_options() {
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
@@ -335,6 +359,8 @@ namespace gsr {
config.record_config.pause_unpause_hotkey = {mgl::Keyboard::Unknown, 0}; config.record_config.pause_unpause_hotkey = {mgl::Keyboard::Unknown, 0};
config.replay_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0}; config.replay_config.start_stop_hotkey = {mgl::Keyboard::Unknown, 0};
config.replay_config.save_hotkey = {mgl::Keyboard::Unknown, 0}; config.replay_config.save_hotkey = {mgl::Keyboard::Unknown, 0};
config.replay_config.save_1_min_hotkey = {mgl::Keyboard::Unknown, 0};
config.replay_config.save_10_min_hotkey = {mgl::Keyboard::Unknown, 0};
config.screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Unknown, 0}; config.screenshot_config.take_screenshot_hotkey = {mgl::Keyboard::Unknown, 0};
config.screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Unknown, 0}; config.screenshot_config.take_screenshot_region_hotkey = {mgl::Keyboard::Unknown, 0};
config.main_config.show_hide_hotkey = {mgl::Keyboard::Unknown, 0}; config.main_config.show_hide_hotkey = {mgl::Keyboard::Unknown, 0};
@@ -374,6 +400,7 @@ namespace gsr {
list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x)); list_ptr->add_widget(std::make_unique<LineSeparator>(LineSeparator::Orientation::HORIZONTAL, subsection->get_inner_size().x));
list_ptr->add_widget(create_show_hide_hotkey_options()); list_ptr->add_widget(create_show_hide_hotkey_options());
list_ptr->add_widget(create_replay_hotkey_options()); list_ptr->add_widget(create_replay_hotkey_options());
list_ptr->add_widget(create_replay_partial_save_hotkey_options());
list_ptr->add_widget(create_record_hotkey_options()); list_ptr->add_widget(create_record_hotkey_options());
list_ptr->add_widget(create_stream_hotkey_options()); list_ptr->add_widget(create_stream_hotkey_options());
list_ptr->add_widget(create_screenshot_hotkey_options()); list_ptr->add_widget(create_screenshot_hotkey_options());
@@ -490,6 +517,8 @@ namespace gsr {
void GlobalSettingsPage::load_hotkeys() { void GlobalSettingsPage::load_hotkeys() {
turn_replay_on_off_button_ptr->set_text(config.replay_config.start_stop_hotkey.to_string()); turn_replay_on_off_button_ptr->set_text(config.replay_config.start_stop_hotkey.to_string());
save_replay_button_ptr->set_text(config.replay_config.save_hotkey.to_string()); save_replay_button_ptr->set_text(config.replay_config.save_hotkey.to_string());
save_replay_1_min_button_ptr->set_text(config.replay_config.save_1_min_hotkey.to_string());
save_replay_10_min_button_ptr->set_text(config.replay_config.save_10_min_hotkey.to_string());
start_stop_recording_button_ptr->set_text(config.record_config.start_stop_hotkey.to_string()); start_stop_recording_button_ptr->set_text(config.record_config.start_stop_hotkey.to_string());
pause_unpause_recording_button_ptr->set_text(config.record_config.pause_unpause_hotkey.to_string()); pause_unpause_recording_button_ptr->set_text(config.record_config.pause_unpause_hotkey.to_string());
@@ -567,6 +596,10 @@ namespace gsr {
return turn_replay_on_off_button_ptr; return turn_replay_on_off_button_ptr;
case ConfigureHotkeyType::REPLAY_SAVE: case ConfigureHotkeyType::REPLAY_SAVE:
return save_replay_button_ptr; return save_replay_button_ptr;
case ConfigureHotkeyType::REPLAY_SAVE_1_MIN:
return save_replay_1_min_button_ptr;
case ConfigureHotkeyType::REPLAY_SAVE_10_MIN:
return save_replay_10_min_button_ptr;
case ConfigureHotkeyType::RECORD_START_STOP: case ConfigureHotkeyType::RECORD_START_STOP:
return start_stop_recording_button_ptr; return start_stop_recording_button_ptr;
case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE: case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE:
@@ -591,6 +624,10 @@ namespace gsr {
return &config.replay_config.start_stop_hotkey; return &config.replay_config.start_stop_hotkey;
case ConfigureHotkeyType::REPLAY_SAVE: case ConfigureHotkeyType::REPLAY_SAVE:
return &config.replay_config.save_hotkey; return &config.replay_config.save_hotkey;
case ConfigureHotkeyType::REPLAY_SAVE_1_MIN:
return &config.replay_config.save_1_min_hotkey;
case ConfigureHotkeyType::REPLAY_SAVE_10_MIN:
return &config.replay_config.save_10_min_hotkey;
case ConfigureHotkeyType::RECORD_START_STOP: case ConfigureHotkeyType::RECORD_START_STOP:
return &config.record_config.start_stop_hotkey; return &config.record_config.start_stop_hotkey;
case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE: case ConfigureHotkeyType::RECORD_PAUSE_UNPAUSE:
@@ -643,6 +680,12 @@ namespace gsr {
case ConfigureHotkeyType::REPLAY_SAVE: case ConfigureHotkeyType::REPLAY_SAVE:
hotkey_configure_action_name = "Save replay"; hotkey_configure_action_name = "Save replay";
break; break;
case ConfigureHotkeyType::REPLAY_SAVE_1_MIN:
hotkey_configure_action_name = "Save 1 minute replay";
break;
case ConfigureHotkeyType::REPLAY_SAVE_10_MIN:
hotkey_configure_action_name = "Save 10 minute replay";
break;
case ConfigureHotkeyType::RECORD_START_STOP: case ConfigureHotkeyType::RECORD_START_STOP:
hotkey_configure_action_name = "Start/stop recording"; hotkey_configure_action_name = "Start/stop recording";
break; break;

View File

@@ -30,6 +30,10 @@ static void sigint_handler(int signal) {
running = 0; running = 0;
} }
static void signal_ignore(int) {
}
static void disable_prime_run() { static void disable_prime_run() {
unsetenv("__NV_PRIME_RENDER_OFFLOAD"); unsetenv("__NV_PRIME_RENDER_OFFLOAD");
unsetenv("__NV_PRIME_RENDER_OFFLOAD_PROVIDER"); unsetenv("__NV_PRIME_RENDER_OFFLOAD_PROVIDER");
@@ -218,6 +222,16 @@ int main(int argc, char **argv) {
unsetenv("vblank_mode"); unsetenv("vblank_mode");
signal(SIGINT, sigint_handler); signal(SIGINT, sigint_handler);
signal(SIGTERM, sigint_handler);
signal(SIGUSR1, signal_ignore);
signal(SIGUSR2, signal_ignore);
signal(SIGRTMIN, signal_ignore);
signal(SIGRTMIN+1, signal_ignore);
signal(SIGRTMIN+2, signal_ignore);
signal(SIGRTMIN+3, signal_ignore);
signal(SIGRTMIN+4, signal_ignore);
signal(SIGRTMIN+5, signal_ignore);
signal(SIGRTMIN+6, signal_ignore);
gsr::GsrInfo gsr_info; gsr::GsrInfo gsr_info;
// TODO: Show the error in ui // TODO: Show the error in ui