Query capture options when opening settings and validate capture options when starting recording

This commit is contained in:
dec05eba
2024-12-08 14:32:11 +01:00
parent 6b66eebb68
commit f3565fdd77
12 changed files with 243 additions and 153 deletions

View File

@@ -27,6 +27,8 @@ These are the dependencies needed to build GPU Screen Recorder UI:
* libxkbcommon * libxkbcommon
## Runtime dependencies ## Runtime dependencies
There are also additional dependencies needed at runtime:
* [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/) * [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/)
* [GPU Screen Recorder Notification](https://git.dec05eba.com/gpu-screen-recorder-notification/) * [GPU Screen Recorder Notification](https://git.dec05eba.com/gpu-screen-recorder-notification/)

4
TODO
View File

@@ -66,7 +66,7 @@ Make save-video-in-game-folder.sh and notify-saved-name.sh run ~/.config/gpu-scr
if the profile is called 4chan. if the profile is called 4chan.
Create a directory of such example scripts, including 4chan webm one. Create a directory of such example scripts, including 4chan webm one.
On nvidia check if suspend fix is applied. If not, show a popup asking the user to apply it (and apply it automatically). On nvidia check if suspend fix is applied. If not, show a popup asking the user to apply it (and apply it automatically). This is a requirement before this package is made to a flatpak.
Show warning when using steam deck or when trying to capture hevc/av1 on amd (the same warnings as gpu screen recorder gtk). Show warning when using steam deck or when trying to capture hevc/av1 on amd (the same warnings as gpu screen recorder gtk).
@@ -103,4 +103,4 @@ Dont allow autostart of replay if capture option is window recording (when windo
Use global shortcuts desktop portal protocol on wayland when available. Use global shortcuts desktop portal protocol on wayland when available.
Use `gpu-screen-recorder --list-capture-options` instead of gsr_info.supported_capture_options.monitors and update it everytime when opening setting page and when starting recording. When support for window capture is enabled on x11 then make sure to not save the window except temporary while the program is open.

View File

@@ -7,7 +7,7 @@
#include <optional> #include <optional>
namespace gsr { namespace gsr {
struct GsrInfo; struct SupportedCaptureOptions;
struct ConfigHotkey { struct ConfigHotkey {
int64_t keysym = 0; int64_t keysym = 0;
@@ -92,7 +92,7 @@ namespace gsr {
}; };
struct Config { struct Config {
Config(const GsrInfo &gsr_info); Config(const SupportedCaptureOptions &capture_options);
MainConfig main_config; MainConfig main_config;
StreamingConfig streaming_config; StreamingConfig streaming_config;
@@ -100,6 +100,6 @@ namespace gsr {
ReplayConfig replay_config; ReplayConfig replay_config;
}; };
std::optional<Config> read_config(const GsrInfo &gsr_info); std::optional<Config> read_config(const SupportedCaptureOptions &capture_options);
void save_config(Config &config); void save_config(Config &config);
} }

View File

@@ -52,13 +52,13 @@ namespace gsr {
struct GpuInfo { struct GpuInfo {
GpuVendor vendor = GpuVendor::UNKNOWN; GpuVendor vendor = GpuVendor::UNKNOWN;
std::string card_path;
}; };
struct GsrInfo { struct GsrInfo {
SystemInfo system_info; SystemInfo system_info;
GpuInfo gpu_info; GpuInfo gpu_info;
SupportedVideoCodecs supported_video_codecs; SupportedVideoCodecs supported_video_codecs;
SupportedCaptureOptions supported_capture_options;
}; };
enum class GsrInfoExitStatus { enum class GsrInfoExitStatus {
@@ -78,4 +78,5 @@ namespace gsr {
std::vector<AudioDevice> get_audio_devices(); std::vector<AudioDevice> get_audio_devices();
std::vector<std::string> get_application_audio(); std::vector<std::string> get_application_audio();
SupportedCaptureOptions get_supported_capture_options(const GsrInfo &gsr_info);
} }

View File

@@ -36,7 +36,7 @@ namespace gsr {
class Overlay { class Overlay {
public: public:
Overlay(std::string resources_path, GsrInfo gsr_info, egl_functions egl_funcs); Overlay(std::string resources_path, GsrInfo gsr_info, SupportedCaptureOptions capture_options, egl_functions egl_funcs);
Overlay(const Overlay&) = delete; Overlay(const Overlay&) = delete;
Overlay& operator=(const Overlay&) = delete; Overlay& operator=(const Overlay&) = delete;
~Overlay(); ~Overlay();

View File

@@ -25,17 +25,17 @@ namespace gsr {
STREAM STREAM
}; };
SettingsPage(Type type, const GsrInfo &gsr_info, Config &config, PageStack *page_stack); SettingsPage(Type type, const GsrInfo *gsr_info, Config &config, PageStack *page_stack);
SettingsPage(const SettingsPage&) = delete; SettingsPage(const SettingsPage&) = delete;
SettingsPage& operator=(const SettingsPage&) = delete; SettingsPage& operator=(const SettingsPage&) = delete;
void load(const GsrInfo &gsr_info); void load();
void save(); void save();
void on_navigate_away_from_page() override; void on_navigate_away_from_page() override;
private: private:
std::unique_ptr<RadioButton> create_view_radio_button(); std::unique_ptr<RadioButton> create_view_radio_button();
std::unique_ptr<ComboBox> create_record_area_box(const GsrInfo &gsr_info); std::unique_ptr<ComboBox> create_record_area_box();
std::unique_ptr<Widget> create_record_area(const GsrInfo &gsr_info); std::unique_ptr<Widget> create_record_area();
std::unique_ptr<List> create_select_window(); std::unique_ptr<List> create_select_window();
std::unique_ptr<Entry> create_area_width_entry(); std::unique_ptr<Entry> create_area_width_entry();
std::unique_ptr<Entry> create_area_height_entry(); std::unique_ptr<Entry> create_area_height_entry();
@@ -48,7 +48,7 @@ namespace gsr {
std::unique_ptr<CheckBox> create_restore_portal_session_checkbox(); std::unique_ptr<CheckBox> create_restore_portal_session_checkbox();
std::unique_ptr<List> create_restore_portal_session_section(); std::unique_ptr<List> create_restore_portal_session_section();
std::unique_ptr<Widget> create_change_video_resolution_section(); std::unique_ptr<Widget> create_change_video_resolution_section();
std::unique_ptr<Widget> create_capture_target(const GsrInfo &gsr_info); std::unique_ptr<Widget> create_capture_target();
std::unique_ptr<ComboBox> create_audio_device_selection_combobox(); std::unique_ptr<ComboBox> create_audio_device_selection_combobox();
std::unique_ptr<Button> create_remove_audio_device_button(List *audio_device_list_ptr); std::unique_ptr<Button> create_remove_audio_device_button(List *audio_device_list_ptr);
std::unique_ptr<List> create_audio_device(); std::unique_ptr<List> create_audio_device();
@@ -70,8 +70,8 @@ namespace gsr {
std::unique_ptr<ComboBox> create_color_range_box(); std::unique_ptr<ComboBox> create_color_range_box();
std::unique_ptr<List> create_color_range(); std::unique_ptr<List> create_color_range();
std::unique_ptr<List> create_video_quality_section(); std::unique_ptr<List> create_video_quality_section();
std::unique_ptr<ComboBox> create_video_codec_box(const GsrInfo &gsr_info); std::unique_ptr<ComboBox> create_video_codec_box();
std::unique_ptr<List> create_video_codec(const GsrInfo &gsr_info); std::unique_ptr<List> create_video_codec();
std::unique_ptr<ComboBox> create_audio_codec_box(); std::unique_ptr<ComboBox> create_audio_codec_box();
std::unique_ptr<List> create_audio_codec(); std::unique_ptr<List> create_audio_codec();
std::unique_ptr<Entry> create_framerate_entry(); std::unique_ptr<Entry> create_framerate_entry();
@@ -80,24 +80,24 @@ namespace gsr {
std::unique_ptr<List> create_framerate_mode(); std::unique_ptr<List> create_framerate_mode();
std::unique_ptr<List> create_framerate_section(); std::unique_ptr<List> create_framerate_section();
std::unique_ptr<Widget> create_record_cursor_section(); std::unique_ptr<Widget> create_record_cursor_section();
std::unique_ptr<Widget> create_video_section(const GsrInfo &gsr_info); std::unique_ptr<Widget> create_video_section();
std::unique_ptr<Widget> create_settings(const GsrInfo &gsr_info); std::unique_ptr<Widget> create_settings();
void add_widgets(const GsrInfo &gsr_info); void add_widgets();
void add_page_specific_widgets(const GsrInfo &gsr_info); void add_page_specific_widgets();
std::unique_ptr<List> create_save_directory(const char *label); std::unique_ptr<List> create_save_directory(const char *label);
std::unique_ptr<ComboBox> create_container_box(); std::unique_ptr<ComboBox> create_container_box();
std::unique_ptr<List> create_container_section(); std::unique_ptr<List> create_container_section();
std::unique_ptr<Entry> create_replay_time_entry(); std::unique_ptr<Entry> create_replay_time_entry();
std::unique_ptr<List> create_replay_time(); std::unique_ptr<List> create_replay_time();
std::unique_ptr<RadioButton> create_start_replay_automatically(const GsrInfo &gsr_info); std::unique_ptr<RadioButton> create_start_replay_automatically();
std::unique_ptr<CheckBox> create_save_replay_in_game_folder(const GsrInfo &gsr_info); std::unique_ptr<CheckBox> create_save_replay_in_game_folder();
std::unique_ptr<Label> create_estimated_file_size(); std::unique_ptr<Label> create_estimated_file_size();
void update_estimated_file_size(); void update_estimated_file_size();
std::unique_ptr<CheckBox> create_save_recording_in_game_folder(const GsrInfo &gsr_info); std::unique_ptr<CheckBox> create_save_recording_in_game_folder();
void add_replay_widgets(const GsrInfo &gsr_info); void add_replay_widgets();
void add_record_widgets(const GsrInfo &gsr_info); void add_record_widgets();
std::unique_ptr<ComboBox> create_streaming_service_box(); std::unique_ptr<ComboBox> create_streaming_service_box();
std::unique_ptr<List> create_streaming_service_section(); std::unique_ptr<List> create_streaming_service_section();
@@ -105,13 +105,13 @@ namespace gsr {
std::unique_ptr<List> create_stream_url_section(); std::unique_ptr<List> create_stream_url_section();
std::unique_ptr<ComboBox> create_stream_container_box(); std::unique_ptr<ComboBox> create_stream_container_box();
std::unique_ptr<List> create_stream_container_section(); std::unique_ptr<List> create_stream_container_section();
void add_stream_widgets(const GsrInfo &gsr_info); void add_stream_widgets();
void load_audio_tracks(const RecordOptions &record_options, const GsrInfo &gsr_info); void load_audio_tracks(const RecordOptions &record_options);
void load_common(RecordOptions &record_options, const GsrInfo &gsr_info); void load_common(RecordOptions &record_options);
void load_replay(const GsrInfo &gsr_info); void load_replay();
void load_record(const GsrInfo &gsr_info); void load_record();
void load_stream(const GsrInfo &gsr_info); void load_stream();
void save_common(RecordOptions &record_options); void save_common(RecordOptions &record_options);
void save_replay(); void save_replay();
@@ -120,8 +120,10 @@ namespace gsr {
private: private:
Type type; Type type;
Config &config; Config &config;
const GsrInfo *gsr_info = nullptr;
std::vector<AudioDevice> audio_devices; std::vector<AudioDevice> audio_devices;
std::vector<std::string> application_audio; std::vector<std::string> application_audio;
SupportedCaptureOptions capture_options;
GsrPage *content_page_ptr = nullptr; GsrPage *content_page_ptr = nullptr;
ScrollablePage *settings_scrollable_page_ptr = nullptr; ScrollablePage *settings_scrollable_page_ptr = nullptr;

View File

@@ -13,7 +13,7 @@
#define CONFIG_FILE_VERSION 1 #define CONFIG_FILE_VERSION 1
namespace gsr { namespace gsr {
Config::Config(const GsrInfo &gsr_info) { Config::Config(const SupportedCaptureOptions &capture_options) {
const std::string default_save_directory = get_videos_dir(); const std::string default_save_directory = get_videos_dir();
streaming_config.record_options.video_quality = "custom"; streaming_config.record_options.video_quality = "custom";
@@ -29,10 +29,10 @@ namespace gsr {
replay_config.record_options.audio_tracks.push_back("default_output"); replay_config.record_options.audio_tracks.push_back("default_output");
replay_config.record_options.video_bitrate = 45000; replay_config.record_options.video_bitrate = 45000;
if(!gsr_info.supported_capture_options.monitors.empty()) { if(!capture_options.monitors.empty()) {
streaming_config.record_options.record_area_option = gsr_info.supported_capture_options.monitors.front().name; streaming_config.record_options.record_area_option = capture_options.monitors.front().name;
record_config.record_options.record_area_option = gsr_info.supported_capture_options.monitors.front().name; record_config.record_options.record_area_option = capture_options.monitors.front().name;
replay_config.record_options.record_area_option = gsr_info.supported_capture_options.monitors.front().name; replay_config.record_options.record_area_option = capture_options.monitors.front().name;
} }
} }
@@ -140,7 +140,7 @@ namespace gsr {
}; };
} }
std::optional<Config> read_config(const GsrInfo &gsr_info) { std::optional<Config> read_config(const SupportedCaptureOptions &capture_options) {
std::optional<Config> config; std::optional<Config> config;
const std::string config_path = get_config_dir() + "/config_ui"; const std::string config_path = get_config_dir() + "/config_ui";
@@ -150,7 +150,7 @@ namespace gsr {
return config; return config;
} }
config = Config(gsr_info); config = Config(capture_options);
config->streaming_config.record_options.audio_tracks.clear(); config->streaming_config.record_options.audio_tracks.clear();
config->record_config.record_options.audio_tracks.clear(); config->record_config.record_options.audio_tracks.clear();
config->replay_config.record_options.audio_tracks.clear(); config->replay_config.record_options.audio_tracks.clear();

View File

@@ -38,6 +38,8 @@ namespace gsr {
gsr_info->gpu_info.vendor = GpuVendor::INTEL; gsr_info->gpu_info.vendor = GpuVendor::INTEL;
else if(key_value->value == "nvidia") else if(key_value->value == "nvidia")
gsr_info->gpu_info.vendor = GpuVendor::NVIDIA; gsr_info->gpu_info.vendor = GpuVendor::NVIDIA;
} else if(key_value->key == "card_path") {
gsr_info->gpu_info.card_path = key_value->value;
} }
} }
@@ -64,38 +66,6 @@ namespace gsr {
gsr_info->supported_video_codecs.vp9 = true; gsr_info->supported_video_codecs.vp9 = true;
} }
static std::optional<GsrMonitor> capture_option_line_to_monitor(std::string_view line) {
std::optional<GsrMonitor> monitor;
const std::optional<KeyValue> key_value = parse_key_value(line);
if(!key_value)
return monitor;
char value_buffer[256];
snprintf(value_buffer, sizeof(value_buffer), "%.*s", (int)key_value->value.size(), key_value->value.data());
monitor = GsrMonitor{std::string(key_value->key), mgl::vec2i{0, 0}};
if(sscanf(value_buffer, "%dx%d", &monitor->size.x, &monitor->size.y) != 2)
monitor->size = {0, 0};
return monitor;
}
static void parse_capture_options_line(GsrInfo *gsr_info, std::string_view line) {
if(line == "window")
gsr_info->supported_capture_options.window = true;
else if(line == "focused")
gsr_info->supported_capture_options.focused = true;
else if(line == "screen")
gsr_info->supported_capture_options.screen = true;
else if(line == "portal")
gsr_info->supported_capture_options.portal = true;
else {
std::optional<GsrMonitor> monitor = capture_option_line_to_monitor(line);
if(monitor)
gsr_info->supported_capture_options.monitors.push_back(std::move(monitor.value()));
}
}
enum class GsrInfoSection { enum class GsrInfoSection {
UNKNOWN, UNKNOWN,
SYSTEM_INFO, SYSTEM_INFO,
@@ -161,7 +131,7 @@ namespace gsr {
break; break;
} }
case GsrInfoSection::CAPTURE_OPTIONS: { case GsrInfoSection::CAPTURE_OPTIONS: {
parse_capture_options_line(gsr_info, line); // Intentionally ignore, get capture options with get_supported_capture_options instead
break; break;
} }
} }
@@ -230,7 +200,7 @@ namespace gsr {
return application_audio; return application_audio;
} }
char output[16384]; char output[8192];
ssize_t bytes_read = fread(output, 1, sizeof(output) - 1, f); ssize_t bytes_read = fread(output, 1, sizeof(output) - 1, f);
if(bytes_read < 0 || ferror(f)) { if(bytes_read < 0 || ferror(f)) {
fprintf(stderr, "error: failed to read 'gpu-screen-recorder --list-application-audio' output\n"); fprintf(stderr, "error: failed to read 'gpu-screen-recorder --list-application-audio' output\n");
@@ -246,4 +216,75 @@ namespace gsr {
return application_audio; return application_audio;
} }
static std::optional<GsrMonitor> capture_option_line_to_monitor(std::string_view line) {
std::optional<GsrMonitor> monitor;
const std::optional<KeyValue> key_value = parse_key_value(line);
if(!key_value)
return monitor;
char value_buffer[256];
snprintf(value_buffer, sizeof(value_buffer), "%.*s", (int)key_value->value.size(), key_value->value.data());
monitor = GsrMonitor{std::string(key_value->key), mgl::vec2i{0, 0}};
if(sscanf(value_buffer, "%dx%d", &monitor->size.x, &monitor->size.y) != 2)
monitor->size = {0, 0};
return monitor;
}
static void parse_capture_options_line(SupportedCaptureOptions &capture_options, std::string_view line) {
if(line == "window")
capture_options.window = true;
else if(line == "focused")
capture_options.focused = true;
else if(line == "screen")
capture_options.screen = true;
else if(line == "portal")
capture_options.portal = true;
else {
std::optional<GsrMonitor> monitor = capture_option_line_to_monitor(line);
if(monitor)
capture_options.monitors.push_back(std::move(monitor.value()));
}
}
static const char* gpu_vendor_to_string(GpuVendor vendor) {
switch(vendor) {
case GpuVendor::UNKNOWN: return "unknown";
case GpuVendor::AMD: return "amd";
case GpuVendor::INTEL: return "intel";
case GpuVendor::NVIDIA: return "nvidia";
}
return "unknown";
}
SupportedCaptureOptions get_supported_capture_options(const GsrInfo &gsr_info) {
SupportedCaptureOptions capture_options;
char command[512];
snprintf(command, sizeof(command), "gpu-screen-recorder --list-capture-options %s %s", gsr_info.gpu_info.card_path.c_str(), gpu_vendor_to_string(gsr_info.gpu_info.vendor));
FILE *f = popen(command, "r");
if(!f) {
fprintf(stderr, "error: 'gpu-screen-recorder --list-capture-options' failed\n");
return capture_options;
}
char output[8192];
ssize_t bytes_read = fread(output, 1, sizeof(output) - 1, f);
if(bytes_read < 0 || ferror(f)) {
fprintf(stderr, "error: failed to read 'gpu-screen-recorder --list-capture-options' output\n");
pclose(f);
return capture_options;
}
output[bytes_read] = '\0';
string_split_char({output, (size_t)bytes_read}, '\n', [&](std::string_view line) {
parse_capture_options_line(capture_options, line);
return true;
});
return capture_options;
}
} }

View File

@@ -393,11 +393,11 @@ namespace gsr {
return true; return true;
} }
Overlay::Overlay(std::string resources_path, GsrInfo gsr_info, egl_functions egl_funcs) : Overlay::Overlay(std::string resources_path, GsrInfo gsr_info, SupportedCaptureOptions capture_options, egl_functions egl_funcs) :
resources_path(std::move(resources_path)), resources_path(std::move(resources_path)),
gsr_info(gsr_info), gsr_info(std::move(gsr_info)),
egl_funcs(egl_funcs), egl_funcs(egl_funcs),
config(gsr_info), config(capture_options),
bg_screenshot_overlay({0.0f, 0.0f}), bg_screenshot_overlay({0.0f, 0.0f}),
top_bar_background({0.0f, 0.0f}), top_bar_background({0.0f, 0.0f}),
close_button_widget({0.0f, 0.0f}) close_button_widget({0.0f, 0.0f})
@@ -416,11 +416,11 @@ namespace gsr {
memset(&window_texture, 0, sizeof(window_texture)); memset(&window_texture, 0, sizeof(window_texture));
std::optional<Config> new_config = read_config(gsr_info); std::optional<Config> new_config = read_config(capture_options);
if(new_config) if(new_config)
config = std::move(new_config.value()); config = std::move(new_config.value());
init_color_theme(gsr_info); init_color_theme(this->gsr_info);
power_supply_online_filepath = get_power_supply_online_filepath(); power_supply_online_filepath = get_power_supply_online_filepath();
@@ -875,7 +875,7 @@ namespace gsr {
button->set_item_icon("save", &get_theme().save_texture); button->set_item_icon("save", &get_theme().save_texture);
button->on_click = [this](const std::string &id) { button->on_click = [this](const std::string &id) {
if(id == "settings") { if(id == "settings") {
auto replay_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::REPLAY, gsr_info, config, &page_stack); auto replay_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::REPLAY, &gsr_info, config, &page_stack);
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();
@@ -896,7 +896,7 @@ namespace gsr {
button->set_item_icon("pause", &get_theme().pause_texture); button->set_item_icon("pause", &get_theme().pause_texture);
button->on_click = [this](const std::string &id) { button->on_click = [this](const std::string &id) {
if(id == "settings") { if(id == "settings") {
auto record_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::RECORD, gsr_info, config, &page_stack); auto record_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::RECORD, &gsr_info, config, &page_stack);
page_stack.push(std::move(record_settings_page)); page_stack.push(std::move(record_settings_page));
} else if(id == "pause") { } else if(id == "pause") {
toggle_pause(); toggle_pause();
@@ -915,7 +915,7 @@ namespace gsr {
button->set_item_icon("start", &get_theme().play_texture); button->set_item_icon("start", &get_theme().play_texture);
button->on_click = [this](const std::string &id) { button->on_click = [this](const std::string &id) {
if(id == "settings") { if(id == "settings") {
auto stream_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::STREAM, gsr_info, config, &page_stack); auto stream_settings_page = std::make_unique<SettingsPage>(SettingsPage::Type::STREAM, &gsr_info, config, &page_stack);
page_stack.push(std::move(stream_settings_page)); page_stack.push(std::move(stream_settings_page));
} else if(id == "start") { } else if(id == "start") {
on_press_start_stream(); on_press_start_stream();
@@ -1525,6 +1525,24 @@ namespace gsr {
} }
} }
static bool validate_capture_target(const GsrInfo &gsr_info, const std::string &capture_target) {
const SupportedCaptureOptions capture_options = get_supported_capture_options(gsr_info);
// TODO: Also check x11 window when enabled (check if capture_target is a decminal/hex number)
if(capture_target == "focused" && !capture_options.focused) {
return false;
} else if(capture_target == "screen" && !capture_options.screen) {
return false;
} else if(capture_target == "portal" && !capture_options.portal) {
return false;
} else {
for(const GsrMonitor &monitor : capture_options.monitors) {
if(capture_target == monitor.name)
return true;
}
return false;
}
}
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;
@@ -1570,6 +1588,13 @@ namespace gsr {
return; return;
} }
if(!validate_capture_target(gsr_info, config.replay_config.record_options.record_area_option)) {
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", config.replay_config.record_options.record_area_option.c_str());
show_notification(err_msg, 3.0, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::REPLAY);
return;
}
// TODO: Validate input, fallback to valid values // TODO: Validate input, fallback to valid values
const std::string fps = std::to_string(config.replay_config.record_options.fps); 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 video_bitrate = std::to_string(config.replay_config.record_options.video_bitrate);
@@ -1677,6 +1702,13 @@ namespace gsr {
return; return;
} }
if(!validate_capture_target(gsr_info, config.record_config.record_options.record_area_option)) {
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", config.record_config.record_options.record_area_option.c_str());
show_notification(err_msg, 3.0, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::RECORD);
return;
}
record_filepath.clear(); record_filepath.clear();
// TODO: Validate input, fallback to valid values // TODO: Validate input, fallback to valid values
@@ -1806,6 +1838,13 @@ namespace gsr {
return; return;
} }
if(!validate_capture_target(gsr_info, config.streaming_config.record_options.record_area_option)) {
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", config.streaming_config.record_options.record_area_option.c_str());
show_notification(err_msg, 3.0, mgl::Color(255, 0, 0, 0), mgl::Color(255, 0, 0, 0), NotificationType::STREAM);
return;
}
// TODO: Validate input, fallback to valid values // TODO: Validate input, fallback to valid values
const std::string fps = std::to_string(config.streaming_config.record_options.fps); 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::string video_bitrate = std::to_string(config.streaming_config.record_options.video_bitrate);

View File

@@ -22,15 +22,17 @@ namespace gsr {
APPLICATION_CUSTOM APPLICATION_CUSTOM
}; };
SettingsPage::SettingsPage(Type type, const GsrInfo &gsr_info, Config &config, PageStack *page_stack) : SettingsPage::SettingsPage(Type type, const GsrInfo *gsr_info, Config &config, PageStack *page_stack) :
StaticPage(mgl::vec2f(get_theme().window_width, get_theme().window_height).floor()), StaticPage(mgl::vec2f(get_theme().window_width, get_theme().window_height).floor()),
type(type), type(type),
config(config), config(config),
gsr_info(gsr_info),
page_stack(page_stack), page_stack(page_stack),
settings_title_text("Settings", get_theme().title_font) settings_title_text("Settings", get_theme().title_font)
{ {
audio_devices = get_audio_devices(); audio_devices = get_audio_devices();
application_audio = get_application_audio(); application_audio = get_application_audio();
capture_options = get_supported_capture_options(*gsr_info);
auto content_page = std::make_unique<GsrPage>(); auto content_page = std::make_unique<GsrPage>();
content_page->add_button("Back", "back", get_color_theme().page_bg_color); content_page->add_button("Back", "back", get_color_theme().page_bg_color);
@@ -41,9 +43,9 @@ namespace gsr {
content_page_ptr = content_page.get(); content_page_ptr = content_page.get();
add_widget(std::move(content_page)); add_widget(std::move(content_page));
add_widgets(gsr_info); add_widgets();
add_page_specific_widgets(gsr_info); add_page_specific_widgets();
load(gsr_info); load();
} }
std::unique_ptr<RadioButton> SettingsPage::create_view_radio_button() { std::unique_ptr<RadioButton> SettingsPage::create_view_radio_button() {
@@ -55,31 +57,31 @@ namespace gsr {
return view_radio_button; return view_radio_button;
} }
std::unique_ptr<ComboBox> SettingsPage::create_record_area_box(const GsrInfo &gsr_info) { std::unique_ptr<ComboBox> SettingsPage::create_record_area_box() {
auto record_area_box = std::make_unique<ComboBox>(&get_theme().body_font); auto record_area_box = std::make_unique<ComboBox>(&get_theme().body_font);
// TODO: Show options not supported but disable them // TODO: Show options not supported but disable them
// TODO: Enable this // TODO: Enable this
//if(gsr_info.supported_capture_options.window) //if(capture_options.window)
// record_area_box->add_item("Window", "window"); // record_area_box->add_item("Window", "window");
if(gsr_info.supported_capture_options.focused) if(capture_options.focused)
record_area_box->add_item("Follow focused window", "focused"); record_area_box->add_item("Follow focused window", "focused");
if(gsr_info.supported_capture_options.screen) if(capture_options.screen)
record_area_box->add_item("All monitors", "screen"); record_area_box->add_item("All monitors", "screen");
for(const auto &monitor : gsr_info.supported_capture_options.monitors) { for(const auto &monitor : capture_options.monitors) {
char name[256]; char name[256];
snprintf(name, sizeof(name), "Monitor %s (%dx%d)", monitor.name.c_str(), monitor.size.x, monitor.size.y); snprintf(name, sizeof(name), "Monitor %s (%dx%d)", monitor.name.c_str(), monitor.size.x, monitor.size.y);
record_area_box->add_item(name, monitor.name); record_area_box->add_item(name, monitor.name);
} }
if(gsr_info.supported_capture_options.portal) if(capture_options.portal)
record_area_box->add_item("Desktop portal", "portal"); record_area_box->add_item("Desktop portal", "portal");
record_area_box_ptr = record_area_box.get(); record_area_box_ptr = record_area_box.get();
return record_area_box; return record_area_box;
} }
std::unique_ptr<Widget> SettingsPage::create_record_area(const GsrInfo &gsr_info) { std::unique_ptr<Widget> SettingsPage::create_record_area() {
auto record_area_list = std::make_unique<List>(List::Orientation::VERTICAL); auto record_area_list = std::make_unique<List>(List::Orientation::VERTICAL);
record_area_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Capture target:", get_color_theme().text_color)); record_area_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Capture target:", get_color_theme().text_color));
record_area_list->add_widget(create_record_area_box(gsr_info)); record_area_list->add_widget(create_record_area_box());
return record_area_list; return record_area_list;
} }
@@ -172,11 +174,11 @@ namespace gsr {
return checkbox; return checkbox;
} }
std::unique_ptr<Widget> SettingsPage::create_capture_target(const GsrInfo &gsr_info) { std::unique_ptr<Widget> SettingsPage::create_capture_target() {
auto ll = std::make_unique<List>(List::Orientation::VERTICAL); auto ll = std::make_unique<List>(List::Orientation::VERTICAL);
auto capture_target_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER); auto capture_target_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
capture_target_list->add_widget(create_record_area(gsr_info)); capture_target_list->add_widget(create_record_area());
capture_target_list->add_widget(create_select_window()); capture_target_list->add_widget(create_select_window());
capture_target_list->add_widget(create_area_size_section()); capture_target_list->add_widget(create_area_size_section());
capture_target_list->add_widget(create_video_resolution_section()); capture_target_list->add_widget(create_video_resolution_section());
@@ -378,40 +380,40 @@ namespace gsr {
return quality_list; return quality_list;
} }
std::unique_ptr<ComboBox> SettingsPage::create_video_codec_box(const GsrInfo &gsr_info) { std::unique_ptr<ComboBox> SettingsPage::create_video_codec_box() {
auto video_codec_box = std::make_unique<ComboBox>(&get_theme().body_font); auto video_codec_box = std::make_unique<ComboBox>(&get_theme().body_font);
// TODO: Show options not supported but disable them. // TODO: Show options not supported but disable them.
// TODO: Show error if no encoders are supported. // TODO: Show error if no encoders are supported.
// TODO: Show warning (once) if only software encoder is available. // TODO: Show warning (once) if only software encoder is available.
video_codec_box->add_item("Auto (Recommended)", "auto"); video_codec_box->add_item("Auto (Recommended)", "auto");
if(gsr_info.supported_video_codecs.h264) if(gsr_info->supported_video_codecs.h264)
video_codec_box->add_item("H264", "h264"); video_codec_box->add_item("H264", "h264");
if(gsr_info.supported_video_codecs.hevc) if(gsr_info->supported_video_codecs.hevc)
video_codec_box->add_item("HEVC", "hevc"); video_codec_box->add_item("HEVC", "hevc");
if(gsr_info.supported_video_codecs.av1) if(gsr_info->supported_video_codecs.av1)
video_codec_box->add_item("AV1", "av1"); video_codec_box->add_item("AV1", "av1");
if(gsr_info.supported_video_codecs.vp8) if(gsr_info->supported_video_codecs.vp8)
video_codec_box->add_item("VP8", "vp8"); video_codec_box->add_item("VP8", "vp8");
if(gsr_info.supported_video_codecs.vp9) if(gsr_info->supported_video_codecs.vp9)
video_codec_box->add_item("VP9", "vp9"); video_codec_box->add_item("VP9", "vp9");
if(gsr_info.supported_video_codecs.hevc_hdr) if(gsr_info->supported_video_codecs.hevc_hdr)
video_codec_box->add_item("HEVC (HDR)", "hevc_hdr"); video_codec_box->add_item("HEVC (HDR)", "hevc_hdr");
if(gsr_info.supported_video_codecs.hevc_10bit) if(gsr_info->supported_video_codecs.hevc_10bit)
video_codec_box->add_item("HEVC (10 bit, reduces banding)", "hevc_10bit"); video_codec_box->add_item("HEVC (10 bit, reduces banding)", "hevc_10bit");
if(gsr_info.supported_video_codecs.av1_hdr) if(gsr_info->supported_video_codecs.av1_hdr)
video_codec_box->add_item("AV1 (HDR)", "av1_hdr"); video_codec_box->add_item("AV1 (HDR)", "av1_hdr");
if(gsr_info.supported_video_codecs.av1_10bit) if(gsr_info->supported_video_codecs.av1_10bit)
video_codec_box->add_item("AV1 (10 bit, reduces banding)", "av1_10bit"); video_codec_box->add_item("AV1 (10 bit, reduces banding)", "av1_10bit");
if(gsr_info.supported_video_codecs.h264_software) if(gsr_info->supported_video_codecs.h264_software)
video_codec_box->add_item("H264 Software Encoder (Slow, not recommended)", "h264_software"); video_codec_box->add_item("H264 Software Encoder (Slow, not recommended)", "h264_software");
video_codec_box_ptr = video_codec_box.get(); video_codec_box_ptr = video_codec_box.get();
return video_codec_box; return video_codec_box;
} }
std::unique_ptr<List> SettingsPage::create_video_codec(const GsrInfo &gsr_info) { std::unique_ptr<List> SettingsPage::create_video_codec() {
auto video_codec_list = std::make_unique<List>(List::Orientation::VERTICAL); auto video_codec_list = std::make_unique<List>(List::Orientation::VERTICAL);
video_codec_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Video codec:", get_color_theme().text_color)); video_codec_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Video codec:", get_color_theme().text_color));
video_codec_list->add_widget(create_video_codec_box(gsr_info)); video_codec_list->add_widget(create_video_codec_box());
video_codec_ptr = video_codec_list.get(); video_codec_ptr = video_codec_list.get();
return video_codec_list; return video_codec_list;
} }
@@ -477,16 +479,16 @@ namespace gsr {
return record_cursor_checkbox; return record_cursor_checkbox;
} }
std::unique_ptr<Widget> SettingsPage::create_video_section(const GsrInfo &gsr_info) { std::unique_ptr<Widget> SettingsPage::create_video_section() {
auto video_section_list = std::make_unique<List>(List::Orientation::VERTICAL); auto video_section_list = std::make_unique<List>(List::Orientation::VERTICAL);
video_section_list->add_widget(create_video_quality_section()); video_section_list->add_widget(create_video_quality_section());
video_section_list->add_widget(create_video_codec(gsr_info)); video_section_list->add_widget(create_video_codec());
video_section_list->add_widget(create_framerate_section()); video_section_list->add_widget(create_framerate_section());
video_section_list->add_widget(create_record_cursor_section()); video_section_list->add_widget(create_record_cursor_section());
return std::make_unique<Subsection>("Video", std::move(video_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)); return std::make_unique<Subsection>("Video", std::move(video_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f));
} }
std::unique_ptr<Widget> SettingsPage::create_settings(const GsrInfo &gsr_info) { std::unique_ptr<Widget> SettingsPage::create_settings() {
auto page_list = std::make_unique<List>(List::Orientation::VERTICAL); auto page_list = std::make_unique<List>(List::Orientation::VERTICAL);
page_list->set_spacing(0.018f); page_list->set_spacing(0.018f);
page_list->add_widget(create_view_radio_button()); page_list->add_widget(create_view_radio_button());
@@ -496,16 +498,16 @@ namespace gsr {
auto settings_list = std::make_unique<List>(List::Orientation::VERTICAL); auto settings_list = std::make_unique<List>(List::Orientation::VERTICAL);
settings_list->set_spacing(0.018f); settings_list->set_spacing(0.018f);
settings_list->add_widget(create_capture_target(gsr_info)); settings_list->add_widget(create_capture_target());
settings_list->add_widget(create_audio_section()); settings_list->add_widget(create_audio_section());
settings_list->add_widget(create_video_section(gsr_info)); settings_list->add_widget(create_video_section());
settings_list_ptr = settings_list.get(); settings_list_ptr = settings_list.get();
settings_scrollable_page_ptr->add_widget(std::move(settings_list)); settings_scrollable_page_ptr->add_widget(std::move(settings_list));
return page_list; return page_list;
} }
void SettingsPage::add_widgets(const GsrInfo &gsr_info) { void SettingsPage::add_widgets() {
content_page_ptr->add_widget(create_settings(gsr_info)); content_page_ptr->add_widget(create_settings());
record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) { record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) {
(void)text; (void)text;
@@ -534,32 +536,32 @@ namespace gsr {
}; };
video_quality_box_ptr->on_selection_changed("", video_quality_box_ptr->get_selected_id()); video_quality_box_ptr->on_selection_changed("", video_quality_box_ptr->get_selected_id());
if(!gsr_info.supported_capture_options.monitors.empty()) if(!capture_options.monitors.empty())
record_area_box_ptr->set_selected_item(gsr_info.supported_capture_options.monitors.front().name); record_area_box_ptr->set_selected_item(capture_options.monitors.front().name);
else if(gsr_info.supported_capture_options.portal) else if(capture_options.portal)
record_area_box_ptr->set_selected_item("portal"); record_area_box_ptr->set_selected_item("portal");
else if(gsr_info.supported_capture_options.window) else if(capture_options.window)
record_area_box_ptr->set_selected_item("window"); record_area_box_ptr->set_selected_item("window");
else else
record_area_box_ptr->on_selection_changed("", ""); record_area_box_ptr->on_selection_changed("", "");
if(!gsr_info.system_info.supports_app_audio) { if(!gsr_info->system_info.supports_app_audio) {
add_application_audio_button_ptr->set_visible(false); add_application_audio_button_ptr->set_visible(false);
add_custom_application_audio_button_ptr->set_visible(false); add_custom_application_audio_button_ptr->set_visible(false);
application_audio_invert_checkbox_ptr->set_visible(false); application_audio_invert_checkbox_ptr->set_visible(false);
} }
} }
void SettingsPage::add_page_specific_widgets(const GsrInfo &gsr_info) { void SettingsPage::add_page_specific_widgets() {
switch(type) { switch(type) {
case Type::REPLAY: case Type::REPLAY:
add_replay_widgets(gsr_info); add_replay_widgets();
break; break;
case Type::RECORD: case Type::RECORD:
add_record_widgets(gsr_info); add_record_widgets();
break; break;
case Type::STREAM: case Type::STREAM:
add_stream_widgets(gsr_info); add_stream_widgets();
break; break;
} }
} }
@@ -622,9 +624,9 @@ namespace gsr {
return replay_time_list; return replay_time_list;
} }
std::unique_ptr<RadioButton> SettingsPage::create_start_replay_automatically(const GsrInfo &gsr_info) { std::unique_ptr<RadioButton> SettingsPage::create_start_replay_automatically() {
char fullscreen_text[256]; char fullscreen_text[256];
snprintf(fullscreen_text, sizeof(fullscreen_text), "Turn on replay when starting a fullscreen application%s", gsr_info.system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)"); snprintf(fullscreen_text, sizeof(fullscreen_text), "Turn on replay when starting a fullscreen application%s", gsr_info->system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)");
auto radiobutton = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::VERTICAL); auto radiobutton = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::VERTICAL);
radiobutton->add_item("Don't turn on replay automatically", "dont_turn_on_automatically"); radiobutton->add_item("Don't turn on replay automatically", "dont_turn_on_automatically");
@@ -635,9 +637,9 @@ namespace gsr {
return radiobutton; return radiobutton;
} }
std::unique_ptr<CheckBox> SettingsPage::create_save_replay_in_game_folder(const GsrInfo &gsr_info) { std::unique_ptr<CheckBox> SettingsPage::create_save_replay_in_game_folder() {
char text[256]; char text[256];
snprintf(text, sizeof(text), "Save video in a folder with the name of the game%s", gsr_info.system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)"); snprintf(text, sizeof(text), "Save video in a folder with the name of the game%s", gsr_info->system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)");
auto checkbox = std::make_unique<CheckBox>(&get_theme().body_font, text); auto checkbox = std::make_unique<CheckBox>(&get_theme().body_font, text);
save_replay_in_game_folder_ptr = checkbox.get(); save_replay_in_game_folder_ptr = checkbox.get();
return checkbox; return checkbox;
@@ -659,7 +661,7 @@ namespace gsr {
estimated_file_size_ptr->set_text(buffer); estimated_file_size_ptr->set_text(buffer);
} }
void SettingsPage::add_replay_widgets(const GsrInfo &gsr_info) { void SettingsPage::add_replay_widgets() {
auto file_info_list = std::make_unique<List>(List::Orientation::VERTICAL); auto file_info_list = std::make_unique<List>(List::Orientation::VERTICAL);
auto file_info_data_list = std::make_unique<List>(List::Orientation::HORIZONTAL); auto file_info_data_list = std::make_unique<List>(List::Orientation::HORIZONTAL);
file_info_data_list->add_widget(create_save_directory("Directory to save replays:")); file_info_data_list->add_widget(create_save_directory("Directory to save replays:"));
@@ -670,8 +672,8 @@ namespace gsr {
settings_list_ptr->add_widget(std::make_unique<Subsection>("File info", std::move(file_info_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); settings_list_ptr->add_widget(std::make_unique<Subsection>("File info", std::move(file_info_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
auto general_list = std::make_unique<List>(List::Orientation::VERTICAL); auto general_list = std::make_unique<List>(List::Orientation::VERTICAL);
general_list->add_widget(create_start_replay_automatically(gsr_info)); general_list->add_widget(create_start_replay_automatically());
general_list->add_widget(create_save_replay_in_game_folder(gsr_info)); general_list->add_widget(create_save_replay_in_game_folder());
settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL); auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL);
@@ -716,22 +718,22 @@ namespace gsr {
}; };
} }
std::unique_ptr<CheckBox> SettingsPage::create_save_recording_in_game_folder(const GsrInfo &gsr_info) { std::unique_ptr<CheckBox> SettingsPage::create_save_recording_in_game_folder() {
char text[256]; char text[256];
snprintf(text, sizeof(text), "Save video in a folder with the name of the game%s", gsr_info.system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)"); snprintf(text, sizeof(text), "Save video in a folder with the name of the game%s", gsr_info->system_info.display_server == DisplayServer::X11 ? "" : " (X11 only)");
auto checkbox = std::make_unique<CheckBox>(&get_theme().body_font, text); auto checkbox = std::make_unique<CheckBox>(&get_theme().body_font, text);
save_recording_in_game_folder_ptr = checkbox.get(); save_recording_in_game_folder_ptr = checkbox.get();
return checkbox; return checkbox;
} }
void SettingsPage::add_record_widgets(const GsrInfo &gsr_info) { void SettingsPage::add_record_widgets() {
auto file_list = std::make_unique<List>(List::Orientation::HORIZONTAL); auto file_list = std::make_unique<List>(List::Orientation::HORIZONTAL);
file_list->add_widget(create_save_directory("Directory to save the video:")); file_list->add_widget(create_save_directory("Directory to save the video:"));
file_list->add_widget(create_container_section()); file_list->add_widget(create_container_section());
settings_list_ptr->add_widget(std::make_unique<Subsection>("File info", std::move(file_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); settings_list_ptr->add_widget(std::make_unique<Subsection>("File info", std::move(file_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
auto general_list = std::make_unique<List>(List::Orientation::VERTICAL); auto general_list = std::make_unique<List>(List::Orientation::VERTICAL);
general_list->add_widget(create_save_recording_in_game_folder(gsr_info)); general_list->add_widget(create_save_recording_in_game_folder());
settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f))); settings_list_ptr->add_widget(std::make_unique<Subsection>("General", std::move(general_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL); auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL);
@@ -825,7 +827,7 @@ namespace gsr {
return container_list; return container_list;
} }
void SettingsPage::add_stream_widgets(const GsrInfo&) { void SettingsPage::add_stream_widgets() {
auto streaming_info_list = std::make_unique<List>(List::Orientation::HORIZONTAL); auto streaming_info_list = std::make_unique<List>(List::Orientation::HORIZONTAL);
streaming_info_list->add_widget(create_streaming_service_section()); streaming_info_list->add_widget(create_streaming_service_section());
streaming_info_list->add_widget(create_stream_key_section()); streaming_info_list->add_widget(create_stream_key_section());
@@ -879,16 +881,16 @@ namespace gsr {
save(); save();
} }
void SettingsPage::load(const GsrInfo &gsr_info) { void SettingsPage::load() {
switch(type) { switch(type) {
case Type::REPLAY: case Type::REPLAY:
load_replay(gsr_info); load_replay();
break; break;
case Type::RECORD: case Type::RECORD:
load_record(gsr_info); load_record();
break; break;
case Type::STREAM: case Type::STREAM:
load_stream(gsr_info); load_stream();
break; break;
} }
} }
@@ -921,11 +923,11 @@ namespace gsr {
return str.size() >= len && memcmp(str.data(), substr, len) == 0; return str.size() >= len && memcmp(str.data(), substr, len) == 0;
} }
void SettingsPage::load_audio_tracks(const RecordOptions &record_options, const GsrInfo &gsr_info) { void SettingsPage::load_audio_tracks(const RecordOptions &record_options) {
audio_track_list_ptr->clear(); audio_track_list_ptr->clear();
for(const std::string &audio_track : record_options.audio_tracks) { for(const std::string &audio_track : record_options.audio_tracks) {
if(starts_with(audio_track, "app:")) { if(starts_with(audio_track, "app:")) {
if(!gsr_info.system_info.supports_app_audio) if(!gsr_info->system_info.supports_app_audio)
continue; continue;
std::string audio_track_name = audio_track.substr(4); std::string audio_track_name = audio_track.substr(4);
@@ -955,12 +957,12 @@ namespace gsr {
} }
} }
void SettingsPage::load_common(RecordOptions &record_options, const GsrInfo &gsr_info) { void SettingsPage::load_common(RecordOptions &record_options) {
record_area_box_ptr->set_selected_item(record_options.record_area_option); record_area_box_ptr->set_selected_item(record_options.record_area_option);
merge_audio_tracks_checkbox_ptr->set_checked(record_options.merge_audio_tracks); merge_audio_tracks_checkbox_ptr->set_checked(record_options.merge_audio_tracks);
application_audio_invert_checkbox_ptr->set_checked(record_options.application_audio_invert); application_audio_invert_checkbox_ptr->set_checked(record_options.application_audio_invert);
change_video_resolution_checkbox_ptr->set_checked(record_options.change_video_resolution); change_video_resolution_checkbox_ptr->set_checked(record_options.change_video_resolution);
load_audio_tracks(record_options, gsr_info); load_audio_tracks(record_options);
color_range_box_ptr->set_selected_item(record_options.color_range); color_range_box_ptr->set_selected_item(record_options.color_range);
video_quality_box_ptr->set_selected_item(record_options.video_quality); video_quality_box_ptr->set_selected_item(record_options.video_quality);
video_codec_box_ptr->set_selected_item(record_options.video_codec); video_codec_box_ptr->set_selected_item(record_options.video_codec);
@@ -1009,8 +1011,8 @@ namespace gsr {
video_bitrate_entry_ptr->set_text(std::to_string(record_options.video_bitrate)); video_bitrate_entry_ptr->set_text(std::to_string(record_options.video_bitrate));
} }
void SettingsPage::load_replay(const GsrInfo &gsr_info) { void SettingsPage::load_replay() {
load_common(config.replay_config.record_options, gsr_info); load_common(config.replay_config.record_options);
turn_on_replay_automatically_mode_ptr->set_selected_item(config.replay_config.turn_on_replay_automatically_mode); turn_on_replay_automatically_mode_ptr->set_selected_item(config.replay_config.turn_on_replay_automatically_mode);
save_replay_in_game_folder_ptr->set_checked(config.replay_config.save_video_in_game_folder); save_replay_in_game_folder_ptr->set_checked(config.replay_config.save_video_in_game_folder);
show_replay_started_notification_checkbox_ptr->set_checked(config.replay_config.show_replay_started_notifications); show_replay_started_notification_checkbox_ptr->set_checked(config.replay_config.show_replay_started_notifications);
@@ -1024,8 +1026,8 @@ namespace gsr {
replay_time_entry_ptr->set_text(std::to_string(config.replay_config.replay_time)); replay_time_entry_ptr->set_text(std::to_string(config.replay_config.replay_time));
} }
void SettingsPage::load_record(const GsrInfo &gsr_info) { void SettingsPage::load_record() {
load_common(config.record_config.record_options, gsr_info); load_common(config.record_config.record_options);
save_recording_in_game_folder_ptr->set_checked(config.record_config.save_video_in_game_folder); save_recording_in_game_folder_ptr->set_checked(config.record_config.save_video_in_game_folder);
show_recording_started_notification_checkbox_ptr->set_checked(config.record_config.show_recording_started_notifications); show_recording_started_notification_checkbox_ptr->set_checked(config.record_config.show_recording_started_notifications);
show_video_saved_notification_checkbox_ptr->set_checked(config.record_config.show_video_saved_notifications); show_video_saved_notification_checkbox_ptr->set_checked(config.record_config.show_video_saved_notifications);
@@ -1033,8 +1035,8 @@ namespace gsr {
container_box_ptr->set_selected_item(config.record_config.container); container_box_ptr->set_selected_item(config.record_config.container);
} }
void SettingsPage::load_stream(const GsrInfo &gsr_info) { void SettingsPage::load_stream() {
load_common(config.streaming_config.record_options, gsr_info); load_common(config.streaming_config.record_options);
show_streaming_started_notification_checkbox_ptr->set_checked(config.streaming_config.show_streaming_started_notifications); show_streaming_started_notification_checkbox_ptr->set_checked(config.streaming_config.show_streaming_started_notifications);
show_streaming_stopped_notification_checkbox_ptr->set_checked(config.streaming_config.show_streaming_stopped_notifications); show_streaming_stopped_notification_checkbox_ptr->set_checked(config.streaming_config.show_streaming_stopped_notifications);
streaming_service_box_ptr->set_selected_item(config.streaming_config.streaming_service); streaming_service_box_ptr->set_selected_item(config.streaming_config.streaming_service);

View File

@@ -168,8 +168,11 @@ int main(void) {
exit(1); exit(1);
} }
if(gsr_info.system_info.display_server == gsr::DisplayServer::WAYLAND) const gsr::DisplayServer display_server = gsr_info.system_info.display_server;
fprintf(stderr, "warning: Wayland support is experimental and requires XWayland. Things may not work as expected.\n"); if(display_server == gsr::DisplayServer::WAYLAND)
fprintf(stderr, "warning: Wayland support is experimental and requires XWayland. Things may not work as expected.\n");
gsr::SupportedCaptureOptions capture_options = gsr::get_supported_capture_options(gsr_info);
std::string resources_path; std::string resources_path;
if(access("sibs-build", F_OK) == 0) { if(access("sibs-build", F_OK) == 0) {
@@ -197,11 +200,11 @@ int main(void) {
fprintf(stderr, "info: gsr ui is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n"); fprintf(stderr, "info: gsr ui is now ready, waiting for inputs. Press alt+z to show/hide the overlay\n");
auto overlay = std::make_unique<gsr::Overlay>(resources_path, gsr_info, egl_funcs); auto overlay = std::make_unique<gsr::Overlay>(resources_path, std::move(gsr_info), std::move(capture_options), egl_funcs);
//overlay.show(); //overlay.show();
std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = nullptr; std::unique_ptr<gsr::GlobalHotkeys> global_hotkeys = nullptr;
if(gsr_info.system_info.display_server == gsr::DisplayServer::X11) { if(display_server == gsr::DisplayServer::X11) {
global_hotkeys = register_x11_hotkeys(overlay.get()); global_hotkeys = register_x11_hotkeys(overlay.get());
if(!global_hotkeys) { if(!global_hotkeys) {
fprintf(stderr, "info: failed to register some x11 hotkeys because they are registered by another program. Will use linux hotkeys instead that can clash with keys used by other applications\n"); fprintf(stderr, "info: failed to register some x11 hotkeys because they are registered by another program. Will use linux hotkeys instead that can clash with keys used by other applications\n");