diff options
Diffstat (limited to 'src/Overlay.cpp')
-rw-r--r-- | src/Overlay.cpp | 299 |
1 files changed, 202 insertions, 97 deletions
diff --git a/src/Overlay.cpp b/src/Overlay.cpp index 3d99e46..fe7c88e 100644 --- a/src/Overlay.cpp +++ b/src/Overlay.cpp @@ -338,6 +338,13 @@ namespace gsr { fprintf(stderr, "pressed %s\n", id.c_str()); overlay->take_screenshot_region(); }); + + global_hotkeys->bind_key_press( + config_hotkey_to_hotkey(ConfigHotkey{ mgl::Keyboard::Key::Escape, HOTKEY_MOD_LCTRL | HOTKEY_MOD_LSHIFT | HOTKEY_MOD_LALT }), + "exit", [overlay](const std::string &id) { + fprintf(stderr, "pressed %s\n", id.c_str()); + overlay->go_back_to_old_ui(); + }); } static std::unique_ptr<GlobalHotkeysLinux> register_linux_hotkeys(Overlay *overlay, GlobalHotkeysLinux::GrabType grab_type) { @@ -678,6 +685,8 @@ namespace gsr { } bool Overlay::draw() { + remove_widgets_to_be_removed(); + update_notification_process_status(); update_gsr_replay_save(); update_gsr_process_status(); @@ -1242,6 +1251,7 @@ namespace gsr { while(!page_stack.empty()) { page_stack.pop(); } + remove_widgets_to_be_removed(); if(default_cursor) { XFreeCursor(display, default_cursor); @@ -1377,7 +1387,38 @@ namespace gsr { return nullptr; } - void Overlay::show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type) { + static bool is_hex_num(char c) { + return (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9'); + } + + static bool contains_non_hex_number(const char *str) { + bool hex_start = false; + size_t len = strlen(str); + if(len >= 2 && memcmp(str, "0x", 2) == 0) { + str += 2; + len -= 2; + hex_start = true; + } + + bool is_hex = false; + for(size_t i = 0; i < len; ++i) { + char c = str[i]; + if(c == '\0') + return false; + if(!is_hex_num(c)) + return true; + if((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) + is_hex = true; + } + + return is_hex && !hex_start; + } + + static bool is_capture_target_monitor(const char *capture_target) { + return strcmp(capture_target, "focused") != 0 && strcmp(capture_target, "region") != 0 && strcmp(capture_target, "portal") != 0 && contains_non_hex_number(capture_target); + } + + void Overlay::show_notification(const char *str, double timeout_seconds, mgl::Color icon_color, mgl::Color bg_color, NotificationType notification_type, const char *capture_target) { char timeout_seconds_str[32]; snprintf(timeout_seconds_str, sizeof(timeout_seconds_str), "%f", timeout_seconds); @@ -1395,15 +1436,20 @@ namespace gsr { notification_args[arg_index++] = notification_type_str; } - std::optional<CursorInfo> cursor_info; - if(cursor_tracker) { - cursor_tracker->update(); - cursor_info = cursor_tracker->get_latest_cursor_info(); - } - - if(cursor_info) { + if(capture_target && is_capture_target_monitor(capture_target)) { notification_args[arg_index++] = "--monitor"; - notification_args[arg_index++] = cursor_info->monitor_name.c_str(); + notification_args[arg_index++] = capture_target; + } else { + std::optional<CursorInfo> cursor_info; + if(cursor_tracker) { + cursor_tracker->update(); + cursor_info = cursor_tracker->get_latest_cursor_info(); + } + + if(cursor_info) { + notification_args[arg_index++] = "--monitor"; + notification_args[arg_index++] = cursor_info->monitor_name.c_str(); + } } notification_args[arg_index++] = nullptr; @@ -1432,6 +1478,19 @@ namespace gsr { do_exit = true; } + void Overlay::go_back_to_old_ui() { + const bool inside_flatpak = getenv("FLATPAK_ID") != NULL; + if(inside_flatpak) + exit_reason = "back-to-old-ui"; + else + exit_reason = "exit"; + + const char *args[] = { "systemctl", "disable", "--user", "gpu-screen-recorder-ui", nullptr }; + std::string stdout_str; + exec_program_on_host_get_stdout(args, stdout_str); + exit(); + } + const Config& Overlay::get_config() const { return config; } @@ -1514,31 +1573,52 @@ namespace gsr { rename(video_filepath, new_video_filepath.c_str()); truncate_string(focused_window_name, 20); - std::string text; + const char *capture_target = nullptr; + char msg[512]; + const std::string filename = focused_window_name + "/" + video_filename; + switch(notification_type) { case NotificationType::RECORD: { if(!config.record_config.show_video_saved_notifications) return; - text = "Saved recording to '" + focused_window_name + "/" + video_filename + "'"; + + 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()); + else + snprintf(msg, sizeof(msg), "Saved a recording of %s to '%s'", recording_capture_target.c_str(), filename.c_str()); + + capture_target = recording_capture_target.c_str(); break; } case NotificationType::REPLAY: { if(!config.replay_config.show_replay_saved_notifications) return; - text = "Saved replay to '" + focused_window_name + "/" + video_filename + "'"; + + if(is_capture_target_monitor(replay_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str()); + else + snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_capture_target.c_str(), filename.c_str()); + + capture_target = replay_capture_target.c_str(); break; } case NotificationType::SCREENSHOT: { if(!config.screenshot_config.show_screenshot_saved_notifications) return; - text = "Saved screenshot to '" + focused_window_name + "/" + video_filename + "'"; + + if(is_capture_target_monitor(screenshot_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Saved a screenshot of this monitor to '%s'", filename.c_str()); + else + snprintf(msg, sizeof(msg), "Saved a screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str()); + + capture_target = screenshot_capture_target.c_str(); break; } case NotificationType::NONE: case NotificationType::STREAM: break; } - show_notification(text.c_str(), notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type); + show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, notification_type, capture_target); } void Overlay::on_replay_saved(const char *replay_saved_filepath) { @@ -1546,8 +1626,13 @@ namespace gsr { if(config.replay_config.save_video_in_game_folder) { save_video_in_current_game_directory(replay_saved_filepath, NotificationType::REPLAY); } else { - const std::string text = "Saved replay to '" + filepath_get_filename(replay_saved_filepath) + "'"; - show_notification(text.c_str(), notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::REPLAY); + const std::string filename = filepath_get_filename(replay_saved_filepath); + char msg[512]; + if(is_capture_target_monitor(replay_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Saved a replay of this monitor to '%s'", filename.c_str()); + else + snprintf(msg, sizeof(msg), "Saved a replay of %s to '%s'", replay_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()); } } @@ -1644,8 +1729,13 @@ namespace gsr { if(config.screenshot_config.save_screenshot_in_game_folder) { save_video_in_current_game_directory(screenshot_filepath.c_str(), NotificationType::SCREENSHOT); } else { - const std::string text = "Saved screenshot to '" + filepath_get_filename(screenshot_filepath.c_str()) + "'"; - show_notification(text.c_str(), notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::SCREENSHOT); + const std::string filename = filepath_get_filename(screenshot_filepath.c_str()); + char msg[512]; + if(is_capture_target_monitor(screenshot_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Saved a screenshot of this monitor to '%s'", filename.c_str()); + else + snprintf(msg, sizeof(msg), "Saved a screenshot of %s to '%s'", screenshot_capture_target.c_str(), filename.c_str()); + show_notification(msg, notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::SCREENSHOT, screenshot_capture_target.c_str()); } } else { fprintf(stderr, "Warning: gpu-screen-recorder (%d) exited with exit status %d\n", (int)gpu_screen_recorder_screenshot_process, exit_code); @@ -1655,28 +1745,25 @@ namespace gsr { gpu_screen_recorder_screenshot_process = -1; } - static bool starts_with(std::string_view str, const char *substr) { - size_t len = strlen(substr); - return str.size() >= len && memcmp(str.data(), substr, len) == 0; - } - - static bool are_all_audio_tracks_available_to_capture(const std::vector<std::string> &audio_tracks) { + static bool are_all_audio_tracks_available_to_capture(const std::vector<AudioTrack> &audio_tracks) { const auto audio_devices = get_audio_devices(); - for(const std::string &audio_track : audio_tracks) { - std::string_view audio_track_name(audio_track.c_str()); - const bool is_app_audio = starts_with(audio_track_name, "app:"); - if(is_app_audio) - continue; + for(const AudioTrack &audio_track : audio_tracks) { + for(const std::string &audio_input : audio_track.audio_inputs) { + std::string_view audio_track_name(audio_input.c_str()); + const bool is_app_audio = starts_with(audio_track_name, "app:"); + if(is_app_audio) + continue; - if(starts_with(audio_track_name, "device:")) - audio_track_name.remove_prefix(7); + if(starts_with(audio_track_name, "device:")) + audio_track_name.remove_prefix(7); - auto it = std::find_if(audio_devices.begin(), audio_devices.end(), [&](const auto &audio_device) { - return audio_device.name == audio_track_name; - }); - if(it == audio_devices.end()) { - //fprintf(stderr, "Audio not ready\n"); - return false; + auto it = std::find_if(audio_devices.begin(), audio_devices.end(), [&](const auto &audio_device) { + return audio_device.name == audio_track_name; + }); + if(it == audio_devices.end()) { + //fprintf(stderr, "Audio not ready\n"); + return false; + } } } return true; @@ -1707,7 +1794,7 @@ namespace gsr { focused_window_is_fullscreen = focused_window != 0 && window_is_fullscreen(display, focused_window); if(focused_window_is_fullscreen != prev_focused_window_is_fullscreen) { if(recording_status == RecordingStatus::NONE && focused_window_is_fullscreen) { - if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks)) + if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list)) on_press_start_replay(false, false); } else if(recording_status == RecordingStatus::REPLAY && !focused_window_is_fullscreen) { on_press_start_replay(true, false); @@ -1724,7 +1811,7 @@ namespace gsr { power_supply_connected = power_supply_online_filepath.empty() || power_supply_is_connected(power_supply_online_filepath.c_str()); if(power_supply_connected != prev_power_supply_status) { if(recording_status == RecordingStatus::NONE && power_supply_connected) { - if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks)) + if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list)) on_press_start_replay(false, false); } else if(recording_status == RecordingStatus::REPLAY && !power_supply_connected) { on_press_start_replay(false, false); @@ -1736,7 +1823,7 @@ namespace gsr { if(replay_startup_mode != ReplayStartupMode::TURN_ON_AT_SYSTEM_STARTUP || recording_status != RecordingStatus::NONE || !try_replay_startup) return; - if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks)) + if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list)) on_press_start_replay(true, false); } @@ -1745,8 +1832,13 @@ namespace gsr { if(config.record_config.save_video_in_game_folder) { save_video_in_current_game_directory(record_filepath.c_str(), NotificationType::RECORD); } else { - const std::string text = "Saved recording to '" + filepath_get_filename(record_filepath.c_str()) + "'"; - show_notification(text.c_str(), notification_timeout_seconds, mgl::Color(255, 255, 255), get_color_theme().tint_color, NotificationType::RECORD); + const std::string filename = filepath_get_filename(record_filepath.c_str()); + char msg[512]; + 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()); + else + snprintf(msg, sizeof(msg), "Saved a recording 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::RECORD, recording_capture_target.c_str()); } } else { fprintf(stderr, "Warning: gpu-screen-recorder (%d) exited with exit status %d\n", (int)gpu_screen_recorder_process, exit_code); @@ -1855,29 +1947,31 @@ namespace gsr { return container; } - static std::vector<std::string> create_audio_tracks_real_names(const std::vector<std::string> &audio_tracks, bool application_audio_invert, const GsrInfo &gsr_info) { + static std::vector<std::string> create_audio_tracks_cli_args(const std::vector<AudioTrack> &audio_tracks, const GsrInfo &gsr_info) { std::vector<std::string> result; - for(const std::string &audio_track : audio_tracks) { - std::string audio_track_name = audio_track; - const bool is_app_audio = starts_with(audio_track_name, "app:"); - if(is_app_audio && !gsr_info.system_info.supports_app_audio) - continue; + result.reserve(audio_tracks.size()); + + for(const AudioTrack &audio_track : audio_tracks) { + std::string audio_track_merged; + for(const std::string &audio_input_name : audio_track.audio_inputs) { + std::string new_audio_input_name = audio_input_name; + const bool is_app_audio = starts_with(new_audio_input_name, "app:"); + if(is_app_audio && !gsr_info.system_info.supports_app_audio) + continue; - if(is_app_audio && application_audio_invert) - audio_track_name.replace(0, 4, "app-inverse:"); + if(is_app_audio && audio_track.application_audio_invert) + new_audio_input_name.replace(0, 4, "app-inverse:"); - result.push_back(std::move(audio_track_name)); - } - return result; - } + if(!audio_track_merged.empty()) + audio_track_merged += "|"; - static std::string merge_audio_tracks(const std::vector<std::string> &audio_tracks) { - std::string result; - for(size_t i = 0; i < audio_tracks.size(); ++i) { - if(i > 0) - result += "|"; - result += audio_tracks[i]; + audio_track_merged += new_audio_input_name; + } + + if(!audio_track_merged.empty()) + result.push_back(std::move(audio_track_merged)); } + return result; } @@ -1892,7 +1986,7 @@ namespace gsr { args.push_back(region_str); } - static void add_common_gpu_screen_recorder_args(std::vector<const char*> &args, const RecordOptions &record_options, const std::vector<std::string> &audio_tracks, const std::string &video_bitrate, const char *region, const std::string &audio_devices_merged, char *region_str, int region_str_size, const RegionSelector ®ion_selector) { + static void add_common_gpu_screen_recorder_args(std::vector<const char*> &args, const RecordOptions &record_options, const std::vector<std::string> &audio_tracks, const std::string &video_bitrate, const char *region, char *region_str, int region_str_size, const RegionSelector ®ion_selector) { if(record_options.video_quality == "custom") { args.push_back("-bm"); args.push_back("cbr"); @@ -1908,16 +2002,9 @@ namespace gsr { args.push_back(region); } - if(record_options.merge_audio_tracks) { - if(!audio_devices_merged.empty()) { - args.push_back("-a"); - args.push_back(audio_devices_merged.c_str()); - } - } else { - for(const std::string &audio_track : audio_tracks) { - args.push_back("-a"); - args.push_back(audio_track.c_str()); - } + for(const std::string &audio_track : audio_tracks) { + args.push_back("-a"); + args.push_back(audio_track.c_str()); } if(record_options.restore_portal_session) { @@ -2021,10 +2108,10 @@ namespace gsr { } const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); - const std::string capture_target = get_capture_target(config.replay_config.record_options.record_area_option, capture_options); - if(!validate_capture_target(capture_target, capture_options)) { + replay_capture_target = get_capture_target(config.replay_config.record_options.record_area_option, capture_options); + if(!validate_capture_target(replay_capture_target, capture_options)) { 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", 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", replay_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); return false; } @@ -2041,8 +2128,7 @@ namespace gsr { const std::string fps = std::to_string(config.replay_config.record_options.fps); const std::string video_bitrate = std::to_string(config.replay_config.record_options.video_bitrate); const std::string output_directory = config.replay_config.save_directory; - const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.replay_config.record_options.audio_tracks, config.replay_config.record_options.application_audio_invert, gsr_info); - const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks); + const std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.replay_config.record_options.audio_tracks_list, gsr_info); const std::string framerate_mode = config.replay_config.record_options.framerate_mode == "auto" ? "vfr" : config.replay_config.record_options.framerate_mode; const std::string replay_time = std::to_string(config.replay_config.replay_time); const char *video_codec = config.replay_config.record_options.video_codec.c_str(); @@ -2061,7 +2147,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); std::vector<const char*> args = { - "gpu-screen-recorder", "-w", capture_target.c_str(), + "gpu-screen-recorder", "-w", replay_capture_target.c_str(), "-c", config.replay_config.container.c_str(), "-ac", config.replay_config.record_options.audio_codec.c_str(), "-cursor", config.replay_config.record_options.record_cursor ? "yes" : "no", @@ -2081,7 +2167,7 @@ namespace gsr { } char region_str[128]; - add_common_gpu_screen_recorder_args(args, config.replay_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, 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); args.push_back(nullptr); @@ -2108,8 +2194,14 @@ 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(!disable_notification && config.replay_config.show_replay_started_notifications) - show_notification("Replay has started", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::REPLAY); + if(!disable_notification && config.replay_config.show_replay_started_notifications) { + char msg[256]; + if(is_capture_target_monitor(replay_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Started replaying this monitor"); + else + snprintf(msg, sizeof(msg), "Started replaying %s", replay_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()); + } return true; } @@ -2156,10 +2248,10 @@ namespace gsr { } const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); - const std::string capture_target = get_capture_target(config.record_config.record_options.record_area_option, capture_options); + recording_capture_target = get_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]; - snprintf(err_msg, sizeof(err_msg), "Failed to start recording, capture target \"%s\" is invalid. Please change capture target in settings", 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); return; } @@ -2178,8 +2270,7 @@ namespace gsr { const std::string fps = std::to_string(config.record_config.record_options.fps); const std::string video_bitrate = std::to_string(config.record_config.record_options.video_bitrate); const std::string output_file = config.record_config.save_directory + "/Video_" + get_date_str() + "." + container_to_file_extension(config.record_config.container.c_str()); - const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.record_config.record_options.audio_tracks, config.record_config.record_options.application_audio_invert, gsr_info); - const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks); + const std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.record_config.record_options.audio_tracks_list, gsr_info); const std::string framerate_mode = config.record_config.record_options.framerate_mode == "auto" ? "vfr" : config.record_config.record_options.framerate_mode; const char *video_codec = config.record_config.record_options.video_codec.c_str(); const char *encoder = "gpu"; @@ -2197,7 +2288,7 @@ namespace gsr { snprintf(size, sizeof(size), "%dx%d", (int)config.record_config.record_options.video_width, (int)config.record_config.record_options.video_height); std::vector<const char*> args = { - "gpu-screen-recorder", "-w", capture_target.c_str(), + "gpu-screen-recorder", "-w", recording_capture_target.c_str(), "-c", config.record_config.container.c_str(), "-ac", config.record_config.record_options.audio_codec.c_str(), "-cursor", config.record_config.record_options.record_cursor ? "yes" : "no", @@ -2211,7 +2302,7 @@ namespace gsr { }; char region_str[128]; - add_common_gpu_screen_recorder_args(args, config.record_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, region_str, sizeof(region_str), region_selector); + add_common_gpu_screen_recorder_args(args, config.record_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector); args.push_back(nullptr); @@ -2230,8 +2321,14 @@ namespace gsr { // Starting recording in 3... // 2... // 1... - if(config.record_config.show_recording_started_notifications) - show_notification("Recording has started", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::RECORD); + if(config.record_config.show_recording_started_notifications) { + char msg[256]; + if(is_capture_target_monitor(recording_capture_target.c_str())) + snprintf(msg, sizeof(msg), "Started recording this monitor"); + else + snprintf(msg, sizeof(msg), "Started recording %s", recording_capture_target.c_str()); + show_notification(msg, notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::RECORD, recording_capture_target.c_str()); + } } static std::string streaming_get_url(const Config &config) { @@ -2325,8 +2422,11 @@ namespace gsr { // TODO: Validate input, fallback to valid values const std::string fps = std::to_string(config.streaming_config.record_options.fps); const std::string video_bitrate = std::to_string(config.streaming_config.record_options.video_bitrate); - const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.streaming_config.record_options.audio_tracks, config.streaming_config.record_options.application_audio_invert, gsr_info); - const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks); + std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.streaming_config.record_options.audio_tracks_list, gsr_info); + // This isn't possible unless the user modified the config file manually, + // But we check it anyways as streaming on some sites can fail if there is more than one audio track + if(audio_tracks.size() > 1) + audio_tracks.resize(1); const std::string framerate_mode = config.streaming_config.record_options.framerate_mode == "auto" ? "vfr" : config.streaming_config.record_options.framerate_mode; const char *video_codec = config.streaming_config.record_options.video_codec.c_str(); const char *encoder = "gpu"; @@ -2362,9 +2462,8 @@ namespace gsr { "-o", url.c_str() }; - config.streaming_config.record_options.merge_audio_tracks = true; char region_str[128]; - add_common_gpu_screen_recorder_args(args, config.streaming_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, 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); args.push_back(nullptr); @@ -2385,8 +2484,14 @@ 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.streaming_config.show_streaming_started_notifications) - show_notification("Streaming has started", notification_timeout_seconds, get_color_theme().tint_color, get_color_theme().tint_color, NotificationType::STREAM); + if(config.streaming_config.show_streaming_started_notifications) { + char msg[256]; + if(is_capture_target_monitor(capture_target.c_str())) + snprintf(msg, sizeof(msg), "Started streaming this monitor"); + else + snprintf(msg, sizeof(msg), "Started streaming %s", 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()); + } } void Overlay::on_press_take_screenshot(bool finished_region_selection, bool force_region_capture) { @@ -2401,10 +2506,10 @@ namespace gsr { const bool region_capture = config.screenshot_config.record_area_option == "region" || force_region_capture; const char *record_area_option = region_capture ? "region" : config.screenshot_config.record_area_option.c_str(); const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info); - const std::string capture_target = get_capture_target(record_area_option, capture_options); + screenshot_capture_target = get_capture_target(record_area_option, capture_options); if(!validate_capture_target(record_area_option, capture_options)) { 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", 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); return; } @@ -2422,7 +2527,7 @@ namespace gsr { const std::string output_file = config.screenshot_config.save_directory + "/Screenshot_" + get_date_str() + "." + config.screenshot_config.image_format; // TODO: Validate image format std::vector<const char*> args = { - "gpu-screen-recorder", "-w", capture_target.c_str(), + "gpu-screen-recorder", "-w", screenshot_capture_target.c_str(), "-cursor", config.screenshot_config.record_cursor ? "yes" : "no", "-v", "no", "-q", config.screenshot_config.image_quality.c_str(), |