aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--TODO7
-rw-r--r--src/config.hpp6
-rw-r--r--src/main.cpp310
4 files changed, 296 insertions, 29 deletions
diff --git a/README.md b/README.md
index a6ab1d4..8072785 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ There is a new alternative UI for GPU Screen Recorder in the style of ShadowPlay
# Installation
This program depends on [GPU Screen Recorder](https://git.dec05eba.com/gpu-screen-recorder/) which needs to be installed first.\
-Run `sudo ./install.sh` or if you are running Arch Linux, then you can find gpu screen recorder gtk on aur under the name gpu-screen-recorder-gtk-git (`yay -S gpu-screen-recorder-gtk-git`).\
+Run `sudo ./install.sh` or if you are running Arch Linux, then you can find gpu screen recorder gtk on aur under the name gpu-screen-recorder-gtk (`yay -S gpu-screen-recorder-gtk`).\
You can also install gpu screen recorder (the gtk gui version) from [flathub](https://flathub.org/apps/details/com.dec05eba.gpu_screen_recorder). This flatpak includes gpu-screen-recorder so no need to install that first.
# Dependencies
diff --git a/TODO b/TODO
index 6e79dd5..cc2ae46 100644
--- a/TODO
+++ b/TODO
@@ -66,3 +66,10 @@ Save gpu screen recorder status in $XDG_RUNTIME_DIR.
Add option to capture application audio. This should show a popup where you can use one of the available applications or a custom one and choose to record that application or all applications except that one.
Add profile option. Convert view to profile, add an option at the bottom that says "Edit profiles..." which should show a popup where you can create/remove profiles. New profiles should always be in advanced view.
+
+Make content scrollable. The window is too tall now.
+Change audio devices movable items to same type of list as application audio.
+
+Move x11 hotkey code to its own file.
+
+Add audio devices/app refresh button. \ No newline at end of file
diff --git a/src/config.hpp b/src/config.hpp
index 0ab8af2..82bdb9f 100644
--- a/src/config.hpp
+++ b/src/config.hpp
@@ -28,8 +28,11 @@ struct MainConfig {
int32_t fps = 60;
int32_t video_bitrate = 15000;
bool merge_audio_tracks = true;
+ bool record_app_audio_inverted = false;
bool change_video_resolution = false;
+ std::string audio_type_view = "audio_devices";
std::vector<std::string> audio_input;
+ std::vector<std::string> application_audio;
std::string color_range;
std::string quality;
std::string codec; // Video codec
@@ -313,8 +316,11 @@ static std::map<std::string, ConfigValue> get_config_options(Config &config) {
{"main.fps", {CONFIG_TYPE_I32, &config.main_config.fps}},
{"main.video_bitrate", {CONFIG_TYPE_I32, &config.main_config.video_bitrate}},
{"main.merge_audio_tracks", {CONFIG_TYPE_BOOL, &config.main_config.merge_audio_tracks}},
+ {"main.record_app_audio_inverted", {CONFIG_TYPE_BOOL, &config.main_config.record_app_audio_inverted}},
{"main.change_video_resolution", {CONFIG_TYPE_BOOL, &config.main_config.change_video_resolution}},
+ {"main.audio_type_view", {CONFIG_TYPE_STRING, &config.main_config.audio_type_view}},
{"main.audio_input", {CONFIG_TYPE_STRING_ARRAY, &config.main_config.audio_input}},
+ {"main.application_audio", {CONFIG_TYPE_STRING_ARRAY, &config.main_config.application_audio}},
{"main.color_range", {CONFIG_TYPE_STRING, &config.main_config.color_range}},
{"main.quality", {CONFIG_TYPE_STRING, &config.main_config.quality}},
{"main.codec", {CONFIG_TYPE_STRING, &config.main_config.codec}},
diff --git a/src/main.cpp b/src/main.cpp
index 44793ac..3d6a873 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -91,12 +91,12 @@ static GtkEntry *custom_stream_url_entry;
static GtkSpinButton *replay_time_entry;
static GtkButton *select_window_button;
static GtkWidget *audio_input_used_list;
-static GtkWidget *add_audio_input_button;
static GtkWidget *record_start_stop_hotkey_button;
static GtkWidget *pause_unpause_hotkey_button;
static GtkWidget *replay_start_stop_hotkey_button;
static GtkWidget *replay_save_hotkey_button;
static GtkWidget *streaming_start_stop_hotkey_button;
+static GtkWidget *record_app_audio_inverted_button;
static GtkWidget *merge_audio_tracks_button;
static GtkFrame *notifications_frame;
static GtkWidget *show_recording_started_notification_button;
@@ -104,6 +104,11 @@ static GtkWidget *show_recording_stopped_notification_button;
static GtkWidget *show_recording_saved_notification_button;
static GtkWidget *record_cursor_button;
static GtkWidget *restore_portal_session_button;
+static GtkWidget *audio_devices_radio_button;
+static GtkWidget *application_audio_radio_button;
+static GtkGrid *audio_devices_grid;
+static GtkGrid *application_audio_grid;
+static GtkBox *application_audio_items_box;
static GtkGrid *video_codec_grid;
static GtkGrid *audio_codec_grid;
static GtkGrid *color_range_grid;
@@ -170,6 +175,7 @@ struct AudioInput {
};
static std::vector<AudioInput> audio_inputs;
+static std::vector<std::string> application_audio;
enum class HotkeyMode {
NoAction,
@@ -547,6 +553,33 @@ static std::vector<AudioInput> get_audio_devices() {
return inputs;
}
+static std::vector<std::string> get_application_audio() {
+ std::vector<std::string> application_audio;
+
+ FILE *f = popen("gpu-screen-recorder --list-application-audio", "r");
+ if(!f) {
+ fprintf(stderr, "error: 'gpu-screen-recorder --list-application-audio' failed\n");
+ return application_audio;
+ }
+
+ char output[16384];
+ ssize_t bytes_read = fread(output, 1, sizeof(output) - 1, f);
+ if(bytes_read < 0 || ferror(f)) {
+ fprintf(stderr, "error: failed to read 'gpu-screen-recorder --list-application-audio' output\n");
+ pclose(f);
+ return application_audio;
+ }
+ output[bytes_read] = '\0';
+
+ string_split_char(output, '\n', [&](StringView line) {
+ std::string line_str(line.str, line.size);
+ application_audio.emplace_back(std::move(line_str));
+ return true;
+ });
+
+ return application_audio;
+}
+
static void used_audio_input_loop_callback(GtkWidget *row, gpointer userdata) {
const AudioRow *audio_row = (AudioRow*)g_object_get_data(G_OBJECT(row), "audio-row");
std::function<void(const AudioRow*)> &callback = *(std::function<void(const AudioRow*)>*)userdata;
@@ -791,6 +824,58 @@ static GtkWidget* create_used_audio_input_row(void) {
return row;
}
+static GtkWidget* create_application_audio_combo_box_row(const std::string &selected_row_id) {
+ GtkGrid *grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_column_spacing(grid, 10);
+ gtk_widget_set_hexpand(GTK_WIDGET(grid), true);
+
+ GtkComboBoxText *application_audio_combo_box = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new());
+ for(const std::string &app_audio : application_audio) {
+ gtk_combo_box_text_append(application_audio_combo_box, app_audio.c_str(), app_audio.c_str());
+ }
+
+ if(!application_audio.empty() && selected_row_id.empty())
+ gtk_combo_box_set_active(GTK_COMBO_BOX(application_audio_combo_box), 0);
+ else if(!selected_row_id.empty())
+ gtk_combo_box_set_active_id(GTK_COMBO_BOX(application_audio_combo_box), selected_row_id.c_str());
+
+ gtk_widget_set_hexpand(GTK_WIDGET(application_audio_combo_box), true);
+ gtk_grid_attach(grid, GTK_WIDGET(application_audio_combo_box), 0, 0, 1, 1);
+
+ GtkButton *remove_button = GTK_BUTTON(gtk_button_new_with_label("Remove"));
+ gtk_grid_attach(grid, GTK_WIDGET(remove_button), 1, 0, 1, 1);
+
+ g_signal_connect(remove_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer userdata){
+ GtkGrid *grid = (GtkGrid*)userdata;
+ gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(grid))), GTK_WIDGET(grid));
+ return true;
+ }), grid);
+
+ return GTK_WIDGET(grid);
+}
+
+static GtkWidget* create_application_audio_custom_row(const std::string &text) {
+ GtkGrid *grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_column_spacing(grid, 10);
+ gtk_widget_set_hexpand(GTK_WIDGET(grid), true);
+
+ GtkEntry *application_audio_entry = GTK_ENTRY(gtk_entry_new());
+ gtk_widget_set_hexpand(GTK_WIDGET(application_audio_entry), true);
+ gtk_entry_set_text(application_audio_entry, text.c_str());
+ gtk_grid_attach(grid, GTK_WIDGET(application_audio_entry), 0, 0, 1, 1);
+
+ GtkButton *remove_button = GTK_BUTTON(gtk_button_new_with_label("Remove"));
+ gtk_grid_attach(grid, GTK_WIDGET(remove_button), 1, 0, 1, 1);
+
+ g_signal_connect(remove_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer userdata){
+ GtkGrid *grid = (GtkGrid*)userdata;
+ gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(grid))), GTK_WIDGET(grid));
+ return true;
+ }), grid);
+
+ return GTK_WIDGET(grid);
+}
+
// Return true from |callback_func| to continue to the next row
static void for_each_item_in_combo_box(GtkComboBox *combo_box, std::function<bool(gint row_index, const gchar *row_id, const gchar *row_text)> callback_func) {
const int id_column = gtk_combo_box_get_id_column(GTK_COMBO_BOX(combo_box));
@@ -864,12 +949,31 @@ static void save_configs() {
config.main_config.fps = gtk_spin_button_get_value_as_int(fps_entry);
config.main_config.video_bitrate = gtk_spin_button_get_value_as_int(video_bitrate_entry);
config.main_config.merge_audio_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button));
+ config.main_config.record_app_audio_inverted = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(record_app_audio_inverted_button));
config.main_config.change_video_resolution = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(change_video_resolution_button));
+ config.main_config.audio_type_view.clear();
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(audio_devices_radio_button)))
+ config.main_config.audio_type_view = "audio_devices";
+ else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(application_audio_radio_button)))
+ config.main_config.audio_type_view = "app_audio";
+
config.main_config.audio_input.clear();
for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [](const AudioRow *audio_row) {
config.main_config.audio_input.push_back(gtk_combo_box_text_get_active_text(audio_row->input_list));
});
+
+ config.main_config.application_audio.clear();
+ gtk_container_foreach(GTK_CONTAINER(application_audio_items_box), [](GtkWidget *widget, gpointer) {
+ GtkWidget *row_item_widget = gtk_grid_get_child_at(GTK_GRID(widget), 0, 0);
+ const char *text = "";
+ if(GTK_IS_COMBO_BOX_TEXT(row_item_widget))
+ text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(row_item_widget));
+ else if(GTK_IS_ENTRY(row_item_widget))
+ text = gtk_entry_get_text(GTK_ENTRY(row_item_widget));
+ config.main_config.application_audio.push_back(text);
+ }, nullptr);
+
config.main_config.color_range = gtk_combo_box_get_active_id(GTK_COMBO_BOX(color_range_input_menu));
config.main_config.quality = gtk_combo_box_get_active_id(GTK_COMBO_BOX(quality_input_menu));
config.main_config.codec = video_codec_selection_menu_get_active_id();
@@ -1537,20 +1641,64 @@ static bool kill_gpu_screen_recorder_get_result(bool *already_dead) {
return exit_success;
}
+struct ApplicationAudioCallbackUserdata {
+ const char *arg_option;
+ std::vector<const char*> &args;
+};
+
static void add_audio_command_line_args(std::vector<const char*> &args, std::string &merge_audio_tracks_arg_value) {
- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button))) {
- for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&merge_audio_tracks_arg_value](const AudioRow *audio_row) {
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(audio_devices_radio_button))) {
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button))) {
+ for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&merge_audio_tracks_arg_value](const AudioRow *audio_row) {
+ if(!merge_audio_tracks_arg_value.empty())
+ merge_audio_tracks_arg_value += '|';
+ merge_audio_tracks_arg_value += gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_row->input_list));
+ });
+
if(!merge_audio_tracks_arg_value.empty())
- merge_audio_tracks_arg_value += '|';
- merge_audio_tracks_arg_value += gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_row->input_list));
- });
+ args.insert(args.end(), { "-a", merge_audio_tracks_arg_value.c_str() });
+ } else {
+ for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&args](const AudioRow *audio_row) {
+ args.insert(args.end(), { "-a", gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_row->input_list)) });
+ });
+ }
+ } else if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(application_audio_radio_button))) {
+ const char *arg_option = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(record_app_audio_inverted_button)) ? "-aai" : "-aa";
+ ApplicationAudioCallbackUserdata app_audio_callback = {
+ arg_option,
+ args
+ };
+
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button))) {
+ gtk_container_foreach(GTK_CONTAINER(application_audio_items_box), [](GtkWidget *widget, gpointer userdata) {
+ std::string &merge_audio_tracks_arg_value = *(std::string*)userdata;
+ GtkWidget *row_item_widget = gtk_grid_get_child_at(GTK_GRID(widget), 0, 0);
+
+ const char *text = "";
+ if(GTK_IS_COMBO_BOX_TEXT(row_item_widget))
+ text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(row_item_widget));
+ else if(GTK_IS_ENTRY(row_item_widget))
+ text = gtk_entry_get_text(GTK_ENTRY(row_item_widget));
+
+ if(!merge_audio_tracks_arg_value.empty())
+ merge_audio_tracks_arg_value += '|';
+ merge_audio_tracks_arg_value += text;
+ }, &merge_audio_tracks_arg_value);
- if(!merge_audio_tracks_arg_value.empty())
- args.insert(args.end(), { "-a", merge_audio_tracks_arg_value.c_str() });
- } else {
- for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&args](const AudioRow *audio_row) {
- args.insert(args.end(), { "-a", gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_row->input_list)) });
- });
+ if(!merge_audio_tracks_arg_value.empty())
+ args.insert(args.end(), { arg_option, merge_audio_tracks_arg_value.c_str() });
+ } else {
+ gtk_container_foreach(GTK_CONTAINER(application_audio_items_box), [](GtkWidget *widget, gpointer userdata) {
+ ApplicationAudioCallbackUserdata *app_audio_callback = (ApplicationAudioCallbackUserdata*)userdata;
+ GtkWidget *row_item_widget = gtk_grid_get_child_at(GTK_GRID(widget), 0, 0);
+ const char *text = "";
+ if(GTK_IS_COMBO_BOX_TEXT(row_item_widget))
+ text = gtk_combo_box_get_active_id(GTK_COMBO_BOX(row_item_widget));
+ else if(GTK_IS_ENTRY(row_item_widget))
+ text = gtk_entry_get_text(GTK_ENTRY(row_item_widget));
+ app_audio_callback->args.insert(app_audio_callback->args.end(), { app_audio_callback->arg_option, text });
+ }, &app_audio_callback);
+ }
}
}
@@ -2608,6 +2756,19 @@ static void video_codec_set_sensitive(GtkCellLayout *cell_layout, GtkCellRendere
g_free(id);
}
+static void audio_devices_application_audio_radio_toggled(GtkButton *button, gpointer) {
+ if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
+ return;
+
+ if(GTK_WIDGET(button) == audio_devices_radio_button) {
+ gtk_widget_set_visible(GTK_WIDGET(audio_devices_grid), true);
+ gtk_widget_set_visible(GTK_WIDGET(application_audio_grid), false);
+ } else if(GTK_WIDGET(button) == application_audio_radio_button) {
+ gtk_widget_set_visible(GTK_WIDGET(audio_devices_grid), false);
+ gtk_widget_set_visible(GTK_WIDGET(application_audio_grid), true);
+ }
+}
+
static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *app) {
GtkGrid *grid = GTK_GRID(gtk_grid_new());
gtk_stack_add_named(stack, GTK_WIDGET(grid), "common-settings");
@@ -2802,24 +2963,87 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a
gtk_widget_set_margin(GTK_WIDGET(audio_grid), 10, 10, 10, 10);
gtk_container_add(GTK_CONTAINER(audio_input_frame), GTK_WIDGET(audio_grid));
- GtkGrid *add_audio_grid = GTK_GRID(gtk_grid_new());
- gtk_grid_set_row_spacing(add_audio_grid, 10);
- gtk_grid_set_column_spacing(add_audio_grid, 10);
- gtk_grid_attach(audio_grid, GTK_WIDGET(add_audio_grid), 0, audio_input_area_row++, 1, 1);
+ GtkBox *radio_button_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10));
+ gtk_grid_attach(audio_grid, GTK_WIDGET(radio_button_box), 0, audio_input_area_row++, 2, 1);
- add_audio_input_button = gtk_button_new_with_label("Add audio track");
- gtk_grid_attach(add_audio_grid, add_audio_input_button, 0, 0, 1, 1);
- g_signal_connect(add_audio_input_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer){
- GtkWidget *row = create_used_audio_input_row();
- gtk_widget_show_all(row);
- gtk_list_box_insert(GTK_LIST_BOX(audio_input_used_list), row, -1);
- return true;
- }), nullptr);
+ audio_devices_radio_button = gtk_radio_button_new_with_label_from_widget(nullptr, "Audio devices");
+ gtk_box_pack_start(radio_button_box, audio_devices_radio_button, false, false, 0);
+ g_signal_connect(audio_devices_radio_button, "toggled", G_CALLBACK(audio_devices_application_audio_radio_toggled), nullptr);
- audio_input_used_list = gtk_list_box_new();
- gtk_widget_set_hexpand (audio_input_used_list, TRUE);
- gtk_list_box_set_selection_mode (GTK_LIST_BOX (audio_input_used_list), GTK_SELECTION_NONE);
- gtk_grid_attach(audio_grid, audio_input_used_list, 0, audio_input_area_row++, 2, 1);
+ application_audio_radio_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(audio_devices_radio_button), "Application audio");
+ gtk_box_pack_start(radio_button_box, GTK_WIDGET(application_audio_radio_button), false, false, 0);
+ g_signal_connect(application_audio_radio_button, "toggled", G_CALLBACK(audio_devices_application_audio_radio_toggled), nullptr);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(audio_devices_radio_button), true);
+
+ {
+ int audio_devices_row = 0;
+
+ audio_devices_grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_row_spacing(audio_devices_grid, 10);
+ gtk_grid_set_column_spacing(audio_devices_grid, 10);
+ gtk_widget_set_margin(GTK_WIDGET(audio_devices_grid), 0, 0, 0, 0);
+ gtk_grid_attach(audio_grid, GTK_WIDGET(audio_devices_grid), 0, audio_input_area_row++, 2, 1);
+
+ GtkGrid *add_audio_grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_row_spacing(add_audio_grid, 10);
+ gtk_grid_set_column_spacing(add_audio_grid, 10);
+ gtk_grid_attach(audio_devices_grid, GTK_WIDGET(add_audio_grid), 0, audio_devices_row++, 1, 1);
+
+ GtkWidget *add_audio_device_button = gtk_button_new_with_label("Add audio device");
+ gtk_grid_attach(add_audio_grid, add_audio_device_button, 0, 0, 1, 1);
+ g_signal_connect(add_audio_device_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer){
+ GtkWidget *row = create_used_audio_input_row();
+ gtk_widget_show_all(row);
+ gtk_list_box_insert(GTK_LIST_BOX(audio_input_used_list), row, -1);
+ return true;
+ }), nullptr);
+
+ audio_input_used_list = gtk_list_box_new();
+ gtk_widget_set_hexpand (audio_input_used_list, TRUE);
+ gtk_list_box_set_selection_mode (GTK_LIST_BOX (audio_input_used_list), GTK_SELECTION_NONE);
+ gtk_grid_attach(audio_devices_grid, audio_input_used_list, 0, audio_devices_row++, 2, 1);
+ }
+
+ {
+ int application_audio_row = 0;
+
+ application_audio_grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_row_spacing(application_audio_grid, 10);
+ gtk_grid_set_column_spacing(application_audio_grid, 10);
+ gtk_widget_set_margin(GTK_WIDGET(application_audio_grid), 0, 0, 0, 0);
+ gtk_grid_attach(audio_grid, GTK_WIDGET(application_audio_grid), 0, audio_input_area_row++, 2, 1);
+
+ GtkGrid *add_button_grid = GTK_GRID(gtk_grid_new());
+ gtk_grid_set_column_spacing(add_button_grid, 10);
+ gtk_grid_attach(application_audio_grid, GTK_WIDGET(add_button_grid), 0, application_audio_row++, 2, 1);
+
+ GtkWidget *add_application_audio_button = gtk_button_new_with_label("Add application audio");
+ gtk_grid_attach(add_button_grid, add_application_audio_button, 0, 0, 1, 1);
+ g_signal_connect(add_application_audio_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer){
+ GtkWidget *row = create_application_audio_combo_box_row("");
+ gtk_widget_show_all(row);
+ gtk_box_pack_start(application_audio_items_box, row, false, false, 0);
+ return true;
+ }), nullptr);
+
+ GtkWidget *add_custom_application_audio_button = gtk_button_new_with_label("Add custom application audio");
+ gtk_grid_attach(add_button_grid, add_custom_application_audio_button, 1, 0, 1, 1);
+ g_signal_connect(add_custom_application_audio_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer){
+ GtkWidget *row = create_application_audio_custom_row("");
+ gtk_widget_show_all(row);
+ gtk_box_pack_start(application_audio_items_box, row, false, false, 0);
+ return true;
+ }), nullptr);
+
+ application_audio_items_box = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 10));
+ gtk_grid_attach(application_audio_grid, GTK_WIDGET(application_audio_items_box), 0, application_audio_row++, 2, 1);
+
+ record_app_audio_inverted_button = gtk_check_button_new_with_label("Record all applications except the selected ones");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(record_app_audio_inverted_button), false);
+ gtk_widget_set_halign(record_app_audio_inverted_button, GTK_ALIGN_START);
+ gtk_grid_attach(application_audio_grid, record_app_audio_inverted_button, 0, application_audio_row++, 2, 1);
+ }
merge_audio_tracks_button = gtk_check_button_new_with_label("Merge audio tracks");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button), true);
@@ -3728,6 +3952,14 @@ static void add_audio_input_track(const char *name) {
gtk_list_box_insert (GTK_LIST_BOX(audio_input_used_list), row, -1);
}
+static const std::string* get_application_audio_by_name_case_insensitive(const std::vector<std::string> &application_audio, const std::string &name) {
+ for(const auto &app_audio : application_audio) {
+ if(strcasecmp(app_audio.c_str(), name.c_str()) == 0)
+ return &app_audio;
+ }
+ return nullptr;
+}
+
static void load_config() {
bool config_empty = false;
config = read_config(config_empty);
@@ -3823,6 +4055,7 @@ static void load_config() {
gtk_spin_button_set_value(fps_entry, config.main_config.fps);
gtk_spin_button_set_value(video_bitrate_entry, config.main_config.video_bitrate);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button), config.main_config.merge_audio_tracks);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(record_app_audio_inverted_button), config.main_config.record_app_audio_inverted);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(change_video_resolution_button), config.main_config.change_video_resolution);
for(const std::string &audio_input : config.main_config.audio_input) {
@@ -3832,6 +4065,18 @@ static void load_config() {
if(config_empty && config.main_config.audio_input.empty())
add_audio_input_track("Default output");
+ for(const std::string &app_audio : config.main_config.application_audio) {
+ const std::string *app_audio_existing = get_application_audio_by_name_case_insensitive(application_audio, app_audio);
+ GtkWidget *row = nullptr;
+ if(app_audio_existing)
+ row = create_application_audio_combo_box_row(*app_audio_existing);
+ else
+ row = create_application_audio_custom_row(app_audio);
+
+ gtk_widget_show_all(row);
+ gtk_box_pack_start(application_audio_items_box, row, false, false, 0);
+ }
+
gtk_combo_box_set_active_id(GTK_COMBO_BOX(color_range_input_menu), config.main_config.color_range.c_str());
gtk_combo_box_set_active_id(GTK_COMBO_BOX(quality_input_menu), config.main_config.quality.c_str());
video_codec_selection_menu_set_active_id("auto");
@@ -3881,6 +4126,14 @@ static void load_config() {
on_change_video_resolution_button_click(GTK_BUTTON(change_video_resolution_button), nullptr);
+ if(config.main_config.audio_type_view == "app_audio") {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(application_audio_radio_button), true);
+ audio_devices_application_audio_radio_toggled(GTK_BUTTON(application_audio_radio_button), nullptr);
+ } else /*if(config.main_config.audio_type_view == "audio_devices") */{
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(audio_devices_radio_button), true);
+ audio_devices_application_audio_radio_toggled(GTK_BUTTON(audio_devices_radio_button), nullptr);
+ }
+
std::string dummy;
if(!config.main_config.software_encoding_warning_shown && !switch_video_codec_to_usable_hardware_encoder(dummy)) {
GtkWidget *dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
@@ -4044,6 +4297,7 @@ static void activate(GtkApplication *app, gpointer) {
select_window_userdata.app = app;
audio_inputs = get_audio_devices();
+ application_audio = get_application_audio();
if(gsr_info.system_info.display_server != DisplayServer::WAYLAND)
crosshair_cursor = XCreateFontCursor(gdk_x11_get_default_xdisplay(), XC_crosshair);