pidgin/prefs/pidginvvprefs.c

changeset 42191
68380e709c16
parent 42108
bc9f3f1dd14b
child 42202
2273647d24b0
equal deleted inserted replaced
42190:a8bad57aa8c3 42191:68380e709c16
38 38
39 struct _PidginVVPrefs { 39 struct _PidginVVPrefs {
40 AdwPreferencesPage parent; 40 AdwPreferencesPage parent;
41 41
42 struct { 42 struct {
43 PidginPrefCombo input; 43 AdwComboRow *input;
44 PidginPrefCombo output; 44 AdwComboRow *output;
45 GtkWidget *threshold_row; 45 GtkWidget *threshold_row;
46 GtkWidget *threshold; 46 GtkWidget *threshold;
47 GtkWidget *volume; 47 GtkWidget *volume;
48 GtkWidget *test; 48 GtkWidget *test;
49 GtkWidget *level; 49 GtkWidget *level;
50 GtkWidget *drop; 50 GtkWidget *drop;
51 GstElement *pipeline; 51 GstElement *pipeline;
52 } voice; 52 } voice;
53 53
54 struct { 54 struct {
55 PidginPrefCombo input; 55 AdwComboRow *input;
56 PidginPrefCombo output; 56 AdwComboRow *output;
57 GtkWidget *frame; 57 GtkWidget *frame;
58 GtkWidget *test; 58 GtkWidget *test;
59 GstElement *pipeline; 59 GstElement *pipeline;
60 } video; 60 } video;
61 }; 61 };
68 68
69 /****************************************************************************** 69 /******************************************************************************
70 * Helpers 70 * Helpers
71 *****************************************************************************/ 71 *****************************************************************************/
72 static void 72 static void
73 populate_vv_device_menuitems(PurpleMediaElementType type, GtkListStore *store) 73 populate_vv_device_menuitems(AdwComboRow *row, PurpleMediaElementType type,
74 const char *active)
74 { 75 {
75 PurpleMediaManager *manager = NULL; 76 PurpleMediaManager *manager = NULL;
77 GListStore *store = NULL;
76 GList *devices; 78 GList *devices;
77 79 guint selected = 0; /* Default to auto{audio,video}{src,sink} elements. */
78 gtk_list_store_clear(store); 80
81 store = G_LIST_STORE(adw_combo_row_get_model(row));
82
83 g_list_store_remove_all(store);
79 84
80 manager = purple_media_manager_get(); 85 manager = purple_media_manager_get();
81 devices = purple_media_manager_enumerate_elements(manager, type); 86 devices = purple_media_manager_enumerate_elements(manager, type);
82 for (; devices; devices = g_list_delete_link(devices, devices)) { 87 for (; devices; devices = g_list_delete_link(devices, devices)) {
83 PurpleMediaElementInfo *info = devices->data; 88 PurpleMediaElementInfo *info = devices->data;
84 GtkTreeIter iter; 89 char *id;
85 char *name, *id; 90
86
87 name = purple_media_element_info_get_name(info);
88 id = purple_media_element_info_get_id(info); 91 id = purple_media_element_info_get_id(info);
89 92 if(purple_strequal(id, active)) {
90 gtk_list_store_append(store, &iter); 93 /* The index will be for the *next* appended item. */
91 gtk_list_store_set(store, &iter, PIDGIN_PREF_COMBO_TEXT, name, 94 selected = g_list_model_get_n_items(G_LIST_MODEL(store));
92 PIDGIN_PREF_COMBO_VALUE, id, -1); 95 }
93
94 g_free(name);
95 g_free(id); 96 g_free(id);
97
98 g_list_store_append(store, info);
99
96 g_object_unref(info); 100 g_object_unref(info);
97 } 101 }
102
103 adw_combo_row_set_selected(row, selected);
98 } 104 }
99 105
100 static GstElement * 106 static GstElement *
101 create_test_element(PurpleMediaElementType type) 107 create_test_element(PurpleMediaElementType type)
102 { 108 {
433 439
434 return NULL; 440 return NULL;
435 } 441 }
436 442
437 static void 443 static void
438 bind_vv_dropdown(PidginPrefCombo *combo, PurpleMediaElementType element_type) 444 vv_combo_row_set(GObject *obj, G_GNUC_UNUSED GParamSpec *pspec, gpointer data)
439 { 445 {
440 const gchar *preference_key; 446 const char *key = data;
441 GtkTreeModel *model; 447 PurpleMediaElementInfo *item = NULL;
442 448 char *id = NULL;
443 preference_key = purple_media_type_to_preference_key(element_type); 449
444 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo->combo)); 450 item = adw_combo_row_get_selected_item(ADW_COMBO_ROW(obj));
445 populate_vv_device_menuitems(element_type, GTK_LIST_STORE(model)); 451 id = purple_media_element_info_get_id(item);
446 452 purple_prefs_set_string(key, id);
447 combo->type = PURPLE_PREF_STRING; 453 g_free(id);
448 combo->key = preference_key; 454 }
449 pidgin_prefs_bind_dropdown(combo); 455
450 } 456 static void
451 457 bind_vv_combo(PidginVVPrefs *prefs, AdwComboRow *row,
452 static void
453 bind_vv_frame(PidginVVPrefs *prefs, PidginPrefCombo *combo,
454 PurpleMediaElementType type) 458 PurpleMediaElementType type)
455 { 459 {
456 bind_vv_dropdown(combo, type); 460 const char *pref_key = NULL;
457 461 const char *pref_value = NULL;
458 purple_prefs_connect_callback(combo->combo, 462
459 purple_media_type_to_preference_key(type), 463 pref_key = purple_media_type_to_preference_key(type);
460 vv_device_changed_cb, prefs); 464 pref_value = purple_prefs_get_string(pref_key);
461 g_signal_connect_swapped(combo->combo, "destroy", 465
466 populate_vv_device_menuitems(row, type, pref_value);
467
468 g_signal_connect(row, "notify::selected", G_CALLBACK(vv_combo_row_set),
469 (gpointer)pref_key);
470
471 purple_prefs_connect_callback(row, pref_key, vv_device_changed_cb, prefs);
472 g_signal_connect_swapped(row, "destroy",
462 G_CALLBACK(purple_prefs_disconnect_by_handle), 473 G_CALLBACK(purple_prefs_disconnect_by_handle),
463 combo->combo); 474 row);
464 475
465 g_object_set_data(G_OBJECT(combo->combo), "vv_media_type", 476 g_object_set_data(G_OBJECT(row), "vv_media_type", GINT_TO_POINTER(type));
466 (gpointer)type);
467 g_object_set_data(G_OBJECT(combo->combo), "vv_combo", combo);
468 } 477 }
469 478
470 static void 479 static void
471 device_list_changed_cb(G_GNUC_UNUSED PurpleMediaManager *manager, 480 device_list_changed_cb(G_GNUC_UNUSED PurpleMediaManager *manager,
472 GtkWidget *widget) 481 gpointer data)
473 { 482 {
474 PidginPrefCombo *combo; 483 AdwComboRow *row = data;
484 PurpleMediaElementInfo *original = NULL;
485 PurpleMediaElementInfo *selected = NULL;
475 PurpleMediaElementType media_type; 486 PurpleMediaElementType media_type;
476 const gchar *preference_key; 487 const char *pref_key = NULL;
477 guint signal_id; 488 const char *pref_value = NULL;
478 GtkTreeModel *model; 489
479 490 original = g_object_ref(adw_combo_row_get_selected_item(row));
480 combo = g_object_get_data(G_OBJECT(widget), "vv_combo"); 491
481 media_type = (PurpleMediaElementType)GPOINTER_TO_INT(g_object_get_data( 492 media_type = (PurpleMediaElementType)GPOINTER_TO_INT(
482 G_OBJECT(widget), 493 g_object_get_data(
483 "vv_media_type")); 494 G_OBJECT(row),
484 preference_key = purple_media_type_to_preference_key(media_type); 495 "vv_media_type"));
496 pref_key = purple_media_type_to_preference_key(media_type);
497 pref_value = purple_prefs_get_string(pref_key);
485 498
486 /* Block signals so pref doesn't get re-saved while changing UI. */ 499 /* Block signals so pref doesn't get re-saved while changing UI. */
487 signal_id = g_signal_lookup("changed", GTK_TYPE_COMBO_BOX); 500 g_signal_handlers_block_by_func(row, vv_combo_row_set, (gpointer)pref_key);
488 g_signal_handlers_block_matched(combo->combo, G_SIGNAL_MATCH_ID, signal_id, 501
489 0, NULL, NULL, NULL); 502 populate_vv_device_menuitems(row, media_type, pref_value);
490 503
491 model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo->combo)); 504 g_signal_handlers_unblock_by_func(row, vv_combo_row_set,
492 populate_vv_device_menuitems(media_type, GTK_LIST_STORE(model)); 505 (gpointer)pref_key);
493 gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo->combo), 506
494 purple_prefs_get_string(preference_key)); 507 selected = adw_combo_row_get_selected_item(row);
495 508 if(original != selected) {
496 g_signal_handlers_unblock_matched(combo->combo, G_SIGNAL_MATCH_ID, 509 /* We blocked signals to prevent accidentally changing the selected
497 signal_id, 0, NULL, NULL, NULL); 510 * element while the combo row repopulates, but now the original
511 * element is gone, so we need to push this change back to the pref. */
512 char *id = purple_media_element_info_get_id(selected);
513 purple_prefs_set_string(pref_key, id);
514 g_free(id);
515 }
516
517 g_clear_object(&original);
498 } 518 }
499 519
500 /****************************************************************************** 520 /******************************************************************************
501 * GObject Implementation 521 * GObject Implementation
502 *****************************************************************************/ 522 *****************************************************************************/
509 widget_class, 529 widget_class,
510 "/im/pidgin/Pidgin3/Prefs/vv.ui" 530 "/im/pidgin/Pidgin3/Prefs/vv.ui"
511 ); 531 );
512 532
513 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 533 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
514 voice.input.combo); 534 voice.input);
515 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 535 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
516 voice.output.combo); 536 voice.output);
517 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 537 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
518 voice.volume); 538 voice.volume);
519 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 539 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
520 voice.threshold_row); 540 voice.threshold_row);
521 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 541 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
531 threshold_value_changed_cb); 551 threshold_value_changed_cb);
532 gtk_widget_class_bind_template_callback(widget_class, 552 gtk_widget_class_bind_template_callback(widget_class,
533 toggle_voice_test_cb); 553 toggle_voice_test_cb);
534 554
535 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 555 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
536 video.input.combo); 556 video.input);
537 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 557 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
538 video.output.combo); 558 video.output);
539 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 559 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
540 video.frame); 560 video.frame);
541 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs, 561 gtk_widget_class_bind_template_child(widget_class, PidginVVPrefs,
542 video.test); 562 video.test);
543 gtk_widget_class_bind_template_callback(widget_class, 563 gtk_widget_class_bind_template_callback(widget_class,
551 571
552 gtk_widget_init_template(GTK_WIDGET(prefs)); 572 gtk_widget_init_template(GTK_WIDGET(prefs));
553 573
554 manager = purple_media_manager_get(); 574 manager = purple_media_manager_get();
555 575
556 bind_vv_frame(prefs, &prefs->voice.input, 576 bind_vv_combo(prefs, prefs->voice.input,
557 PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SRC); 577 PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SRC);
558 g_signal_connect_object(manager, "elements-changed::audiosrc", 578 g_signal_connect_object(manager, "elements-changed::audiosrc",
559 G_CALLBACK(device_list_changed_cb), 579 G_CALLBACK(device_list_changed_cb),
560 prefs->voice.input.combo, 0); 580 prefs->voice.input, 0);
561 581
562 bind_vv_frame(prefs, &prefs->voice.output, 582 bind_vv_combo(prefs, prefs->voice.output,
563 PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SINK); 583 PURPLE_MEDIA_ELEMENT_AUDIO | PURPLE_MEDIA_ELEMENT_SINK);
564 g_signal_connect_object(manager, "elements-changed::audiosink", 584 g_signal_connect_object(manager, "elements-changed::audiosink",
565 G_CALLBACK(device_list_changed_cb), 585 G_CALLBACK(device_list_changed_cb),
566 prefs->voice.output.combo, 0); 586 prefs->voice.output, 0);
567 587
568 bind_voice_test(prefs); 588 bind_voice_test(prefs);
569 589
570 bind_vv_frame(prefs, &prefs->video.input, 590 bind_vv_combo(prefs, prefs->video.input,
571 PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC); 591 PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SRC);
572 g_signal_connect_object(manager, "elements-changed::videosrc", 592 g_signal_connect_object(manager, "elements-changed::videosrc",
573 G_CALLBACK(device_list_changed_cb), 593 G_CALLBACK(device_list_changed_cb),
574 prefs->video.input.combo, 0); 594 prefs->video.input, 0);
575 595
576 bind_vv_frame(prefs, &prefs->video.output, 596 bind_vv_combo(prefs, prefs->video.output,
577 PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SINK); 597 PURPLE_MEDIA_ELEMENT_VIDEO | PURPLE_MEDIA_ELEMENT_SINK);
578 g_signal_connect_object(manager, "elements-changed::videosink", 598 g_signal_connect_object(manager, "elements-changed::videosink",
579 G_CALLBACK(device_list_changed_cb), 599 G_CALLBACK(device_list_changed_cb),
580 prefs->video.output.combo, 0); 600 prefs->video.output, 0);
581 } 601 }
582 602
583 /****************************************************************************** 603 /******************************************************************************
584 * API 604 * API
585 *****************************************************************************/ 605 *****************************************************************************/

mercurial