aboutsummaryrefslogtreecommitdiff
path: root/src/gui/SettingsPage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/SettingsPage.cpp')
-rw-r--r--src/gui/SettingsPage.cpp461
1 files changed, 292 insertions, 169 deletions
diff --git a/src/gui/SettingsPage.cpp b/src/gui/SettingsPage.cpp
index 663e941..363b48c 100644
--- a/src/gui/SettingsPage.cpp
+++ b/src/gui/SettingsPage.cpp
@@ -11,6 +11,8 @@
#include <string.h>
namespace gsr {
+ static const char *custom_app_audio_tag = "[custom]";
+
enum class AudioTrackType {
DEVICE,
APPLICATION,
@@ -194,129 +196,229 @@ namespace gsr {
return std::make_unique<Subsection>("Record area", std::move(ll), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f));
}
- std::unique_ptr<ComboBox> SettingsPage::create_audio_device_selection_combobox() {
+ static bool audio_device_is_output(const std::string &audio_device_id) {
+ return audio_device_id == "default_output" || ends_with(audio_device_id, ".monitor");
+ }
+
+ std::unique_ptr<ComboBox> SettingsPage::create_audio_device_selection_combobox(AudioDeviceType device_type) {
auto audio_device_box = std::make_unique<ComboBox>(&get_theme().body_font);
for(const auto &audio_device : audio_devices) {
- audio_device_box->add_item(audio_device.description, audio_device.name);
+ const bool device_is_output = audio_device_is_output(audio_device.name);
+ if((device_type == AudioDeviceType::OUTPUT && device_is_output) || (device_type == AudioDeviceType::INPUT && !device_is_output)) {
+ std::string description = audio_device.description;
+ if(starts_with(description, "Monitor of "))
+ description.erase(0, 11);
+ audio_device_box->add_item(description, audio_device.name);
+ }
}
return audio_device_box;
}
- std::unique_ptr<Button> SettingsPage::create_remove_audio_device_button(List *audio_device_list_ptr) {
- auto remove_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Remove", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
- remove_audio_track_button->on_click = [this, audio_device_list_ptr]() {
- audio_track_list_ptr->remove_widget(audio_device_list_ptr);
+ static void set_application_audio_options_visible(Subsection *audio_track_subsection, bool visible, const GsrInfo &gsr_info) {
+ if(!gsr_info.system_info.supports_app_audio)
+ visible = false;
+
+ List *audio_track_items_list = dynamic_cast<List*>(audio_track_subsection->get_inner_widget());
+
+ List *buttons_list = dynamic_cast<List*>(audio_track_items_list->get_child_widget_by_index(1));
+ Button *add_application_audio_button = dynamic_cast<Button*>(buttons_list->get_child_widget_by_index(2));
+ add_application_audio_button->set_visible(visible);
+
+ CheckBox *invert_app_audio_checkbox = dynamic_cast<CheckBox*>(audio_track_items_list->get_child_widget_by_index(3));
+ invert_app_audio_checkbox->set_visible(visible);
+ }
+
+ static void set_application_audio_options_visible(List *audio_track_section_list_ptr, bool visible, const GsrInfo &gsr_info) {
+ audio_track_section_list_ptr->for_each_child_widget([visible, &gsr_info](std::unique_ptr<Widget> &widget) {
+ Subsection *audio_track_subsection = dynamic_cast<Subsection*>(widget.get());
+ set_application_audio_options_visible(audio_track_subsection, visible, gsr_info);
+ return true;
+ });
+ }
+
+ std::unique_ptr<Button> SettingsPage::create_remove_audio_device_button(List *audio_input_list_ptr, List *audio_device_list_ptr) {
+ auto remove_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 0));
+ remove_audio_track_button->set_icon(&get_theme().trash_texture);
+ remove_audio_track_button->set_icon_padding_scale(0.75f);
+ remove_audio_track_button->on_click = [audio_input_list_ptr, audio_device_list_ptr]() {
+ audio_input_list_ptr->remove_widget(audio_device_list_ptr);
};
return remove_audio_track_button;
}
- std::unique_ptr<List> SettingsPage::create_audio_device() {
+ std::unique_ptr<List> SettingsPage::create_audio_device(AudioDeviceType device_type, List *audio_input_list_ptr) {
auto audio_device_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
audio_device_list->userdata = (void*)(uintptr_t)AudioTrackType::DEVICE;
- audio_device_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Device:", get_color_theme().text_color));
- audio_device_list->add_widget(create_audio_device_selection_combobox());
- audio_device_list->add_widget(create_remove_audio_device_button(audio_device_list.get()));
+ audio_device_list->add_widget(std::make_unique<Label>(&get_theme().body_font, device_type == AudioDeviceType::OUTPUT ? "Output device:" : "Input device: ", get_color_theme().text_color));
+ audio_device_list->add_widget(create_audio_device_selection_combobox(device_type));
+ audio_device_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, audio_device_list.get()));
return audio_device_list;
}
- std::unique_ptr<Button> SettingsPage::create_add_audio_device_button() {
- auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add audio device", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
- add_audio_track_button->on_click = [this]() {
+ std::unique_ptr<Button> SettingsPage::create_add_audio_track_button() {
+ auto button = std::make_unique<Button>(&get_theme().body_font, "Add audio track", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
+ button->on_click = [this]() {
+ audio_track_section_list_ptr->add_widget(create_audio_track_section(audio_section_ptr));
+ };
+ button->set_visible(type != Type::STREAM);
+ return button;
+ }
+
+ std::unique_ptr<Button> SettingsPage::create_add_audio_output_device_button(List *audio_input_list_ptr) {
+ auto button = std::make_unique<Button>(&get_theme().body_font, "Add output device", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
+ button->on_click = [this, audio_input_list_ptr]() {
audio_devices = get_audio_devices();
- audio_track_list_ptr->add_widget(create_audio_device());
+ audio_input_list_ptr->add_widget(create_audio_device(AudioDeviceType::OUTPUT, audio_input_list_ptr));
};
- return add_audio_track_button;
+ return button;
+ }
+
+ std::unique_ptr<Button> SettingsPage::create_add_audio_input_device_button(List *audio_input_list_ptr) {
+ auto button = std::make_unique<Button>(&get_theme().body_font, "Add input device", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
+ button->on_click = [this, audio_input_list_ptr]() {
+ audio_devices = get_audio_devices();
+ audio_input_list_ptr->add_widget(create_audio_device(AudioDeviceType::INPUT, audio_input_list_ptr));
+ };
+ return button;
}
- std::unique_ptr<ComboBox> SettingsPage::create_application_audio_selection_combobox() {
+ std::unique_ptr<ComboBox> SettingsPage::create_application_audio_selection_combobox(List *application_audio_row) {
auto audio_device_box = std::make_unique<ComboBox>(&get_theme().body_font);
+ ComboBox *audio_device_box_ptr = audio_device_box.get();
for(const auto &app_audio : application_audio) {
audio_device_box->add_item(app_audio, app_audio);
}
+ audio_device_box->add_item("Custom...", custom_app_audio_tag);
+
+ audio_device_box->on_selection_changed = [application_audio_row, audio_device_box_ptr](const std::string&, const std::string &id) {
+ if(id == custom_app_audio_tag) {
+ application_audio_row->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION_CUSTOM;
+ auto custom_app_audio_entry = std::make_unique<Entry>(&get_theme().body_font, "", (int)(get_theme().body_font.get_character_size() * 10.0f));
+ application_audio_row->replace_widget(audio_device_box_ptr, std::move(custom_app_audio_entry));
+ }
+ };
+
return audio_device_box;
}
- std::unique_ptr<List> SettingsPage::create_application_audio() {
+ std::unique_ptr<List> SettingsPage::create_application_audio(List *audio_input_list_ptr) {
auto application_audio_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
application_audio_list->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION;
- application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "App: ", get_color_theme().text_color));
- application_audio_list->add_widget(create_application_audio_selection_combobox());
- application_audio_list->add_widget(create_remove_audio_device_button(application_audio_list.get()));
+ application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Application: ", get_color_theme().text_color));
+ application_audio_list->add_widget(create_application_audio_selection_combobox(application_audio_list.get()));
+ application_audio_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, application_audio_list.get()));
return application_audio_list;
}
- std::unique_ptr<List> SettingsPage::create_custom_application_audio() {
+ std::unique_ptr<List> SettingsPage::create_custom_application_audio(List *audio_input_list_ptr) {
auto application_audio_list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
application_audio_list->userdata = (void*)(uintptr_t)AudioTrackType::APPLICATION_CUSTOM;
- application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "App: ", get_color_theme().text_color));
+ application_audio_list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Application: ", get_color_theme().text_color));
application_audio_list->add_widget(std::make_unique<Entry>(&get_theme().body_font, "", (int)(get_theme().body_font.get_character_size() * 10.0f)));
- application_audio_list->add_widget(create_remove_audio_device_button(application_audio_list.get()));
+ application_audio_list->add_widget(create_remove_audio_device_button(audio_input_list_ptr, application_audio_list.get()));
return application_audio_list;
}
- std::unique_ptr<Button> SettingsPage::create_add_application_audio_button() {
+ std::unique_ptr<Button> SettingsPage::create_add_application_audio_button(List *audio_input_list_ptr) {
auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add application audio", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
- add_application_audio_button_ptr = add_audio_track_button.get();
- add_audio_track_button->on_click = [this]() {
+ add_audio_track_button->on_click = [this, audio_input_list_ptr]() {
application_audio = get_application_audio();
- audio_track_list_ptr->add_widget(create_application_audio());
- };
- return add_audio_track_button;
- }
-
- std::unique_ptr<Button> SettingsPage::create_add_custom_application_audio_button() {
- auto add_audio_track_button = std::make_unique<Button>(&get_theme().body_font, "Add custom application audio", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 120));
- add_custom_application_audio_button_ptr = add_audio_track_button.get();
- add_audio_track_button->on_click = [this]() {
- audio_track_list_ptr->add_widget(create_custom_application_audio());
+ if(application_audio.empty())
+ audio_input_list_ptr->add_widget(create_custom_application_audio(audio_input_list_ptr));
+ else
+ audio_input_list_ptr->add_widget(create_application_audio(audio_input_list_ptr));
};
return add_audio_track_button;
}
- std::unique_ptr<List> SettingsPage::create_add_audio_buttons() {
+ std::unique_ptr<List> SettingsPage::create_add_audio_buttons(List *audio_input_list_ptr) {
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
- list->add_widget(create_add_audio_device_button());
- list->add_widget(create_add_application_audio_button());
- list->add_widget(create_add_custom_application_audio_button());
+ list->add_widget(create_add_audio_output_device_button(audio_input_list_ptr));
+ list->add_widget(create_add_audio_input_device_button(audio_input_list_ptr));
+ list->add_widget(create_add_application_audio_button(audio_input_list_ptr));
return list;
}
- std::unique_ptr<List> SettingsPage::create_audio_track_track_section() {
+ std::unique_ptr<List> SettingsPage::create_audio_input_section() {
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
- audio_track_list_ptr = list.get();
- audio_track_list_ptr->add_widget(create_audio_device()); // Add default_output by default
+ //list->add_widget(create_audio_device(list.get())); // Add default_output by default
return list;
}
- std::unique_ptr<CheckBox> SettingsPage::create_split_audio_checkbox() {
- auto split_audio_checkbox = std::make_unique<CheckBox>(&get_theme().body_font, "Split each device/app audio into separate audio tracks");
- split_audio_checkbox->set_checked(false);
- split_audio_checkbox_ptr = split_audio_checkbox.get();
- return split_audio_checkbox;
- }
-
std::unique_ptr<CheckBox> SettingsPage::create_application_audio_invert_checkbox() {
auto application_audio_invert_checkbox = std::make_unique<CheckBox>(&get_theme().body_font, "Record audio from all applications except the selected ones");
application_audio_invert_checkbox->set_checked(false);
- application_audio_invert_checkbox_ptr = application_audio_invert_checkbox.get();
return application_audio_invert_checkbox;
}
- std::unique_ptr<Widget> SettingsPage::create_audio_track_section() {
+ static void update_audio_track_titles(List *audio_track_section_list_ptr) {
+ int index = 0;
+ audio_track_section_list_ptr->for_each_child_widget([&index](std::unique_ptr<Widget> &widget) {
+ char audio_track_name[32];
+ snprintf(audio_track_name, sizeof(audio_track_name), "Audio track #%d", 1 + index);
+ ++index;
+
+ Subsection *subsection = dynamic_cast<Subsection*>(widget.get());
+ List *subesection_items = dynamic_cast<List*>(subsection->get_inner_widget());
+ Label *audio_track_title = dynamic_cast<Label*>(dynamic_cast<List*>(subesection_items->get_child_widget_by_index(0))->get_child_widget_by_index(0));
+ audio_track_title->set_text(audio_track_name);
+ return true;
+ });
+ }
+
+ std::unique_ptr<List> SettingsPage::create_audio_track_title_and_remove(Subsection *audio_track_subsection, const char *title) {
+ auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
+ list->add_widget(std::make_unique<Label>(&get_theme().title_font, title, get_color_theme().text_color));
+
+ auto remove_track_button = std::make_unique<Button>(&get_theme().body_font, "", mgl::vec2f(0.0f, 0.0f), mgl::Color(0, 0, 0, 0));
+ remove_track_button->set_icon(&get_theme().trash_texture);
+ remove_track_button->set_icon_padding_scale(0.75f);
+ remove_track_button->on_click = [this, audio_track_subsection]() {
+ audio_track_section_list_ptr->remove_widget(audio_track_subsection);
+ update_audio_track_titles(audio_track_section_list_ptr);
+ };
+ list->add_widget(std::move(remove_track_button));
+ list->set_visible(type != Type::STREAM);
+ return list;
+ }
+
+ std::unique_ptr<Subsection> SettingsPage::create_audio_track_section(Widget *parent_widget) {
+ char audio_track_name[32];
+ snprintf(audio_track_name, sizeof(audio_track_name), "Audio track #%d", 1 + (int)audio_track_section_list_ptr->get_num_children());
+
+ auto audio_input_section = create_audio_input_section();
+ List *audio_input_section_ptr = audio_input_section.get();
+
+ auto list = std::make_unique<List>(List::Orientation::VERTICAL);
+ List *list_ptr = list.get();
+ auto subsection = std::make_unique<Subsection>("", std::move(std::move(list)), mgl::vec2f(parent_widget->get_inner_size().x, 0.0f));
+ subsection->set_bg_color(mgl::Color(35, 40, 44));
+
+ list_ptr->add_widget(create_audio_track_title_and_remove(subsection.get(), audio_track_name));
+ list_ptr->add_widget(create_add_audio_buttons(audio_input_section_ptr));
+ list_ptr->add_widget(std::move(audio_input_section));
+ list_ptr->add_widget(create_application_audio_invert_checkbox());
+
+ set_application_audio_options_visible(subsection.get(), view_radio_button_ptr->get_selected_id() == "advanced", *gsr_info);
+ return subsection;
+ }
+
+ std::unique_ptr<List> SettingsPage::create_audio_track_section_list() {
auto list = std::make_unique<List>(List::Orientation::VERTICAL);
- list->add_widget(create_add_audio_buttons());
- list->add_widget(create_audio_track_track_section());
+ audio_track_section_list_ptr = list.get();
return list;
}
std::unique_ptr<Widget> SettingsPage::create_audio_section() {
auto audio_device_section_list = std::make_unique<List>(List::Orientation::VERTICAL);
- audio_device_section_list->add_widget(create_audio_track_section());
- if(type != Type::STREAM)
- audio_device_section_list->add_widget(create_split_audio_checkbox());
- audio_device_section_list->add_widget(create_application_audio_invert_checkbox());
- audio_device_section_list->add_widget(create_audio_codec());
- return std::make_unique<Subsection>("Audio", std::move(audio_device_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f));
+ List *audio_device_section_list_ptr = audio_device_section_list.get();
+
+ auto subsection = std::make_unique<Subsection>("Audio", std::move(audio_device_section_list), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f));
+ audio_section_ptr = subsection.get();
+ audio_device_section_list_ptr->add_widget(create_add_audio_track_button());
+ audio_device_section_list_ptr->add_widget(create_audio_track_section_list());
+ audio_device_section_list_ptr->add_widget(create_audio_codec());
+ return subsection;
}
std::unique_ptr<List> SettingsPage::create_video_quality_box() {
@@ -531,8 +633,7 @@ namespace gsr {
void SettingsPage::add_widgets() {
content_page_ptr->add_widget(create_settings());
- record_area_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) {
- (void)text;
+ record_area_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) {
const bool window_selected = id == "window";
const bool focused_selected = id == "focused";
const bool portal_selected = id == "portal";
@@ -549,8 +650,7 @@ namespace gsr {
video_resolution_list_ptr->set_visible(!focused_selected && checked);
};
- video_quality_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) {
- (void)text;
+ video_quality_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) {
const bool custom_selected = id == "custom";
video_bitrate_list_ptr->set_visible(custom_selected);
@@ -569,12 +669,6 @@ namespace gsr {
record_area_box_ptr->set_selected_item("window");
else
record_area_box_ptr->on_selection_changed("", "");
-
- if(!gsr_info->system_info.supports_app_audio) {
- add_application_audio_button_ptr->set_visible(false);
- add_custom_application_audio_button_ptr->set_visible(false);
- application_audio_invert_checkbox_ptr->set_visible(false);
- }
}
void SettingsPage::add_page_specific_widgets() {
@@ -641,7 +735,7 @@ namespace gsr {
auto list = std::make_unique<List>(List::Orientation::HORIZONTAL, List::Alignment::CENTER);
auto replay_time_entry = std::make_unique<Entry>(&get_theme().body_font, "60", get_theme().body_font.get_character_size() * 3);
- replay_time_entry->validate_handler = create_entry_validator_integer_in_range(1, 10800);
+ replay_time_entry->validate_handler = create_entry_validator_integer_in_range(2, 86400);
replay_time_entry_ptr = replay_time_entry.get();
list->add_widget(std::move(replay_time_entry));
@@ -659,6 +753,24 @@ namespace gsr {
return replay_time_list;
}
+ std::unique_ptr<List> SettingsPage::create_replay_storage() {
+ auto list = std::make_unique<List>(List::Orientation::VERTICAL);
+ list->add_widget(std::make_unique<Label>(&get_theme().body_font, "Where should temporary replay data be stored?", get_color_theme().text_color));
+ auto replay_storage_button = std::make_unique<RadioButton>(&get_theme().body_font, RadioButton::Orientation::HORIZONTAL);
+ replay_storage_button_ptr = replay_storage_button.get();
+ replay_storage_button->add_item("RAM", "ram");
+ replay_storage_button->add_item("Disk (Not recommended on SSDs)", "disk");
+
+ replay_storage_button->on_selection_changed = [this](const std::string&, const std::string &id) {
+ update_estimated_replay_file_size(id);
+ return true;
+ };
+
+ list->add_widget(std::move(replay_storage_button));
+ list->set_visible(gsr_info->system_info.gsr_version >= GsrVersion{5, 5, 0});
+ return list;
+ }
+
std::unique_ptr<RadioButton> SettingsPage::create_start_replay_automatically() {
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 applications only)");
@@ -692,13 +804,13 @@ namespace gsr {
return label;
}
- void SettingsPage::update_estimated_replay_file_size() {
+ void SettingsPage::update_estimated_replay_file_size(const std::string &replay_storage_type) {
const int64_t replay_time_seconds = atoi(replay_time_entry_ptr->get_text().c_str());
const int64_t video_bitrate_bps = atoi(video_bitrate_entry_ptr->get_text().c_str()) * 1000LL / 8LL;
const double video_filesize_mb = ((double)replay_time_seconds * (double)video_bitrate_bps) / 1000.0 / 1000.0 * 1.024;
char buffer[256];
- snprintf(buffer, sizeof(buffer), "Estimated video max file size in RAM: %.2fMB.\nChange video bitrate or replay duration to change file size.", video_filesize_mb);
+ snprintf(buffer, sizeof(buffer), "Estimated video max file size %s: %.2fMB.\nChange video bitrate or replay duration to change file size.", replay_storage_type == "ram" ? "in RAM" : "on disk", video_filesize_mb);
estimated_file_size_ptr->set_text(buffer);
}
@@ -716,6 +828,16 @@ namespace gsr {
replay_time_label_ptr->set_text(buffer);
}
+ void SettingsPage::view_changed(bool advanced_view, Subsection *notifications_subsection_ptr) {
+ color_range_list_ptr->set_visible(advanced_view);
+ audio_codec_ptr->set_visible(advanced_view);
+ video_codec_ptr->set_visible(advanced_view);
+ framerate_mode_list_ptr->set_visible(advanced_view);
+ notifications_subsection_ptr->set_visible(advanced_view);
+ set_application_audio_options_visible(audio_track_section_list_ptr, advanced_view, *gsr_info);
+ settings_scrollable_page_ptr->reset_scroll();
+ }
+
void SettingsPage::add_replay_widgets() {
auto file_info_list = std::make_unique<List>(List::Orientation::VERTICAL);
auto file_info_data_list = std::make_unique<List>(List::Orientation::HORIZONTAL);
@@ -727,12 +849,14 @@ 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)));
auto general_list = std::make_unique<List>(List::Orientation::VERTICAL);
- general_list->add_widget(create_start_replay_automatically());
+ general_list->add_widget(create_replay_storage());
general_list->add_widget(create_save_replay_in_game_folder());
if(gsr_info->system_info.gsr_version >= GsrVersion{5, 0, 3})
general_list->add_widget(create_restart_replay_on_save());
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>("Autostart", create_start_replay_automatically(), mgl::vec2f(settings_scrollable_page_ptr->get_inner_size().x, 0.0f)));
+
auto checkboxes_list = std::make_unique<List>(List::Orientation::VERTICAL);
auto show_replay_started_notification_checkbox = std::make_unique<CheckBox>(&get_theme().body_font, "Show replay started notification");
@@ -754,27 +878,19 @@ namespace gsr {
Subsection *notifications_subsection_ptr = notifications_subsection.get();
settings_list_ptr->add_widget(std::move(notifications_subsection));
- view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) {
- (void)text;
- const bool advanced_view = id == "advanced";
- color_range_list_ptr->set_visible(advanced_view);
- audio_codec_ptr->set_visible(advanced_view);
- video_codec_ptr->set_visible(advanced_view);
- framerate_mode_list_ptr->set_visible(advanced_view);
- notifications_subsection_ptr->set_visible(advanced_view);
- split_audio_checkbox_ptr->set_visible(advanced_view);
- settings_scrollable_page_ptr->reset_scroll();
+ view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) {
+ view_changed(id == "advanced", notifications_subsection_ptr);
return true;
};
view_radio_button_ptr->on_selection_changed("Simple", "simple");
replay_time_entry_ptr->on_changed = [this](const std::string&) {
- update_estimated_replay_file_size();
+ update_estimated_replay_file_size(replay_storage_button_ptr->get_selected_id());
update_replay_time_text();
};
video_bitrate_entry_ptr->on_changed = [this](const std::string&) {
- update_estimated_replay_file_size();
+ update_estimated_replay_file_size(replay_storage_button_ptr->get_selected_id());
};
}
@@ -828,16 +944,8 @@ namespace gsr {
Subsection *notifications_subsection_ptr = notifications_subsection.get();
settings_list_ptr->add_widget(std::move(notifications_subsection));
- view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) {
- (void)text;
- const bool advanced_view = id == "advanced";
- color_range_list_ptr->set_visible(advanced_view);
- audio_codec_ptr->set_visible(advanced_view);
- video_codec_ptr->set_visible(advanced_view);
- framerate_mode_list_ptr->set_visible(advanced_view);
- notifications_subsection_ptr->set_visible(advanced_view);
- split_audio_checkbox_ptr->set_visible(advanced_view);
- settings_scrollable_page_ptr->reset_scroll();
+ view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) {
+ view_changed(id == "advanced", notifications_subsection_ptr);
return true;
};
view_radio_button_ptr->on_selection_changed("Simple", "simple");
@@ -933,8 +1041,7 @@ namespace gsr {
Subsection *notifications_subsection_ptr = notifications_subsection.get();
settings_list_ptr->add_widget(std::move(notifications_subsection));
- streaming_service_box_ptr->on_selection_changed = [this](const std::string &text, const std::string &id) {
- (void)text;
+ streaming_service_box_ptr->on_selection_changed = [this](const std::string&, const std::string &id) {
const bool twitch_option = id == "twitch";
const bool youtube_option = id == "youtube";
const bool custom_option = id == "custom";
@@ -947,15 +1054,8 @@ namespace gsr {
};
streaming_service_box_ptr->on_selection_changed("Twitch", "twitch");
- view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string &text, const std::string &id) {
- (void)text;
- const bool advanced_view = id == "advanced";
- color_range_list_ptr->set_visible(advanced_view);
- audio_codec_ptr->set_visible(advanced_view);
- video_codec_ptr->set_visible(advanced_view);
- framerate_mode_list_ptr->set_visible(advanced_view);
- notifications_subsection_ptr->set_visible(advanced_view);
- settings_scrollable_page_ptr->reset_scroll();
+ view_radio_button_ptr->on_selection_changed = [this, notifications_subsection_ptr](const std::string&, const std::string &id) {
+ view_changed(id == "advanced", notifications_subsection_ptr);
return true;
};
view_radio_button_ptr->on_selection_changed("Simple", "simple");
@@ -1006,50 +1106,64 @@ namespace gsr {
return nullptr;
}
- 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;
- }
-
void SettingsPage::load_audio_tracks(const RecordOptions &record_options) {
- audio_track_list_ptr->clear();
- for(const std::string &audio_track : record_options.audio_tracks) {
- if(starts_with(audio_track, "app:")) {
- if(!gsr_info->system_info.supports_app_audio)
- continue;
-
- std::string audio_track_name = audio_track.substr(4);
- const std::string *app_audio = get_application_audio_by_name_case_insensitive(application_audio, audio_track_name);
- if(app_audio) {
- std::unique_ptr<List> application_audio_widget = create_application_audio();
- ComboBox *application_audio_box = static_cast<ComboBox*>(application_audio_widget->get_child_widget_by_index(1));
- application_audio_box->set_selected_item(*app_audio);
- audio_track_list_ptr->add_widget(std::move(application_audio_widget));
+ audio_track_section_list_ptr->clear();
+ for(const AudioTrack &audio_track : record_options.audio_tracks_list) {
+ auto audio_track_section = create_audio_track_section(audio_section_ptr);
+ List *audio_track_section_items_list_ptr = dynamic_cast<List*>(audio_track_section->get_inner_widget());
+ List *audio_input_list_ptr = dynamic_cast<List*>(audio_track_section_items_list_ptr->get_child_widget_by_index(2));
+ CheckBox *application_audio_invert_checkbox_ptr = dynamic_cast<CheckBox*>(audio_track_section_items_list_ptr->get_child_widget_by_index(3));
+ application_audio_invert_checkbox_ptr->set_checked(audio_track.application_audio_invert);
+
+ audio_input_list_ptr->clear();
+ for(const std::string &audio_input : audio_track.audio_inputs) {
+ if(starts_with(audio_input, "app:")) {
+ if(!gsr_info->system_info.supports_app_audio)
+ continue;
+
+ std::string audio_track_name = audio_input.substr(4);
+ const std::string *app_audio = get_application_audio_by_name_case_insensitive(application_audio, audio_track_name);
+ if(app_audio) {
+ std::unique_ptr<List> application_audio_widget = create_application_audio(audio_input_list_ptr);
+ ComboBox *application_audio_box = dynamic_cast<ComboBox*>(application_audio_widget->get_child_widget_by_index(1));
+ application_audio_box->set_selected_item(*app_audio);
+ audio_input_list_ptr->add_widget(std::move(application_audio_widget));
+ } else {
+ std::unique_ptr<List> application_audio_widget = create_custom_application_audio(audio_input_list_ptr);
+ Entry *application_audio_entry = dynamic_cast<Entry*>(application_audio_widget->get_child_widget_by_index(1));
+ application_audio_entry->set_text(std::move(audio_track_name));
+ audio_input_list_ptr->add_widget(std::move(application_audio_widget));
+ }
+ } else if(starts_with(audio_input, "device:")) {
+ const std::string device_name = audio_input.substr(7);
+ const AudioDeviceType audio_device_type = audio_device_is_output(device_name) ? AudioDeviceType::OUTPUT : AudioDeviceType::INPUT;
+ std::unique_ptr<List> audio_track_widget = create_audio_device(audio_device_type, audio_input_list_ptr);
+ ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1));
+ audio_device_box->set_selected_item(device_name);
+ audio_input_list_ptr->add_widget(std::move(audio_track_widget));
} else {
- std::unique_ptr<List> application_audio_widget = create_custom_application_audio();
- Entry *application_audio_entry = static_cast<Entry*>(application_audio_widget->get_child_widget_by_index(1));
- application_audio_entry->set_text(std::move(audio_track_name));
- audio_track_list_ptr->add_widget(std::move(application_audio_widget));
+ const AudioDeviceType audio_device_type = audio_device_is_output(audio_input) ? AudioDeviceType::OUTPUT : AudioDeviceType::INPUT;
+ std::unique_ptr<List> audio_track_widget = create_audio_device(audio_device_type, audio_input_list_ptr);
+ ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1));
+ audio_device_box->set_selected_item(audio_input);
+ audio_input_list_ptr->add_widget(std::move(audio_track_widget));
}
- } else if(starts_with(audio_track, "device:")) {
- std::unique_ptr<List> audio_track_widget = create_audio_device();
- ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1));
- audio_device_box->set_selected_item(audio_track.substr(7));
- audio_track_list_ptr->add_widget(std::move(audio_track_widget));
- } else {
- std::unique_ptr<List> audio_track_widget = create_audio_device();
- ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_widget->get_child_widget_by_index(1));
- audio_device_box->set_selected_item(audio_track);
- audio_track_list_ptr->add_widget(std::move(audio_track_widget));
}
+
+ audio_track_section_list_ptr->add_widget(std::move(audio_track_section));
+
+ if(type == Type::STREAM)
+ break;
+ }
+
+ if(type == Type::STREAM && audio_track_section_list_ptr->get_num_children() == 0) {
+ auto audio_track_section = create_audio_track_section(audio_section_ptr);
+ audio_track_section_list_ptr->add_widget(std::move(audio_track_section));
}
}
void SettingsPage::load_common(RecordOptions &record_options) {
record_area_box_ptr->set_selected_item(record_options.record_area_option);
- if(split_audio_checkbox_ptr)
- split_audio_checkbox_ptr->set_checked(!record_options.merge_audio_tracks);
- application_audio_invert_checkbox_ptr->set_checked(record_options.application_audio_invert);
change_video_resolution_checkbox_ptr->set_checked(record_options.change_video_resolution);
load_audio_tracks(record_options);
color_range_box_ptr->set_selected_item(record_options.color_range);
@@ -1102,6 +1216,7 @@ namespace gsr {
void SettingsPage::load_replay() {
load_common(config.replay_config.record_options);
+ replay_storage_button_ptr->set_selected_item(config.replay_config.replay_storage);
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);
if(restart_replay_on_save)
@@ -1114,8 +1229,8 @@ namespace gsr {
if(config.replay_config.replay_time < 2)
config.replay_config.replay_time = 2;
- if(config.replay_config.replay_time > 10800)
- config.replay_config.replay_time = 10800;
+ if(config.replay_config.replay_time > 86400)
+ config.replay_config.replay_time = 86400;
replay_time_entry_ptr->set_text(std::to_string(config.replay_config.replay_time));
}
@@ -1139,28 +1254,38 @@ namespace gsr {
container_box_ptr->set_selected_item(config.streaming_config.custom.container);
}
- static void save_audio_tracks(std::vector<std::string> &audio_devices, List *audio_devices_list_ptr) {
- audio_devices.clear();
- audio_devices_list_ptr->for_each_child_widget([&audio_devices](std::unique_ptr<Widget> &child_widget) {
- List *audio_track_line = static_cast<List*>(child_widget.get());
- const AudioTrackType audio_track_type = (AudioTrackType)(uintptr_t)audio_track_line->userdata;
- switch(audio_track_type) {
- case AudioTrackType::DEVICE: {
- ComboBox *audio_device_box = static_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1));
- audio_devices.push_back("device:" + audio_device_box->get_selected_id());
- break;
+ static void save_audio_tracks(std::vector<AudioTrack> &audio_tracks, List *audio_track_section_list_ptr) {
+ audio_tracks.clear();
+ audio_track_section_list_ptr->for_each_child_widget([&audio_tracks](std::unique_ptr<Widget> &child_widget) {
+ Subsection *audio_subsection = dynamic_cast<Subsection*>(child_widget.get());
+ List *audio_track_section_items_list_ptr = dynamic_cast<List*>(audio_subsection->get_inner_widget());
+ List *audio_input_list_ptr = dynamic_cast<List*>(audio_track_section_items_list_ptr->get_child_widget_by_index(2));
+ CheckBox *application_audio_invert_checkbox_ptr = dynamic_cast<CheckBox*>(audio_track_section_items_list_ptr->get_child_widget_by_index(3));
+
+ audio_tracks.push_back({std::vector<std::string>{}, application_audio_invert_checkbox_ptr->is_checked()});
+ audio_input_list_ptr->for_each_child_widget([&audio_tracks](std::unique_ptr<Widget> &child_widget){
+ List *audio_track_line = dynamic_cast<List*>(child_widget.get());
+ const AudioTrackType audio_track_type = (AudioTrackType)(uintptr_t)audio_track_line->userdata;
+ switch(audio_track_type) {
+ case AudioTrackType::DEVICE: {
+ ComboBox *audio_device_box = dynamic_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1));
+ audio_tracks.back().audio_inputs.push_back("device:" + audio_device_box->get_selected_id());
+ break;
+ }
+ case AudioTrackType::APPLICATION: {
+ ComboBox *application_audio_box = dynamic_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1));
+ audio_tracks.back().audio_inputs.push_back("app:" + application_audio_box->get_selected_id());
+ break;
+ }
+ case AudioTrackType::APPLICATION_CUSTOM: {
+ Entry *application_audio_entry = dynamic_cast<Entry*>(audio_track_line->get_child_widget_by_index(1));
+ audio_tracks.back().audio_inputs.push_back("app:" + application_audio_entry->get_text());
+ break;
+ }
}
- case AudioTrackType::APPLICATION: {
- ComboBox *application_audio_box = static_cast<ComboBox*>(audio_track_line->get_child_widget_by_index(1));
- audio_devices.push_back("app:" + application_audio_box->get_selected_id());
- break;
- }
- case AudioTrackType::APPLICATION_CUSTOM: {
- Entry *application_audio_entry = static_cast<Entry*>(audio_track_line->get_child_widget_by_index(1));
- audio_devices.push_back("app:" + application_audio_entry->get_text());
- break;
- }
- }
+ return true;
+ });
+
return true;
});
}
@@ -1173,11 +1298,8 @@ namespace gsr {
record_options.video_height = atoi(video_height_entry_ptr->get_text().c_str());
record_options.fps = atoi(framerate_entry_ptr->get_text().c_str());
record_options.video_bitrate = atoi(video_bitrate_entry_ptr->get_text().c_str());
- if(split_audio_checkbox_ptr)
- record_options.merge_audio_tracks = !split_audio_checkbox_ptr->is_checked();
- record_options.application_audio_invert = application_audio_invert_checkbox_ptr->is_checked();
record_options.change_video_resolution = change_video_resolution_checkbox_ptr->is_checked();
- save_audio_tracks(record_options.audio_tracks, audio_track_list_ptr);
+ save_audio_tracks(record_options.audio_tracks_list, audio_track_section_list_ptr);
record_options.color_range = color_range_box_ptr->get_selected_id();
record_options.video_quality = video_quality_box_ptr->get_selected_id();
record_options.video_codec = video_codec_box_ptr->get_selected_id();
@@ -1244,6 +1366,7 @@ namespace gsr {
config.replay_config.save_directory = save_directory_button_ptr->get_text();
config.replay_config.container = container_box_ptr->get_selected_id();
config.replay_config.replay_time = atoi(replay_time_entry_ptr->get_text().c_str());
+ config.replay_config.replay_storage = replay_storage_button_ptr->get_selected_id();
if(config.replay_config.replay_time < 5) {
config.replay_config.replay_time = 5;