From 19c054d92887434a31f13ad49b323f13688b895a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 21 Oct 2023 18:23:40 +0200 Subject: Redesign audio input to make it easier to understand that you have to add audio to use it. Add framerate mode option. --- TODO | 7 +- com.dec05eba.gpu_screen_recorder.appdata.xml | 9 + project.conf | 2 +- src/config.hpp | 7 +- src/main.cpp | 287 +++++++++++---------------- 5 files changed, 142 insertions(+), 170 deletions(-) diff --git a/TODO b/TODO index 5ed8f8a..b945462 100644 --- a/TODO +++ b/TODO @@ -13,6 +13,9 @@ Add translation support (using gettext, which uses .mo files and _ macro). It sh telling them to copy the file content and then send me the file by email with the language name (then I can add it to the correct) file with correct locale. Or if they know how to use git they can use that directly. Add option to start replay on system startup (use the gpu screen recorder systemd file?) and use the settings from the replay page. This is not possible unless gsr-kms-server has cap (on amd/intel and nvidia wayland), so no flatpak. + Dont add this option if not running systemd, or disable the button then. The program should minimize to taskbar on minimize. -Add default audio output by default if no config file exists. Or redesign audio where there is only a button at first, no list. The button should say: add audio, - and then each audio item has a dropdown list where you can select which audio device to use. +Bypass password prompt in flatpak with polkit policy: https://gitlab.com/corectrl/corectrl/-/wikis/Setup#dont-ask-for-user-password + autostart can also be done by adding the application to ~/.config/autostart/com.dec05eba.gpu_screen_recorder, but that may not work on minimal window manager setups. So maybe use systemd instead. + The frontpage should have a toggle button saying "dont ask for password when recording", which should add those polkit changes to the system (requires root). Shouldn't this be done by the polkitd user? + Check if this is possible (if /etc/polkit-1/localauthority or /etc/polkit-1/rules.d exists). \ No newline at end of file diff --git a/com.dec05eba.gpu_screen_recorder.appdata.xml b/com.dec05eba.gpu_screen_recorder.appdata.xml index b91a691..2306e18 100644 --- a/com.dec05eba.gpu_screen_recorder.appdata.xml +++ b/com.dec05eba.gpu_screen_recorder.appdata.xml @@ -52,6 +52,15 @@ + + +
    +

    AMD/Intel: workaround driver bug that causes vram leak

    +
  • Add framerate mode option in advanced menu
  • +
  • Redesign audio input to make it clear that you have to add audio to use it
  • +
+
+

NVIDIA: Workaround new nvidia driver bug that causes recording of a small window to freeze recording.

