From 1d2fc77cfcd3d40c3a382d3f5f8e6c28e8b38da9 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 26 Oct 2024 11:37:52 +0200 Subject: Make the ui the daemon instead, add hotkey for recording/pause --- src/Overlay.cpp | 281 ++++++++++++++++++--------------------------- src/Theme.cpp | 3 + src/Utils.cpp | 17 --- src/gui/DropdownButton.cpp | 11 +- src/gui/FileChooser.cpp | 39 ++++--- src/main.cpp | 53 ++++++--- 6 files changed, 183 insertions(+), 221 deletions(-) (limited to 'src') diff --git a/src/Overlay.cpp b/src/Overlay.cpp index ff12770..204ff6f 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -197,32 +197,32 @@ namespace gsr { close_button_widget({0.0f, 0.0f}) { memset(&window_texture, 0, sizeof(window_texture)); - load_program_status(); - load_program_pid(); - key_bindings[0].key_event.code = mgl::Keyboard::Z; - key_bindings[0].key_event.alt = true; + key_bindings[0].key_event.code = mgl::Keyboard::Escape; + key_bindings[0].key_event.alt = false; key_bindings[0].key_event.control = false; key_bindings[0].key_event.shift = false; key_bindings[0].key_event.system = false; key_bindings[0].callback = [this]() { - while(!page_stack.empty()) { - page_stack.pop(); - } + page_stack.pop(); }; } Overlay::~Overlay() { hide(); - // if(gpu_screen_recorder_process > 0) { - // kill(gpu_screen_recorder_process, SIGINT); - // int status; - // if(waitpid(gpu_screen_recorder_process, &status, 0) == -1) { - // perror("waitpid failed"); - // /* Ignore... */ - // } - // gpu_screen_recorder_process = -1; - // } + if(gpu_screen_recorder_process > 0) { + kill(gpu_screen_recorder_process, SIGINT); + int status; + if(waitpid(gpu_screen_recorder_process, &status, 0) == -1) { + perror("waitpid failed"); + /* Ignore... */ + } + gpu_screen_recorder_process = -1; + + // 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) + show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_theme().tint_color, NotificationType::RECORD); + } } static uint32_t key_event_to_bitmask(mgl::Event::KeyEvent key_event) { @@ -248,12 +248,10 @@ namespace gsr { return; close_button_widget.on_event(event, window, mgl::vec2f(0.0f, 0.0f)); - page_stack.on_event(event, window, mgl::vec2f(0.0f, 0.0f)); - if(event.type == mgl::Event::KeyReleased) { - if(event.key.code == mgl::Keyboard::Escape) - page_stack.pop(); - } - //process_key_bindings(event); + if(!page_stack.on_event(event, window, mgl::vec2f(0.0f, 0.0f))) + return; + + process_key_bindings(event); } void Overlay::draw(mgl::Window &window) { @@ -337,7 +335,7 @@ namespace gsr { auto main_buttons_list = std::make_unique(List::Orientation::HORIZONTAL); main_buttons_list->set_spacing(0.0f); { - auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Instant Replay", "On", "Off", &get_theme().replay_button_texture, + auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Instant Replay", "Off", &get_theme().replay_button_texture, mgl::vec2f(button_width, button_height)); replay_dropdown_button_ptr = button.get(); button->add_item("Turn on", "start", "Alt+Shift+F10"); @@ -347,18 +345,19 @@ namespace gsr { main_buttons_list->add_widget(std::move(button)); } { - auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Record", "Recording", "Not recording", &get_theme().record_button_texture, + auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Record", "Not recording", &get_theme().record_button_texture, mgl::vec2f(button_width, button_height)); record_dropdown_button_ptr = button.get(); button->add_item("Start", "start", "Alt+F9"); button->add_item("Pause", "pause", "Alt+F7"); button->add_item("Settings", "settings"); button->set_item_icon("start", &get_theme().play_texture); + button->set_item_icon("pause", &get_theme().pause_texture); button->on_click = std::bind(&Overlay::on_press_start_record, this, std::placeholders::_1); main_buttons_list->add_widget(std::move(button)); } { - auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Livestream", "Streaming", "Not streaming", &get_theme().stream_button_texture, + auto button = std::make_unique(&get_theme().title_font, &get_theme().body_font, "Livestream", "Not streaming", &get_theme().stream_button_texture, mgl::vec2f(button_width, button_height)); stream_dropdown_button_ptr = button.get(); button->add_item("Start", "start", "Alt+F8"); @@ -439,6 +438,9 @@ namespace gsr { if(gpu_screen_recorder_process > 0 && recording_status == RecordingStatus::RECORD) update_ui_recording_started(); + + if(paused) + update_ui_recording_paused(); } void Overlay::hide() { @@ -466,6 +468,58 @@ namespace gsr { show(); } + void Overlay::toggle_record() { + on_press_start_record("start"); + } + + void Overlay::toggle_pause() { + if(recording_status != RecordingStatus::RECORD || gpu_screen_recorder_process <= 0) + return; + + if(paused) { + update_ui_recording_unpaused(); + show_notification("Recording has been unpaused", 3.0, mgl::Color(255, 255, 255), get_theme().tint_color, NotificationType::RECORD); + } else { + update_ui_recording_paused(); + show_notification("Recording has been paused", 3.0, mgl::Color(255, 255, 255), get_theme().tint_color, NotificationType::RECORD); + } + + kill(gpu_screen_recorder_process, SIGUSR2); + paused = !paused; + } + + static const char* notification_type_to_string(NotificationType notification_type) { + switch(notification_type) { + case NotificationType::NONE: return nullptr; + case NotificationType::RECORD: return "record"; + case NotificationType::REPLAY: return "replay"; + case NotificationType::STREAM: return "stream"; + } + return nullptr; + } + + void Overlay::show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type) { + char timeout_seconds_str[32]; + snprintf(timeout_seconds_str, sizeof(timeout_seconds_str), "%f", timeout_seconds); + + const std::string icon_color_str = color_to_hex_str(icon_color); + const std::string bg_color_str = color_to_hex_str(bg_color); + const char *notification_args[12] = { + "gsr-notify", "--text", str, "--timeout", timeout_seconds_str, + "--icon-color", icon_color_str.c_str(), "--bg-color", bg_color_str.c_str(), + }; + + const char *notification_type_str = notification_type_to_string(notification_type); + if(notification_type_str) { + notification_args[9] = "--icon"; + notification_args[10] = "record", + notification_args[11] = nullptr; + } else { + notification_args[9] = nullptr; + } + exec_program_daemonized(notification_args); + } + bool Overlay::is_open() const { return visible; } @@ -499,153 +553,52 @@ namespace gsr { gpu_screen_recorder_process = -1; recording_status = RecordingStatus::NONE; - recording_stopped_remove_runtime_files(); update_ui_recording_stopped(); if(exit_code == 0) { - if(config->record_config.show_video_saved_notifications) { - const std::string tint_color_as_hex = color_to_hex_str(get_theme().tint_color); - const char *notification_args[] = { - "gsr-notify", "--text", "Recording has been saved", "--timeout", "3.0", - "--icon", "record", - "--icon-color", "ffffff", "--bg-color", tint_color_as_hex.c_str(), - nullptr - }; - exec_program_daemonized(notification_args); - } + if(config->record_config.show_video_saved_notifications) + show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_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); - const char *notification_args[] = { - "gsr-notify", "--text", "Failed to start/save recording", "--timeout", "3.0", - "--icon", "record", - "--icon-color", "ff0000", "--bg-color", "ff0000", - nullptr - }; - exec_program_daemonized(notification_args); - } - } - - static RecordingStatus recording_status_from_string(const char *status) { - RecordingStatus recording_status = RecordingStatus::NONE; - if(strcmp(status, "none") == 0) - recording_status = RecordingStatus::NONE; - else if(strcmp(status, "replay") == 0) - recording_status = RecordingStatus::REPLAY; - else if(strcmp(status, "record") == 0) - recording_status = RecordingStatus::RECORD; - else if(strcmp(status, "stream") == 0) - recording_status = RecordingStatus::STREAM; - return recording_status; - } - - static const char* recording_status_to_string(RecordingStatus status) { - switch(status) { - case RecordingStatus::NONE: return "none"; - case RecordingStatus::REPLAY: return "replay"; - case RecordingStatus::RECORD: return "record"; - case RecordingStatus::STREAM: return "stream"; + show_notification("Failed to start/save recording", 3.0, mgl::Color(255, 0, 0), mgl::Color(255, 0, 0), NotificationType::RECORD); } - return "none"; } - void Overlay::load_program_status() { - recording_status = RecordingStatus::NONE; - - std::optional status_filepath = get_gsr_runtime_dir(); - if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); - - status_filepath.value() += "/status"; - - std::string file_content; - if(!file_get_content(status_filepath.value().c_str(), file_content)) + void Overlay::update_ui_recording_paused() { + if(!visible || recording_status != RecordingStatus::RECORD) return; - recording_status = recording_status_from_string(file_content.c_str()); + record_dropdown_button_ptr->set_description("Paused"); + record_dropdown_button_ptr->set_item_label("pause", "Unpause"); + record_dropdown_button_ptr->set_item_icon("pause", &get_theme().play_texture); } - void Overlay::save_program_status() { - std::optional status_filepath = get_gsr_runtime_dir(); - if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); - - status_filepath.value() += "/status"; - if(!file_overwrite(status_filepath.value().c_str(), recording_status_to_string(recording_status))) - fprintf(stderr, "Error: failed to update status to file %s\n", status_filepath.value().c_str()); - } - - void Overlay::load_program_pid() { - gpu_screen_recorder_process = -1; - - std::optional status_filepath = get_gsr_runtime_dir(); - if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); - - status_filepath.value() += "/pid"; - - std::string file_content; - if(!file_get_content(status_filepath.value().c_str(), file_content)) + void Overlay::update_ui_recording_unpaused() { + if(!visible || recording_status != RecordingStatus::RECORD) return; - int pid = -1; - if(sscanf(file_content.c_str(), "%d", &pid) != 1) { - fprintf(stderr, "Error: failed to read pid from file %s, content: %s\n", status_filepath.value().c_str(), file_content.c_str()); - return; - } - - char cmdline_path[256]; - snprintf(cmdline_path, sizeof(cmdline_path), "/proc/%d/cmdline", pid); - - char program_arg0[PATH_MAX]; - program_arg0[0] = '\0'; - if(!read_cmdline_arg0(cmdline_path, program_arg0)) { - fprintf(stderr, "Error: failed to parse arg0 from file %s. Was the gpu-screen-recorder process that was started by gsr-ui closed by another program or the user?\n", cmdline_path); - return; - } - - if(strcmp(program_arg0, "gpu-screen-recorder") != 0) { - fprintf(stderr, "Warning: process %d exists but doesn't belong to gpu-screen-recorder (is instead %s). Was the gpu-screen-recorder process that was started by gsr-ui closed by another program or the user?\n", pid, program_arg0); - return; - } - - gpu_screen_recorder_process = pid; + record_dropdown_button_ptr->set_description("Recording"); + record_dropdown_button_ptr->set_item_label("pause", "Pause"); + record_dropdown_button_ptr->set_item_icon("pause", &get_theme().pause_texture); } - void Overlay::save_program_pid() { - std::optional status_filepath = get_gsr_runtime_dir(); - if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); - - status_filepath.value() += "/pid"; - - char str[32]; - snprintf(str, sizeof(str), "%d", (int)gpu_screen_recorder_process); - if(!file_overwrite(status_filepath.value().c_str(), str)) - fprintf(stderr, "Error: failed to update pid to file %s\n", status_filepath.value().c_str()); - } - - void Overlay::recording_stopped_remove_runtime_files() { - std::optional status_filepath = get_gsr_runtime_dir(); - if(!status_filepath) { - fprintf(stderr, "Error: Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); + void Overlay::update_ui_recording_started() { + if(!visible) return; - } - const std::string status_file = status_filepath.value() + "/status"; - const std::string pid_file = status_filepath.value() + "/pid"; - remove(status_file.c_str()); - remove(pid_file.c_str()); - } - - void Overlay::update_ui_recording_started() { record_dropdown_button_ptr->set_item_label("start", "Stop and save"); record_dropdown_button_ptr->set_activated(true); + record_dropdown_button_ptr->set_description("Recording"); record_dropdown_button_ptr->set_item_icon("start", &get_theme().stop_texture); } void Overlay::update_ui_recording_stopped() { + if(!visible) + return; + record_dropdown_button_ptr->set_item_label("start", "Start"); record_dropdown_button_ptr->set_activated(false); + record_dropdown_button_ptr->set_description("Not recording"); record_dropdown_button_ptr->set_item_icon("start", &get_theme().play_texture); } @@ -700,23 +653,30 @@ namespace gsr { } void Overlay::on_press_start_record(const std::string &id) { + audio_devices = get_audio_devices(); + if(id == "settings") { auto record_settings_page = std::make_unique(SettingsPage::Type::RECORD, gsr_info, audio_devices, config, &page_stack); page_stack.push(std::move(record_settings_page)); return; } + if(id == "pause") { + toggle_pause(); + return; + } + if(id != "start") return; if(!config) config = Config(); + paused = false; + // window.close(); // usleep(1000 * 50); // 50 milliseconds - const std::string tint_color_as_hex = color_to_hex_str(get_theme().tint_color); - if(gpu_screen_recorder_process > 0) { kill(gpu_screen_recorder_process, SIGINT); int status; @@ -730,19 +690,11 @@ namespace gsr { //exit(0); gpu_screen_recorder_process = -1; recording_status = RecordingStatus::NONE; - recording_stopped_remove_runtime_files(); 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) { - const char *notification_args[] = { - "gsr-notify", "--text", "Recording has been saved", "--timeout", "3.0", - "--icon", "record", - "--icon-color", "ffffff", "--bg-color", tint_color_as_hex.c_str(), - nullptr - }; - exec_program_daemonized(notification_args); - } + if(config->record_config.show_video_saved_notifications) + show_notification("Recording has been saved", 3.0, mgl::Color(255, 255, 255), get_theme().tint_color, NotificationType::RECORD); return; } @@ -799,8 +751,6 @@ namespace gsr { // TODO: Show notification failed to start } else { recording_status = RecordingStatus::RECORD; - save_program_status(); - save_program_pid(); update_ui_recording_started(); } @@ -813,15 +763,8 @@ namespace gsr { // TODO: Do not run this is a daemon. Instead get the pid and when launching another notification close the current notification // program and start another one. This can also be used to check when the notification has finished by checking with waitpid NOWAIT // to see when the program has exit. - if(config->record_config.show_recording_started_notifications) { - const char *notification_args[] = { - "gsr-notify", "--text", "Recording has started", "--timeout", "3.0", - "--icon", "record", - "--icon-color", tint_color_as_hex.c_str(), "--bg-color", tint_color_as_hex.c_str(), - nullptr - }; - exec_program_daemonized(notification_args); - } + if(config->record_config.show_recording_started_notifications) + show_notification("Recording has started", 3.0, get_theme().tint_color, get_theme().tint_color, NotificationType::RECORD); //exit(0); // window.set_visible(false); // window.close(); diff --git a/src/Theme.cpp b/src/Theme.cpp index 037f159..3c8b981 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -94,6 +94,9 @@ namespace gsr { if(!theme->stop_texture.load_from_file((resources_path + "images/stop.png").c_str())) goto error; + if(!theme->pause_texture.load_from_file((resources_path + "images/pause.png").c_str())) + goto error; + return true; error: diff --git a/src/Utils.cpp b/src/Utils.cpp index 0f86ecc..6d45196 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -198,21 +198,4 @@ namespace gsr { } return result; } - - std::optional get_gsr_runtime_dir() { - std::optional result; - char runtime_dir_path[256]; - snprintf(runtime_dir_path, sizeof(runtime_dir_path), "/run/user/%u", (unsigned int)getuid()); - - struct stat st; - if(stat(runtime_dir_path, &st) == -1 || !S_ISDIR(st.st_mode)) - snprintf(runtime_dir_path, sizeof(runtime_dir_path), "/tmp"); - - strcat(runtime_dir_path, "/gsr-ui"); - if(create_directory_recursive(runtime_dir_path) != 0) - return result; - - result = runtime_dir_path; - return result; - } } \ No newline at end of file diff --git a/src/gui/DropdownButton.cpp b/src/gui/DropdownButton.cpp index b9b962f..28c1b5b 100644 --- a/src/gui/DropdownButton.cpp +++ b/src/gui/DropdownButton.cpp @@ -15,9 +15,8 @@ namespace gsr { static const float icon_spacing_scale = 0.008f; static const float border_scale = 0.003f; - DropdownButton::DropdownButton(mgl::Font *title_font, mgl::Font *description_font, const char *title, const char *description_activated, const char *description_deactivated, mgl::Texture *icon_texture, mgl::vec2f size) : - title_font(title_font), description_font(description_font), size(size), title(title, *title_font), description(description_deactivated, *description_font), - description_activated(description_activated), description_deactivated(description_deactivated) + DropdownButton::DropdownButton(mgl::Font *title_font, mgl::Font *description_font, const char *title, const char *description, mgl::Texture *icon_texture, mgl::vec2f size) : + title_font(title_font), description_font(description_font), size(size), title(title, *title_font), description(description, *description_font) { if(icon_texture && icon_texture->is_valid()) { icon_sprite.set_texture(icon_texture); @@ -202,6 +201,10 @@ namespace gsr { } } + void DropdownButton::set_description(std::string description_text) { + description.set_string(std::move(description_text)); + } + void DropdownButton::set_activated(bool activated) { if(this->activated == activated) return; @@ -209,11 +212,9 @@ namespace gsr { this->activated = activated; if(activated) { - description = mgl::Text(description_activated, *description_font); description.set_color(get_theme().tint_color); icon_sprite.set_color(get_theme().tint_color); } else { - description = mgl::Text(description_deactivated, *description_font); description.set_color(mgl::Color(150, 150, 150)); icon_sprite.set_color(mgl::Color(255, 255, 255)); } diff --git a/src/gui/FileChooser.cpp b/src/gui/FileChooser.cpp index 8ec498f..d445ccf 100644 --- a/src/gui/FileChooser.cpp +++ b/src/gui/FileChooser.cpp @@ -223,15 +223,36 @@ namespace gsr { current_directory_padding_top_scale * get_theme().window_height + current_directory_padding_bottom_scale * get_theme().window_height ); - mgl::vec2f current_directory_background_size = mgl::vec2f(size.x, current_directory_text.get_bounds().size.y + current_directory_padding.y).floor(); + const float current_directory_background_height = (int)(current_directory_text.get_bounds().size.y + current_directory_padding.y); + + draw_pos += mgl::vec2f(0.0f, current_directory_background_height + spacing_between_current_directory_and_content * get_theme().window_height); + const mgl::vec2f body_size = mgl::vec2f(size.x, size.y - (draw_pos.y - draw_pos_start.y)).floor(); + scrollable_page.set_size(body_size); + file_chooser_body_ptr->set_size(scrollable_page.get_inner_size()); + mgl::Rectangle content_background(scrollable_page.get_inner_size().floor()); + content_background.set_position(draw_pos.floor()); + content_background.set_color(mgl::Color(0, 0, 0, 120)); + window.draw(content_background); + + draw_navigation(window, draw_pos_start); + + scrollable_page.draw(window, draw_pos.floor()); + } + + void FileChooser::draw_navigation(mgl::Window &window, mgl::vec2f draw_pos) { + const mgl::vec2f current_directory_padding( + current_directory_padding_left_scale * get_theme().window_height + current_directory_padding_right_scale * get_theme().window_height, + current_directory_padding_top_scale * get_theme().window_height + current_directory_padding_bottom_scale * get_theme().window_height + ); + mgl::vec2f current_directory_background_size = mgl::vec2f(size.x, current_directory_text.get_bounds().size.y + current_directory_padding.y).floor(); up_arrow_sprite.set_height((int)(current_directory_background_size.y * 0.8f)); - up_arrow_sprite.set_position((draw_pos + mgl::vec2f(size.x - up_arrow_sprite.get_size().x, current_directory_background_size.y * 0.5f - up_arrow_sprite.get_size().y * 0.5f)).floor()); + up_arrow_sprite.set_position((draw_pos + mgl::vec2f(file_chooser_body_ptr->get_size().x - up_arrow_sprite.get_size().x, current_directory_background_size.y * 0.5f - up_arrow_sprite.get_size().y * 0.5f)).floor()); const bool mouse_inside_up_arrow = mgl::FloatRect(up_arrow_sprite.get_position(), up_arrow_sprite.get_size()).contains(window.get_mouse_position().to_vec2f()) && !has_parent_with_selected_child_widget(); up_arrow_sprite.set_color(mouse_inside_up_arrow ? get_theme().tint_color : mgl::Color(255, 255, 255)); window.draw(up_arrow_sprite); - current_directory_background_size.x -= (up_arrow_sprite.get_size().x + up_button_spacing_scale * get_theme().window_height); + current_directory_background_size.x = file_chooser_body_ptr->get_size().x - up_arrow_sprite.get_size().x - up_button_spacing_scale * get_theme().window_height; mgl::Rectangle current_directory_background(current_directory_background_size.floor()); current_directory_background.set_color(mgl::Color(0, 0, 0, 120)); current_directory_background.set_position(draw_pos.floor()); @@ -240,18 +261,6 @@ namespace gsr { current_directory_text.set_color(get_theme().text_color); current_directory_text.set_position((draw_pos + mgl::vec2f(current_directory_padding.x, current_directory_background_size.y * 0.5f - current_directory_text.get_bounds().size.y * 0.5f)).floor()); window.draw(current_directory_text); - - draw_pos += mgl::vec2f(0.0f, current_directory_background_size.y + spacing_between_current_directory_and_content * get_theme().window_height); - const mgl::vec2f body_size = mgl::vec2f(size.x, size.y - (draw_pos.y - draw_pos_start.y)).floor(); - scrollable_page.set_size(body_size); - file_chooser_body_ptr->set_size(scrollable_page.get_inner_size()); - - mgl::Rectangle content_background(scrollable_page.get_inner_size().floor()); - content_background.set_position(draw_pos.floor()); - content_background.set_color(mgl::Color(0, 0, 0, 120)); - window.draw(content_background); - - scrollable_page.draw(window, draw_pos.floor()); } mgl::vec2f FileChooser::get_size() { diff --git a/src/main.cpp b/src/main.cpp index 198cb9f..4f265fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,8 +10,7 @@ #include #include -#define XK_LATIN1 -#include +#include #include #include #include @@ -33,7 +32,7 @@ extern "C" { const mgl::Color bg_color(0, 0, 0, 100); static void usage() { - fprintf(stderr, "usage: window-overlay\n"); + fprintf(stderr, "usage: gsr-ui [toggle-record|toggle-pause]\n"); exit(1); } @@ -49,10 +48,15 @@ static void sigint_handler(int signal) { } int main(int argc, char **argv) { - (void)argv; - if(argc != 1) + setlocale(LC_ALL, "C"); // Sigh... stupid C + + if(argc > 3) usage(); + const char *action = NULL; + if(argc > 1) + action = argv[1]; + signal(SIGINT, sigint_handler); gsr::GsrInfo gsr_info; @@ -124,25 +128,44 @@ int main(int argc, char **argv) { exit(1); } + fprintf(stderr, "info: gsr ui is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n"); + gsr::Overlay overlay(window, resources_path, gsr_info, egl_funcs, bg_color); - overlay.show(); + //overlay.show(); + + gsr::GlobalHotkeysX11 global_hotkeys; + const bool show_hotkey_registered = global_hotkeys.bind_key_press({ XK_z, Mod1Mask }, "open/hide", [&](const std::string &id) { + fprintf(stderr, "pressed %s\n", id.c_str()); + overlay.toggle_show(); + }); + + const bool record_hotkey_registered = global_hotkeys.bind_key_press({ XK_F9, Mod1Mask }, "record/save", [&](const std::string &id) { + fprintf(stderr, "pressed %s\n", id.c_str()); + overlay.toggle_record(); + }); + + const bool pause_hotkey_registered = global_hotkeys.bind_key_press({ XK_F7, Mod1Mask }, "pause/unpause", [&](const std::string &id) { + fprintf(stderr, "pressed %s\n", id.c_str()); + overlay.toggle_pause(); + }); + + if(!show_hotkey_registered) + fprintf(stderr, "error: failed to register hotkey alt+z for showing the overlay because the hotkey is registed by another program\n"); - // gsr::GlobalHotkeysX11 global_hotkeys; - // global_hotkeys.bind_key_press({ XK_z, Mod1Mask }, "open/hide", [&](const std::string &id) { - // fprintf(stderr, "pressed %s\n", id.c_str()); - // overlay.toggle_show(); - // }); + if(!record_hotkey_registered) + fprintf(stderr, "error: failed to register hotkey alt+f9 for recording because the hotkey is registed by another program\n"); - //fprintf(stderr, "info: gsr ui is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n"); + if(!pause_hotkey_registered) + fprintf(stderr, "error: failed to register hotkey alt+f7 for pausing because the hotkey is registed by another program\n"); mgl::Event event; mgl::Clock frame_delta_clock; - while(window.is_open() && overlay.is_open() && running) { + while(window.is_open() && running) { const double frame_delta_seconds = frame_delta_clock.get_elapsed_time_seconds(); frame_delta_clock.restart(); gsr::set_frame_delta_seconds(frame_delta_seconds); - //global_hotkeys.poll_events(); + global_hotkeys.poll_events(); while(window.poll_event(event)) { overlay.on_event(event, window); } @@ -152,7 +175,7 @@ int main(int argc, char **argv) { window.display(); } - fprintf(stderr, "shutting down!\n"); + fprintf(stderr, "info: shutting down!\n"); gsr::deinit_theme(); window.close(); -- cgit v1.2.3