--- a/pidgin/prefs/pidginvvprefs.c Thu Mar 30 22:03:24 2023 -0500
+++ b/pidgin/prefs/pidginvvprefs.c Thu Mar 30 22:30:46 2023 -0500
@@ -40,8 +40,8 @@
AdwPreferencesPage parent;
- PidginPrefCombo output;
GtkWidget *threshold_row;
@@ -52,8 +52,8 @@
- PidginPrefCombo output;
@@ -70,31 +70,37 @@
*****************************************************************************/
-populate_vv_device_menuitems(PurpleMediaElementType type, GtkListStore *store)
+populate_vv_device_menuitems(AdwComboRow *row, PurpleMediaElementType type, PurpleMediaManager *manager = NULL;
+ GListStore *store = NULL; + guint selected = 0; /* Default to auto{audio,video}{src,sink} elements. */ - gtk_list_store_clear(store);
+ store = G_LIST_STORE(adw_combo_row_get_model(row)); + g_list_store_remove_all(store); manager = purple_media_manager_get();
devices = purple_media_manager_enumerate_elements(manager, type);
for (; devices; devices = g_list_delete_link(devices, devices)) {
PurpleMediaElementInfo *info = devices->data;
- name = purple_media_element_info_get_name(info);
- id = purple_media_element_info_get_id(info);
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter, PIDGIN_PREF_COMBO_TEXT, name,
- PIDGIN_PREF_COMBO_VALUE, id, -1);
+ id = purple_media_element_info_get_id(info); + if(purple_strequal(id, active)) { + /* The index will be for the *next* appended item. */ + selected = g_list_model_get_n_items(G_LIST_MODEL(store));
+ g_list_store_append(store, info); + adw_combo_row_set_selected(row, selected); @@ -435,66 +441,80 @@
-bind_vv_dropdown(PidginPrefCombo *combo, PurpleMediaElementType element_type)
+vv_combo_row_set(GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer data) - const gchar *preference_key;
+ const char *key = data; + PurpleMediaElementInfo *item = NULL; - preference_key = purple_media_type_to_preference_key(element_type);
- model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo->combo));
- populate_vv_device_menuitems(element_type, GTK_LIST_STORE(model));
- combo->type = PURPLE_PREF_STRING;
- combo->key = preference_key;
- pidgin_prefs_bind_dropdown(combo);
+ item = adw_combo_row_get_selected_item(ADW_COMBO_ROW(obj)); + id = purple_media_element_info_get_id(item); + purple_prefs_set_string(key, id); -bind_vv_frame(PidginVVPrefs *prefs, PidginPrefCombo *combo,
+bind_vv_combo(PidginVVPrefs *prefs, AdwComboRow *row, PurpleMediaElementType type)
- bind_vv_dropdown(combo, type);
+ const char *pref_key = NULL; + const char *pref_value = NULL; + pref_key = purple_media_type_to_preference_key(type); + pref_value = purple_prefs_get_string(pref_key); + populate_vv_device_menuitems(row, type, pref_value); - purple_prefs_connect_callback(combo->combo,
- purple_media_type_to_preference_key(type),
- vv_device_changed_cb, prefs);
- g_signal_connect_swapped(combo->combo, "destroy",
+ g_signal_connect(row, "notify::selected", G_CALLBACK(vv_combo_row_set), + purple_prefs_connect_callback(row, pref_key, vv_device_changed_cb, prefs); + g_signal_connect_swapped(row, "destroy", G_CALLBACK(purple_prefs_disconnect_by_handle),
- g_object_set_data(G_OBJECT(combo->combo), "vv_media_type",
- g_object_set_data(G_OBJECT(combo->combo), "vv_combo", combo);
+ g_object_set_data(G_OBJECT(row), "vv_media_type", GINT_TO_POINTER(type)); device_list_changed_cb(G_GNUC_UNUSED PurpleMediaManager *manager,
- PidginPrefCombo *combo;
+ AdwComboRow *row = data; + PurpleMediaElementInfo *original = NULL; + PurpleMediaElementInfo *selected = NULL; PurpleMediaElementType media_type;
- const gchar *preference_key;
+ const char *pref_key = NULL; + const char *pref_value = NULL; + original = g_object_ref(adw_combo_row_get_selected_item(row)); - combo = g_object_get_data(G_OBJECT(widget), "vv_combo");
- media_type = (PurpleMediaElementType)GPOINTER_TO_INT(g_object_get_data(
- preference_key = purple_media_type_to_preference_key(media_type);
+ media_type = (PurpleMediaElementType)GPOINTER_TO_INT( + pref_key = purple_media_type_to_preference_key(media_type); + pref_value = purple_prefs_get_string(pref_key); /* Block signals so pref doesn't get re-saved while changing UI. */
- signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX);
- g_signal_handlers_block_matched(combo->combo, G_SIGNAL_MATCH_ID, signal_id,
+ g_signal_handlers_block_by_func(row, vv_combo_row_set, (gpointer)pref_key); + populate_vv_device_menuitems(row, media_type, pref_value); + g_signal_handlers_unblock_by_func(row, vv_combo_row_set, - model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo->combo));
- populate_vv_device_menuitems(media_type, GTK_LIST_STORE(model));
- gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo->combo),
- purple_prefs_get_string(preference_key));
+ selected = adw_combo_row_get_selected_item(row); + if(original != selected) { + /* We blocked signals to prevent accidentally changing the selected + * element while the combo row repopulates, but now the original + * element is gone, so we need to push this change back to the pref. */ + char *id = purple_media_element_info_get_id(selected); + purple_prefs_set_string(pref_key, id); - g_signal_handlers_unblock_matched(combo->combo, G_SIGNAL_MATCH_ID,
- signal_id, 0, NULL, NULL, NULL);
+ g_clear_object(&original); /******************************************************************************
@@ -511,9 +531,9 @@
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
@@ -533,9 +553,9 @@
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
@@ -553,31 +573,31 @@
manager = purple_media_manager_get();
- bind_vv_frame(prefs, &prefs->voice.input,
+ bind_vv_combo(prefs, prefs->voice.input, PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SRC);
g_signal_connect_object(manager, "elements-changed::audiosrc",
G_CALLBACK(device_list_changed_cb),
- prefs->voice.input.combo, 0);
+ prefs->voice.input, 0); - bind_vv_frame(prefs, &prefs->voice.output,
+ bind_vv_combo(prefs, prefs->voice.output, PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SINK);
g_signal_connect_object(manager, "elements-changed::audiosink",
G_CALLBACK(device_list_changed_cb),
- prefs->voice.output.combo, 0);
+ prefs->voice.output, 0); - bind_vv_frame(prefs, &prefs->video.input,
+ bind_vv_combo(prefs, prefs->video.input, PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC);
g_signal_connect_object(manager, "elements-changed::videosrc",
G_CALLBACK(device_list_changed_cb),
- prefs->video.input.combo, 0);
+ prefs->video.input, 0); - bind_vv_frame(prefs, &prefs->video.output,
+ bind_vv_combo(prefs, prefs->video.output, PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SINK);
g_signal_connect_object(manager, "elements-changed::videosink",
G_CALLBACK(device_list_changed_cb),
- prefs->video.output.combo, 0);
+ prefs->video.output, 0); /******************************************************************************
--- a/pidgin/resources/Prefs/vv.ui Thu Mar 30 22:03:24 2023 -0500
+++ b/pidgin/resources/Prefs/vv.ui Thu Mar 30 22:30:46 2023 -0500
@@ -33,78 +33,51 @@
<property name="step-increment">1</property>
<property name="page-increment">10</property>
- <object class="GtkListStore" id="video.input.store">
- <!-- column-name text -->
- <column type="gchararray"/>
- <!-- column-name value -->
- <column type="gchararray"/>
- <object class="GtkListStore" id="video.output.store">
- <!-- column-name text -->
- <column type="gchararray"/>
- <!-- column-name value -->
- <column type="gchararray"/>
- <object class="GtkListStore" id="voice.input.store">
- <!-- column-name text -->
- <column type="gchararray"/>
- <!-- column-name value -->
- <column type="gchararray"/>
- <object class="GtkListStore" id="voice.output.store">
- <!-- column-name text -->
- <column type="gchararray"/>
- <!-- column-name value -->
- <column type="gchararray"/>
+ <object class="GtkBuilderListItemFactory" id="element-info-factory"> + <property name="bytes"> +<?xml version="1.0" encoding="UTF-8"?> + <template class="GtkListItem"> + <property name="child"> + <object class="GtkLabel"> + <property name="xalign">0</property> + <lookup name="name" type="PurpleMediaElementInfo"> + <lookup name="item">GtkListItem</lookup> <template class="PidginVVPrefs" parent="AdwPreferencesPage">
<object class="AdwPreferencesGroup">
<property name="title" translatable="1">Audio</property>
- <object class="AdwActionRow">
- <property name="activatable-widget">voice.input.combo</property>
+ <object class="AdwComboRow" id="voice.input"> <property name="title" translatable="1" context="Input for Audio">Input Device</property>
- <object class="GtkComboBox" id="voice.input.combo">
- <property name="id-column">1</property>
- <property name="model">voice.input.store</property>
- <property name="valign">center</property>
- <object class="GtkCellRendererText"/>
- <attribute name="text">0</attribute>
+ <property name="factory">element-info-factory</property> + <property name="model"> + <object class="GListStore"> + <property name="item-type">PurpleMediaElementInfo</property>
- <object class="AdwActionRow">
- <property name="activatable-widget">voice.output.combo</property>
+ <object class="AdwComboRow" id="voice.output"> <property name="title" translatable="1" context="Device for Audio Output">Output Device</property>
- <object class="GtkComboBox" id="voice.output.combo">
- <property name="id-column">1</property>
- <property name="model">voice.output.store</property>
- <property name="valign">center</property>
- <object class="GtkCellRendererText"/>
- <attribute name="text">0</attribute>
+ <property name="factory">element-info-factory</property> + <property name="model"> + <object class="GListStore"> + <property name="item-type">PurpleMediaElementInfo</property>
@@ -188,43 +161,25 @@
<object class="AdwPreferencesGroup">
<property name="title" translatable="1">Video</property>
- <object class="AdwActionRow">
- <property name="activatable-widget">video.input.combo</property>
+ <object class="AdwComboRow" id="video.input"> <property name="title" translatable="1" context="Device for Video Input">Input Device</property>
- <object class="GtkComboBox" id="video.input.combo">
- <property name="id-column">1</property>
- <property name="hexpand">1</property>
- <property name="model">video.input.store</property>
- <property name="valign">center</property>
- <object class="GtkCellRendererText"/>
- <attribute name="text">0</attribute>
+ <property name="factory">element-info-factory</property> + <property name="model"> + <object class="GListStore"> + <property name="item-type">PurpleMediaElementInfo</property>
- <object class="AdwActionRow">
- <property name="activatable-widget">video.output.combo</property>
+ <object class="AdwComboRow" id="video.output"> <property name="title" translatable="1" context="Device for Video Output">Output Device</property>
- <object class="GtkComboBox" id="video.output.combo">
- <property name="hexpand">1</property>
- <property name="id-column">1</property>
- <property name="valign">center</property>
- <property name="model">video.output.store</property>
- <object class="GtkCellRendererText"/>
- <attribute name="text">0</attribute>
+ <property name="factory">element-info-factory</property> + <property name="model"> + <object class="GListStore"> + <property name="item-type">PurpleMediaElementInfo</property>