From 846241189e2a73dcd11605d3f77d61dce0469e02 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 8 Aug 2024 01:45:35 +0200 Subject: Add -portal-session-token-filepath option to specify where desktop portal session token is saved/restore --- src/capture/portal.c | 54 ++++++++++++++++++++++++++++------------------------ src/egl.c | 3 ++- src/main.cpp | 25 ++++++++++++++++++++---- 3 files changed, 52 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/capture/portal.c b/src/capture/portal.c index a53f0a1..00972e3 100644 --- a/src/capture/portal.c +++ b/src/capture/portal.c @@ -78,19 +78,7 @@ static void gsr_capture_portal_create_input_textures(gsr_capture_portal *self) { self->params.egl->glBindTexture(GL_TEXTURE_2D, 0); } -static void get_gpu_screen_recorder_config_directory_path(char *buffer, size_t buffer_size) { - const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); - if(xdg_config_home) { - snprintf(buffer, buffer_size, "%s/gpu-screen-recorder", xdg_config_home); - } else { - const char *home = getenv("HOME"); - if(!home) - home = "/tmp"; - snprintf(buffer, buffer_size, "%s/.config/gpu-screen-recorder", home); - } -} - -static void get_gpu_screen_recorder_restore_token_path(char *buffer, size_t buffer_size) { +static void get_default_gpu_screen_recorder_restore_token_path(char *buffer, size_t buffer_size) { const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); if(xdg_config_home) { snprintf(buffer, buffer_size, "%s/gpu-screen-recorder/restore_token", xdg_config_home); @@ -102,19 +90,32 @@ static void get_gpu_screen_recorder_restore_token_path(char *buffer, size_t buff } } -static void gsr_capture_portal_save_restore_token(const char *restore_token) { - char config_path[PATH_MAX]; - config_path[0] = '\0'; - get_gpu_screen_recorder_config_directory_path(config_path, sizeof(config_path)); +static bool create_directory_to_file(const char *filepath) { + char dir[PATH_MAX]; + dir[0] = '\0'; - if(create_directory_recursive(config_path) != 0) { - fprintf(stderr, "gsr warning: gsr_capture_portal_save_restore_token: failed to create directory (%s) for restore token\n", config_path); - return; + const char *split = strrchr(filepath, '/'); + if(!split) /* Assuming it's the current directory (for example if filepath is "restore_token"), which doesn't need to be created */ + return true; + + snprintf(dir, sizeof(dir), "%.*s", (int)(split - filepath), filepath); + if(create_directory_recursive(dir) != 0) { + fprintf(stderr, "gsr warning: gsr_capture_portal_save_restore_token: failed to create directory (%s) for restore token\n", dir); + return false; } + return true; +} +static void gsr_capture_portal_save_restore_token(const char *restore_token, const char *portal_session_token_filepath) { char restore_token_path[PATH_MAX]; restore_token_path[0] = '\0'; - get_gpu_screen_recorder_restore_token_path(restore_token_path, sizeof(restore_token_path)); + if(portal_session_token_filepath) + snprintf(restore_token_path, sizeof(restore_token_path), "%s", portal_session_token_filepath); + else + get_default_gpu_screen_recorder_restore_token_path(restore_token_path, sizeof(restore_token_path)); + + if(!create_directory_to_file(restore_token_path)) + return; FILE *f = fopen(restore_token_path, "wb"); if(!f) { @@ -133,13 +134,16 @@ static void gsr_capture_portal_save_restore_token(const char *restore_token) { fclose(f); } -static void gsr_capture_portal_get_restore_token_from_cache(char *buffer, size_t buffer_size) { +static void gsr_capture_portal_get_restore_token_from_cache(char *buffer, size_t buffer_size, const char *portal_session_token_filepath) { assert(buffer_size > 0); buffer[0] = '\0'; char restore_token_path[PATH_MAX]; restore_token_path[0] = '\0'; - get_gpu_screen_recorder_restore_token_path(restore_token_path, sizeof(restore_token_path)); + if(portal_session_token_filepath) + snprintf(restore_token_path, sizeof(restore_token_path), "%s", portal_session_token_filepath); + else + get_default_gpu_screen_recorder_restore_token_path(restore_token_path, sizeof(restore_token_path)); FILE *f = fopen(restore_token_path, "rb"); if(!f) { @@ -173,7 +177,7 @@ static int gsr_capture_portal_setup_dbus(gsr_capture_portal *self, int *pipewire char restore_token[1024]; restore_token[0] = '\0'; if(self->params.restore_portal_session) - gsr_capture_portal_get_restore_token_from_cache(restore_token, sizeof(restore_token)); + gsr_capture_portal_get_restore_token_from_cache(restore_token, sizeof(restore_token), self->params.portal_session_token_filepath); if(!gsr_dbus_init(&self->dbus, restore_token)) return -1; @@ -201,7 +205,7 @@ static int gsr_capture_portal_setup_dbus(gsr_capture_portal *self, int *pipewire const char *screencast_restore_token = gsr_dbus_screencast_get_restore_token(&self->dbus); if(screencast_restore_token) - gsr_capture_portal_save_restore_token(screencast_restore_token); + gsr_capture_portal_save_restore_token(screencast_restore_token, self->params.portal_session_token_filepath); fprintf(stderr, "gsr info: gsr_capture_portal_setup_dbus: OpenPipeWireRemote\n"); if(!gsr_dbus_screencast_open_pipewire_remote(&self->dbus, self->session_handle, pipewire_fd)) { diff --git a/src/egl.c b/src/egl.c index da8dc9f..87bb8fb 100644 --- a/src/egl.c +++ b/src/egl.c @@ -12,7 +12,7 @@ #include #include -// TODO: rename gsr_egl to something else since this includes both egl and eglx and in the future maybe vulkan too +// TODO: rename gsr_egl to something else since this includes both egl and glx and in the future maybe vulkan too // TODO: Move this shit to a separate wayland file, and have a separate file for x11. @@ -251,6 +251,7 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) { } if(wayland) { + // TODO: Error check? self->wayland.surface = wl_compositor_create_surface(self->wayland.compositor); self->wayland.window = wl_egl_window_create(self->wayland.surface, 16, 16); self->egl_surface = self->eglCreateWindowSurface(self->egl_display, ecfg, (EGLNativeWindowType)self->wayland.window, NULL); diff --git a/src/main.cpp b/src/main.cpp index 1067ccd..b4bb46b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -379,7 +379,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, } //codec_context->chroma_sample_location = AVCHROMA_LOC_CENTER; if(codec->id == AV_CODEC_ID_HEVC) - codec_context->codec_tag = MKTAG('h', 'v', 'c', '1'); + codec_context->codec_tag = MKTAG('h', 'v', 'c', '1'); // QuickTime on MacOS requires this or the video wont be playable switch(video_quality) { case VideoQuality::MEDIUM: //codec_context->qmin = 35; @@ -1004,7 +1004,7 @@ static void open_video_hardware(AVCodecContext *codec_context, VideoQuality vide static void usage_header() { const bool inside_flatpak = getenv("FLATPAK_ID") != NULL; const char *program_name = inside_flatpak ? "flatpak run --command=gpu-screen-recorder com.dec05eba.gpu_screen_recorder" : "gpu-screen-recorder"; - fprintf(stderr, "usage: %s -w [-c ] [-s WxH] -f [-a ] [-q ] [-r ] [-k h264|hevc|hevc_hdr|av1|av1_hdr|vp8|vp9] [-ac aac|opus|flac] [-ab ] [-oc yes|no] [-fm cfr|vfr|content] [-cr limited|full] [-df yes|no] [-sc ] [-cursor yes|no] [-keyint ] [-restore-portal-session yes|no] [-encoder gpu|cpu] [-o ] [-v yes|no] [-h|--help]\n", program_name); + fprintf(stderr, "usage: %s -w [-c ] [-s WxH] -f [-a ] [-q ] [-r ] [-k h264|hevc|hevc_hdr|av1|av1_hdr|vp8|vp9] [-ac aac|opus|flac] [-ab ] [-oc yes|no] [-fm cfr|vfr|content] [-cr limited|full] [-df yes|no] [-sc ] [-cursor yes|no] [-keyint ] [-restore-portal-session yes|no] [-portal-session-token-filepath filepath] [-encoder gpu|cpu] [-o ] [-v yes|no] [-h|--help]\n", program_name); } // TODO: Update with portal info @@ -1088,6 +1088,12 @@ static void usage_full() { fprintf(stderr, " If GPU Screen Recorder should use the same capture option as the last time. Using this option removes the popup asking what you want to record the next time you record with '-w portal' if you selected the option to save session (token) in the desktop portal screencast popup.\n"); fprintf(stderr, " This option may not have any effect on your Wayland compositor and your systems desktop portal needs to support ScreenCast version 5 or later. Optional, set to 'no' by default.\n"); fprintf(stderr, "\n"); + fprintf(stderr, " -portal-session-token-filepath\n"); + fprintf(stderr, " This option is used together with -restore-portal-session option to specify the file path to save/restore the portal session token to/from.\n"); + fprintf(stderr, " This can be used to remember different portal capture options depending on different recording option (such as recording/replay).\n"); + fprintf(stderr, " Optional, set to \"$XDG_CONFIG_HOME/gpu-screen-recorder/restore_token\" by default ($XDG_CONFIG_HOME defaults to \"$HOME/.config\").\n"); + fprintf(stderr, " Note: the directory to the portal session token file is created automatically if it doesn't exist.\n"); + fprintf(stderr, "\n"); fprintf(stderr, " -encoder\n"); fprintf(stderr, " Which device should be used for video encoding. Should either be 'gpu' or 'cpu'. Does currently only work with h264 codec option (-k).\n"); fprintf(stderr, " Optional, set to 'gpu' by default.\n"); @@ -1819,7 +1825,7 @@ static void list_audio_devices_command() { _exit(0); } -static gsr_capture* create_capture_impl(const char *window_str, const char *screen_region, bool wayland, gsr_egl *egl, int fps, bool overclock, VideoCodec video_codec, gsr_color_range color_range, bool record_cursor, bool track_damage, bool use_software_video_encoder, bool restore_portal_session) { +static gsr_capture* create_capture_impl(const char *window_str, const char *screen_region, bool wayland, gsr_egl *egl, int fps, bool overclock, VideoCodec video_codec, gsr_color_range color_range, bool record_cursor, bool track_damage, bool use_software_video_encoder, bool restore_portal_session, const char *portal_session_token_filepath) { vec2i region_size = { 0, 0 }; Window src_window_id = None; bool follow_focused = false; @@ -1865,6 +1871,7 @@ static gsr_capture* create_capture_impl(const char *window_str, const char *scre portal_params.color_range = color_range; portal_params.record_cursor = record_cursor; portal_params.restore_portal_session = restore_portal_session; + portal_params.portal_session_token_filepath = portal_session_token_filepath; capture = gsr_capture_portal_create(&portal_params); if(!capture) _exit(1); @@ -2154,6 +2161,7 @@ int main(int argc, char **argv) { { "-cursor", Arg { {}, true, false } }, { "-keyint", Arg { {}, true, false } }, { "-restore-portal-session", Arg { {}, true, false } }, + { "-portal-session-token-filepath", Arg { {}, true, false } }, { "-encoder", Arg { {}, true, false } }, }; @@ -2341,6 +2349,15 @@ int main(int argc, char **argv) { usage(); } + const char *portal_session_token_filepath = args["-portal-session-token-filepath"].value(); + if(portal_session_token_filepath) { + int len = strlen(portal_session_token_filepath); + if(len > 0 && portal_session_token_filepath[len - 1] == '/') { + fprintf(stderr, "Error: -portal-session-token-filepath should be a path to a file but it ends with a /: %s\n", portal_session_token_filepath); + _exit(1); + } + } + const char *recording_saved_script = args["-sc"].value(); if(recording_saved_script) { struct stat buf; @@ -2795,7 +2812,7 @@ int main(int argc, char **argv) { _exit(2); } - gsr_capture *capture = create_capture_impl(window_str, screen_region, wayland, &egl, fps, overclock, video_codec, color_range, record_cursor, framerate_mode == FramerateMode::CONTENT, use_software_video_encoder, restore_portal_session); + gsr_capture *capture = create_capture_impl(window_str, screen_region, wayland, &egl, fps, overclock, video_codec, color_range, record_cursor, framerate_mode == FramerateMode::CONTENT, use_software_video_encoder, restore_portal_session, portal_session_token_filepath); // (Some?) livestreaming services require at least one audio track to work. // If not audio is provided then create one silent audio track. -- cgit v1.2.3