No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | gvc/gvc-mixer-card.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2008 William Jon McCann
4 * Copyright (C) 2009 Bastien Nocera
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27
28 #include <glib.h>
29 #include <glib/gi18n-lib.h>
30
31 #include <pulse/pulseaudio.h>
32
33 #include "gvc-mixer-card.h"
34 #include "gvc-mixer-card-private.h"
35
36 #define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate))
37
38 static guint32 card_serial = 1;
39
40 struct GvcMixerCardPrivate
41 {
42 pa_context *pa_context;
43 guint id;
44 guint index;
45 char *name;
46 char *icon_name;
47 char *profile;
48 char *target_profile;
49 char *human_profile;
50 GList *profiles;
51 pa_operation *profile_op;
52 };
53
54 enum
55 {
56 PROP_0,
57 PROP_ID,
58 PROP_PA_CONTEXT,
59 PROP_INDEX,
60 PROP_NAME,
61 PROP_ICON_NAME,
62 PROP_PROFILE,
63 PROP_HUMAN_PROFILE,
64 };
65
66 static void gvc_mixer_card_class_init (GvcMixerCardClass *klass);
67 static void gvc_mixer_card_init (GvcMixerCard *mixer_card);
68 static void gvc_mixer_card_finalize (GObject *object);
69
70 G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
71
72 static guint32
73 get_next_card_serial (void)
74 {
75 guint32 serial;
76
77 serial = card_serial++;
78
79 if ((gint32)card_serial < 0) {
80 card_serial = 1;
81 }
82
83 return serial;
84 }
85
86 pa_context *
87 gvc_mixer_card_get_pa_context (GvcMixerCard *card)
88 {
89 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
90 return card->priv->pa_context;
91 }
92
93 guint
94 gvc_mixer_card_get_index (GvcMixerCard *card)
95 {
96 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
97 return card->priv->index;
98 }
99
100 guint
101 gvc_mixer_card_get_id (GvcMixerCard *card)
102 {
103 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
104 return card->priv->id;
105 }
106
107 const char *
108 gvc_mixer_card_get_name (GvcMixerCard *card)
109 {
110 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
111 return card->priv->name;
112 }
113
114 gboolean
115 gvc_mixer_card_set_name (GvcMixerCard *card,
116 const char *name)
117 {
118 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
119
120 g_free (card->priv->name);
121 card->priv->name = g_strdup (name);
122 g_object_notify (G_OBJECT (card), "name");
123
124 return TRUE;
125 }
126
127 const char *
128 gvc_mixer_card_get_icon_name (GvcMixerCard *card)
129 {
130 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
131 return card->priv->icon_name;
132 }
133
134 gboolean
135 gvc_mixer_card_set_icon_name (GvcMixerCard *card,
136 const char *icon_name)
137 {
138 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
139
140 g_free (card->priv->icon_name);
141 card->priv->icon_name = g_strdup (icon_name);
142 g_object_notify (G_OBJECT (card), "icon-name");
143
144 return TRUE;
145 }
146
147 /**
148 * gvc_mixer_card_get_profile: (skip)
149 * @card:
150 *
151 * Returns:
152 */
153 GvcMixerCardProfile *
154 gvc_mixer_card_get_profile (GvcMixerCard *card)
155 {
156 GList *l;
157
158 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
159 g_return_val_if_fail (card->priv->profiles != NULL, NULL);
160
161 for (l = card->priv->profiles; l != NULL; l = l->next) {
162 GvcMixerCardProfile *p = l->data;
163 if (g_str_equal (card->priv->profile, p->profile)) {
164 return p;
165 }
166 }
167
168 g_assert_not_reached ();
169
170 return NULL;
171 }
172
173 gboolean
174 gvc_mixer_card_set_profile (GvcMixerCard *card,
175 const char *profile)
176 {
177 GList *l;
178
179 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
180 g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
181
182 g_free (card->priv->profile);
183 card->priv->profile = g_strdup (profile);
184
185 g_free (card->priv->human_profile);
186 card->priv->human_profile = NULL;
187
188 for (l = card->priv->profiles; l != NULL; l = l->next) {
189 GvcMixerCardProfile *p = l->data;
190 if (g_str_equal (card->priv->profile, p->profile)) {
191 card->priv->human_profile = g_strdup (p->human_profile);
192 break;
193 }
194 }
195
196 g_object_notify (G_OBJECT (card), "profile");
197
198 return TRUE;
199 }
200
201 static void
202 _pa_context_set_card_profile_by_index_cb (pa_context *context,
203 int success,
204 void *userdata)
205 {
206 GvcMixerCard *card = GVC_MIXER_CARD (userdata);
207
208 g_assert (card->priv->target_profile);
209
210 if (success > 0) {
211 gvc_mixer_card_set_profile (card, card->priv->target_profile);
212 } else {
213 g_debug ("Failed to switch profile on '%s' from '%s' to '%s'",
214 card->priv->name,
215 card->priv->profile,
216 card->priv->target_profile);
217 }
218 g_free (card->priv->target_profile);
219 card->priv->target_profile = NULL;
220
221 pa_operation_unref (card->priv->profile_op);
222 card->priv->profile_op = NULL;
223 }
224
225 gboolean
226 gvc_mixer_card_change_profile (GvcMixerCard *card,
227 const char *profile)
228 {
229 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
230 g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
231
232 /* Same profile, or already requested? */
233 if (g_strcmp0 (card->priv->profile, profile) == 0)
234 return TRUE;
235 if (g_strcmp0 (profile, card->priv->target_profile) == 0)
236 return TRUE;
237 if (card->priv->profile_op != NULL) {
238 pa_operation_cancel (card->priv->profile_op);
239 pa_operation_unref (card->priv->profile_op);
240 card->priv->profile_op = NULL;
241 }
242
243 if (card->priv->profile != NULL) {
244 g_free (card->priv->target_profile);
245 card->priv->target_profile = g_strdup (profile);
246
247 card->priv->profile_op = pa_context_set_card_profile_by_index (card->priv->pa_context,
248 card->priv->index,
249 card->priv->target_profile,
250 _pa_context_set_card_profile_by_index_cb,
251 card);
252
253 if (card->priv->profile_op == NULL) {
254 g_warning ("pa_context_set_card_profile_by_index() failed");
255 return FALSE;
256 }
257 } else {
258 g_assert (card->priv->human_profile == NULL);
259 card->priv->profile = g_strdup (profile);
260 }
261
262 return TRUE;
263 }
264
265 /**
266 * gvc_mixer_card_get_profiles:
267 *
268 * Return value: (transfer none) (element-type GvcMixerCardProfile):
269 */
270 const GList *
271 gvc_mixer_card_get_profiles (GvcMixerCard *card)
272 {
273 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
274 return card->priv->profiles;
275 }
276
277 static int
278 sort_profiles (GvcMixerCardProfile *a,
279 GvcMixerCardProfile *b)
280 {
281 if (a->priority == b->priority)
282 return 0;
283 if (a->priority > b->priority)
284 return 1;
285 return -1;
286 }
287
288 /**
289 * gvc_mixer_card_set_profiles:
290 * @profiles: (transfer full) (element-type GvcMixerCardProfile):
291 */
292 gboolean
293 gvc_mixer_card_set_profiles (GvcMixerCard *card,
294 GList *profiles)
295 {
296 g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
297 g_return_val_if_fail (card->priv->profiles == NULL, FALSE);
298
299 card->priv->profiles = g_list_sort (profiles, (GCompareFunc) sort_profiles);
300
301 return TRUE;
302 }
303
304 static void
305 gvc_mixer_card_set_property (GObject *object,
306 guint prop_id,
307 const GValue *value,
308 GParamSpec *pspec)
309 {
310 GvcMixerCard *self = GVC_MIXER_CARD (object);
311
312 switch (prop_id) {
313 case PROP_PA_CONTEXT:
314 self->priv->pa_context = g_value_get_pointer (value);
315 break;
316 case PROP_INDEX:
317 self->priv->index = g_value_get_ulong (value);
318 break;
319 case PROP_ID:
320 self->priv->id = g_value_get_ulong (value);
321 break;
322 case PROP_NAME:
323 gvc_mixer_card_set_name (self, g_value_get_string (value));
324 break;
325 case PROP_ICON_NAME:
326 gvc_mixer_card_set_icon_name (self, g_value_get_string (value));
327 break;
328 case PROP_PROFILE:
329 gvc_mixer_card_set_profile (self, g_value_get_string (value));
330 break;
331 default:
332 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
333 break;
334 }
335 }
336
337 static void
338 gvc_mixer_card_get_property (GObject *object,
339 guint prop_id,
340 GValue *value,
341 GParamSpec *pspec)
342 {
343 GvcMixerCard *self = GVC_MIXER_CARD (object);
344
345 switch (prop_id) {
346 case PROP_PA_CONTEXT:
347 g_value_set_pointer (value, self->priv->pa_context);
348 break;
349 case PROP_INDEX:
350 g_value_set_ulong (value, self->priv->index);
351 break;
352 case PROP_ID:
353 g_value_set_ulong (value, self->priv->id);
354 break;
355 case PROP_NAME:
356 g_value_set_string (value, self->priv->name);
357 break;
358 case PROP_ICON_NAME:
359 g_value_set_string (value, self->priv->icon_name);
360 break;
361 case PROP_PROFILE:
362 g_value_set_string (value, self->priv->profile);
363 break;
364 case PROP_HUMAN_PROFILE:
365 g_value_set_string (value, self->priv->human_profile);
366 break;
367 default:
368 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
369 break;
370 }
371 }
372
373 static GObject *
374 gvc_mixer_card_constructor (GType type,
375 guint n_construct_properties,
376 GObjectConstructParam *construct_params)
377 {
378 GObject *object;
379 GvcMixerCard *self;
380
381 object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params);
382
383 self = GVC_MIXER_CARD (object);
384
385 self->priv->id = get_next_card_serial ();
386
387 return object;
388 }
389
390 static void
391 gvc_mixer_card_class_init (GvcMixerCardClass *klass)
392 {
393 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
394
395 gobject_class->constructor = gvc_mixer_card_constructor;
396 gobject_class->finalize = gvc_mixer_card_finalize;
397
398 gobject_class->set_property = gvc_mixer_card_set_property;
399 gobject_class->get_property = gvc_mixer_card_get_property;
400
401 g_object_class_install_property (gobject_class,
402 PROP_INDEX,
403 g_param_spec_ulong ("index",
404 "Index",
405 "The index for this card",
406 0, G_MAXULONG, 0,
407 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
408 g_object_class_install_property (gobject_class,
409 PROP_ID,
410 g_param_spec_ulong ("id",
411 "id",
412 "The id for this card",
413 0, G_MAXULONG, 0,
414 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
415 g_object_class_install_property (gobject_class,
416 PROP_PA_CONTEXT,
417 g_param_spec_pointer ("pa-context",
418 "PulseAudio context",
419 "The PulseAudio context for this card",
420 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
421 g_object_class_install_property (gobject_class,
422 PROP_NAME,
423 g_param_spec_string ("name",
424 "Name",
425 "Name to display for this card",
426 NULL,
427 G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
428 g_object_class_install_property (gobject_class,
429 PROP_ICON_NAME,
430 g_param_spec_string ("icon-name",
431 "Icon Name",
432 "Name of icon to display for this card",
433 NULL,
434 G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
435 g_object_class_install_property (gobject_class,
436 PROP_PROFILE,
437 g_param_spec_string ("profile",
438 "Profile",
439 "Name of current profile for this card",
440 NULL,
441 G_PARAM_READWRITE));
442 g_object_class_install_property (gobject_class,
443 PROP_HUMAN_PROFILE,
444 g_param_spec_string ("human-profile",
445 "Profile (Human readable)",
446 "Name of current profile for this card in human readable form",
447 NULL,
448 G_PARAM_READABLE));
449
450 g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate));
451 }
452
453 static void
454 gvc_mixer_card_init (GvcMixerCard *card)
455 {
456 card->priv = GVC_MIXER_CARD_GET_PRIVATE (card);
457 }
458
459 GvcMixerCard *
460 gvc_mixer_card_new (pa_context *context,
461 guint index)
462 {
463 GObject *object;
464
465 object = g_object_new (GVC_TYPE_MIXER_CARD,
466 "index", index,
467 "pa-context", context,
468 NULL);
469 return GVC_MIXER_CARD (object);
470 }
471
472 static void
473 free_profile (GvcMixerCardProfile *p)
474 {
475 g_free (p->profile);
476 g_free (p->human_profile);
477 g_free (p->status);
478 g_free (p);
479 }
480
481 static void
482 gvc_mixer_card_finalize (GObject *object)
483 {
484 GvcMixerCard *mixer_card;
485
486 g_return_if_fail (object != NULL);
487 g_return_if_fail (GVC_IS_MIXER_CARD (object));
488
489 mixer_card = GVC_MIXER_CARD (object);
490
491 g_return_if_fail (mixer_card->priv != NULL);
492
493 g_free (mixer_card->priv->name);
494 mixer_card->priv->name = NULL;
495
496 g_free (mixer_card->priv->icon_name);
497 mixer_card->priv->icon_name = NULL;
498
499 g_free (mixer_card->priv->target_profile);
500 mixer_card->priv->target_profile = NULL;
501
502 g_free (mixer_card->priv->profile);
503 mixer_card->priv->profile = NULL;
504
505 g_free (mixer_card->priv->human_profile);
506 mixer_card->priv->human_profile = NULL;
507
508 g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);
509 g_list_free (mixer_card->priv->profiles);
510 mixer_card->priv->profiles = NULL;
511
512 G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object);
513 }