diff --git a/project.conf b/project.conf index 9c58c71..8c6239e 100644 --- a/project.conf +++ b/project.conf @@ -5,7 +5,7 @@ version = "3.0.0" platforms = ["posix"] [config] -error_on_warning = "true" +#error_on_warning = "true" [dependencies] gtk+-3.0 = "3" diff --git a/src/config.hpp b/src/config.hpp index 30eab74..f812c5a 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -27,6 +27,7 @@ struct MainConfig { std::string quality; std::string codec; // Video codec std::string audio_codec; + std::string framerate_mode; bool advanced_view = false; bool overclock = false; }; @@ -201,13 +202,14 @@ static bool string_to_int(std::string str, int &value) { return true; } -static Config read_config() { +static Config read_config(bool &config_empty) { Config config; const std::string config_path = get_config_dir() + "/config"; std::string file_content; if(!file_get_content(config_path.c_str(), file_content)) { fprintf(stderr, "Warning: Failed to read config file: %s\n", config_path.c_str()); + config_empty = true; return config; } @@ -248,6 +250,8 @@ static Config read_config() { config.main_config.codec.assign(value.str, value.size); } else if(key == "main.audio_codec") { config.main_config.audio_codec.assign(value.str, value.size); + } else if(key == "main.framerate_mode") { + config.main_config.framerate_mode.assign(value.str, value.size); } else if(key == "main.advanced_view") { if(value == "true") config.main_config.advanced_view = true; @@ -342,6 +346,7 @@ static void save_config(const Config &config) { fprintf(file, "main.quality %s\n", config.main_config.quality.c_str()); fprintf(file, "main.codec %s\n", config.main_config.codec.c_str()); fprintf(file, "main.audio_codec %s\n", config.main_config.audio_codec.c_str()); + fprintf(file, "main.framerate_mode %s\n", config.main_config.framerate_mode.c_str()); fprintf(file, "main.advanced_view %s\n", config.main_config.advanced_view ? "true" : "false"); fprintf(file, "main.overclock %s\n", config.main_config.overclock ? "true" : "false"); diff --git a/src/main.cpp b/src/main.cpp index bd6a21f..bae4137 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,10 +48,10 @@ static GtkGrid *area_size_grid; static GtkSpinButton *area_width_entry; static GtkSpinButton *area_height_entry; static GtkComboBoxText *record_area_selection_menu; -static GtkComboBoxText *audio_input_menu_todo; static GtkComboBoxText *quality_input_menu; static GtkComboBoxText *video_codec_input_menu; static GtkComboBoxText *audio_codec_input_menu; +static GtkComboBoxText *framerate_mode_input_menu; static GtkComboBoxText *stream_service_input_menu; static GtkComboBoxText *record_container; static GtkComboBoxText *replay_container; @@ -80,6 +80,7 @@ static GtkWidget *streaming_hotkey_button; static GtkWidget *merge_audio_tracks_button; static GtkGrid *video_codec_grid; static GtkGrid *audio_codec_grid; +static GtkGrid *framerate_mode_grid; static GtkComboBoxText *view_combo_box; static GtkGrid *overclock_grid; static GtkWidget *overclock_button; @@ -93,7 +94,6 @@ static bool streaming = false; static pid_t gpu_screen_recorder_process = -1; static int prev_exit_status = -1; static Config config; -static int num_audio_inputs_addable = 0; static std::string record_file_current_filename; static bool nvfbc_installed = false; @@ -101,6 +101,19 @@ static bool wayland = false; static char drm_card_path[128]; static gsr_egl egl; +struct AudioInput { + std::string name; + std::string description; +}; + +struct PulseAudioServerInfo { + std::string default_sink_name; + std::string default_source_name; +}; + +static std::vector audio_inputs; +static PulseAudioServerInfo pa_default_sources; + enum class HotkeyMode { NoAction, NewHotkey, @@ -138,9 +151,7 @@ static const Container supported_containers[] = { struct AudioRow { GtkWidget *row; - GtkWidget *track_number_label; - GtkWidget *label; - std::string id; + GtkComboBoxText *input_list; }; typedef enum { @@ -229,18 +240,7 @@ static void drag_data_get(GtkWidget *widget, GdkDragContext*, GtkSelectionData * sizeof(gpointer)); } -static void update_used_audio_input_track_ids() { - int track_number = 1; - for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&](const AudioRow *audio_row) { - char track_number_str[32]; - snprintf(track_number_str, sizeof(track_number_str), "%d:", track_number); - GtkWidget *track_number_label = ((AudioRow*)g_object_get_data(G_OBJECT(audio_row->row), "audio-row"))->track_number_label; - gtk_label_set_text(GTK_LABEL(track_number_label), track_number_str); - ++track_number; - }); -} - -static void drag_data_received (GtkWidget *widget, GdkDragContext*, +static void drag_data_received(GtkWidget *widget, GdkDragContext*, gint, gint, GtkSelectionData *selection_data, guint, guint32, gpointer) @@ -259,8 +259,6 @@ static void drag_data_received (GtkWidget *widget, GdkDragContext*, gtk_container_remove(GTK_CONTAINER(list_box), source); gtk_list_box_insert(GTK_LIST_BOX(list_box), source, pos); g_object_unref(source); - - update_used_audio_input_track_ids(); } static void enable_stream_record_button_if_info_filled() { @@ -273,13 +271,13 @@ static void enable_stream_record_button_if_info_filled() { return; } } - + gtk_widget_set_sensitive(GTK_WIDGET(replay_button), true); gtk_widget_set_sensitive(GTK_WIDGET(record_button), true); gtk_widget_set_sensitive(GTK_WIDGET(stream_button), true); } -static GtkWidget* create_used_audio_input_row(const char *id, const char *text) { +static GtkWidget* create_used_audio_input_row(void) { char entry_name[] = "GTK_LIST_BOX_ROW"; const GtkTargetEntry entries[] = { { entry_name, GTK_TARGET_SAME_APP, 0 } @@ -295,20 +293,14 @@ static GtkWidget* create_used_audio_input_row(const char *id, const char *text) gtk_container_add(GTK_CONTAINER(handle), image); gtk_container_add(GTK_CONTAINER(box), handle); - int track_number = 1; - for_each_used_audio_input(GTK_LIST_BOX(audio_input_used_list), [&track_number](const AudioRow*) { - ++track_number; - }); - - char track_number_str[32]; - snprintf(track_number_str, sizeof(track_number_str), "%d:", track_number); - GtkWidget *track_number_label = gtk_label_new(track_number_str); - gtk_label_set_xalign(GTK_LABEL(track_number_label), 0.0f); - gtk_container_add(GTK_CONTAINER(box), track_number_label); - - GtkWidget *label = gtk_label_new(text); - gtk_label_set_xalign(GTK_LABEL(label), 0.0f); - gtk_container_add_with_properties(GTK_CONTAINER(box), label, "expand", TRUE, NULL); + GtkComboBoxText *input_list = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new()); + for(const auto &audio_input : audio_inputs) { + gtk_combo_box_text_append(input_list, audio_input.name.c_str(), audio_input.description.c_str()); + } + gtk_widget_set_hexpand(GTK_WIDGET(input_list), true); + gtk_combo_box_set_active(GTK_COMBO_BOX(input_list), 0); + //gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo), id); + gtk_container_add(GTK_CONTAINER(box), GTK_WIDGET(input_list)); GtkWidget *remove_button = gtk_button_new_with_label("Remove"); gtk_widget_set_halign(remove_button, GTK_ALIGN_END); @@ -323,24 +315,12 @@ static GtkWidget* create_used_audio_input_row(const char *id, const char *text) AudioRow *audio_row = new AudioRow(); audio_row->row = row; - audio_row->track_number_label = track_number_label; - audio_row->label = label; - audio_row->id = id; + audio_row->input_list = input_list; g_object_set_data(G_OBJECT(row), "audio-row", audio_row); g_signal_connect(remove_button, "clicked", G_CALLBACK(+[](GtkButton*, gpointer userdata){ AudioRow *audio_row = (AudioRow*)userdata; - gtk_combo_box_text_append(audio_input_menu_todo, audio_row->id.c_str(), gtk_label_get_text(GTK_LABEL(audio_row->label))); - gtk_container_remove (GTK_CONTAINER(gtk_widget_get_parent(audio_row->row)), audio_row->row); - - ++num_audio_inputs_addable; - if(num_audio_inputs_addable == 1) { - gtk_combo_box_set_active(GTK_COMBO_BOX(audio_input_menu_todo), 0); - gtk_widget_set_sensitive(add_audio_input_button, true); - } - - update_used_audio_input_track_ids(); - enable_stream_record_button_if_info_filled(); + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(audio_row->row)), audio_row->row); delete audio_row; return true; }), audio_row); @@ -421,11 +401,12 @@ static void save_configs() { 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_label_get_text(GTK_LABEL(audio_row->label))); + config.main_config.audio_input.push_back(gtk_combo_box_text_get_active_text(audio_row->input_list)); }); config.main_config.quality = gtk_combo_box_get_active_id(GTK_COMBO_BOX(quality_input_menu)); config.main_config.codec = gtk_combo_box_get_active_id(GTK_COMBO_BOX(video_codec_input_menu)); config.main_config.audio_codec = gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_codec_input_menu)); + config.main_config.framerate_mode = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); config.main_config.advanced_view = strcmp(gtk_combo_box_get_active_id(GTK_COMBO_BOX(view_combo_box)), "advanced") == 0; config.main_config.overclock = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button)); @@ -1277,6 +1258,23 @@ static bool kill_gpu_screen_recorder_get_result() { return exit_success; } +static void add_audio_command_line_args(std::vector &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(!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()) + 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)) }); + }); + } +} + static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdata) { GtkApplication *app = (GtkApplication*)userdata; const gchar *dir = gtk_button_get_label(replay_file_chooser_button); @@ -1336,6 +1334,7 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat const gchar* quality_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(quality_input_menu)); const gchar* video_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(video_codec_input_menu)); const gchar* audio_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_codec_input_menu)); + const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); char area[64]; snprintf(area, sizeof(area), "%dx%d", record_width, record_height); @@ -1347,21 +1346,11 @@ static gboolean on_start_replay_button_click(GtkButton *button, gpointer userdat if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); - 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(!merge_audio_tracks_arg_value.empty()) - merge_audio_tracks_arg_value += '|'; - merge_audio_tracks_arg_value += audio_row->id; - }); + if(strcmp(framerate_mode_input_str, "auto") != 0) + args.insert(args.end(), { "-fm", framerate_mode_input_str }); - 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", audio_row->id.c_str() }); - }); - } + std::string merge_audio_tracks_arg_value; + add_audio_command_line_args(args, merge_audio_tracks_arg_value); if(follow_focused) args.insert(args.end(), { "-s", area }); @@ -1464,6 +1453,7 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user const gchar* quality_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(quality_input_menu)); const gchar* video_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(video_codec_input_menu)); const gchar* audio_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_codec_input_menu)); + const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); char area[64]; snprintf(area, sizeof(area), "%dx%d", record_width, record_height); @@ -1475,21 +1465,11 @@ static gboolean on_start_recording_button_click(GtkButton *button, gpointer user if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); - 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(!merge_audio_tracks_arg_value.empty()) - merge_audio_tracks_arg_value += '|'; - merge_audio_tracks_arg_value += audio_row->id; - }); + if(strcmp(framerate_mode_input_str, "auto") != 0) + args.insert(args.end(), { "-fm", framerate_mode_input_str }); - 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", audio_row->id.c_str() }); - }); - } + std::string merge_audio_tracks_arg_value; + add_audio_command_line_args(args, merge_audio_tracks_arg_value); if(follow_focused) args.insert(args.end(), { "-s", area }); @@ -1592,6 +1572,7 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user const gchar* quality_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(quality_input_menu)); const gchar* video_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(video_codec_input_menu)); const gchar* audio_codec_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_codec_input_menu)); + const gchar* framerate_mode_input_str = gtk_combo_box_get_active_id(GTK_COMBO_BOX(framerate_mode_input_menu)); char area[64]; snprintf(area, sizeof(area), "%dx%d", record_width, record_height); @@ -1603,21 +1584,11 @@ static gboolean on_start_streaming_button_click(GtkButton *button, gpointer user if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(overclock_button))) args.insert(args.end(), { "-oc", "yes" }); - 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(!merge_audio_tracks_arg_value.empty()) - merge_audio_tracks_arg_value += '|'; - merge_audio_tracks_arg_value += audio_row->id; - }); + if(strcmp(framerate_mode_input_str, "auto") != 0) + args.insert(args.end(), { "-fm", framerate_mode_input_str }); - 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", audio_row->id.c_str() }); - }); - } + std::string merge_audio_tracks_arg_value; + add_audio_command_line_args(args, merge_audio_tracks_arg_value); if(follow_focused) args.insert(args.end(), { "-s", area }); @@ -1679,11 +1650,6 @@ static void pa_state_cb(pa_context *c, void *userdata) { } } -struct AudioInput { - std::string name; - std::string description; -}; - static void pa_sourcelist_cb(pa_context*, const pa_source_info *source_info, int eol, void *userdata) { if(eol > 0) return; @@ -1736,11 +1702,6 @@ static std::vector get_pulseaudio_inputs() { return {}; } -struct PulseAudioServerInfo { - std::string default_sink_name; - std::string default_source_name; -}; - static void server_info_callback(pa_context*, const pa_server_info *server_info, void *userdata) { PulseAudioServerInfo *u = (PulseAudioServerInfo*)userdata; if(server_info->default_sink_name) @@ -1807,6 +1768,7 @@ static void view_combo_box_change_callback(GtkComboBox *widget, gpointer userdat const gchar *selected_view = gtk_combo_box_get_active_id(widget); gtk_widget_set_visible(GTK_WIDGET(video_codec_grid), strcmp(selected_view, "advanced") == 0); gtk_widget_set_visible(GTK_WIDGET(audio_codec_grid), strcmp(selected_view, "advanced") == 0); + gtk_widget_set_visible(GTK_WIDGET(framerate_mode_grid), strcmp(selected_view, "advanced") == 0); gtk_widget_set_visible(GTK_WIDGET(overclock_grid), strcmp(selected_view, "advanced") == 0 && gpu_inf.vendor == GPU_VENDOR_NVIDIA && !wayland); } @@ -2110,7 +2072,7 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a if(!gsr_egl_supports_wayland_capture(&egl)) label += ", requires root access"; } else if(gpu_inf.vendor != GPU_VENDOR_NVIDIA) { - label += ", requires root access, may perform better"; + label += ", requires root access"; } label += ")"; @@ -2161,7 +2123,7 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a gtk_grid_attach(area_size_grid, GTK_WIDGET(area_height_entry), 2, 0, 1, 1); } - GtkFrame *audio_input_frame = GTK_FRAME(gtk_frame_new("Audio input")); + GtkFrame *audio_input_frame = GTK_FRAME(gtk_frame_new("Audio")); gtk_grid_attach(grid, GTK_WIDGET(audio_input_frame), 0, grid_row++, 2, 1); GtkGrid *audio_grid = GTK_GRID(gtk_grid_new()); @@ -2177,69 +2139,39 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a 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); - audio_input_menu_todo = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new()); + // TODO: const PulseAudioServerInfo pa_server_info = get_pulseaudio_default_inputs(); - const auto audio_inputs = get_pulseaudio_inputs(); - if(!pa_server_info.default_sink_name.empty() && audio_inputs_contains(audio_inputs, pa_server_info.default_sink_name)) { - gtk_combo_box_text_append(audio_input_menu_todo, pa_server_info.default_sink_name.c_str(), "Default output"); - ++num_audio_inputs_addable; - } + // if(!pa_server_info.default_sink_name.empty() && audio_inputs_contains(audio_inputs, pa_server_info.default_sink_name)) { + // gtk_combo_box_text_append(audio_input_menu_todo, pa_server_info.default_sink_name.c_str(), "Default output"); + // ++num_audio_inputs_addable; + // } - if(!pa_server_info.default_source_name.empty() && audio_inputs_contains(audio_inputs, pa_server_info.default_source_name)) { - gtk_combo_box_text_append(audio_input_menu_todo, pa_server_info.default_source_name.c_str(), "Default input"); - ++num_audio_inputs_addable; - } + // if(!pa_server_info.default_source_name.empty() && audio_inputs_contains(audio_inputs, pa_server_info.default_source_name)) { + // gtk_combo_box_text_append(audio_input_menu_todo, pa_server_info.default_source_name.c_str(), "Default input"); + // ++num_audio_inputs_addable; + // } - for(const AudioInput &audio_input : audio_inputs) { - std::string text = audio_input.description; - gtk_combo_box_text_append(audio_input_menu_todo, audio_input.name.c_str(), audio_input.description.c_str()); - ++num_audio_inputs_addable; - } - gtk_widget_set_hexpand(GTK_WIDGET(audio_input_menu_todo), true); - gtk_grid_attach(add_audio_grid, GTK_WIDGET(audio_input_menu_todo), 0, 0, 1, 1); + // for(const AudioInput &audio_input : audio_inputs) { + // std::string text = audio_input.description; + // gtk_combo_box_text_append(audio_input_menu_todo, audio_input.name.c_str(), audio_input.description.c_str()); + // ++num_audio_inputs_addable; + // } - add_audio_input_button = gtk_button_new_with_label("Add"); - gtk_widget_set_halign(add_audio_input_button, GTK_ALIGN_END); - gtk_grid_attach(add_audio_grid, add_audio_input_button, 1, 0, 1, 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){ - const gint selected_audio_input = gtk_combo_box_get_active(GTK_COMBO_BOX(audio_input_menu_todo)); - const char *active_id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(audio_input_menu_todo)); - const char *active_text = gtk_combo_box_text_get_active_text(audio_input_menu_todo); - if(selected_audio_input == -1 || !active_id || !active_text) - return true; - - GtkWidget *row = create_used_audio_input_row(active_id, active_text); + 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); - gtk_combo_box_text_remove(audio_input_menu_todo, selected_audio_input); - - --num_audio_inputs_addable; - if(num_audio_inputs_addable > 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(audio_input_menu_todo), num_audio_inputs_addable - 1); - else - gtk_widget_set_sensitive(add_audio_input_button, false); - - enable_stream_record_button_if_info_filled(); + gtk_list_box_insert(GTK_LIST_BOX(audio_input_used_list), row, -1); return true; }), nullptr); - if(num_audio_inputs_addable > 0) { - gtk_combo_box_set_active(GTK_COMBO_BOX(audio_input_menu_todo), 0); - gtk_widget_set_sensitive(add_audio_input_button, true); - } else { - gtk_widget_set_sensitive(add_audio_input_button, false); - } - 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); - GtkWidget *selected_audio_inputs_label = gtk_label_new("Selected audio inputs:"); - gtk_widget_set_halign(selected_audio_inputs_label, GTK_ALIGN_START); - gtk_grid_attach(add_audio_grid, selected_audio_inputs_label, 0, ++audio_input_area_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); gtk_widget_set_halign(merge_audio_tracks_button, GTK_ALIGN_START); @@ -2287,6 +2219,17 @@ static GtkWidget* create_common_settings_page(GtkStack *stack, GtkApplication *a gtk_grid_attach(audio_codec_grid, GTK_WIDGET(audio_codec_input_menu), 1, 0, 1, 1); gtk_combo_box_set_active(GTK_COMBO_BOX(audio_codec_input_menu), 0); + framerate_mode_grid = GTK_GRID(gtk_grid_new()); + gtk_grid_attach(grid, GTK_WIDGET(framerate_mode_grid), 0, grid_row++, 2, 1); + gtk_grid_attach(framerate_mode_grid, gtk_label_new("Framerate mode: "), 0, 0, 1, 1); + framerate_mode_input_menu = GTK_COMBO_BOX_TEXT(gtk_combo_box_text_new()); + gtk_combo_box_text_append(framerate_mode_input_menu, "auto", "Auto (Recommended)"); + gtk_combo_box_text_append(framerate_mode_input_menu, "cfr", "Constant"); + gtk_combo_box_text_append(framerate_mode_input_menu, "vfr", "Variable"); + gtk_widget_set_hexpand(GTK_WIDGET(framerate_mode_input_menu), true); + gtk_grid_attach(framerate_mode_grid, GTK_WIDGET(framerate_mode_input_menu), 1, 0, 1, 1); + gtk_combo_box_set_active(GTK_COMBO_BOX(framerate_mode_input_menu), 0); + overclock_grid = GTK_GRID(gtk_grid_new()); gtk_grid_attach(grid, GTK_WIDGET(overclock_grid), 0, grid_row++, 2, 1); overclock_button = gtk_check_button_new_with_label("Overclock memory transfer rate to workaround NVIDIA driver performance bug"); @@ -2638,27 +2581,22 @@ static gboolean handle_child_process_death(gpointer userdata) { return G_SOURCE_CONTINUE; } -// Only adds the item if |name| matches an item in the audio input menu static void add_audio_input_track(const char *name) { - std::string audio_input_id; - const gint audio_input_row = combo_box_text_get_row_by_label(GTK_COMBO_BOX(audio_input_menu_todo), name, audio_input_id); - if(audio_input_row == -1) - return; + GtkWidget *row = create_used_audio_input_row(); + + const AudioRow *audio_row = (AudioRow*)g_object_get_data(G_OBJECT(row), "audio-row"); + std::string audio_id; + gint target_combo_box_index = combo_box_text_get_row_by_label(GTK_COMBO_BOX(audio_row->input_list), name, audio_id); + if(target_combo_box_index != -1) + gtk_combo_box_set_active(GTK_COMBO_BOX(audio_row->input_list), target_combo_box_index); - GtkWidget *row = create_used_audio_input_row(audio_input_id.c_str(), name); gtk_widget_show_all(row); gtk_list_box_insert (GTK_LIST_BOX(audio_input_used_list), row, -1); - gtk_combo_box_text_remove(audio_input_menu_todo, audio_input_row); - - --num_audio_inputs_addable; - if(num_audio_inputs_addable > 0) - gtk_combo_box_set_active(GTK_COMBO_BOX(audio_input_menu_todo), num_audio_inputs_addable - 1); - else - gtk_widget_set_sensitive(add_audio_input_button, false); } static void load_config(const gpu_info &gpu_inf) { - config = read_config(); + bool config_empty = false; + config = read_config(config_empty); if(!wayland && strcmp(config.main_config.record_area_option.c_str(), "window") == 0) { // @@ -2717,6 +2655,9 @@ static void load_config(const gpu_info &gpu_inf) { if(config.main_config.audio_codec != "opus" && config.main_config.audio_codec != "aac" && config.main_config.audio_codec != "flac") config.main_config.audio_codec = "opus"; + if(config.main_config.framerate_mode != "auto" && config.main_config.framerate_mode != "cfr" && config.main_config.framerate_mode != "vfr") + config.main_config.framerate_mode = "auto"; + if(config.streaming_config.streaming_service != "twitch" && config.streaming_config.streaming_service != "youtube" && config.streaming_config.streaming_service != "custom") config.streaming_config.streaming_service = "twitch"; @@ -2741,12 +2682,18 @@ static void load_config(const gpu_info &gpu_inf) { } gtk_spin_button_set_value(fps_entry, config.main_config.fps); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(merge_audio_tracks_button), config.main_config.merge_audio_tracks); + for(const std::string &audio_input : config.main_config.audio_input) { add_audio_input_track(audio_input.c_str()); } + + if(config_empty && config.main_config.audio_input.empty()) + add_audio_input_track("Default output"); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(quality_input_menu), config.main_config.quality.c_str()); gtk_combo_box_set_active_id(GTK_COMBO_BOX(video_codec_input_menu), config.main_config.codec.c_str()); gtk_combo_box_set_active_id(GTK_COMBO_BOX(audio_codec_input_menu), config.main_config.audio_codec.c_str()); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(framerate_mode_input_menu), config.main_config.framerate_mode.c_str()); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(overclock_button), config.main_config.overclock); gtk_combo_box_set_active_id(GTK_COMBO_BOX(stream_service_input_menu), config.streaming_config.streaming_service.c_str()); @@ -2933,6 +2880,14 @@ static void activate(GtkApplication *app, gpointer) { gtk_window_set_resizable(GTK_WINDOW(window), false); select_window_userdata.app = app; + audio_inputs = get_pulseaudio_inputs(); + pa_default_sources = get_pulseaudio_default_inputs(); + + if(!pa_default_sources.default_source_name.empty() && audio_inputs_contains(audio_inputs, pa_default_sources.default_source_name)) + audio_inputs.insert(audio_inputs.begin(), { pa_default_sources.default_source_name.c_str(), "Default input" }); + + if(!pa_default_sources.default_sink_name.empty() && audio_inputs_contains(audio_inputs, pa_default_sources.default_sink_name)) + audio_inputs.insert(audio_inputs.begin(), { pa_default_sources.default_sink_name.c_str(), "Default output" }); if(!wayland) crosshair_cursor = XCreateFontCursor(gdk_x11_get_default_xdisplay(), XC_crosshair); -- cgit v1.2.3