GCC Code Coverage Report


Directory: ./
File: panels/sound/cc-sound-panel.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 158 0.0%
Functions: 0 18 0.0%
Branches: 0 23 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2008 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <libintl.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <errno.h>
25
26 #include <glib/gi18n-lib.h>
27 #include <glib.h>
28 #include <gtk/gtk.h>
29 #include <pulse/pulseaudio.h>
30 #include <gvc-mixer-control.h>
31
32 #include "cc-list-row.h"
33 #include "cc-alert-chooser-window.h"
34 #include "cc-balance-slider.h"
35 #include "cc-device-combo-box.h"
36 #include "cc-fade-slider.h"
37 #include "cc-level-bar.h"
38 #include "cc-output-test-window.h"
39 #include "cc-profile-combo-box.h"
40 #include "cc-sound-panel.h"
41 #include "cc-sound-resources.h"
42 #include "cc-subwoofer-slider.h"
43 #include "cc-volume-levels-window.h"
44 #include "cc-volume-slider.h"
45
46 struct _CcSoundPanel
47 {
48 CcPanel parent_instance;
49
50 AdwPreferencesGroup *output_group;
51 CcLevelBar *output_level_bar;
52 CcDeviceComboBox *output_device_combo_box;
53 AdwPreferencesRow *output_profile_row;
54 CcProfileComboBox *output_profile_combo_box;
55 CcVolumeSlider *output_volume_slider;
56 CcBalanceSlider *balance_slider;
57 AdwPreferencesRow *fade_row;
58 CcFadeSlider *fade_slider;
59 AdwPreferencesRow *subwoofer_row;
60 CcSubwooferSlider *subwoofer_slider;
61 AdwPreferencesGroup *output_no_devices_group;
62 AdwPreferencesGroup *input_group;
63 CcLevelBar *input_level_bar;
64 CcDeviceComboBox *input_device_combo_box;
65 AdwPreferencesRow *input_profile_row;
66 CcProfileComboBox *input_profile_combo_box;
67 CcVolumeSlider *input_volume_slider;
68 AdwPreferencesGroup *input_no_devices_group;
69 CcListRow *alert_sound_row;
70
71 GvcMixerControl *mixer_control;
72 GSettings *sound_settings;
73 };
74
75 CC_PANEL_REGISTER (CcSoundPanel, cc_sound_panel)
76
77 enum
78 {
79 PROP_0,
80 PROP_PARAMETERS
81 };
82
83 #define KEY_SOUNDS_SCHEMA "org.gnome.desktop.sound"
84
85 static void
86 update_alert_sound_label (CcSoundPanel *self)
87 {
88 const gchar *alert_name = get_selected_alert_display_name ();
89 cc_list_row_set_secondary_label (self->alert_sound_row, alert_name);
90 }
91
92 static void
93 allow_amplified_changed_cb (CcSoundPanel *self)
94 {
95 cc_volume_slider_set_is_amplified (self->output_volume_slider,
96 g_settings_get_boolean (self->sound_settings, "allow-volume-above-100-percent"));
97 }
98
99 static void
100 set_output_stream (CcSoundPanel *self,
101 GvcMixerStream *stream)
102 {
103 GvcChannelMap *map = NULL;
104 gboolean can_fade = FALSE, has_lfe = FALSE;
105
106 cc_volume_slider_set_stream (self->output_volume_slider, stream, CC_STREAM_TYPE_OUTPUT);
107 cc_level_bar_set_stream (self->output_level_bar, stream);
108
109 if (stream != NULL)
110 {
111 map = (GvcChannelMap *) gvc_mixer_stream_get_channel_map (stream);
112 can_fade = gvc_channel_map_can_fade (map);
113 has_lfe = gvc_channel_map_has_lfe (map);
114 }
115 cc_fade_slider_set_channel_map (self->fade_slider, map);
116 cc_balance_slider_set_channel_map (self->balance_slider, map);
117 cc_subwoofer_slider_set_channel_map (self->subwoofer_slider, map);
118
119 gtk_widget_set_visible (GTK_WIDGET (self->fade_row), can_fade);
120 gtk_widget_set_visible (GTK_WIDGET (self->subwoofer_row), has_lfe);
121 }
122
123 static void
124 output_device_changed_cb (CcSoundPanel *self)
125 {
126 GvcMixerUIDevice *device;
127
128 device = cc_device_combo_box_get_device (self->output_device_combo_box);
129
130 if (device != NULL)
131 gvc_mixer_control_change_output (self->mixer_control, device);
132 }
133
134 static void
135 set_input_stream (CcSoundPanel *self,
136 GvcMixerStream *stream)
137 {
138 cc_volume_slider_set_stream (self->input_volume_slider, stream, CC_STREAM_TYPE_INPUT);
139 cc_level_bar_set_stream (self->input_level_bar, stream);
140 }
141
142 static void
143 input_device_changed_cb (CcSoundPanel *self)
144 {
145 GvcMixerUIDevice *device;
146
147 device = cc_device_combo_box_get_device (self->input_device_combo_box);
148
149 if (device != NULL)
150 gvc_mixer_control_change_input (self->mixer_control, device);
151 }
152
153 static void
154 output_device_update_cb (CcSoundPanel *self,
155 guint id)
156 {
157 GvcMixerUIDevice *device;
158 gboolean has_multi_profiles;
159 GvcMixerStream *stream = NULL;
160
161 g_signal_handlers_block_by_func(self->output_device_combo_box, output_device_changed_cb, self);
162 cc_device_combo_box_active_device_changed (self->output_device_combo_box, id);
163 g_signal_handlers_unblock_by_func(self->output_device_combo_box, output_device_changed_cb, self);
164
165 device = cc_device_combo_box_get_device (self->output_device_combo_box);
166
167 gtk_widget_set_visible (GTK_WIDGET (self->output_group), device != NULL);
168 gtk_widget_set_visible (GTK_WIDGET (self->output_no_devices_group), device == NULL);
169
170 cc_profile_combo_box_set_device (self->output_profile_combo_box, self->mixer_control, device);
171 has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->output_profile_combo_box) > 1);
172 gtk_widget_set_visible (GTK_WIDGET (self->output_profile_row),
173 has_multi_profiles);
174
175 if (device)
176 stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
177
178 set_output_stream (self, stream);
179 }
180
181 static void
182 input_device_update_cb (CcSoundPanel *self,
183 guint id)
184 {
185 GvcMixerUIDevice *device;
186 gboolean has_multi_profiles;
187 GvcMixerStream *stream = NULL;
188
189 g_signal_handlers_block_by_func(self->input_device_combo_box, input_device_changed_cb, self);
190 cc_device_combo_box_active_device_changed (self->input_device_combo_box, id);
191 g_signal_handlers_unblock_by_func(self->input_device_combo_box, input_device_changed_cb, self);
192
193 device = cc_device_combo_box_get_device (self->input_device_combo_box);
194
195 gtk_widget_set_visible (GTK_WIDGET (self->input_group), device != NULL);
196 gtk_widget_set_visible (GTK_WIDGET (self->input_no_devices_group), device != NULL);
197
198 cc_profile_combo_box_set_device (self->input_profile_combo_box, self->mixer_control, device);
199 has_multi_profiles = (cc_profile_combo_box_get_profile_count (self->input_profile_combo_box) > 1);
200 gtk_widget_set_visible (GTK_WIDGET (self->input_profile_row),
201 has_multi_profiles);
202
203 if (device)
204 stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
205
206 set_input_stream (self, stream);
207 }
208
209 static void
210 test_output_configuration_button_clicked_cb (CcSoundPanel *self)
211 {
212 GvcMixerUIDevice *device;
213 GvcMixerStream *stream = NULL;
214 CcOutputTestWindow *window;
215
216 device = cc_device_combo_box_get_device (self->output_device_combo_box);
217 if (device != NULL)
218 stream = gvc_mixer_control_get_stream_from_device (self->mixer_control, device);
219
220 window = cc_output_test_window_new (stream);
221 adw_dialog_present (ADW_DIALOG (window), GTK_WIDGET (self));
222 }
223
224 static void
225 volume_levels_activated_cb (CcSoundPanel *self)
226 {
227 CcVolumeLevelsWindow *volume_levels;
228
229 volume_levels = cc_volume_levels_window_new (self->mixer_control);
230 adw_dialog_present (ADW_DIALOG (volume_levels), GTK_WIDGET (self));
231 }
232
233 static void
234 alert_sound_activated_cb (CcSoundPanel *self)
235 {
236 CcAlertChooserWindow *alert_chooser;
237
238 alert_chooser = cc_alert_chooser_window_new ();
239
240 g_signal_connect_object (alert_chooser, "destroy",
241 G_CALLBACK (update_alert_sound_label),
242 self, G_CONNECT_SWAPPED);
243
244 adw_dialog_present (ADW_DIALOG (alert_chooser), GTK_WIDGET (self));
245 }
246
247 static const char *
248 cc_sound_panel_get_help_uri (CcPanel *panel)
249 {
250 return "help:gnome-help/media#sound";
251 }
252
253 static void
254 cc_sound_panel_finalize (GObject *object)
255 {
256 CcSoundPanel *self = CC_SOUND_PANEL (object);
257
258 g_clear_object (&self->mixer_control);
259 g_clear_object (&self->sound_settings);
260
261 G_OBJECT_CLASS (cc_sound_panel_parent_class)->finalize (object);
262 }
263
264 static void
265 cc_sound_panel_class_init (CcSoundPanelClass *klass)
266 {
267 GObjectClass *object_class = G_OBJECT_CLASS (klass);
268 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
269 CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
270
271 panel_class->get_help_uri = cc_sound_panel_get_help_uri;
272
273 object_class->finalize = cc_sound_panel_finalize;
274
275 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/sound/cc-sound-panel.ui");
276
277 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_group);
278 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_level_bar);
279 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_device_combo_box);
280 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_profile_row);
281 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_profile_combo_box);
282 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_volume_slider);
283 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, balance_slider);
284 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, fade_row);
285 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, fade_slider);
286 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_row);
287 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, subwoofer_slider);
288 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, output_no_devices_group);
289 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_group);
290 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_level_bar);
291 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_device_combo_box);
292 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_profile_row);
293 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_profile_combo_box);
294 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_volume_slider);
295 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, input_no_devices_group);
296 gtk_widget_class_bind_template_child (widget_class, CcSoundPanel, alert_sound_row);
297
298 gtk_widget_class_bind_template_callback (widget_class, input_device_changed_cb);
299 gtk_widget_class_bind_template_callback (widget_class, output_device_changed_cb);
300 gtk_widget_class_bind_template_callback (widget_class, test_output_configuration_button_clicked_cb);
301 gtk_widget_class_bind_template_callback (widget_class, volume_levels_activated_cb);
302 gtk_widget_class_bind_template_callback (widget_class, alert_sound_activated_cb);
303
304 g_type_ensure (CC_TYPE_BALANCE_SLIDER);
305 g_type_ensure (CC_TYPE_DEVICE_COMBO_BOX);
306 g_type_ensure (CC_TYPE_FADE_SLIDER);
307 g_type_ensure (CC_TYPE_LEVEL_BAR);
308 g_type_ensure (CC_TYPE_PROFILE_COMBO_BOX);
309 g_type_ensure (CC_TYPE_SUBWOOFER_SLIDER);
310 g_type_ensure (CC_TYPE_VOLUME_SLIDER);
311 g_type_ensure (CC_TYPE_LIST_ROW);
312 }
313
314 static void
315 cc_sound_panel_init (CcSoundPanel *self)
316 {
317 g_resources_register (cc_sound_get_resource ());
318
319 gtk_widget_init_template (GTK_WIDGET (self));
320
321 self->sound_settings = g_settings_new (KEY_SOUNDS_SCHEMA);
322 g_signal_connect_object (self->sound_settings,
323 "changed::allow-volume-above-100-percent",
324 G_CALLBACK (allow_amplified_changed_cb),
325 self,
326 G_CONNECT_SWAPPED);
327 allow_amplified_changed_cb (self);
328
329 self->mixer_control = gvc_mixer_control_new ("GNOME Settings");
330
331 cc_volume_slider_set_mixer_control (self->input_volume_slider, self->mixer_control);
332 cc_volume_slider_set_mixer_control (self->output_volume_slider, self->mixer_control);
333 cc_subwoofer_slider_set_mixer_control (self->subwoofer_slider, self->mixer_control);
334 cc_device_combo_box_set_mixer_control (self->input_device_combo_box, self->mixer_control, FALSE);
335 cc_device_combo_box_set_mixer_control (self->output_device_combo_box, self->mixer_control, TRUE);
336
337 g_signal_connect_object (self->mixer_control,
338 "input-added",
339 G_CALLBACK (cc_device_combo_box_device_added),
340 self->input_device_combo_box,
341 G_CONNECT_SWAPPED);
342 g_signal_connect_object (self->mixer_control,
343 "input-removed",
344 G_CALLBACK (cc_device_combo_box_device_removed),
345 self->input_device_combo_box,
346 G_CONNECT_SWAPPED);
347 g_signal_connect_object (self->mixer_control,
348 "active-input-update",
349 G_CALLBACK (input_device_update_cb),
350 self,
351 G_CONNECT_SWAPPED);
352
353 g_signal_connect_object (self->mixer_control,
354 "output-added",
355 G_CALLBACK (cc_device_combo_box_device_added),
356 self->output_device_combo_box,
357 G_CONNECT_SWAPPED);
358 g_signal_connect_object (self->mixer_control,
359 "output-removed",
360 G_CALLBACK (cc_device_combo_box_device_removed),
361 self->output_device_combo_box,
362 G_CONNECT_SWAPPED);
363 g_signal_connect_object (self->mixer_control,
364 "active-output-update",
365 G_CALLBACK (output_device_update_cb),
366 self,
367 G_CONNECT_SWAPPED);
368
369 gvc_mixer_control_open (self->mixer_control);
370
371 update_alert_sound_label (self);
372 }
373