123
119
static void on_adjustment_value_changed (GtkAdjustment *adjustment,
124
120
GvcMixerDialog *dialog);
121
static void on_control_active_output_update (GvcMixerControl *control,
123
GvcMixerDialog *dialog);
125
static void on_control_active_input_update (GvcMixerControl *control,
127
GvcMixerDialog *dialog);
129
static void on_test_speakers_clicked (GvcComboBox *widget,
126
133
G_DEFINE_TYPE (GvcMixerDialog, gvc_mixer_dialog, GTK_TYPE_VBOX)
129
update_default_input (GvcMixerDialog *dialog)
135
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
136
ret = gtk_tree_model_get_iter_first (model, &iter);
138
g_debug ("No default input selected or available");
145
GvcMixerStream *stream;
147
gtk_tree_model_get (model, &iter,
149
ACTIVE_COLUMN, &toggled,
152
stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
153
if (stream == NULL) {
154
g_warning ("Unable to find stream for id: %u", id);
159
if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
163
gtk_list_store_set (GTK_LIST_STORE (model),
165
ACTIVE_COLUMN, is_default,
168
GtkTreeSelection *selection;
170
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
171
gtk_tree_selection_select_iter (selection, &iter);
173
} while (gtk_tree_model_iter_next (model, &iter));
177
update_description (GvcMixerDialog *dialog,
180
GvcMixerStream *stream)
186
if (GVC_IS_MIXER_SOURCE (stream))
187
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
188
else if (GVC_IS_MIXER_SINK (stream))
189
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
191
g_assert_not_reached ();
192
gtk_tree_model_get_iter_first (model, &iter);
194
id = gvc_mixer_stream_get_id (stream);
198
gtk_tree_model_get (model, &iter,
199
ID_COLUMN, ¤t_id,
201
if (id != current_id)
204
gtk_list_store_set (GTK_LIST_STORE (model),
209
} while (gtk_tree_model_iter_next (model, &iter));
213
port_selection_changed (GvcComboBox *combo_box,
215
GvcMixerDialog *dialog)
217
GvcMixerStream *stream;
219
stream = g_object_get_data (G_OBJECT (combo_box), "stream");
220
if (stream == NULL) {
221
g_warning ("Could not find stream for port combo box");
224
if (gvc_mixer_stream_change_port (stream, port) == FALSE) {
225
g_warning ("Could not change port for stream");
230
update_output_settings (GvcMixerDialog *dialog)
136
profile_selection_changed (GvcComboBox *combo_box,
138
GvcMixerDialog *dialog)
140
GvcMixerUIDevice *output;
142
g_debug ("profile_selection_changed() to %s", profile);
144
output = g_object_get_data (G_OBJECT (combo_box), "uidevice");
146
if (output == NULL) {
147
g_warning ("Could not find Output for profile combo box");
151
g_debug ("on profile selection changed on output '%s' (origin: %s, id: %i)",
152
gvc_mixer_ui_device_get_description (output),
153
gvc_mixer_ui_device_get_origin (output),
154
gvc_mixer_ui_device_get_id (output));
156
if (gvc_mixer_control_change_profile_on_selected_device (dialog->priv->mixer_control, output, profile) == FALSE) {
157
g_warning ("Could not change profile on device %s",
158
gvc_mixer_ui_device_get_description (output));
163
update_output_settings (GvcMixerDialog *dialog,
164
GvcMixerUIDevice *device)
232
166
GvcMixerStream *stream;
233
167
const GvcChannelMap *map;
168
const GList *profiles;
235
169
GtkAdjustment *adj;
237
171
g_debug ("Updating output settings");
316
251
gtk_widget_show (dialog->priv->output_lfe_bar);
319
ports = gvc_mixer_stream_get_ports (stream);
321
const GvcMixerStreamPort *port;
322
port = gvc_mixer_stream_get_port (stream);
324
dialog->priv->output_port_combo = gvc_combo_box_new (_("Co_nnector:"));
325
gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->output_port_combo),
327
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_port_combo), port->port);
328
g_object_set_data (G_OBJECT (dialog->priv->output_port_combo), "stream", stream);
329
g_signal_connect (G_OBJECT (dialog->priv->output_port_combo), "changed",
330
G_CALLBACK (port_selection_changed), dialog);
254
profiles = gvc_mixer_ui_device_get_profiles (device);
255
/* FIXME: How do we make sure the "Test speakers" button is shown
256
* even when there are no profiles to choose between? */
257
if (TRUE /*g_list_length((GList *) profiles) >= 2 */) {
258
const gchar *active_profile;
260
dialog->priv->output_profile_combo = gvc_combo_box_new (_("_Profile:"));
262
g_object_set (G_OBJECT (dialog->priv->output_profile_combo), "button-label", _("_Test Speakers"), NULL);
263
g_object_set (G_OBJECT (dialog->priv->output_profile_combo),
264
"show-button", TRUE, NULL);
265
g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "button-clicked",
266
G_CALLBACK (on_test_speakers_clicked), dialog);
269
gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
332
271
gtk_box_pack_start (GTK_BOX (dialog->priv->output_settings_box),
333
dialog->priv->output_port_combo,
272
dialog->priv->output_profile_combo,
336
275
if (dialog->priv->size_group != NULL) {
337
gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_port_combo),
276
gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->output_profile_combo),
338
277
dialog->priv->size_group, FALSE);
341
gtk_widget_show (dialog->priv->output_port_combo);
280
active_profile = gvc_mixer_ui_device_get_active_profile (device);
282
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->output_profile_combo), active_profile);
284
g_object_set_data (G_OBJECT (dialog->priv->output_profile_combo),
287
if (g_list_length((GList *) profiles))
288
g_signal_connect (G_OBJECT (dialog->priv->output_profile_combo), "changed",
289
G_CALLBACK (profile_selection_changed), dialog);
291
gtk_widget_show (dialog->priv->output_profile_combo);
344
294
/* FIXME: We could make this into a "No settings" label instead */
345
295
gtk_widget_set_sensitive (dialog->priv->output_balance_bar, gvc_channel_map_can_balance (map));
349
update_default_output (GvcMixerDialog *dialog)
354
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
355
gtk_tree_model_get_iter_first (model, &iter);
360
GvcMixerStream *stream;
362
gtk_tree_model_get (model, &iter,
364
ACTIVE_COLUMN, &toggled,
367
stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
368
if (stream == NULL) {
369
g_warning ("Unable to find stream for id: %u", id);
374
if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
378
gtk_list_store_set (GTK_LIST_STORE (model),
380
ACTIVE_COLUMN, is_default,
383
GtkTreeSelection *selection;
385
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
386
gtk_tree_selection_select_iter (selection, &iter);
388
} while (gtk_tree_model_iter_next (model, &iter));
392
on_mixer_control_default_sink_changed (GvcMixerControl *control,
394
GvcMixerDialog *dialog)
396
GvcMixerStream *stream;
398
g_debug ("GvcMixerDialog: default sink changed: %u", id);
400
if (id == PA_INVALID_INDEX)
403
stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control,
405
bar_set_stream (dialog, dialog->priv->output_bar, stream);
407
update_output_settings (dialog);
409
update_default_output (dialog);
413
298
#define DECAY_STEP .15
627
514
gtk_adjustment_set_value (adj,
628
515
gvc_mixer_stream_get_volume (stream));
630
ports = gvc_mixer_stream_get_ports (stream);
632
const GvcMixerStreamPort *port;
633
port = gvc_mixer_stream_get_port (stream);
635
dialog->priv->input_port_combo = gvc_combo_box_new (_("Co_nnector:"));
636
gvc_combo_box_set_ports (GVC_COMBO_BOX (dialog->priv->input_port_combo),
638
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_port_combo), port->port);
639
g_object_set_data (G_OBJECT (dialog->priv->input_port_combo), "stream", stream);
640
g_signal_connect (G_OBJECT (dialog->priv->input_port_combo), "changed",
641
G_CALLBACK (port_selection_changed), dialog);
643
if (dialog->priv->size_group != NULL) {
644
gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_port_combo),
645
dialog->priv->size_group, FALSE);
517
profiles = gvc_mixer_ui_device_get_profiles (device);
518
if (g_list_length ((GList *) profiles) >= 2) {
519
const gchar *active_profile;
521
dialog->priv->input_profile_combo = gvc_combo_box_new (_("_Profile:"));
522
gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
647
525
gtk_box_pack_start (GTK_BOX (dialog->priv->input_settings_box),
648
dialog->priv->input_port_combo,
526
dialog->priv->input_profile_combo,
650
gtk_widget_show (dialog->priv->input_port_combo);
529
if (dialog->priv->size_group != NULL) {
530
gvc_combo_box_set_size_group (GVC_COMBO_BOX (dialog->priv->input_profile_combo),
531
dialog->priv->size_group, FALSE);
534
active_profile = gvc_mixer_ui_device_get_active_profile (device);
536
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->input_profile_combo), active_profile);
538
g_object_set_data (G_OBJECT (dialog->priv->input_profile_combo),
541
g_signal_connect (G_OBJECT (dialog->priv->input_profile_combo), "changed",
542
G_CALLBACK (profile_selection_changed), dialog);
544
gtk_widget_show (dialog->priv->input_profile_combo);
653
547
create_monitor_stream_for_source (dialog, stream);
657
on_mixer_control_default_source_changed (GvcMixerControl *control,
659
GvcMixerDialog *dialog)
661
GvcMixerStream *stream;
664
g_debug ("GvcMixerDialog: default source changed: %u", id);
666
if (id == PA_INVALID_INDEX)
669
stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, id);
671
/* Disconnect the adj, otherwise it might change if is_amplified changes */
672
adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (dialog->priv->input_bar)));
673
g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
675
bar_set_stream (dialog, dialog->priv->input_bar, stream);
676
update_input_settings (dialog);
678
g_signal_connect (adj,
680
G_CALLBACK (on_adjustment_value_changed),
683
update_default_input (dialog);
687
551
gvc_mixer_dialog_set_mixer_control (GvcMixerDialog *dialog,
688
552
GvcMixerControl *control)
695
559
if (dialog->priv->mixer_control != NULL) {
696
560
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
697
G_CALLBACK (on_mixer_control_default_sink_changed),
561
G_CALLBACK (on_control_active_input_update),
699
563
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
700
G_CALLBACK (on_mixer_control_default_source_changed),
564
G_CALLBACK (on_control_active_output_update),
702
566
g_object_unref (dialog->priv->mixer_control);
705
569
dialog->priv->mixer_control = control;
571
/* FIXME: Why are some mixer_control signals connected here,
572
* and others in the dialog constructor? (And similar for disconnect) */
707
573
g_signal_connect (dialog->priv->mixer_control,
708
"default-sink-changed",
709
G_CALLBACK (on_mixer_control_default_sink_changed),
574
"active-input-update",
575
G_CALLBACK (on_control_active_input_update),
711
577
g_signal_connect (dialog->priv->mixer_control,
712
"default-source-changed",
713
G_CALLBACK (on_mixer_control_default_source_changed),
578
"active-output-update",
579
G_CALLBACK (on_control_active_output_update),
716
582
g_object_notify (G_OBJECT (dialog), "mixer-control");
826
lookup_combo_box_for_stream (GvcMixerDialog *dialog,
827
GvcMixerStream *stream)
829
GvcMixerStream *combo_stream;
832
id = gvc_mixer_stream_get_id (stream);
834
if (dialog->priv->output_port_combo != NULL) {
835
combo_stream = g_object_get_data (G_OBJECT (dialog->priv->output_port_combo),
837
if (combo_stream != NULL) {
838
if (id == gvc_mixer_stream_get_id (combo_stream))
839
return dialog->priv->output_port_combo;
843
if (dialog->priv->input_port_combo != NULL) {
844
combo_stream = g_object_get_data (G_OBJECT (dialog->priv->input_port_combo),
846
if (combo_stream != NULL) {
847
if (id == gvc_mixer_stream_get_id (combo_stream))
848
return dialog->priv->input_port_combo;
856
on_stream_description_notify (GvcMixerStream *stream,
858
GvcMixerDialog *dialog)
860
update_description (dialog, NAME_COLUMN,
861
gvc_mixer_stream_get_description (stream),
866
on_stream_port_notify (GObject *object,
868
GvcMixerDialog *dialog)
870
GvcComboBox *combo_box;
873
combo_box = GVC_COMBO_BOX (lookup_combo_box_for_stream (dialog, GVC_MIXER_STREAM (object)));
874
if (combo_box == NULL)
877
g_signal_handlers_block_by_func (G_OBJECT (combo_box),
878
port_selection_changed,
881
g_object_get (object, "port", &port, NULL);
882
gvc_combo_box_set_active (GVC_COMBO_BOX (combo_box), port);
884
g_signal_handlers_unblock_by_func (G_OBJECT (combo_box),
885
port_selection_changed,
890
692
on_stream_volume_notify (GObject *object,
891
693
GParamSpec *pspec,
813
/* active_input_update
814
* Handle input update change from the backend (control).
815
* Trust the backend whole-heartedly to deliver the correct input. */
817
active_input_update (GvcMixerDialog *dialog,
818
GvcMixerUIDevice *active_input)
820
/* First make sure the correct UI device is selected. */
823
GvcMixerStream *stream;
825
g_debug ("active_input_update device id = %i",
826
gvc_mixer_ui_device_get_id (active_input));
828
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
830
if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
831
g_warning ("No devices in the tree, so cannot set the active output");
836
gboolean is_selected = FALSE;
839
gtk_tree_model_get (model, &iter,
843
is_selected = id == gvc_mixer_ui_device_get_id (active_input);
845
gtk_list_store_set (GTK_LIST_STORE (model),
847
ACTIVE_COLUMN, is_selected,
851
GtkTreeSelection *selection;
852
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
853
gtk_tree_selection_select_iter (selection, &iter);
855
} while (gtk_tree_model_iter_next (model, &iter));
857
stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
859
if (stream == NULL) {
860
g_warning ("Couldn't find a stream from the active input");
861
gtk_widget_set_sensitive (dialog->priv->input_bar, FALSE);
865
bar_set_stream (dialog, dialog->priv->input_bar, stream);
866
update_input_settings (dialog, active_input);
870
/* active_output_update
871
* Handle output update change from the backend (control).
872
* Trust the backend whole heartedly to deliver the correct output. */
874
active_output_update (GvcMixerDialog *dialog,
875
GvcMixerUIDevice *active_output)
877
/* First make sure the correct UI device is selected. */
878
GvcMixerStream *stream;
882
g_debug ("active output update device id = %i",
883
gvc_mixer_ui_device_get_id (active_output));
885
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
887
if (gtk_tree_model_get_iter_first (model, &iter) == FALSE){
888
g_warning ("No devices in the tree, so cannot set the active output");
893
gboolean is_selected;
896
gtk_tree_model_get (model, &iter,
898
ACTIVE_COLUMN, &is_selected,
901
if (is_selected && id == gvc_mixer_ui_device_get_id (active_output)) {
902
/* XXX: profile change on the same device? */
903
g_debug ("Unneccessary active output update");
906
is_selected = id == gvc_mixer_ui_device_get_id (active_output);
908
gtk_list_store_set (GTK_LIST_STORE (model),
910
ACTIVE_COLUMN, is_selected,
914
GtkTreeSelection *selection;
915
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
916
gtk_tree_selection_select_iter (selection, &iter);
918
} while (gtk_tree_model_iter_next (model, &iter));
920
stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control,
922
if (stream == NULL) {
923
g_warning ("Couldn't find a stream from the active output");
927
bar_set_stream (dialog, dialog->priv->output_bar, stream);
928
update_output_settings (dialog, active_output);
1012
932
bar_set_stream (GvcMixerDialog *dialog,
1077
992
add_stream (GvcMixerDialog *dialog,
1078
993
GvcMixerStream *stream)
1082
gboolean is_default;
1086
g_assert (stream != NULL);
1088
if (gvc_mixer_stream_is_event_stream (stream) != FALSE)
996
GvcMixerStream *old_stream;
1093
id = gvc_mixer_stream_get_application_id (stream);
1095
if (stream == gvc_mixer_control_get_default_sink (dialog->priv->mixer_control)) {
1096
bar = dialog->priv->output_bar;
1097
is_muted = gvc_mixer_stream_get_is_muted (stream);
1099
gtk_widget_set_sensitive (dialog->priv->applications_box,
1101
adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
1102
g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1103
update_output_settings (dialog);
1104
} else if (stream == gvc_mixer_control_get_default_source (dialog->priv->mixer_control)) {
1105
bar = dialog->priv->input_bar;
1106
adj = GTK_ADJUSTMENT (gvc_channel_bar_get_adjustment (GVC_CHANNEL_BAR (bar)));
1107
g_signal_handlers_disconnect_by_func(adj, on_adjustment_value_changed, dialog);
1108
update_input_settings (dialog);
1110
} else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
1000
if (GVC_IS_MIXER_SOURCE (stream) || GVC_IS_MIXER_SINK (stream))
1002
else if (stream == gvc_mixer_control_get_event_sink_input (dialog->priv->mixer_control)) {
1111
1003
bar = dialog->priv->effects_bar;
1112
1004
g_debug ("Adding effects stream");
1113
} else if (! GVC_IS_MIXER_SOURCE (stream)
1114
&& !GVC_IS_MIXER_SINK (stream)
1115
&& !gvc_mixer_stream_is_virtual (stream)
1116
&& g_strcmp0 (id, "org.gnome.VolumeControl") != 0
1117
&& g_strcmp0 (id, "org.PulseAudio.pavucontrol") != 0) {
1006
/* Must be an application stream */
1118
1007
const char *name;
1120
1008
name = gvc_mixer_stream_get_name (stream);
1009
g_debug ("Add bar for application stream : %s", name);
1121
1011
bar = create_app_bar (dialog, name,
1122
1012
gvc_mixer_stream_get_icon_name (stream));
1124
1013
gtk_box_pack_start (GTK_BOX (dialog->priv->applications_box), bar, FALSE, FALSE, 12);
1125
1014
dialog->priv->num_apps++;
1126
1015
gtk_widget_hide (dialog->priv->no_apps_label);
1129
if (GVC_IS_MIXER_SOURCE (stream)) {
1130
GtkTreeModel *model;
1134
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1135
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1137
icon = gvc_mixer_stream_get_gicon (stream);
1138
gtk_list_store_set (GTK_LIST_STORE (model),
1140
NAME_COLUMN, gvc_mixer_stream_get_description (stream),
1142
ACTIVE_COLUMN, is_default,
1144
ID_COLUMN, gvc_mixer_stream_get_id (stream),
1147
g_object_unref (icon);
1150
GtkTreeSelection *selection;
1152
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->input_treeview));
1153
gtk_tree_selection_select_iter (selection, &iter);
1156
g_signal_connect (stream,
1157
"notify::description",
1158
G_CALLBACK (on_stream_description_notify),
1160
} else if (GVC_IS_MIXER_SINK (stream)) {
1161
GtkTreeModel *model;
1165
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1166
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1168
icon = gvc_mixer_stream_get_gicon (stream);
1169
gtk_list_store_set (GTK_LIST_STORE (model),
1171
NAME_COLUMN, gvc_mixer_stream_get_description (stream),
1173
ACTIVE_COLUMN, is_default,
1175
ID_COLUMN, gvc_mixer_stream_get_id (stream),
1178
g_object_unref (icon);
1181
GtkTreeSelection *selection;
1183
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->output_treeview));
1184
gtk_tree_selection_select_iter (selection, &iter);
1187
g_signal_connect (stream,
1188
"notify::description",
1189
G_CALLBACK (on_stream_description_notify),
1018
/* We should have a bar by now. */
1019
g_assert (bar != NULL);
1193
1021
if (bar != NULL) {
1022
old_stream = g_object_get_data (G_OBJECT (bar), "gvc-mixer-dialog-stream");
1023
if (old_stream != NULL) {
1026
g_object_get (bar, "name", &name, NULL);
1027
g_debug ("Disconnecting old stream '%s' from bar '%s'",
1028
gvc_mixer_stream_get_name (old_stream), name);
1031
g_signal_handlers_disconnect_by_func (old_stream, on_stream_is_muted_notify, dialog);
1032
g_signal_handlers_disconnect_by_func (old_stream, on_stream_volume_notify, dialog);
1033
g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (gvc_mixer_stream_get_id (old_stream)));
1035
save_bar_for_stream (dialog, stream, bar);
1194
1036
bar_set_stream (dialog, bar, stream);
1195
1037
gtk_widget_show (bar);
1101
add_input_ui_entry (GvcMixerDialog *dialog,
1102
GvcMixerUIDevice *input)
1110
GtkTreeModel *model;
1115
g_debug ("Add input ui entry with id :%u",
1116
gvc_mixer_ui_device_get_id (input));
1118
g_object_get (G_OBJECT (input),
1119
"stream-id", &stream_id,
1122
"description", &description,
1123
"port-name", &port_name,
1124
"port-available", &available,
1127
if (origin && origin[0] != '\0')
1128
final_name = g_strdup_printf ("%s - %s", description, origin);
1130
final_name = g_strdup (description);
1134
g_free (description);
1137
GvcMixerStream *stream;
1138
g_debug ("just detected a network source");
1139
stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, input);
1140
if (stream == NULL) {
1141
g_warning ("tried to add the network source but the stream was null - fail ?!");
1142
g_free (final_name);
1145
icon = gvc_mixer_stream_get_gicon (stream);
1147
icon = gvc_mixer_card_get_gicon (card);
1150
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1151
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1153
gtk_list_store_set (GTK_LIST_STORE (model),
1155
NAME_COLUMN, final_name,
1157
ACTIVE_COLUMN, FALSE,
1159
ID_COLUMN, gvc_mixer_ui_device_get_id (input),
1163
g_object_unref (icon);
1164
g_free (final_name);
1168
add_output_ui_entry (GvcMixerDialog *dialog,
1169
GvcMixerUIDevice *output)
1171
gchar *sink_port_name;
1176
gint sink_stream_id;
1177
GtkTreeModel *model;
1182
g_debug ("Add output ui entry with id :%u",
1183
gvc_mixer_ui_device_get_id (output));
1185
g_object_get (G_OBJECT (output),
1186
"stream-id", &sink_stream_id,
1189
"description", &description,
1190
"port-name", &sink_port_name,
1191
"port-available", &available,
1194
if (origin && origin[0] != '\0')
1195
final_name = g_strdup_printf ("%s - %s", description, origin);
1197
final_name = g_strdup (description);
1199
g_free (sink_port_name);
1201
g_free (description);
1204
GvcMixerStream *stream;
1206
g_debug ("just detected a network sink");
1207
stream = gvc_mixer_control_get_stream_from_device (dialog->priv->mixer_control, output);
1209
if (stream == NULL) {
1210
g_warning ("tried to add the network sink but the stream was null - fail ?!");
1211
g_free (final_name);
1214
icon = gvc_mixer_stream_get_gicon (stream);
1216
icon = gvc_mixer_card_get_gicon (card);
1218
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1219
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1221
gtk_list_store_set (GTK_LIST_STORE (model),
1223
NAME_COLUMN, final_name,
1225
ACTIVE_COLUMN, FALSE,
1227
ID_COLUMN, gvc_mixer_ui_device_get_id (output),
1231
g_object_unref (icon);
1232
g_free (final_name);
1237
on_control_active_input_update (GvcMixerControl *control,
1239
GvcMixerDialog *dialog)
1241
GvcMixerUIDevice* in = NULL;
1242
in = gvc_mixer_control_lookup_input_id (control, id);
1245
g_warning ("on_control_active_input_update - tried to fetch an input of id %u but got nothing", id);
1248
active_input_update (dialog, in);
1252
on_control_active_output_update (GvcMixerControl *control,
1254
GvcMixerDialog *dialog)
1256
GvcMixerUIDevice* out = NULL;
1257
out = gvc_mixer_control_lookup_output_id (control, id);
1260
g_warning ("on_control_active_output_update - tried to fetch an output of id %u but got nothing", id);
1263
active_output_update (dialog, out);
1267
on_control_input_added (GvcMixerControl *control,
1269
GvcMixerDialog *dialog)
1271
GvcMixerUIDevice* in = NULL;
1272
in = gvc_mixer_control_lookup_input_id (control, id);
1275
g_warning ("on_control_input_added - tried to fetch an input of id %u but got nothing", id);
1278
add_input_ui_entry (dialog, in);
1282
on_control_input_removed (GvcMixerControl *control,
1284
GvcMixerDialog *dialog)
1288
GtkTreeModel *model;
1290
GvcMixerUIDevice *in;
1292
in = gvc_mixer_control_lookup_input_id (control, id);
1294
g_object_get (G_OBJECT (in),
1295
"stream-id", &stream_id,
1298
g_debug ("Remove input from dialog, id: %u, stream id: %i",
1302
/* remove from any models */
1303
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1304
found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1306
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1311
on_control_output_added (GvcMixerControl *control,
1313
GvcMixerDialog *dialog)
1315
GvcMixerUIDevice* out = NULL;
1316
out = gvc_mixer_control_lookup_output_id (control, id);
1319
g_warning ("on_control_output_added - tried to fetch an output of id %u but got nothing", id);
1323
add_output_ui_entry (dialog, out);
1327
on_control_output_removed (GvcMixerControl *control,
1329
GvcMixerDialog *dialog)
1333
GtkTreeModel *model;
1334
gint sink_stream_id;
1336
GvcMixerUIDevice* out = NULL;
1337
out = gvc_mixer_control_lookup_output_id (control, id);
1339
g_object_get (G_OBJECT (out),
1340
"stream-id", &sink_stream_id,
1343
g_debug ("Remove output from dialog \n id : %u \n sink stream id : %i \n",
1347
/* remove from any models */
1348
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1349
found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1351
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1248
1356
remove_stream (GvcMixerDialog *dialog,
1254
GtkTreeModel *model;
1360
guint output_id, input_id;
1256
/* remove bars for applications and reset fixed bars */
1257
1362
bar = g_hash_table_lookup (dialog->priv->bars, GUINT_TO_POINTER (id));
1258
if (bar == dialog->priv->output_bar
1259
|| bar == dialog->priv->input_bar
1260
|| bar == dialog->priv->effects_bar) {
1262
g_object_get (bar, "name", &name, NULL);
1263
g_debug ("Removing stream for bar '%s'", name);
1265
bar_set_stream (dialog, bar, NULL);
1266
} else if (bar != NULL) {
1267
1364
g_hash_table_remove (dialog->priv->bars, GUINT_TO_POINTER (id));
1268
1365
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (bar)),
1271
1368
if (dialog->priv->num_apps == 0) {
1272
1369
gtk_widget_show (dialog->priv->no_apps_label);
1276
/* remove from any models */
1277
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1278
found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1280
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1282
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->input_treeview));
1283
found = find_item_by_id (GTK_TREE_MODEL (model), id, ID_COLUMN, &iter);
1285
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1374
output_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog->priv->output_bar), "gvc-mixer-dialog-stream-id"));
1375
input_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog->priv->input_bar), "gvc-mixer-dialog-stream-id"));
1377
if (output_id == id)
1378
bar = dialog->priv->output_bar;
1379
else if (input_id == id)
1380
bar = dialog->priv->input_bar;
1384
g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream-id", NULL);
1385
g_object_set_data (G_OBJECT (bar), "gvc-mixer-dialog-stream", NULL);
1298
add_card (GvcMixerDialog *dialog,
1301
GtkTreeModel *model;
1303
GtkTreeSelection *selection;
1304
GvcMixerCardProfile *profile;
1308
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1309
index = gvc_mixer_card_get_index (card);
1310
if (find_item_by_id (GTK_TREE_MODEL (model), index, HW_ID_COLUMN, &iter) == FALSE)
1311
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1312
profile = gvc_mixer_card_get_profile (card);
1313
g_assert (profile != NULL);
1314
icon = g_themed_icon_new_with_default_fallbacks (gvc_mixer_card_get_icon_name (card));
1315
//FIXME we need the status (default for a profile?) here
1316
gtk_list_store_set (GTK_LIST_STORE (model),
1318
HW_NAME_COLUMN, gvc_mixer_card_get_name (card),
1319
HW_ID_COLUMN, index,
1320
HW_ICON_COLUMN, icon,
1321
HW_PROFILE_COLUMN, profile->profile,
1322
HW_PROFILE_HUMAN_COLUMN, profile->human_profile,
1323
HW_STATUS_COLUMN, profile->status,
1324
HW_SENSITIVE_COLUMN, g_strcmp0 (profile->profile, "off") != 0,
1327
g_object_unref (icon);
1329
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1330
if (gtk_tree_selection_get_selected (selection, NULL, NULL) == FALSE) {
1331
gtk_tree_selection_select_iter (selection, &iter);
1332
} else if (dialog->priv->hw_profile_combo != NULL) {
1333
GvcMixerCard *selected;
1335
/* Set the current profile if it changed for the selected card */
1336
selected = g_object_get_data (G_OBJECT (dialog->priv->hw_profile_combo), "card");
1337
if (gvc_mixer_card_get_index (selected) == gvc_mixer_card_get_index (card)) {
1338
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo),
1340
g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
1341
"show-button", profile->n_sinks == 1,
1348
on_control_card_added (GvcMixerControl *control,
1350
GvcMixerDialog *dialog)
1354
card = gvc_mixer_control_lookup_card_id (control, id);
1356
add_card (dialog, card);
1361
remove_card (GvcMixerDialog *dialog,
1366
GtkTreeModel *model;
1368
/* remove from any models */
1369
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1370
found = find_item_by_id (GTK_TREE_MODEL (model), id, HW_ID_COLUMN, &iter);
1372
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
1376
on_control_card_removed (GvcMixerControl *control,
1378
GvcMixerDialog *dialog)
1380
remove_card (dialog, id);
1384
1397
_gtk_label_make_bold (GtkLabel *label)
1386
1399
PangoFontDescription *font_desc;
1526
on_profile_changed (GvcComboBox *widget,
1527
const char *profile,
1532
card = g_object_get_data (G_OBJECT (widget), "card");
1534
g_warning ("Could not find card for combobox");
1538
g_debug ("Profile changed to %s for card %s", profile,
1539
gvc_mixer_card_get_name (card));
1541
gvc_mixer_card_change_profile (card, profile);
1545
1535
on_test_speakers_clicked (GvcComboBox *widget,
1546
1536
gpointer user_data)
1548
1538
GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
1550
GvcMixerCardProfile *profile;
1539
GtkTreeModel *model;
1542
gint active_output = GVC_MIXER_UI_DEVICE_INVALID;
1543
GvcMixerUIDevice *output;
1544
GvcMixerStream *stream;
1551
1545
GtkWidget *d, *speaker_test, *container;
1554
card = g_object_get_data (G_OBJECT (widget), "card");
1556
g_warning ("Could not find card for combobox");
1559
profile = gvc_mixer_card_get_profile (card);
1561
g_debug ("XXX Start speaker testing for profile '%s', card %s XXX",
1562
profile->profile, gvc_mixer_card_get_name (card));
1564
title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_card_get_name (card));
1548
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->output_treeview));
1550
if (gtk_tree_model_get_iter_first (model, &iter) == FALSE) {
1551
g_warning ("The tree is empty => we have no device to test speakers with return");
1556
gboolean is_selected = FALSE;
1559
gtk_tree_model_get (model, &iter,
1561
ACTIVE_COLUMN, &is_selected,
1568
} while (gtk_tree_model_iter_next (model, &iter));
1570
if (active_output == GVC_MIXER_UI_DEVICE_INVALID) {
1571
g_warning ("Can't find the active output from the UI");
1575
output = gvc_mixer_control_lookup_output_id (dialog->priv->mixer_control, (guint)active_output);
1576
stream_id = gvc_mixer_ui_device_get_stream_id (output);
1578
if (stream_id == GVC_MIXER_UI_DEVICE_INVALID)
1581
g_debug ("Test speakers on '%s'", gvc_mixer_ui_device_get_description (output));
1583
stream = gvc_mixer_control_lookup_stream_id (dialog->priv->mixer_control, stream_id);
1584
if (stream == NULL) {
1585
g_debug ("Stream/sink not found");
1588
title = g_strdup_printf (_("Speaker Testing for %s"), gvc_mixer_ui_device_get_description (output));
1565
1589
d = gtk_dialog_new_with_buttons (title,
1566
1590
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget))),
1567
1591
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1568
1592
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
1570
/* FIXME: this should not be necessary */
1571
1594
gtk_window_set_has_resize_grip (GTK_WINDOW (d), FALSE);
1573
1596
g_free (title);
1574
1597
speaker_test = gvc_speaker_test_new (dialog->priv->mixer_control,
1576
1599
gtk_widget_show (speaker_test);
1577
1600
container = gtk_dialog_get_content_area (GTK_DIALOG (d));
1578
1601
gtk_container_add (GTK_CONTAINER (container), speaker_test);
1581
1604
gtk_widget_destroy (d);
1585
on_card_selection_changed (GtkTreeSelection *selection,
1588
GvcMixerDialog *dialog = GVC_MIXER_DIALOG (user_data);
1589
GtkTreeModel *model;
1591
const GList *profiles;
1594
GvcMixerCardProfile *current_profile;
1596
g_debug ("Card selection changed");
1598
if (dialog->priv->hw_profile_combo != NULL) {
1599
gtk_container_remove (GTK_CONTAINER (dialog->priv->hw_settings_box),
1600
dialog->priv->hw_profile_combo);
1601
dialog->priv->hw_profile_combo = NULL;
1604
if (gtk_tree_selection_get_selected (selection,
1610
model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->priv->hw_treeview));
1611
gtk_tree_model_get (model, &iter,
1614
card = gvc_mixer_control_lookup_card_id (dialog->priv->mixer_control, id);
1616
g_warning ("Unable to find card for id: %u", id);
1620
current_profile = gvc_mixer_card_get_profile (card);
1621
profiles = gvc_mixer_card_get_profiles (card);
1622
dialog->priv->hw_profile_combo = gvc_combo_box_new (_("_Profile:"));
1623
g_object_set (G_OBJECT (dialog->priv->hw_profile_combo), "button-label", _("_Test Speakers"), NULL);
1624
gvc_combo_box_set_profiles (GVC_COMBO_BOX (dialog->priv->hw_profile_combo), profiles);
1625
gvc_combo_box_set_active (GVC_COMBO_BOX (dialog->priv->hw_profile_combo), current_profile->profile);
1627
gtk_box_pack_start (GTK_BOX (dialog->priv->hw_settings_box),
1628
dialog->priv->hw_profile_combo,
1630
g_object_set (G_OBJECT (dialog->priv->hw_profile_combo),
1631
"show-button", current_profile->n_sinks == 1,
1633
gtk_widget_show (dialog->priv->hw_profile_combo);
1635
g_object_set_data (G_OBJECT (dialog->priv->hw_profile_combo), "card", card);
1636
g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo), "changed",
1637
G_CALLBACK (on_profile_changed), dialog);
1638
g_signal_connect (G_OBJECT (dialog->priv->hw_profile_combo), "button-clicked",
1639
G_CALLBACK (on_test_speakers_clicked), dialog);
1643
card_to_text (GtkTreeViewColumn *column,
1644
GtkCellRenderer *cell,
1645
GtkTreeModel *model,
1649
char *name, *status, *profile, *str;
1652
gtk_tree_model_get(model, iter,
1653
HW_NAME_COLUMN, &name,
1654
HW_STATUS_COLUMN, &status,
1655
HW_PROFILE_HUMAN_COLUMN, &profile,
1656
HW_SENSITIVE_COLUMN, &sensitive,
1659
str = g_strdup_printf ("%s\n<i>%s</i>\n<i>%s</i>",
1660
name, status, profile);
1663
"sensitive", sensitive,
1673
create_cards_treeview (GvcMixerDialog *dialog,
1674
GCallback on_changed)
1676
GtkWidget *treeview;
1677
GtkListStore *store;
1678
GtkCellRenderer *renderer;
1679
GtkTreeViewColumn *column;
1680
GtkTreeSelection *selection;
1682
treeview = gtk_tree_view_new ();
1683
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
1685
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
1686
g_signal_connect (G_OBJECT (selection), "changed",
1687
on_changed, dialog);
1689
store = gtk_list_store_new (HW_NUM_COLUMNS,
1697
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
1698
GTK_TREE_MODEL (store));
1700
renderer = gtk_cell_renderer_pixbuf_new ();
1701
g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_DIALOG, NULL);
1702
column = gtk_tree_view_column_new_with_attributes (NULL,
1704
"gicon", HW_ICON_COLUMN,
1705
"sensitive", HW_SENSITIVE_COLUMN,
1707
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
1709
gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (treeview), -1,
1710
_("Name"), gtk_cell_renderer_text_new (),
1711
card_to_text, NULL, NULL);
1716
1607
static GObject *
1717
1608
gvc_mixer_dialog_constructor (GType type,
1718
1609
guint n_construct_properties,
1888
1776
gtk_container_add (GTK_CONTAINER (box), self->priv->input_treeview);
1889
1777
gtk_container_add (GTK_CONTAINER (alignment), box);
1892
self->priv->hw_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1893
gtk_container_set_border_width (GTK_CONTAINER (self->priv->hw_box), 12);
1894
label = gtk_label_new (_("Hardware"));
1895
gtk_notebook_append_page (GTK_NOTEBOOK (self->priv->notebook),
1899
box = gtk_frame_new (_("C_hoose a device to configure:"));
1900
label = gtk_frame_get_label_widget (GTK_FRAME (box));
1901
_gtk_label_make_bold (GTK_LABEL (label));
1902
gtk_label_set_use_underline (GTK_LABEL (label), TRUE);
1903
gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
1904
gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, TRUE, TRUE, 0);
1906
alignment = gtk_alignment_new (0, 0, 1, 1);
1907
gtk_container_add (GTK_CONTAINER (box), alignment);
1908
gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
1910
self->priv->hw_treeview = create_cards_treeview (self,
1911
G_CALLBACK (on_card_selection_changed));
1912
gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->priv->hw_treeview);
1914
box = gtk_scrolled_window_new (NULL, NULL);
1915
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (box),
1917
GTK_POLICY_AUTOMATIC);
1918
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (box),
1920
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (box), 150);
1921
gtk_container_add (GTK_CONTAINER (box), self->priv->hw_treeview);
1922
gtk_container_add (GTK_CONTAINER (alignment), box);
1924
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->hw_treeview));
1925
gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1927
box = gtk_frame_new (_("Settings for the selected device:"));
1928
label = gtk_frame_get_label_widget (GTK_FRAME (box));
1929
_gtk_label_make_bold (GTK_LABEL (label));
1930
gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_NONE);
1931
gtk_box_pack_start (GTK_BOX (self->priv->hw_box), box, FALSE, TRUE, 12);
1932
self->priv->hw_settings_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1933
gtk_container_add (GTK_CONTAINER (box), self->priv->hw_settings_box);
1935
1779
/* Effects page */
1936
1780
self->priv->sound_effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1937
1781
gtk_container_set_border_width (GTK_CONTAINER (self->priv->sound_effects_box), 12);
2006
1852
GvcMixerDialog *dialog = GVC_MIXER_DIALOG (object);
2008
1854
if (dialog->priv->mixer_control != NULL) {
1856
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1857
on_control_output_added,
1859
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1860
on_control_output_removed,
1862
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1863
on_control_input_added,
1865
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1866
on_control_input_removed,
1868
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1869
on_control_active_input_update,
1871
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
1872
on_control_active_output_update,
2009
1874
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2010
1875
on_control_stream_added,
2012
1877
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2013
1878
on_control_stream_removed,
2015
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2016
on_control_card_added,
2018
g_signal_handlers_disconnect_by_func (dialog->priv->mixer_control,
2019
on_control_card_removed,
2022
1881
g_object_unref (dialog->priv->mixer_control);
2023
1882
dialog->priv->mixer_control = NULL;