mirror of
https://repo.dec05eba.com/gpu-screen-recorder-ui
synced 2026-03-31 09:17:04 +09:00
Redesign audio to support multiple audio tracks explicitly
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
#define FORMAT_U32 "%" PRIu32
|
||||
|
||||
namespace gsr {
|
||||
static const std::string_view add_audio_track_tag = "[add_audio_track]";
|
||||
|
||||
static std::vector<mgl::Keyboard::Key> hotkey_modifiers_to_mgl_keys(uint32_t modifiers) {
|
||||
std::vector<mgl::Keyboard::Key> result;
|
||||
if(modifiers & HOTKEY_MOD_LCTRL)
|
||||
@@ -101,6 +103,14 @@ namespace gsr {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AudioTrack::operator==(const AudioTrack &other) const {
|
||||
return audio_inputs == other.audio_inputs && application_audio_invert == other.application_audio_invert;
|
||||
}
|
||||
|
||||
bool AudioTrack::operator!=(const AudioTrack &other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
Config::Config(const SupportedCaptureOptions &capture_options) {
|
||||
const std::string default_videos_save_directory = get_videos_dir();
|
||||
const std::string default_pictures_save_directory = get_pictures_dir();
|
||||
@@ -108,16 +118,16 @@ namespace gsr {
|
||||
set_hotkeys_to_default();
|
||||
|
||||
streaming_config.record_options.video_quality = "custom";
|
||||
streaming_config.record_options.audio_tracks.push_back("default_output");
|
||||
streaming_config.record_options.audio_tracks_list.push_back({std::vector<std::string>{"default_output"}, false});
|
||||
streaming_config.record_options.video_bitrate = 15000;
|
||||
|
||||
record_config.save_directory = default_videos_save_directory;
|
||||
record_config.record_options.audio_tracks.push_back("default_output");
|
||||
record_config.record_options.audio_tracks_list.push_back({std::vector<std::string>{"default_output"}, false});
|
||||
record_config.record_options.video_bitrate = 45000;
|
||||
|
||||
replay_config.record_options.video_quality = "custom";
|
||||
replay_config.save_directory = default_videos_save_directory;
|
||||
replay_config.record_options.audio_tracks.push_back("default_output");
|
||||
replay_config.record_options.audio_tracks_list.push_back({std::vector<std::string>{"default_output"}, false});
|
||||
replay_config.record_options.video_bitrate = 45000;
|
||||
|
||||
screenshot_config.save_directory = default_pictures_save_directory;
|
||||
@@ -152,7 +162,7 @@ namespace gsr {
|
||||
return KeyValue{line.substr(0, space_index), line.substr(space_index + 1)};
|
||||
}
|
||||
|
||||
using ConfigValue = std::variant<bool*, std::string*, int32_t*, ConfigHotkey*, std::vector<std::string>*>;
|
||||
using ConfigValue = std::variant<bool*, std::string*, int32_t*, ConfigHotkey*, std::vector<std::string>*, std::vector<AudioTrack>*>;
|
||||
|
||||
static std::map<std::string_view, ConfigValue> get_config_options(Config &config) {
|
||||
return {
|
||||
@@ -174,6 +184,7 @@ namespace gsr {
|
||||
{"streaming.record_options.application_audio_invert", &config.streaming_config.record_options.application_audio_invert},
|
||||
{"streaming.record_options.change_video_resolution", &config.streaming_config.record_options.change_video_resolution},
|
||||
{"streaming.record_options.audio_track", &config.streaming_config.record_options.audio_tracks},
|
||||
{"streaming.record_options.audio_track_item", &config.streaming_config.record_options.audio_tracks_list},
|
||||
{"streaming.record_options.color_range", &config.streaming_config.record_options.color_range},
|
||||
{"streaming.record_options.video_quality", &config.streaming_config.record_options.video_quality},
|
||||
{"streaming.record_options.codec", &config.streaming_config.record_options.video_codec},
|
||||
@@ -203,6 +214,7 @@ namespace gsr {
|
||||
{"record.record_options.application_audio_invert", &config.record_config.record_options.application_audio_invert},
|
||||
{"record.record_options.change_video_resolution", &config.record_config.record_options.change_video_resolution},
|
||||
{"record.record_options.audio_track", &config.record_config.record_options.audio_tracks},
|
||||
{"record.record_options.audio_track_item", &config.record_config.record_options.audio_tracks_list},
|
||||
{"record.record_options.color_range", &config.record_config.record_options.color_range},
|
||||
{"record.record_options.video_quality", &config.record_config.record_options.video_quality},
|
||||
{"record.record_options.codec", &config.record_config.record_options.video_codec},
|
||||
@@ -231,6 +243,7 @@ namespace gsr {
|
||||
{"replay.record_options.application_audio_invert", &config.replay_config.record_options.application_audio_invert},
|
||||
{"replay.record_options.change_video_resolution", &config.replay_config.record_options.change_video_resolution},
|
||||
{"replay.record_options.audio_track", &config.replay_config.record_options.audio_tracks},
|
||||
{"replay.record_options.audio_track_item", &config.replay_config.record_options.audio_tracks_list},
|
||||
{"replay.record_options.color_range", &config.replay_config.record_options.color_range},
|
||||
{"replay.record_options.video_quality", &config.replay_config.record_options.video_quality},
|
||||
{"replay.record_options.codec", &config.replay_config.record_options.video_codec},
|
||||
@@ -291,6 +304,9 @@ namespace gsr {
|
||||
} else if(std::holds_alternative<std::vector<std::string>*>(it.second)) {
|
||||
if(*std::get<std::vector<std::string>*>(it.second) != *std::get<std::vector<std::string>*>(it_other->second))
|
||||
return false;
|
||||
} else if(std::holds_alternative<std::vector<AudioTrack>*>(it.second)) {
|
||||
if(*std::get<std::vector<AudioTrack>*>(it.second) != *std::get<std::vector<AudioTrack>*>(it_other->second))
|
||||
return false;
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -302,6 +318,17 @@ namespace gsr {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
static void populate_new_audio_track_from_old(RecordOptions &record_options) {
|
||||
if(record_options.merge_audio_tracks) {
|
||||
record_options.audio_tracks_list.push_back({std::move(record_options.audio_tracks), record_options.application_audio_invert});
|
||||
} else {
|
||||
for(const std::string &audio_input : record_options.audio_tracks) {
|
||||
record_options.audio_tracks_list.push_back({std::vector<std::string>{audio_input}, record_options.application_audio_invert});
|
||||
}
|
||||
}
|
||||
record_options.audio_tracks.clear();
|
||||
}
|
||||
|
||||
std::optional<Config> read_config(const SupportedCaptureOptions &capture_options) {
|
||||
std::optional<Config> config;
|
||||
|
||||
@@ -313,10 +340,15 @@ namespace gsr {
|
||||
}
|
||||
|
||||
config = Config(capture_options);
|
||||
|
||||
config->streaming_config.record_options.audio_tracks.clear();
|
||||
config->record_config.record_options.audio_tracks.clear();
|
||||
config->replay_config.record_options.audio_tracks.clear();
|
||||
|
||||
config->streaming_config.record_options.audio_tracks_list.clear();
|
||||
config->record_config.record_options.audio_tracks_list.clear();
|
||||
config->replay_config.record_options.audio_tracks_list.clear();
|
||||
|
||||
auto config_options = get_config_options(config.value());
|
||||
|
||||
string_split_char(file_content, '\n', [&](std::string_view line) {
|
||||
@@ -355,6 +387,23 @@ namespace gsr {
|
||||
} else if(std::holds_alternative<std::vector<std::string>*>(it->second)) {
|
||||
std::string array_value(key_value->value);
|
||||
std::get<std::vector<std::string>*>(it->second)->push_back(std::move(array_value));
|
||||
} else if(std::holds_alternative<std::vector<AudioTrack>*>(it->second)) {
|
||||
const size_t space_index = key_value->value.find(' ');
|
||||
if(space_index == std::string_view::npos) {
|
||||
fprintf(stderr, "Warning: Invalid config option value for %.*s\n", (int)key_value->key.size(), key_value->key.data());
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool application_audio_invert = key_value->value.substr(0, space_index) == "true";
|
||||
const std::string_view audio_input = key_value->value.substr(space_index + 1);
|
||||
std::vector<AudioTrack> &audio_tracks = *std::get<std::vector<AudioTrack>*>(it->second);
|
||||
|
||||
if(audio_input == add_audio_track_tag) {
|
||||
audio_tracks.push_back({std::vector<std::string>{}, application_audio_invert});
|
||||
} else if(!audio_tracks.empty()) {
|
||||
audio_tracks.back().application_audio_invert = application_audio_invert;
|
||||
audio_tracks.back().audio_inputs.emplace_back(audio_input);
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -362,11 +411,16 @@ namespace gsr {
|
||||
return true;
|
||||
});
|
||||
|
||||
if(config->main_config.config_file_version != GSR_CONFIG_FILE_VERSION) {
|
||||
fprintf(stderr, "Info: the config file is outdated, resetting it\n");
|
||||
config = std::nullopt;
|
||||
if(config->main_config.config_file_version == 1) {
|
||||
populate_new_audio_track_from_old(config->streaming_config.record_options);
|
||||
populate_new_audio_track_from_old(config->record_config.record_options);
|
||||
populate_new_audio_track_from_old(config->replay_config.record_options);
|
||||
}
|
||||
|
||||
config->streaming_config.record_options.audio_tracks.clear();
|
||||
config->record_config.record_options.audio_tracks.clear();
|
||||
config->replay_config.record_options.audio_tracks.clear();
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -402,9 +456,17 @@ namespace gsr {
|
||||
const ConfigHotkey *config_hotkey = std::get<ConfigHotkey*>(it.second);
|
||||
fprintf(file, "%.*s " FORMAT_I64 " " FORMAT_U32 "\n", (int)it.first.size(), it.first.data(), config_hotkey->key, config_hotkey->modifiers);
|
||||
} else if(std::holds_alternative<std::vector<std::string>*>(it.second)) {
|
||||
std::vector<std::string> *array = std::get<std::vector<std::string>*>(it.second);
|
||||
for(const std::string &value : *array) {
|
||||
fprintf(file, "%.*s %s\n", (int)it.first.size(), it.first.data(), value.c_str());
|
||||
std::vector<std::string> *audio_inputs = std::get<std::vector<std::string>*>(it.second);
|
||||
for(const std::string &audio_input : *audio_inputs) {
|
||||
fprintf(file, "%.*s %s\n", (int)it.first.size(), it.first.data(), audio_input.c_str());
|
||||
}
|
||||
} else if(std::holds_alternative<std::vector<AudioTrack>*>(it.second)) {
|
||||
std::vector<AudioTrack> *audio_tracks = std::get<std::vector<AudioTrack>*>(it.second);
|
||||
for(const AudioTrack &audio_track : *audio_tracks) {
|
||||
fprintf(file, "%.*s %s %.*s\n", (int)it.first.size(), it.first.data(), audio_track.application_audio_invert ? "true" : "false", (int)add_audio_track_tag.size(), add_audio_track_tag.data());
|
||||
for(const std::string &audio_input : audio_track.audio_inputs) {
|
||||
fprintf(file, "%.*s %s %s\n", (int)it.first.size(), it.first.data(), audio_track.application_audio_invert ? "true" : "false", audio_input.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
|
||||
@@ -77,6 +77,8 @@ namespace gsr {
|
||||
fprintf(stderr, "Error: GlobalHotkeysLinux::~GlobalHotkeysLinux: failed to write command to gsr-global-hotkeys, error: %s\n", strerror(errno));
|
||||
close_fds();
|
||||
}
|
||||
} else {
|
||||
close_fds();
|
||||
}
|
||||
|
||||
if(process_id > 0) {
|
||||
|
||||
@@ -175,11 +175,6 @@ namespace gsr {
|
||||
CAPTURE_OPTIONS
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
GsrInfoExitStatus get_gpu_screen_recorder_info(GsrInfo *gsr_info) {
|
||||
*gsr_info = GsrInfo{};
|
||||
|
||||
|
||||
117
src/Overlay.cpp
117
src/Overlay.cpp
@@ -685,6 +685,8 @@ namespace gsr {
|
||||
}
|
||||
|
||||
bool Overlay::draw() {
|
||||
remove_widgets_to_be_removed();
|
||||
|
||||
update_notification_process_status();
|
||||
update_gsr_replay_save();
|
||||
update_gsr_process_status();
|
||||
@@ -1249,6 +1251,7 @@ namespace gsr {
|
||||
while(!page_stack.empty()) {
|
||||
page_stack.pop();
|
||||
}
|
||||
remove_widgets_to_be_removed();
|
||||
|
||||
if(default_cursor) {
|
||||
XFreeCursor(display, default_cursor);
|
||||
@@ -1742,28 +1745,25 @@ namespace gsr {
|
||||
gpu_screen_recorder_screenshot_process = -1;
|
||||
}
|
||||
|
||||
static bool starts_with(std::string_view str, const char *substr) {
|
||||
size_t len = strlen(substr);
|
||||
return str.size() >= len && memcmp(str.data(), substr, len) == 0;
|
||||
}
|
||||
|
||||
static bool are_all_audio_tracks_available_to_capture(const std::vector<std::string> &audio_tracks) {
|
||||
static bool are_all_audio_tracks_available_to_capture(const std::vector<AudioTrack> &audio_tracks) {
|
||||
const auto audio_devices = get_audio_devices();
|
||||
for(const std::string &audio_track : audio_tracks) {
|
||||
std::string_view audio_track_name(audio_track.c_str());
|
||||
const bool is_app_audio = starts_with(audio_track_name, "app:");
|
||||
if(is_app_audio)
|
||||
continue;
|
||||
for(const AudioTrack &audio_track : audio_tracks) {
|
||||
for(const std::string &audio_input : audio_track.audio_inputs) {
|
||||
std::string_view audio_track_name(audio_input.c_str());
|
||||
const bool is_app_audio = starts_with(audio_track_name, "app:");
|
||||
if(is_app_audio)
|
||||
continue;
|
||||
|
||||
if(starts_with(audio_track_name, "device:"))
|
||||
audio_track_name.remove_prefix(7);
|
||||
if(starts_with(audio_track_name, "device:"))
|
||||
audio_track_name.remove_prefix(7);
|
||||
|
||||
auto it = std::find_if(audio_devices.begin(), audio_devices.end(), [&](const auto &audio_device) {
|
||||
return audio_device.name == audio_track_name;
|
||||
});
|
||||
if(it == audio_devices.end()) {
|
||||
//fprintf(stderr, "Audio not ready\n");
|
||||
return false;
|
||||
auto it = std::find_if(audio_devices.begin(), audio_devices.end(), [&](const auto &audio_device) {
|
||||
return audio_device.name == audio_track_name;
|
||||
});
|
||||
if(it == audio_devices.end()) {
|
||||
//fprintf(stderr, "Audio not ready\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -1794,7 +1794,7 @@ namespace gsr {
|
||||
focused_window_is_fullscreen = focused_window != 0 && window_is_fullscreen(display, focused_window);
|
||||
if(focused_window_is_fullscreen != prev_focused_window_is_fullscreen) {
|
||||
if(recording_status == RecordingStatus::NONE && focused_window_is_fullscreen) {
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks))
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list))
|
||||
on_press_start_replay(false, false);
|
||||
} else if(recording_status == RecordingStatus::REPLAY && !focused_window_is_fullscreen) {
|
||||
on_press_start_replay(true, false);
|
||||
@@ -1811,7 +1811,7 @@ namespace gsr {
|
||||
power_supply_connected = power_supply_online_filepath.empty() || power_supply_is_connected(power_supply_online_filepath.c_str());
|
||||
if(power_supply_connected != prev_power_supply_status) {
|
||||
if(recording_status == RecordingStatus::NONE && power_supply_connected) {
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks))
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list))
|
||||
on_press_start_replay(false, false);
|
||||
} else if(recording_status == RecordingStatus::REPLAY && !power_supply_connected) {
|
||||
on_press_start_replay(false, false);
|
||||
@@ -1823,7 +1823,7 @@ namespace gsr {
|
||||
if(replay_startup_mode != ReplayStartupMode::TURN_ON_AT_SYSTEM_STARTUP || recording_status != RecordingStatus::NONE || !try_replay_startup)
|
||||
return;
|
||||
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks))
|
||||
if(are_all_audio_tracks_available_to_capture(config.replay_config.record_options.audio_tracks_list))
|
||||
on_press_start_replay(true, false);
|
||||
}
|
||||
|
||||
@@ -1947,29 +1947,31 @@ namespace gsr {
|
||||
return container;
|
||||
}
|
||||
|
||||
static std::vector<std::string> create_audio_tracks_real_names(const std::vector<std::string> &audio_tracks, bool application_audio_invert, const GsrInfo &gsr_info) {
|
||||
static std::vector<std::string> create_audio_tracks_cli_args(const std::vector<AudioTrack> &audio_tracks, const GsrInfo &gsr_info) {
|
||||
std::vector<std::string> result;
|
||||
for(const std::string &audio_track : audio_tracks) {
|
||||
std::string audio_track_name = audio_track;
|
||||
const bool is_app_audio = starts_with(audio_track_name, "app:");
|
||||
if(is_app_audio && !gsr_info.system_info.supports_app_audio)
|
||||
continue;
|
||||
result.reserve(audio_tracks.size());
|
||||
|
||||
if(is_app_audio && application_audio_invert)
|
||||
audio_track_name.replace(0, 4, "app-inverse:");
|
||||
for(const AudioTrack &audio_track : audio_tracks) {
|
||||
std::string audio_track_merged;
|
||||
for(const std::string &audio_input_name : audio_track.audio_inputs) {
|
||||
std::string new_audio_input_name = audio_input_name;
|
||||
const bool is_app_audio = starts_with(new_audio_input_name, "app:");
|
||||
if(is_app_audio && !gsr_info.system_info.supports_app_audio)
|
||||
continue;
|
||||
|
||||
result.push_back(std::move(audio_track_name));
|
||||
if(is_app_audio && audio_track.application_audio_invert)
|
||||
new_audio_input_name.replace(0, 4, "app-inverse:");
|
||||
|
||||
if(!audio_track_merged.empty())
|
||||
audio_track_merged += "|";
|
||||
|
||||
audio_track_merged += new_audio_input_name;
|
||||
}
|
||||
|
||||
if(!audio_track_merged.empty())
|
||||
result.push_back(std::move(audio_track_merged));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string merge_audio_tracks(const std::vector<std::string> &audio_tracks) {
|
||||
std::string result;
|
||||
for(size_t i = 0; i < audio_tracks.size(); ++i) {
|
||||
if(i > 0)
|
||||
result += "|";
|
||||
result += audio_tracks[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1984,7 +1986,7 @@ namespace gsr {
|
||||
args.push_back(region_str);
|
||||
}
|
||||
|
||||
static void add_common_gpu_screen_recorder_args(std::vector<const char*> &args, const RecordOptions &record_options, const std::vector<std::string> &audio_tracks, const std::string &video_bitrate, const char *region, const std::string &audio_devices_merged, char *region_str, int region_str_size, const RegionSelector ®ion_selector) {
|
||||
static void add_common_gpu_screen_recorder_args(std::vector<const char*> &args, const RecordOptions &record_options, const std::vector<std::string> &audio_tracks, const std::string &video_bitrate, const char *region, char *region_str, int region_str_size, const RegionSelector ®ion_selector) {
|
||||
if(record_options.video_quality == "custom") {
|
||||
args.push_back("-bm");
|
||||
args.push_back("cbr");
|
||||
@@ -2000,16 +2002,9 @@ namespace gsr {
|
||||
args.push_back(region);
|
||||
}
|
||||
|
||||
if(record_options.merge_audio_tracks) {
|
||||
if(!audio_devices_merged.empty()) {
|
||||
args.push_back("-a");
|
||||
args.push_back(audio_devices_merged.c_str());
|
||||
}
|
||||
} else {
|
||||
for(const std::string &audio_track : audio_tracks) {
|
||||
args.push_back("-a");
|
||||
args.push_back(audio_track.c_str());
|
||||
}
|
||||
for(const std::string &audio_track : audio_tracks) {
|
||||
args.push_back("-a");
|
||||
args.push_back(audio_track.c_str());
|
||||
}
|
||||
|
||||
if(record_options.restore_portal_session) {
|
||||
@@ -2133,8 +2128,7 @@ namespace gsr {
|
||||
const std::string fps = std::to_string(config.replay_config.record_options.fps);
|
||||
const std::string video_bitrate = std::to_string(config.replay_config.record_options.video_bitrate);
|
||||
const std::string output_directory = config.replay_config.save_directory;
|
||||
const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.replay_config.record_options.audio_tracks, config.replay_config.record_options.application_audio_invert, gsr_info);
|
||||
const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks);
|
||||
const std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.replay_config.record_options.audio_tracks_list, gsr_info);
|
||||
const std::string framerate_mode = config.replay_config.record_options.framerate_mode == "auto" ? "vfr" : config.replay_config.record_options.framerate_mode;
|
||||
const std::string replay_time = std::to_string(config.replay_config.replay_time);
|
||||
const char *video_codec = config.replay_config.record_options.video_codec.c_str();
|
||||
@@ -2173,7 +2167,7 @@ namespace gsr {
|
||||
}
|
||||
|
||||
char region_str[128];
|
||||
add_common_gpu_screen_recorder_args(args, config.replay_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, region_str, sizeof(region_str), region_selector);
|
||||
add_common_gpu_screen_recorder_args(args, config.replay_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector);
|
||||
|
||||
args.push_back(nullptr);
|
||||
|
||||
@@ -2276,8 +2270,7 @@ namespace gsr {
|
||||
const std::string fps = std::to_string(config.record_config.record_options.fps);
|
||||
const std::string video_bitrate = std::to_string(config.record_config.record_options.video_bitrate);
|
||||
const std::string output_file = config.record_config.save_directory + "/Video_" + get_date_str() + "." + container_to_file_extension(config.record_config.container.c_str());
|
||||
const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.record_config.record_options.audio_tracks, config.record_config.record_options.application_audio_invert, gsr_info);
|
||||
const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks);
|
||||
const std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.record_config.record_options.audio_tracks_list, gsr_info);
|
||||
const std::string framerate_mode = config.record_config.record_options.framerate_mode == "auto" ? "vfr" : config.record_config.record_options.framerate_mode;
|
||||
const char *video_codec = config.record_config.record_options.video_codec.c_str();
|
||||
const char *encoder = "gpu";
|
||||
@@ -2309,7 +2302,7 @@ namespace gsr {
|
||||
};
|
||||
|
||||
char region_str[128];
|
||||
add_common_gpu_screen_recorder_args(args, config.record_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, region_str, sizeof(region_str), region_selector);
|
||||
add_common_gpu_screen_recorder_args(args, config.record_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector);
|
||||
|
||||
args.push_back(nullptr);
|
||||
|
||||
@@ -2429,8 +2422,11 @@ namespace gsr {
|
||||
// TODO: Validate input, fallback to valid values
|
||||
const std::string fps = std::to_string(config.streaming_config.record_options.fps);
|
||||
const std::string video_bitrate = std::to_string(config.streaming_config.record_options.video_bitrate);
|
||||
const std::vector<std::string> audio_tracks = create_audio_tracks_real_names(config.streaming_config.record_options.audio_tracks, config.streaming_config.record_options.application_audio_invert, gsr_info);
|
||||
const std::string audio_tracks_merged = merge_audio_tracks(audio_tracks);
|
||||
std::vector<std::string> audio_tracks = create_audio_tracks_cli_args(config.streaming_config.record_options.audio_tracks_list, gsr_info);
|
||||
// This isn't possible unless the user modified the config file manually,
|
||||
// But we check it anyways as streaming on some sites can fail if there is more than one audio track
|
||||
if(audio_tracks.size() > 1)
|
||||
audio_tracks.resize(1);
|
||||
const std::string framerate_mode = config.streaming_config.record_options.framerate_mode == "auto" ? "vfr" : config.streaming_config.record_options.framerate_mode;
|
||||
const char *video_codec = config.streaming_config.record_options.video_codec.c_str();
|
||||
const char *encoder = "gpu";
|
||||
@@ -2466,9 +2462,8 @@ namespace gsr {
|
||||
"-o", url.c_str()
|
||||
};
|
||||
|
||||
config.streaming_config.record_options.merge_audio_tracks = true;
|
||||
char region_str[128];
|
||||
add_common_gpu_screen_recorder_args(args, config.streaming_config.record_options, audio_tracks, video_bitrate, size, audio_tracks_merged, region_str, sizeof(region_str), region_selector);
|
||||
add_common_gpu_screen_recorder_args(args, config.streaming_config.record_options, audio_tracks, video_bitrate, size, region_str, sizeof(region_str), region_selector);
|
||||
|
||||
args.push_back(nullptr);
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace gsr {
|
||||
if(!theme->folder_texture.load_from_file((resources_path + "images/folder.png").c_str()))
|
||||
goto error;
|
||||
|
||||
if(!theme->up_arrow_texture.load_from_file((resources_path + "images/up_arrow.png").c_str()))
|
||||
if(!theme->up_arrow_texture.load_from_file((resources_path + "images/up_arrow.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
|
||||
goto error;
|
||||
|
||||
if(!theme->replay_button_texture.load_from_file((resources_path + "images/replay.png").c_str()))
|
||||
@@ -93,10 +93,10 @@ namespace gsr {
|
||||
if(!theme->logo_texture.load_from_file((resources_path + "images/gpu_screen_recorder_logo.png").c_str()))
|
||||
goto error;
|
||||
|
||||
if(!theme->checkbox_circle_texture.load_from_file((resources_path + "images/checkbox_circle.png").c_str()))
|
||||
if(!theme->checkbox_circle_texture.load_from_file((resources_path + "images/checkbox_circle.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
|
||||
goto error;
|
||||
|
||||
if(!theme->checkbox_background_texture.load_from_file((resources_path + "images/checkbox_background.png").c_str()))
|
||||
if(!theme->checkbox_background_texture.load_from_file((resources_path + "images/checkbox_background.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
|
||||
goto error;
|
||||
|
||||
if(!theme->play_texture.load_from_file((resources_path + "images/play.png").c_str()))
|
||||
@@ -114,6 +114,9 @@ namespace gsr {
|
||||
if(!theme->screenshot_texture.load_from_file((resources_path + "images/screenshot.png").c_str()))
|
||||
goto error;
|
||||
|
||||
if(!theme->trash_texture.load_from_file((resources_path + "images/trash.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
|
||||
goto error;
|
||||
|
||||
if(!theme->ps4_home_texture.load_from_file((resources_path + "images/ps4_home.png").c_str(), mgl::Texture::LoadOptions{false, false, true}))
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -22,6 +22,11 @@ namespace gsr {
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string get_home_dir() {
|
||||
const char *home_dir = getenv("HOME");
|
||||
if(!home_dir) {
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace gsr {
|
||||
|
||||
void ComboBox::add_item(const std::string &text, const std::string &id) {
|
||||
items.push_back({mgl::Text(text, *font), id, {0.0f, 0.0f}});
|
||||
items.back().text.set_max_width(font->get_character_size() * 22); // TODO: Make a proper solution
|
||||
items.back().text.set_max_width(font->get_character_size() * 25); // TODO: Make a proper solution
|
||||
//items.back().text.set_max_rows(1);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ namespace gsr {
|
||||
tint_color_radio_button_ptr = tint_color_radio_button.get();
|
||||
tint_color_radio_button->add_item("Red", "amd");
|
||||
tint_color_radio_button->add_item("Green", "nvidia");
|
||||
tint_color_radio_button->add_item("blue", "intel");
|
||||
tint_color_radio_button->add_item("Blue", "intel");
|
||||
tint_color_radio_button->on_selection_changed = [](const std::string&, const std::string &id) {
|
||||
if(id == "amd")
|
||||
get_color_theme().tint_color = mgl::Color(221, 0, 49);
|
||||
|
||||
@@ -39,8 +39,9 @@ namespace gsr {
|
||||
|
||||
// Process widgets by visibility (backwards)
|
||||
return widgets.for_each_reverse([selected_widget, &window, &event, content_page_position](std::unique_ptr<Widget> &widget) {
|
||||
if(widget.get() != selected_widget) {
|
||||
if(!widget->on_event(event, window, content_page_position))
|
||||
Widget *p = widget.get();
|
||||
if(p != selected_widget) {
|
||||
if(!p->on_event(event, window, content_page_position))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -24,14 +24,23 @@ namespace gsr {
|
||||
// Process widgets by visibility (backwards)
|
||||
return widgets.for_each_reverse([selected_widget, &event, &window](std::unique_ptr<Widget> &widget) {
|
||||
// Ignore offset because widgets are positioned with offset in ::draw, this solution is simpler
|
||||
if(widget.get() != selected_widget) {
|
||||
if(!widget->on_event(event, window, mgl::vec2f(0.0f, 0.0f)))
|
||||
Widget *p = widget.get();
|
||||
if(p != selected_widget) {
|
||||
if(!p->on_event(event, window, mgl::vec2f(0.0f, 0.0f)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
List::~List() {
|
||||
widgets.for_each([this](std::unique_ptr<Widget> &widget) {
|
||||
if(widget->parent_widget == this)
|
||||
widget->parent_widget = nullptr;
|
||||
return true;
|
||||
}, true);
|
||||
}
|
||||
|
||||
void List::draw(mgl::Window &window, mgl::vec2f offset) {
|
||||
if(!visible)
|
||||
return;
|
||||
@@ -104,15 +113,6 @@ namespace gsr {
|
||||
selected_widget->draw(window, mgl::vec2f(0.0f, 0.0f));
|
||||
}
|
||||
|
||||
// void List::remove_child_widget(Widget *widget) {
|
||||
// for(auto it = widgets.begin(), end = widgets.end(); it != end; ++it) {
|
||||
// if(it->get() == widget) {
|
||||
// widgets.erase(it);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
void List::add_widget(std::unique_ptr<Widget> widget) {
|
||||
widget->parent_widget = this;
|
||||
widgets.push_back(std::move(widget));
|
||||
@@ -122,6 +122,10 @@ namespace gsr {
|
||||
widgets.remove(widget);
|
||||
}
|
||||
|
||||
void List::replace_widget(Widget *widget, std::unique_ptr<Widget> new_widget) {
|
||||
widgets.replace_item(widget, std::move(new_widget));
|
||||
}
|
||||
|
||||
void List::clear() {
|
||||
widgets.clear();
|
||||
}
|
||||
@@ -137,6 +141,10 @@ namespace gsr {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t List::get_num_children() const {
|
||||
return widgets.size();
|
||||
}
|
||||
|
||||
void List::set_spacing(float spacing) {
|
||||
spacing_scale = spacing;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include "../../include/gui/Page.hpp"
|
||||
|
||||
namespace gsr {
|
||||
// void Page::remove_child_widget(Widget *widget) {
|
||||
// for(auto it = widgets.begin(), end = widgets.end(); it != end; ++it) {
|
||||
// if(it->get() == widget) {
|
||||
// widgets.erase(it);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Page::~Page() {
|
||||
widgets.for_each([this](std::unique_ptr<Widget> &widget) {
|
||||
if(widget->parent_widget == this)
|
||||
widget->parent_widget = nullptr;
|
||||
return true;
|
||||
}, true);
|
||||
}
|
||||
|
||||
void Page::add_widget(std::unique_ptr<Widget> widget) {
|
||||
widget->parent_widget = this;
|
||||
|
||||
@@ -257,8 +257,7 @@ namespace gsr {
|
||||
void ScreenshotSettingsPage::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 portal_selected = id == "portal";
|
||||
select_window_list_ptr->set_visible(window_selected);
|
||||
|
||||
@@ -15,6 +15,14 @@ namespace gsr {
|
||||
|
||||
ScrollablePage::ScrollablePage(mgl::vec2f size) : size(size) {}
|
||||
|
||||
ScrollablePage::~ScrollablePage() {
|
||||
widgets.for_each([this](std::unique_ptr<Widget> &widget) {
|
||||
if(widget->parent_widget == this)
|
||||
widget->parent_widget = nullptr;
|
||||
return true;
|
||||
}, true);
|
||||
}
|
||||
|
||||
bool ScrollablePage::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f offset) {
|
||||
if(!visible)
|
||||
return true;
|
||||
@@ -57,8 +65,9 @@ namespace gsr {
|
||||
|
||||
// Process widgets by visibility (backwards)
|
||||
const bool continue_events = widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) {
|
||||
if(widget.get() != selected_widget) {
|
||||
if(!widget->on_event(event, window, offset))
|
||||
Widget *p = widget.get();
|
||||
if(p != selected_widget) {
|
||||
if(!p->on_event(event, window, offset))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <string.h>
|
||||
|
||||
namespace gsr {
|
||||
static const char *custom_app_audio_tag = "[custom]";
|
||||
|
||||
enum class AudioTrackType {
|
||||
DEVICE,
|
||||
APPLICATION,
|
||||
@@ -202,121 +204,199 @@ namespace gsr {
|
||||
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(1));
|
||||
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(35, 40, 44));
|
||||
remove_audio_track_button->set_icon(&get_theme().trash_texture);
|
||||
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(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(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() {
|
||||
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_device_button(List *audio_input_list_ptr) {
|
||||
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]() {
|
||||
add_audio_track_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(audio_input_list_ptr));
|
||||
};
|
||||
return add_audio_track_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(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<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());
|
||||
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<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());
|
||||
};
|
||||
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_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(35, 40, 44));
|
||||
remove_track_button->set_icon(&get_theme().trash_texture);
|
||||
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->add_widget(create_add_audio_buttons());
|
||||
list->add_widget(create_audio_track_track_section());
|
||||
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);
|
||||
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 +611,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 +628,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 +647,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() {
|
||||
@@ -716,6 +788,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);
|
||||
@@ -754,16 +836,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");
|
||||
@@ -828,16 +902,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 +999,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 +1012,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 +1064,61 @@ 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;
|
||||
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);
|
||||
|
||||
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_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:")) {
|
||||
std::unique_ptr<List> audio_track_widget = create_audio_device(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.substr(7));
|
||||
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));
|
||||
std::unique_ptr<List> audio_track_widget = create_audio_device(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);
|
||||
@@ -1139,28 +1208,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 +1252,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();
|
||||
|
||||
@@ -20,8 +20,9 @@ namespace gsr {
|
||||
|
||||
// Process widgets by visibility (backwards)
|
||||
return widgets.for_each_reverse([selected_widget, &window, &event, offset](std::unique_ptr<Widget> &widget) {
|
||||
if(widget.get() != selected_widget) {
|
||||
if(!widget->on_event(event, window, offset))
|
||||
Widget *p = widget.get();
|
||||
if(p != selected_widget) {
|
||||
if(!p->on_event(event, window, offset))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -12,12 +12,17 @@ namespace gsr {
|
||||
static const float title_spacing_scale = 0.010f;
|
||||
|
||||
Subsection::Subsection(const char *title, std::unique_ptr<Widget> inner_widget, mgl::vec2f size) :
|
||||
label(&get_theme().title_font, title, get_color_theme().text_color),
|
||||
label(&get_theme().title_font, title ? title : "", get_color_theme().text_color),
|
||||
inner_widget(std::move(inner_widget)),
|
||||
size(size)
|
||||
{
|
||||
this->inner_widget->parent_widget = this;
|
||||
}
|
||||
|
||||
Subsection::~Subsection() {
|
||||
if(inner_widget->parent_widget == this)
|
||||
inner_widget->parent_widget = nullptr;
|
||||
}
|
||||
|
||||
bool Subsection::on_event(mgl::Event &event, mgl::Window &window, mgl::vec2f) {
|
||||
if(!visible)
|
||||
@@ -32,7 +37,7 @@ namespace gsr {
|
||||
|
||||
mgl::vec2f draw_pos = position + offset;
|
||||
mgl::Rectangle background(draw_pos.floor(), get_size().floor());
|
||||
background.set_color(mgl::Color(25, 30, 34));
|
||||
background.set_color(bg_color);
|
||||
window.draw(background);
|
||||
|
||||
draw_pos += mgl::vec2f(margin_left_scale, margin_top_scale) * mgl::vec2f(get_theme().window_height, get_theme().window_height);
|
||||
@@ -69,4 +74,12 @@ namespace gsr {
|
||||
const mgl::vec2f margin_size = mgl::vec2f(margin_left_scale + margin_right_scale, margin_top_scale + margin_bottom_scale) * mgl::vec2f(get_theme().window_height, get_theme().window_height);
|
||||
return get_size() - margin_size;
|
||||
}
|
||||
|
||||
Widget* Subsection::get_inner_widget() {
|
||||
return inner_widget.get();
|
||||
}
|
||||
|
||||
void Subsection::set_bg_color(mgl::Color color) {
|
||||
bg_color = color;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
#include "../../include/gui/Widget.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace gsr {
|
||||
static std::vector<std::unique_ptr<Widget>> widgets_to_remove;
|
||||
|
||||
Widget::Widget() {
|
||||
|
||||
}
|
||||
|
||||
Widget::~Widget() {
|
||||
remove_widget_as_selected_in_parent();
|
||||
// if(parent_widget)
|
||||
// parent_widget->remove_child_widget(this);
|
||||
}
|
||||
|
||||
void Widget::set_position(mgl::vec2f position) {
|
||||
@@ -62,4 +63,15 @@ namespace gsr {
|
||||
void Widget::set_visible(bool visible) {
|
||||
this->visible = visible;
|
||||
}
|
||||
|
||||
void add_widget_to_remove(std::unique_ptr<Widget> widget) {
|
||||
widgets_to_remove.push_back(std::move(widget));
|
||||
}
|
||||
|
||||
void remove_widgets_to_be_removed() {
|
||||
for(size_t i = 0; i < widgets_to_remove.size(); ++i) {
|
||||
widgets_to_remove[i].reset();
|
||||
}
|
||||
widgets_to_remove.clear();
|
||||
}
|
||||
}
|
||||
@@ -303,7 +303,10 @@ int main(int argc, char **argv) {
|
||||
if(exit_reason == "back-to-old-ui") {
|
||||
const char *args[] = { "gpu-screen-recorder-gtk", "use-old-ui", nullptr };
|
||||
execvp(args[0], (char* const*)args);
|
||||
return 0;
|
||||
} else if(exit_reason == "exit") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return mgl_is_connected_to_display_server() ? 0 : 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user