1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2008 William Jon McCann
4
* Copyright (C) 2009 Bastien Nocera
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.
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.
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.
29
#include <glib/gi18n-lib.h>
31
#include <pulse/pulseaudio.h>
33
#include "gvc-mixer-card.h"
34
#include "gvc-mixer-card-private.h"
36
#define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate))
38
static guint32 card_serial = 1;
40
struct GvcMixerCardPrivate
42
pa_context *pa_context;
51
pa_operation *profile_op;
67
static void gvc_mixer_card_class_init (GvcMixerCardClass *klass);
68
static void gvc_mixer_card_init (GvcMixerCard *mixer_card);
69
static void gvc_mixer_card_finalize (GObject *object);
71
G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT)
74
get_next_card_serial (void)
78
serial = card_serial++;
80
if ((gint32)card_serial < 0) {
88
gvc_mixer_card_get_pa_context (GvcMixerCard *card)
90
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
91
return card->priv->pa_context;
95
gvc_mixer_card_get_index (GvcMixerCard *card)
97
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
98
return card->priv->index;
102
gvc_mixer_card_get_id (GvcMixerCard *card)
104
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0);
105
return card->priv->id;
109
gvc_mixer_card_get_name (GvcMixerCard *card)
111
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
112
return card->priv->name;
116
gvc_mixer_card_set_name (GvcMixerCard *card,
119
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
121
g_free (card->priv->name);
122
card->priv->name = g_strdup (name);
123
g_object_notify (G_OBJECT (card), "name");
129
gvc_mixer_card_get_icon_name (GvcMixerCard *card)
131
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
132
return card->priv->icon_name;
136
gvc_mixer_card_set_icon_name (GvcMixerCard *card,
137
const char *icon_name)
139
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
141
g_free (card->priv->icon_name);
142
card->priv->icon_name = g_strdup (icon_name);
143
g_object_notify (G_OBJECT (card), "icon-name");
149
* gvc_mixer_card_get_profile: (skip)
155
GvcMixerCardProfile *
156
gvc_mixer_card_get_profile (GvcMixerCard *card)
160
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
161
g_return_val_if_fail (card->priv->profiles != NULL, NULL);
163
for (l = card->priv->profiles; l != NULL; l = l->next) {
164
GvcMixerCardProfile *p = l->data;
165
if (g_str_equal (card->priv->profile, p->profile)) {
170
g_assert_not_reached ();
176
gvc_mixer_card_set_profile (GvcMixerCard *card,
181
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
182
g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
184
g_free (card->priv->profile);
185
card->priv->profile = g_strdup (profile);
187
g_free (card->priv->human_profile);
188
card->priv->human_profile = NULL;
190
for (l = card->priv->profiles; l != NULL; l = l->next) {
191
GvcMixerCardProfile *p = l->data;
192
if (g_str_equal (card->priv->profile, p->profile)) {
193
card->priv->human_profile = g_strdup (p->human_profile);
198
g_object_notify (G_OBJECT (card), "profile");
204
_pa_context_set_card_profile_by_index_cb (pa_context *context,
208
GvcMixerCard *card = GVC_MIXER_CARD (userdata);
210
g_assert (card->priv->target_profile);
213
gvc_mixer_card_set_profile (card, card->priv->target_profile);
215
g_debug ("Failed to switch profile on '%s' from '%s' to '%s'",
218
card->priv->target_profile);
220
g_free (card->priv->target_profile);
221
card->priv->target_profile = NULL;
223
pa_operation_unref (card->priv->profile_op);
224
card->priv->profile_op = NULL;
228
gvc_mixer_card_change_profile (GvcMixerCard *card,
231
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
232
g_return_val_if_fail (card->priv->profiles != NULL, FALSE);
234
/* Same profile, or already requested? */
235
if (g_strcmp0 (card->priv->profile, profile) == 0)
237
if (g_strcmp0 (profile, card->priv->target_profile) == 0)
239
if (card->priv->profile_op != NULL) {
240
pa_operation_cancel (card->priv->profile_op);
241
pa_operation_unref (card->priv->profile_op);
242
card->priv->profile_op = NULL;
245
if (card->priv->profile != NULL) {
246
g_free (card->priv->target_profile);
247
card->priv->target_profile = g_strdup (profile);
249
card->priv->profile_op = pa_context_set_card_profile_by_index (card->priv->pa_context,
251
card->priv->target_profile,
252
_pa_context_set_card_profile_by_index_cb,
255
if (card->priv->profile_op == NULL) {
256
g_warning ("pa_context_set_card_profile_by_index() failed");
260
g_assert (card->priv->human_profile == NULL);
261
card->priv->profile = g_strdup (profile);
268
* gvc_mixer_card_get_profiles:
270
* Return value: (transfer none) (element-type GvcMixerCardProfile):
273
gvc_mixer_card_get_profiles (GvcMixerCard *card)
275
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
276
return card->priv->profiles;
281
* gvc_mixer_card_get_ports:
283
* Return value: (transfer none) (element-type GvcMixerCardPort):
286
gvc_mixer_card_get_ports (GvcMixerCard *card)
288
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
289
return card->priv->ports;
293
* gvc_mixer_card_set_profiles:
294
* @profiles: (transfer full) (element-type GvcMixerCardProfile):
297
gvc_mixer_card_set_profiles (GvcMixerCard *card,
300
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
301
g_return_val_if_fail (card->priv->profiles == NULL, FALSE);
303
card->priv->profiles = g_list_sort (profiles, (GCompareFunc) sort_profiles);
309
* gvc_mixer_card_get_gicon:
311
* Return value: (transfer full) (element-type GIcon):
314
gvc_mixer_card_get_gicon (GvcMixerCard *card)
316
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL);
317
if (card->priv->icon_name == NULL)
319
return g_themed_icon_new_with_default_fallbacks (card->priv->icon_name);
323
* gvc_mixer_card_set_ports:
324
* @profiles: (transfer full) (element-type GvcMixerCardPort):
327
gvc_mixer_card_set_ports (GvcMixerCard *card,
330
g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE);
331
g_return_val_if_fail (card->priv->ports == NULL, FALSE);
333
card->priv->ports = ports;
339
gvc_mixer_card_set_property (GObject *object,
344
GvcMixerCard *self = GVC_MIXER_CARD (object);
347
case PROP_PA_CONTEXT:
348
self->priv->pa_context = g_value_get_pointer (value);
351
self->priv->index = g_value_get_ulong (value);
354
self->priv->id = g_value_get_ulong (value);
357
gvc_mixer_card_set_name (self, g_value_get_string (value));
360
gvc_mixer_card_set_icon_name (self, g_value_get_string (value));
363
gvc_mixer_card_set_profile (self, g_value_get_string (value));
366
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
372
gvc_mixer_card_get_property (GObject *object,
377
GvcMixerCard *self = GVC_MIXER_CARD (object);
380
case PROP_PA_CONTEXT:
381
g_value_set_pointer (value, self->priv->pa_context);
384
g_value_set_ulong (value, self->priv->index);
387
g_value_set_ulong (value, self->priv->id);
390
g_value_set_string (value, self->priv->name);
393
g_value_set_string (value, self->priv->icon_name);
396
g_value_set_string (value, self->priv->profile);
398
case PROP_HUMAN_PROFILE:
399
g_value_set_string (value, self->priv->human_profile);
402
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
408
gvc_mixer_card_constructor (GType type,
409
guint n_construct_properties,
410
GObjectConstructParam *construct_params)
415
object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params);
417
self = GVC_MIXER_CARD (object);
419
self->priv->id = get_next_card_serial ();
425
gvc_mixer_card_class_init (GvcMixerCardClass *klass)
427
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
429
gobject_class->constructor = gvc_mixer_card_constructor;
430
gobject_class->finalize = gvc_mixer_card_finalize;
432
gobject_class->set_property = gvc_mixer_card_set_property;
433
gobject_class->get_property = gvc_mixer_card_get_property;
435
g_object_class_install_property (gobject_class,
437
g_param_spec_ulong ("index",
439
"The index for this card",
441
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
442
g_object_class_install_property (gobject_class,
444
g_param_spec_ulong ("id",
446
"The id for this card",
448
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
449
g_object_class_install_property (gobject_class,
451
g_param_spec_pointer ("pa-context",
452
"PulseAudio context",
453
"The PulseAudio context for this card",
454
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
455
g_object_class_install_property (gobject_class,
457
g_param_spec_string ("name",
459
"Name to display for this card",
461
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
462
g_object_class_install_property (gobject_class,
464
g_param_spec_string ("icon-name",
466
"Name of icon to display for this card",
468
G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
469
g_object_class_install_property (gobject_class,
471
g_param_spec_string ("profile",
473
"Name of current profile for this card",
476
g_object_class_install_property (gobject_class,
478
g_param_spec_string ("human-profile",
479
"Profile (Human readable)",
480
"Name of current profile for this card in human readable form",
484
g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate));
488
gvc_mixer_card_init (GvcMixerCard *card)
490
card->priv = GVC_MIXER_CARD_GET_PRIVATE (card);
495
gvc_mixer_card_new (pa_context *context,
500
object = g_object_new (GVC_TYPE_MIXER_CARD,
502
"pa-context", context,
504
return GVC_MIXER_CARD (object);
508
free_profile (GvcMixerCardProfile *p)
511
g_free (p->human_profile);
517
gvc_mixer_card_finalize (GObject *object)
519
GvcMixerCard *mixer_card;
521
g_return_if_fail (object != NULL);
522
g_return_if_fail (GVC_IS_MIXER_CARD (object));
524
mixer_card = GVC_MIXER_CARD (object);
526
g_return_if_fail (mixer_card->priv != NULL);
528
g_free (mixer_card->priv->name);
529
mixer_card->priv->name = NULL;
531
g_free (mixer_card->priv->icon_name);
532
mixer_card->priv->icon_name = NULL;
534
g_free (mixer_card->priv->target_profile);
535
mixer_card->priv->target_profile = NULL;
537
g_free (mixer_card->priv->profile);
538
mixer_card->priv->profile = NULL;
540
g_free (mixer_card->priv->human_profile);
541
mixer_card->priv->human_profile = NULL;
543
g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL);
544
g_list_free (mixer_card->priv->profiles);
545
mixer_card->priv->profiles = NULL;
547
G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object);