From d84054ecbbd15e92736e5e5f55e36f72f410d3a5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 20 Oct 2024 22:44:15 +0200 Subject: gsr-overlay > gsr-ui --- README.md | 8 +- TODO | 10 +- gpu-screen-recorder-overlay-daemon/main.c | 116 ------------------------ gpu-screen-recorder-overlay-daemon/project.conf | 11 --- gsr-ui-daemon/main.c | 116 ++++++++++++++++++++++++ gsr-ui-daemon/project.conf | 11 +++ install.sh | 2 +- meson.build | 14 +-- project.conf | 4 +- src/Config.cpp | 4 +- src/Overlay.cpp | 14 +-- src/Process.cpp | 2 +- src/Utils.cpp | 2 +- src/gui/FileChooser.cpp | 2 +- src/gui/SettingsPage.cpp | 5 +- src/main.cpp | 6 +- uninstall.sh | 3 +- 17 files changed, 167 insertions(+), 163 deletions(-) delete mode 100644 gpu-screen-recorder-overlay-daemon/main.c delete mode 100644 gpu-screen-recorder-overlay-daemon/project.conf create mode 100644 gsr-ui-daemon/main.c create mode 100644 gsr-ui-daemon/project.conf diff --git a/README.md b/README.md index a0c6cec..f85f909 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -# GPU Screen Recorder Overlay +# GPU Screen Recorder UI A fullscreen overlay UI for [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/about/), in the style of ShadowPlay. # Dependencies -GPU Screen Recorder overlay uses meson build system so you need to install `meson` to build GPU Screen Recorder overlay. +GPU Screen Recorder UI uses meson build system so you need to install `meson` to build GPU Screen Recorder UI. ## Build dependencies -These are the dependencies needed to build GPU Screen Recorder overlay: +These are the dependencies needed to build GPU Screen Recorder UI: * x11 (libx11, libxrandr, libxrender, libxfixes) * libglvnd (which provides libgl, libglx and libegl) # Installation -Run `sudo ./install.sh`. This will install gsr-overlay to `/usr/bin/gsr-overlay`. You can run meson commands manually to install gsr-overlay to another directory. +Run `sudo ./install.sh`. This will install gsr-ui to `/usr/bin/gsr-ui`. You can run meson commands manually to install gsr-ui to another directory. # License This software is licensed under GPL3.0-only. Files under `fonts/` directory are licensed under `SIL Open Font License`. diff --git a/TODO b/TODO index a58a365..dc51b96 100644 --- a/TODO +++ b/TODO @@ -28,8 +28,8 @@ For system startup dont allow default output/input audio, as that can change aft Make hotkeys configurable. -Move hotkey to gsr-overlay-daemon which should execute gpu-screen-recorder --info on start, write that output to /tmp/blabla (or $XDG_RUNTIME_DIR) and gsr-overlay - should read that tmp file. gsr-overlay should remove show/hide functions for overlay and run show on startup. +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. @@ -48,4 +48,8 @@ Show warning when selecting hevc/av1 on amd because of amd driver/ffmpeg bug. Update gsr info and validate saved config when monitors update. The selected monitor/audio may no longer be available. Have different modes. Overlay, window and side menu. Overlay can be used on x11, window and side menu can be used on both x11 and wayland. - Window mode should look similar to overlay. \ No newline at end of file + Window mode should look similar to overlay. + +Look at /home/dec05eba/git/global-hotkeys for hotkeys. + +Show navigation breadcrumbs for settings and deeper navigation (such as selecting a directory to save videos). \ No newline at end of file diff --git a/gpu-screen-recorder-overlay-daemon/main.c b/gpu-screen-recorder-overlay-daemon/main.c deleted file mode 100644 index 18234c2..0000000 --- a/gpu-screen-recorder-overlay-daemon/main.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -bool exec_program(const char **args, pid_t *process_id) { - *process_id = -1; - - /* 1 argument */ - if(args[0] == NULL) - return false; - - pid_t pid = vfork(); - if(pid == -1) { - perror("Failed to vfork"); - return false; - } else if(pid == 0) { /* child */ - execvp(args[0], (char* const*)args); - perror("execvp"); - _exit(127); - } else { /* parent */ - *process_id = pid; - } - - return true; -} - -static int ignore_xerror(Display *display, XErrorEvent *ee) { - (void)display; - (void)ee; - return 0; -} - -static void sigterm_handler(int dummy) { - (void)dummy; -} - -static const KeySym toggle_overlay_key = XK_Z; -static unsigned int toggle_overlay_modifiers = Mod1Mask; - -static void grab_keys(Display *display) { - unsigned int numlockmask = 0; - KeyCode numlock_keycode = XKeysymToKeycode(display, XK_Num_Lock); - XModifierKeymap *modmap = XGetModifierMapping(display); - for(int i = 0; i < 8; ++i) { - for(int j = 0; j < modmap->max_keypermod; ++j) { - if(modmap->modifiermap[i * modmap->max_keypermod + j] == numlock_keycode) - numlockmask = (1 << i); - } - } - XFreeModifiermap(modmap); - - XErrorHandler prev_error_handler = XSetErrorHandler(ignore_xerror); - - Window root_window = DefaultRootWindow(display); - unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; - for(int i = 0; i < 4; ++i) { - XGrabKey(display, XKeysymToKeycode(display, toggle_overlay_key), toggle_overlay_modifiers|modifiers[i], root_window, False, GrabModeAsync, GrabModeAsync); - } - - XSync(display, False); - XSetErrorHandler(prev_error_handler); -} - -int main(void) { - Display *display = XOpenDisplay(NULL); - if(!display) { - fprintf(stderr, "Error: XOpenDisplay failed\n"); - return 1; - } - - grab_keys(display); - const KeyCode overlay_keycode = XKeysymToKeycode(display, toggle_overlay_key); - - XSetErrorHandler(ignore_xerror); - /* Killing gpu-screen-recorder with SIGTERM also gives us SIGTERM. We want to ignore that as that has no meaning here */ - signal(SIGTERM, sigterm_handler); - - pid_t overlay_pid = -1; - - fprintf(stderr, "gsr overlay is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n"); - - XEvent xev; - for(;;) { - XNextEvent(display, &xev); - if(xev.type == KeyPress && xev.xkey.keycode == overlay_keycode) { - if(overlay_pid != -1) { - int status; - if(waitpid(overlay_pid, &status, WNOHANG) == 0) { - kill(overlay_pid, SIGINT); - int status; - if(waitpid(overlay_pid, &status, 0) == -1) { - perror("waitpid failed"); - /* Ignore... */ - } - overlay_pid = -1; - continue; - } else { - overlay_pid = -1; - } - } - - if(overlay_pid == -1) { - fprintf(stderr, "launch overlay\n"); - // TODO: window_with_input_focus - const char *args[] = { "gsr-overlay", NULL }; - exec_program(args, &overlay_pid); - } - } - } - return 0; -} diff --git a/gpu-screen-recorder-overlay-daemon/project.conf b/gpu-screen-recorder-overlay-daemon/project.conf deleted file mode 100644 index 758d50c..0000000 --- a/gpu-screen-recorder-overlay-daemon/project.conf +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "gpu-screen-recorder-overlay-daemon" -type = "executable" -version = "0.1.0" -platforms = ["posix"] - -[config] -ignore_dirs = ["build"] - -[dependencies] -x11 = ">=1" diff --git a/gsr-ui-daemon/main.c b/gsr-ui-daemon/main.c new file mode 100644 index 0000000..18234c2 --- /dev/null +++ b/gsr-ui-daemon/main.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#include +#include + +bool exec_program(const char **args, pid_t *process_id) { + *process_id = -1; + + /* 1 argument */ + if(args[0] == NULL) + return false; + + pid_t pid = vfork(); + if(pid == -1) { + perror("Failed to vfork"); + return false; + } else if(pid == 0) { /* child */ + execvp(args[0], (char* const*)args); + perror("execvp"); + _exit(127); + } else { /* parent */ + *process_id = pid; + } + + return true; +} + +static int ignore_xerror(Display *display, XErrorEvent *ee) { + (void)display; + (void)ee; + return 0; +} + +static void sigterm_handler(int dummy) { + (void)dummy; +} + +static const KeySym toggle_overlay_key = XK_Z; +static unsigned int toggle_overlay_modifiers = Mod1Mask; + +static void grab_keys(Display *display) { + unsigned int numlockmask = 0; + KeyCode numlock_keycode = XKeysymToKeycode(display, XK_Num_Lock); + XModifierKeymap *modmap = XGetModifierMapping(display); + for(int i = 0; i < 8; ++i) { + for(int j = 0; j < modmap->max_keypermod; ++j) { + if(modmap->modifiermap[i * modmap->max_keypermod + j] == numlock_keycode) + numlockmask = (1 << i); + } + } + XFreeModifiermap(modmap); + + XErrorHandler prev_error_handler = XSetErrorHandler(ignore_xerror); + + Window root_window = DefaultRootWindow(display); + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + for(int i = 0; i < 4; ++i) { + XGrabKey(display, XKeysymToKeycode(display, toggle_overlay_key), toggle_overlay_modifiers|modifiers[i], root_window, False, GrabModeAsync, GrabModeAsync); + } + + XSync(display, False); + XSetErrorHandler(prev_error_handler); +} + +int main(void) { + Display *display = XOpenDisplay(NULL); + if(!display) { + fprintf(stderr, "Error: XOpenDisplay failed\n"); + return 1; + } + + grab_keys(display); + const KeyCode overlay_keycode = XKeysymToKeycode(display, toggle_overlay_key); + + XSetErrorHandler(ignore_xerror); + /* Killing gpu-screen-recorder with SIGTERM also gives us SIGTERM. We want to ignore that as that has no meaning here */ + signal(SIGTERM, sigterm_handler); + + pid_t overlay_pid = -1; + + fprintf(stderr, "gsr overlay is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n"); + + XEvent xev; + for(;;) { + XNextEvent(display, &xev); + if(xev.type == KeyPress && xev.xkey.keycode == overlay_keycode) { + if(overlay_pid != -1) { + int status; + if(waitpid(overlay_pid, &status, WNOHANG) == 0) { + kill(overlay_pid, SIGINT); + int status; + if(waitpid(overlay_pid, &status, 0) == -1) { + perror("waitpid failed"); + /* Ignore... */ + } + overlay_pid = -1; + continue; + } else { + overlay_pid = -1; + } + } + + if(overlay_pid == -1) { + fprintf(stderr, "launch overlay\n"); + // TODO: window_with_input_focus + const char *args[] = { "gsr-overlay", NULL }; + exec_program(args, &overlay_pid); + } + } + } + return 0; +} diff --git a/gsr-ui-daemon/project.conf b/gsr-ui-daemon/project.conf new file mode 100644 index 0000000..758d50c --- /dev/null +++ b/gsr-ui-daemon/project.conf @@ -0,0 +1,11 @@ +[package] +name = "gpu-screen-recorder-overlay-daemon" +type = "executable" +version = "0.1.0" +platforms = ["posix"] + +[config] +ignore_dirs = ["build"] + +[dependencies] +x11 = ">=1" diff --git a/install.sh b/install.sh index a3b239a..21ba45c 100755 --- a/install.sh +++ b/install.sh @@ -10,4 +10,4 @@ meson setup build meson configure --prefix=/usr --buildtype=release -Dstrip=true build ninja -C build install -echo "Successfully installed gsr-overlay" +echo "Successfully installed gsr-ui" diff --git a/meson.build b/meson.build index 379d96e..c16e567 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('gsr-overlay', ['c', 'cpp'], version : '1.0.0', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends') +project('gsr-ui', ['c', 'cpp'], version : '1.0.0', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends') if get_option('buildtype') == 'debug' add_project_arguments('-g3', language : ['c', 'cpp']) @@ -47,22 +47,22 @@ dep = [ prefix = get_option('prefix') datadir = get_option('datadir') -gsr_overlay_resources_path = join_paths(prefix, datadir, 'gsr-overlay') +gsr_ui_resources_path = join_paths(prefix, datadir, 'gsr-ui') executable( meson.project_name(), src, install : true, dependencies : dep, - cpp_args : '-DGSR_OVERLAY_RESOURCES_PATH="' + gsr_overlay_resources_path + '"', + cpp_args : '-DGSR_UI_RESOURCES_PATH="' + gsr_ui_resources_path + '"', ) executable( - 'gsr-overlay-daemon', - ['gpu-screen-recorder-overlay-daemon/main.c'], + 'gsr-ui-daemon', + ['gsr-ui-daemon/main.c'], install : true, dependencies : [dependency('x11')], ) -install_subdir('images', install_dir : gsr_overlay_resources_path) -install_subdir('fonts', install_dir : gsr_overlay_resources_path) \ No newline at end of file +install_subdir('images', install_dir : gsr_ui_resources_path) +install_subdir('fonts', install_dir : gsr_ui_resources_path) \ No newline at end of file diff --git a/project.conf b/project.conf index 3421e7b..cf3c0e4 100644 --- a/project.conf +++ b/project.conf @@ -1,5 +1,5 @@ [package] -name = "gsr-overlay" +name = "gsr-ui" type = "executable" version = "0.1.0" platforms = ["posix"] @@ -8,7 +8,7 @@ platforms = ["posix"] version = "c++17" [config] -ignore_dirs = ["build", "gpu-screen-recorder-overlay-daemon"] +ignore_dirs = ["build", "gsr-ui-daemon"] [dependencies] xcomposite = ">=0" \ No newline at end of file diff --git a/src/Config.cpp b/src/Config.cpp index 88eead9..b9319aa 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -111,7 +111,7 @@ namespace gsr { std::optional read_config() { std::optional config; - const std::string config_path = get_config_dir() + "/overlay_config"; + const std::string config_path = get_config_dir() + "/config_ui"; std::string file_content; if(!file_get_content(config_path.c_str(), file_content)) { fprintf(stderr, "Warning: Failed to read config file: %s\n", config_path.c_str()); @@ -173,7 +173,7 @@ namespace gsr { void save_config(Config &config) { config.main_config.config_file_version = CONFIG_FILE_VERSION; - const std::string config_path = get_config_dir() + "/overlay_config"; + const std::string config_path = get_config_dir() + "/config_ui"; char dir_tmp[PATH_MAX]; snprintf(dir_tmp, sizeof(dir_tmp), "%s", config_path.c_str()); diff --git a/src/Overlay.cpp b/src/Overlay.cpp index cee40b7..c8b2678 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -553,7 +553,7 @@ namespace gsr { std::optional status_filepath = get_gsr_runtime_dir(); if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-overlay or /tmp/gsr-overlay"); + throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); status_filepath.value() += "/status"; @@ -567,7 +567,7 @@ namespace gsr { 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-overlay or /tmp/gsr-overlay"); + 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))) @@ -579,7 +579,7 @@ namespace gsr { std::optional status_filepath = get_gsr_runtime_dir(); if(!status_filepath) - throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-overlay or /tmp/gsr-overlay"); + throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); status_filepath.value() += "/pid"; @@ -599,12 +599,12 @@ namespace gsr { 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-overlay closed by another program or the user?\n", cmdline_path); + 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-overlay closed by another program or the user?\n", pid, program_arg0); + 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; } @@ -614,7 +614,7 @@ namespace gsr { 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-overlay or /tmp/gsr-overlay"); + throw std::runtime_error("Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); status_filepath.value() += "/pid"; @@ -627,7 +627,7 @@ namespace gsr { 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-overlay or /tmp/gsr-overlay"); + fprintf(stderr, "Error: Failed to find/create runtime directory /run/user/.../gsr-ui or /tmp/gsr-ui"); return; } diff --git a/src/Process.cpp b/src/Process.cpp index f9c896c..07d9dc6 100644 --- a/src/Process.cpp +++ b/src/Process.cpp @@ -11,7 +11,7 @@ namespace gsr { static void debug_print_args(const char **args) { - fprintf(stderr, "gsr-overlay info: running command:"); + fprintf(stderr, "gsr-ui info: running command:"); while(*args) { fprintf(stderr, " %s", *args); ++args; diff --git a/src/Utils.cpp b/src/Utils.cpp index c3da908..0f86ecc 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -208,7 +208,7 @@ namespace gsr { 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-overlay"); + strcat(runtime_dir_path, "/gsr-ui"); if(create_directory_recursive(runtime_dir_path) != 0) return result; diff --git a/src/gui/FileChooser.cpp b/src/gui/FileChooser.cpp index a48a3b0..8ec498f 100644 --- a/src/gui/FileChooser.cpp +++ b/src/gui/FileChooser.cpp @@ -138,7 +138,7 @@ namespace gsr { DIR *d = opendir(directory); if(!d) { - fprintf(stderr, "gsr-overlay error: failed to open directory: %s, error: %s\n", directory, strerror(errno)); + fprintf(stderr, "gsr-ui error: failed to open directory: %s, error: %s\n", directory, strerror(errno)); return; } diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp index 8b06499..fb2cc68 100644 --- a/src/gui/SettingsPage.cpp +++ b/src/gui/SettingsPage.cpp @@ -48,8 +48,9 @@ namespace gsr { std::unique_ptr SettingsPage::create_record_area_box(const GsrInfo &gsr_info) { auto record_area_box = std::make_unique(&get_theme().body_font); // TODO: Show options not supported but disable them - if(gsr_info.supported_capture_options.window) - record_area_box->add_item("Window", "window"); + // TODO: Enable this + //if(gsr_info.supported_capture_options.window) + // record_area_box->add_item("Window", "window"); if(gsr_info.supported_capture_options.focused) record_area_box->add_item("Follow focused window", "focused"); if(gsr_info.supported_capture_options.screen) diff --git a/src/main.cpp b/src/main.cpp index 120280d..3760368 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,10 +72,10 @@ int main(int argc, char **argv) { if(access("images/gpu_screen_recorder_logo.png", F_OK) == 0) { resources_path = "./"; } else { -#ifdef GSR_OVERLAY_RESOURCES_PATH - resources_path = GSR_OVERLAY_RESOURCES_PATH "/"; +#ifdef GSR_UI_RESOURCES_PATH + resources_path = GSR_UI_RESOURCES_PATH "/"; #else - resources_path = "/usr/share/gsr-overlay/"; + resources_path = "/usr/share/gsr-ui/"; #endif } diff --git a/uninstall.sh b/uninstall.sh index e6ebbee..0dc932f 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -7,5 +7,4 @@ cd "$script_dir" ninja -C build uninstall -echo "Successfully uninstalled gsr-overlay" -c \ No newline at end of file +echo "Successfully uninstalled gsr-ui" \ No newline at end of file -- cgit v1.2.3