diff --git a/.gitmodules b/.gitmodules index 992c00b32..a9208a062 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "egg-list-box"] path = egg-list-box url = git://git.gnome.org/egg-list-box + +[submodule "panels/sound/gvc"] + path = panels/sound/gvc + url = git://git.gnome.org/libgnome-volume-control diff --git a/configure.ac b/configure.ac index 954e73ff1..5416331a2 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,9 @@ PKG_CHECK_MODULES(USER_ACCOUNTS_PANEL, $COMMON_MODULES pwquality libsystemd-login) +PKG_CHECK_MODULES(GVC, gobject-2.0 libpulse libpulse-mainloop-glib) +AM_CONDITIONAL(HAVE_INTROSPECTION, false) + GDESKTOP_PREFIX=`$PKG_CONFIG --variable prefix gsettings-desktop-schemas` AC_SUBST(GDESKTOP_PREFIX) @@ -426,6 +429,7 @@ panels/online-accounts/icons/32x32/Makefile panels/online-accounts/icons/48x48/Makefile panels/online-accounts/icons/256x256/Makefile panels/sound/Makefile +panels/sound/gvc/Makefile panels/sound/data/Makefile panels/sound/data/gnome-sound-panel.desktop.in panels/sound/data/symbolic-icons/Makefile diff --git a/panels/sound/Makefile.am b/panels/sound/Makefile.am index ed758a112..e440dbabc 100644 --- a/panels/sound/Makefile.am +++ b/panels/sound/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = data +SUBDIRS = data gvc # This is used in PANEL_CFLAGS cappletname = sound @@ -8,6 +8,7 @@ ccpanelsdir = $(PANELS_DIR) ccpanels_LTLIBRARIES = libsound.la AM_CPPFLAGS = \ + -I$(srcdir)/gvc/ \ $(PANEL_CFLAGS) \ $(SOUND_PANEL_CFLAGS) \ -DLOCALE_DIR=\""$(datadir)/locale"\" \ @@ -18,40 +19,19 @@ AM_CPPFLAGS = \ -DICON_DATA_DIR="\"$(pkgdatadir)/icons\"" \ $(NULL) -noinst_LTLIBRARIES = libgnomevolumecontrol.la -libgnomevolumecontrol_la_SOURCES = \ - gvc-mixer-card.h \ - gvc-mixer-card.c \ - gvc-mixer-card-private.h \ - gvc-mixer-stream.h \ - gvc-mixer-stream.c \ - gvc-mixer-stream-private.h \ - gvc-channel-map.h \ - gvc-channel-map.c \ - gvc-channel-map-private.h \ - gvc-mixer-ui-device.h \ - gvc-mixer-ui-device.c \ - gvc-mixer-sink.h \ - gvc-mixer-sink.c \ - gvc-mixer-source.h \ - gvc-mixer-source.c \ - gvc-mixer-sink-input.h \ - gvc-mixer-sink-input.c \ - gvc-mixer-source-output.h \ - gvc-mixer-source-output.c \ - gvc-mixer-event-role.h \ - gvc-mixer-event-role.c \ - gvc-mixer-control.h \ - gvc-mixer-control.c \ - gvc-mixer-control-private.h \ +# Needed because Automake complains if +# the same source file is used in a library +# and in an executable +noinst_LTLIBRARIES = libgvcgtk.la +libgvcgtk_la_SOURCES = \ gvc-channel-bar.h \ gvc-channel-bar.c \ - gvc-pulseaudio-fake.h \ $(NULL) libsound_la_LIBADD = \ -lm \ - libgnomevolumecontrol.la \ + gvc/libgvc.la \ + libgvcgtk.la \ $(PANEL_LIBS) \ $(SOUND_PANEL_LIBS) \ $(NULL) diff --git a/panels/sound/gvc b/panels/sound/gvc new file mode 160000 index 000000000..f3df56c39 --- /dev/null +++ b/panels/sound/gvc @@ -0,0 +1 @@ +Subproject commit f3df56c399279f52b141b4a2fa3df0b08bdcec55 diff --git a/panels/sound/gvc-channel-map-private.h b/panels/sound/gvc-channel-map-private.h deleted file mode 100644 index 3949de3a6..000000000 --- a/panels/sound/gvc-channel-map-private.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_CHANNEL_MAP_PRIVATE_H -#define __GVC_CHANNEL_MAP_PRIVATE_H - -#include -#include - -G_BEGIN_DECLS - -GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map); -const pa_channel_map * gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map); - -void gvc_channel_map_volume_changed (GvcChannelMap *map, - const pa_cvolume *cv, - gboolean set); -const pa_cvolume * gvc_channel_map_get_cvolume (const GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_CHANNEL_MAP_PRIVATE_H */ diff --git a/panels/sound/gvc-channel-map.c b/panels/sound/gvc-channel-map.c deleted file mode 100644 index a2073fd33..000000000 --- a/panels/sound/gvc-channel-map.c +++ /dev/null @@ -1,254 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-channel-map.h" -#include "gvc-channel-map-private.h" - -#define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate)) - -struct GvcChannelMapPrivate -{ - pa_channel_map pa_map; - gboolean pa_volume_is_set; - pa_cvolume pa_volume; - gdouble extern_volume[NUM_TYPES]; /* volume, balance, fade, lfe */ - gboolean can_balance; - gboolean can_fade; -}; - -enum { - VOLUME_CHANGED, - LAST_SIGNAL -}; - -static guint signals [LAST_SIGNAL] = { 0, }; - -static void gvc_channel_map_class_init (GvcChannelMapClass *klass); -static void gvc_channel_map_init (GvcChannelMap *channel_map); -static void gvc_channel_map_finalize (GObject *object); - -G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT) - -guint -gvc_channel_map_get_num_channels (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0); - - if (!pa_channel_map_valid(&map->priv->pa_map)) - return 0; - - return map->priv->pa_map.channels; -} - -const gdouble * -gvc_channel_map_get_volume (GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); - - if (!pa_channel_map_valid(&map->priv->pa_map)) - return NULL; - - map->priv->extern_volume[VOLUME] = (gdouble) pa_cvolume_max (&map->priv->pa_volume); - if (gvc_channel_map_can_balance (map)) - map->priv->extern_volume[BALANCE] = (gdouble) pa_cvolume_get_balance (&map->priv->pa_volume, &map->priv->pa_map); - else - map->priv->extern_volume[BALANCE] = 0; - if (gvc_channel_map_can_fade (map)) - map->priv->extern_volume[FADE] = (gdouble) pa_cvolume_get_fade (&map->priv->pa_volume, &map->priv->pa_map); - else - map->priv->extern_volume[FADE] = 0; - if (gvc_channel_map_has_lfe (map)) - map->priv->extern_volume[LFE] = (gdouble) pa_cvolume_get_position (&map->priv->pa_volume, &map->priv->pa_map, PA_CHANNEL_POSITION_LFE); - else - map->priv->extern_volume[LFE] = 0; - - return map->priv->extern_volume; -} - -gboolean -gvc_channel_map_can_balance (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); - - return map->priv->can_balance; -} - -gboolean -gvc_channel_map_can_fade (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); - - return map->priv->can_fade; -} - -const char * -gvc_channel_map_get_mapping (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); - - if (!pa_channel_map_valid(&map->priv->pa_map)) - return NULL; - - return pa_channel_map_to_pretty_name (&map->priv->pa_map); -} - -/** - * gvc_channel_map_has_position: (skip) - * - * @map: - * @position: - * - * Returns: - */ -gboolean -gvc_channel_map_has_position (const GvcChannelMap *map, - pa_channel_position_t position) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE); - - return pa_channel_map_has_position (&(map->priv->pa_map), position); -} - -const pa_channel_map * -gvc_channel_map_get_pa_channel_map (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); - - if (!pa_channel_map_valid(&map->priv->pa_map)) - return NULL; - - return &map->priv->pa_map; -} - -const pa_cvolume * -gvc_channel_map_get_cvolume (const GvcChannelMap *map) -{ - g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL); - - if (!pa_channel_map_valid(&map->priv->pa_map)) - return NULL; - - return &map->priv->pa_volume; -} - -static void -gvc_channel_map_class_init (GvcChannelMapClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = gvc_channel_map_finalize; - - signals [VOLUME_CHANGED] = - g_signal_new ("volume-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - g_type_class_add_private (klass, sizeof (GvcChannelMapPrivate)); -} - -void -gvc_channel_map_volume_changed (GvcChannelMap *map, - const pa_cvolume *cv, - gboolean set) -{ - g_return_if_fail (GVC_IS_CHANNEL_MAP (map)); - g_return_if_fail (cv != NULL); - g_return_if_fail (pa_cvolume_compatible_with_channel_map(cv, &map->priv->pa_map)); - - if (pa_cvolume_equal(cv, &map->priv->pa_volume)) - return; - - map->priv->pa_volume = *cv; - - if (map->priv->pa_volume_is_set == FALSE) { - map->priv->pa_volume_is_set = TRUE; - return; - } - g_signal_emit (map, signals[VOLUME_CHANGED], 0, set); -} - -static void -gvc_channel_map_init (GvcChannelMap *map) -{ - map->priv = GVC_CHANNEL_MAP_GET_PRIVATE (map); - map->priv->pa_volume_is_set = FALSE; -} - -static void -gvc_channel_map_finalize (GObject *object) -{ - GvcChannelMap *channel_map; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_CHANNEL_MAP (object)); - - channel_map = GVC_CHANNEL_MAP (object); - - g_return_if_fail (channel_map->priv != NULL); - - G_OBJECT_CLASS (gvc_channel_map_parent_class)->finalize (object); -} - -GvcChannelMap * -gvc_channel_map_new (void) -{ - GObject *map; - map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL); - return GVC_CHANNEL_MAP (map); -} - -static void -set_from_pa_map (GvcChannelMap *map, - const pa_channel_map *pa_map) -{ - g_assert (pa_channel_map_valid(pa_map)); - - map->priv->can_balance = pa_channel_map_can_balance (pa_map); - map->priv->can_fade = pa_channel_map_can_fade (pa_map); - - map->priv->pa_map = *pa_map; - pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM); -} - -GvcChannelMap * -gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *pa_map) -{ - GObject *map; - map = g_object_new (GVC_TYPE_CHANNEL_MAP, NULL); - - set_from_pa_map (GVC_CHANNEL_MAP (map), pa_map); - - return GVC_CHANNEL_MAP (map); -} diff --git a/panels/sound/gvc-channel-map.h b/panels/sound/gvc-channel-map.h deleted file mode 100644 index 85c577289..000000000 --- a/panels/sound/gvc-channel-map.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_CHANNEL_MAP_H -#define __GVC_CHANNEL_MAP_H - -#include -#include - -G_BEGIN_DECLS - -#define GVC_TYPE_CHANNEL_MAP (gvc_channel_map_get_type ()) -#define GVC_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMap)) -#define GVC_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass)) -#define GVC_IS_CHANNEL_MAP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_CHANNEL_MAP)) -#define GVC_IS_CHANNEL_MAP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_CHANNEL_MAP)) -#define GVC_CHANNEL_MAP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapClass)) - -typedef struct GvcChannelMapPrivate GvcChannelMapPrivate; - -typedef struct -{ - GObject parent; - GvcChannelMapPrivate *priv; -} GvcChannelMap; - -typedef struct -{ - GObjectClass parent_class; - void (*volume_changed) (GvcChannelMap *channel_map, gboolean set); -} GvcChannelMapClass; - -enum { - VOLUME, - BALANCE, - FADE, - LFE, - NUM_TYPES -}; - -GType gvc_channel_map_get_type (void); - -GvcChannelMap * gvc_channel_map_new (void); -guint gvc_channel_map_get_num_channels (const GvcChannelMap *map); -const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map); -gboolean gvc_channel_map_can_balance (const GvcChannelMap *map); -gboolean gvc_channel_map_can_fade (const GvcChannelMap *map); -gboolean gvc_channel_map_has_position (const GvcChannelMap *map, - pa_channel_position_t position); -#define gvc_channel_map_has_lfe(x) gvc_channel_map_has_position (x, PA_CHANNEL_POSITION_LFE) - -const char * gvc_channel_map_get_mapping (const GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_CHANNEL_MAP_H */ diff --git a/panels/sound/gvc-mixer-card-private.h b/panels/sound/gvc-mixer-card-private.h deleted file mode 100644 index e190f7f4b..000000000 --- a/panels/sound/gvc-mixer-card-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008-2009 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_CARD_PRIVATE_H -#define __GVC_MIXER_CARD_PRIVATE_H - -#include -#include "gvc-mixer-card.h" - -G_BEGIN_DECLS - -GvcMixerCard * gvc_mixer_card_new (pa_context *context, - guint index); -pa_context * gvc_mixer_card_get_pa_context (GvcMixerCard *card); - -G_END_DECLS - -#endif /* __GVC_MIXER_CARD_PRIVATE_H */ diff --git a/panels/sound/gvc-mixer-card.c b/panels/sound/gvc-mixer-card.c deleted file mode 100644 index a9b246f6d..000000000 --- a/panels/sound/gvc-mixer-card.c +++ /dev/null @@ -1,570 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * Copyright (C) 2009 Bastien Nocera - * Copyright (C) Conor Curran 2011 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-card.h" -#include "gvc-mixer-card-private.h" - -#define GVC_MIXER_CARD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardPrivate)) - -static guint32 card_serial = 1; - -struct GvcMixerCardPrivate -{ - pa_context *pa_context; - guint id; - guint index; - char *name; - char *icon_name; - char *profile; - char *target_profile; - char *human_profile; - GList *profiles; - pa_operation *profile_op; - GList *ports; -}; - -enum -{ - PROP_0, - PROP_ID, - PROP_PA_CONTEXT, - PROP_INDEX, - PROP_NAME, - PROP_ICON_NAME, - PROP_PROFILE, - PROP_HUMAN_PROFILE, -}; - -static void gvc_mixer_card_class_init (GvcMixerCardClass *klass); -static void gvc_mixer_card_init (GvcMixerCard *mixer_card); -static void gvc_mixer_card_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerCard, gvc_mixer_card, G_TYPE_OBJECT) - -static guint32 -get_next_card_serial (void) -{ - guint32 serial; - - serial = card_serial++; - - if ((gint32)card_serial < 0) { - card_serial = 1; - } - - return serial; -} - -pa_context * -gvc_mixer_card_get_pa_context (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); - return card->priv->pa_context; -} - -guint -gvc_mixer_card_get_index (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); - return card->priv->index; -} - -guint -gvc_mixer_card_get_id (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), 0); - return card->priv->id; -} - -const char * -gvc_mixer_card_get_name (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - return card->priv->name; -} - -gboolean -gvc_mixer_card_set_name (GvcMixerCard *card, - const char *name) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - - g_free (card->priv->name); - card->priv->name = g_strdup (name); - g_object_notify (G_OBJECT (card), "name"); - - return TRUE; -} - -const char * -gvc_mixer_card_get_icon_name (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - return card->priv->icon_name; -} - -gboolean -gvc_mixer_card_set_icon_name (GvcMixerCard *card, - const char *icon_name) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - - g_free (card->priv->icon_name); - card->priv->icon_name = g_strdup (icon_name); - g_object_notify (G_OBJECT (card), "icon-name"); - - return TRUE; -} - -/** - * gvc_mixer_card_get_profile: (skip) - * - * @card: - * - * Returns: - */ -GvcMixerCardProfile * -gvc_mixer_card_get_profile (GvcMixerCard *card) -{ - GList *l; - - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - g_return_val_if_fail (card->priv->profiles != NULL, NULL); - - for (l = card->priv->profiles; l != NULL; l = l->next) { - GvcMixerCardProfile *p = l->data; - if (g_str_equal (card->priv->profile, p->profile)) { - return p; - } - } - - g_assert_not_reached (); - - return NULL; -} - -gboolean -gvc_mixer_card_set_profile (GvcMixerCard *card, - const char *profile) -{ - GList *l; - - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - g_return_val_if_fail (card->priv->profiles != NULL, FALSE); - - g_free (card->priv->profile); - card->priv->profile = g_strdup (profile); - - g_free (card->priv->human_profile); - card->priv->human_profile = NULL; - - for (l = card->priv->profiles; l != NULL; l = l->next) { - GvcMixerCardProfile *p = l->data; - if (g_str_equal (card->priv->profile, p->profile)) { - card->priv->human_profile = g_strdup (p->human_profile); - break; - } - } - - g_object_notify (G_OBJECT (card), "profile"); - - return TRUE; -} - -static void -_pa_context_set_card_profile_by_index_cb (pa_context *context, - int success, - void *userdata) -{ - GvcMixerCard *card = GVC_MIXER_CARD (userdata); - - g_assert (card->priv->target_profile); - - if (success > 0) { - gvc_mixer_card_set_profile (card, card->priv->target_profile); - } else { - g_debug ("Failed to switch profile on '%s' from '%s' to '%s'", - card->priv->name, - card->priv->profile, - card->priv->target_profile); - } - g_free (card->priv->target_profile); - card->priv->target_profile = NULL; - - pa_operation_unref (card->priv->profile_op); - card->priv->profile_op = NULL; -} - -gboolean -gvc_mixer_card_change_profile (GvcMixerCard *card, - const char *profile) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - g_return_val_if_fail (card->priv->profiles != NULL, FALSE); - - /* Same profile, or already requested? */ - if (g_strcmp0 (card->priv->profile, profile) == 0) - return TRUE; - if (g_strcmp0 (profile, card->priv->target_profile) == 0) - return TRUE; - if (card->priv->profile_op != NULL) { - pa_operation_cancel (card->priv->profile_op); - pa_operation_unref (card->priv->profile_op); - card->priv->profile_op = NULL; - } - - if (card->priv->profile != NULL) { - g_free (card->priv->target_profile); - card->priv->target_profile = g_strdup (profile); - - card->priv->profile_op = pa_context_set_card_profile_by_index (card->priv->pa_context, - card->priv->index, - card->priv->target_profile, - _pa_context_set_card_profile_by_index_cb, - card); - - if (card->priv->profile_op == NULL) { - g_warning ("pa_context_set_card_profile_by_index() failed"); - return FALSE; - } - } else { - g_assert (card->priv->human_profile == NULL); - card->priv->profile = g_strdup (profile); - } - - return TRUE; -} - -/** - * gvc_mixer_card_get_profiles: - * - * Return value: (transfer none) (element-type GvcMixerCardProfile): - */ -const GList * -gvc_mixer_card_get_profiles (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - return card->priv->profiles; -} - - -/** - * gvc_mixer_card_get_ports: - * - * Return value: (transfer none) (element-type GvcMixerCardPort): - */ -const GList * -gvc_mixer_card_get_ports (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - return card->priv->ports; -} - -/** - * gvc_mixer_card_profile_compare: - * - * Return value: 1 if @a has a higher priority, -1 if @b has a higher - * priority, 0 if @a and @b have the same priority. - */ -int -gvc_mixer_card_profile_compare (GvcMixerCardProfile *a, - GvcMixerCardProfile *b) -{ - if (a->priority == b->priority) - return 0; - if (a->priority > b->priority) - return 1; - return -1; -} - -/** - * gvc_mixer_card_set_profiles: - * @profiles: (transfer full) (element-type GvcMixerCardProfile): - */ -gboolean -gvc_mixer_card_set_profiles (GvcMixerCard *card, - GList *profiles) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - g_return_val_if_fail (card->priv->profiles == NULL, FALSE); - - card->priv->profiles = g_list_sort (profiles, (GCompareFunc) gvc_mixer_card_profile_compare); - - return TRUE; -} - -/** - * gvc_mixer_card_get_gicon: - * - * @card: - * - * Return value: (transfer full) (element-type GIcon): - */ -GIcon * -gvc_mixer_card_get_gicon (GvcMixerCard *card) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), NULL); - - if (card->priv->icon_name == NULL) - return NULL; - - return g_themed_icon_new_with_default_fallbacks (card->priv->icon_name); -} - -/** - * gvc_mixer_card_set_ports: - * @profiles: (transfer full) (element-type GvcMixerCardPort): - */ -gboolean -gvc_mixer_card_set_ports (GvcMixerCard *card, - GList *ports) -{ - g_return_val_if_fail (GVC_IS_MIXER_CARD (card), FALSE); - g_return_val_if_fail (card->priv->ports == NULL, FALSE); - - card->priv->ports = ports; - - return TRUE; -} - -static void -gvc_mixer_card_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerCard *self = GVC_MIXER_CARD (object); - - switch (prop_id) { - case PROP_PA_CONTEXT: - self->priv->pa_context = g_value_get_pointer (value); - break; - case PROP_INDEX: - self->priv->index = g_value_get_ulong (value); - break; - case PROP_ID: - self->priv->id = g_value_get_ulong (value); - break; - case PROP_NAME: - gvc_mixer_card_set_name (self, g_value_get_string (value)); - break; - case PROP_ICON_NAME: - gvc_mixer_card_set_icon_name (self, g_value_get_string (value)); - break; - case PROP_PROFILE: - gvc_mixer_card_set_profile (self, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_card_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerCard *self = GVC_MIXER_CARD (object); - - switch (prop_id) { - case PROP_PA_CONTEXT: - g_value_set_pointer (value, self->priv->pa_context); - break; - case PROP_INDEX: - g_value_set_ulong (value, self->priv->index); - break; - case PROP_ID: - g_value_set_ulong (value, self->priv->id); - break; - case PROP_NAME: - g_value_set_string (value, self->priv->name); - break; - case PROP_ICON_NAME: - g_value_set_string (value, self->priv->icon_name); - break; - case PROP_PROFILE: - g_value_set_string (value, self->priv->profile); - break; - case PROP_HUMAN_PROFILE: - g_value_set_string (value, self->priv->human_profile); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GObject * -gvc_mixer_card_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GvcMixerCard *self; - - object = G_OBJECT_CLASS (gvc_mixer_card_parent_class)->constructor (type, n_construct_properties, construct_params); - - self = GVC_MIXER_CARD (object); - - self->priv->id = get_next_card_serial (); - - return object; -} - -static void -gvc_mixer_card_class_init (GvcMixerCardClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->constructor = gvc_mixer_card_constructor; - gobject_class->finalize = gvc_mixer_card_finalize; - - gobject_class->set_property = gvc_mixer_card_set_property; - gobject_class->get_property = gvc_mixer_card_get_property; - - g_object_class_install_property (gobject_class, - PROP_INDEX, - g_param_spec_ulong ("index", - "Index", - "The index for this card", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_ID, - g_param_spec_ulong ("id", - "id", - "The id for this card", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_PA_CONTEXT, - g_param_spec_pointer ("pa-context", - "PulseAudio context", - "The PulseAudio context for this card", - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "Name to display for this card", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_ICON_NAME, - g_param_spec_string ("icon-name", - "Icon Name", - "Name of icon to display for this card", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_PROFILE, - g_param_spec_string ("profile", - "Profile", - "Name of current profile for this card", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_HUMAN_PROFILE, - g_param_spec_string ("human-profile", - "Profile (Human readable)", - "Name of current profile for this card in human readable form", - NULL, - G_PARAM_READABLE)); - - g_type_class_add_private (klass, sizeof (GvcMixerCardPrivate)); -} - -static void -gvc_mixer_card_init (GvcMixerCard *card) -{ - card->priv = GVC_MIXER_CARD_GET_PRIVATE (card); -} - -GvcMixerCard * -gvc_mixer_card_new (pa_context *context, - guint index) -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_CARD, - "index", index, - "pa-context", context, - NULL); - return GVC_MIXER_CARD (object); -} - -static void -free_profile (GvcMixerCardProfile *p) -{ - g_free (p->profile); - g_free (p->human_profile); - g_free (p->status); - g_free (p); -} - -static void -gvc_mixer_card_finalize (GObject *object) -{ - GvcMixerCard *mixer_card; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_CARD (object)); - - mixer_card = GVC_MIXER_CARD (object); - - g_return_if_fail (mixer_card->priv != NULL); - - g_free (mixer_card->priv->name); - mixer_card->priv->name = NULL; - - g_free (mixer_card->priv->icon_name); - mixer_card->priv->icon_name = NULL; - - g_free (mixer_card->priv->target_profile); - mixer_card->priv->target_profile = NULL; - - g_free (mixer_card->priv->profile); - mixer_card->priv->profile = NULL; - - g_free (mixer_card->priv->human_profile); - mixer_card->priv->human_profile = NULL; - - g_list_foreach (mixer_card->priv->profiles, (GFunc) free_profile, NULL); - g_list_free (mixer_card->priv->profiles); - mixer_card->priv->profiles = NULL; - - G_OBJECT_CLASS (gvc_mixer_card_parent_class)->finalize (object); -} - diff --git a/panels/sound/gvc-mixer-card.h b/panels/sound/gvc-mixer-card.h deleted file mode 100644 index 7fd6d4c93..000000000 --- a/panels/sound/gvc-mixer-card.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008-2009 Red Hat, Inc. - * Copyright (C) Conor Curran 2011 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_CARD_H -#define __GVC_MIXER_CARD_H - -#include -#include - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_CARD (gvc_mixer_card_get_type ()) -#define GVC_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CARD, GvcMixerCard)) -#define GVC_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CARD, GvcMixerCardClass)) -#define GVC_IS_MIXER_CARD(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CARD)) -#define GVC_IS_MIXER_CARD_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CARD)) -#define GVC_MIXER_CARD_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CARD, GvcMixerCardClass)) - -typedef struct GvcMixerCardPrivate GvcMixerCardPrivate; - -typedef struct -{ - GObject parent; - GvcMixerCardPrivate *priv; -} GvcMixerCard; - -typedef struct -{ - GObjectClass parent_class; - - /* vtable */ -} GvcMixerCardClass; - -typedef struct -{ - char *profile; - char *human_profile; - char *status; - guint priority; - guint n_sinks, n_sources; -} GvcMixerCardProfile; - -typedef struct -{ - char *port; - char *human_port; - guint priority; - gint available; - gint direction; - GList *profiles; -} GvcMixerCardPort; - -GType gvc_mixer_card_get_type (void); - -guint gvc_mixer_card_get_id (GvcMixerCard *card); -guint gvc_mixer_card_get_index (GvcMixerCard *card); -const char * gvc_mixer_card_get_name (GvcMixerCard *card); -const char * gvc_mixer_card_get_icon_name (GvcMixerCard *card); -GvcMixerCardProfile * gvc_mixer_card_get_profile (GvcMixerCard *card); -const GList * gvc_mixer_card_get_profiles (GvcMixerCard *card); -const GList * gvc_mixer_card_get_ports (GvcMixerCard *card); -gboolean gvc_mixer_card_change_profile (GvcMixerCard *card, - const char *profile); -GIcon * gvc_mixer_card_get_gicon (GvcMixerCard *card); - -int gvc_mixer_card_profile_compare (GvcMixerCardProfile *a, - GvcMixerCardProfile *b); - -/* private */ -gboolean gvc_mixer_card_set_name (GvcMixerCard *card, - const char *name); -gboolean gvc_mixer_card_set_icon_name (GvcMixerCard *card, - const char *name); -gboolean gvc_mixer_card_set_profile (GvcMixerCard *card, - const char *profile); -gboolean gvc_mixer_card_set_profiles (GvcMixerCard *card, - GList *profiles); -gboolean gvc_mixer_card_set_ports (GvcMixerCard *stream, - GList *ports); - -G_END_DECLS - -#endif /* __GVC_MIXER_CARD_H */ diff --git a/panels/sound/gvc-mixer-control.c b/panels/sound/gvc-mixer-control.c deleted file mode 100644 index 34ddc0c83..000000000 --- a/panels/sound/gvc-mixer-control.c +++ /dev/null @@ -1,3358 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2006-2008 Lennart Poettering - * Copyright (C) 2008 Sjoerd Simons - * Copyright (C) 2008 William Jon McCann - * Copyright (C) 2012 Conor Curran - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "gvc-mixer-control.h" -#include "gvc-mixer-sink.h" -#include "gvc-mixer-source.h" -#include "gvc-mixer-sink-input.h" -#include "gvc-mixer-source-output.h" -#include "gvc-mixer-event-role.h" -#include "gvc-mixer-card.h" -#include "gvc-mixer-card-private.h" -#include "gvc-channel-map-private.h" -#include "gvc-mixer-control-private.h" -#include "gvc-mixer-ui-device.h" - -#define GVC_MIXER_CONTROL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlPrivate)) - -#define RECONNECT_DELAY 5 - -enum { - PROP_0, - PROP_NAME -}; - -struct GvcMixerControlPrivate -{ - pa_glib_mainloop *pa_mainloop; - pa_mainloop_api *pa_api; - pa_context *pa_context; - int n_outstanding; - guint reconnect_id; - char *name; - - gboolean default_sink_is_set; - guint default_sink_id; - char *default_sink_name; - gboolean default_source_is_set; - guint default_source_id; - char *default_source_name; - - gboolean event_sink_input_is_set; - guint event_sink_input_id; - - GHashTable *all_streams; - GHashTable *sinks; /* fixed outputs */ - GHashTable *sources; /* fixed inputs */ - GHashTable *sink_inputs; /* routable output streams */ - GHashTable *source_outputs; /* routable input streams */ - GHashTable *clients; - GHashTable *cards; - - GvcMixerStream *new_default_sink_stream; /* new default sink stream, used in gvc_mixer_control_set_default_sink () */ - GvcMixerStream *new_default_source_stream; /* new default source stream, used in gvc_mixer_control_set_default_source () */ - - GHashTable *ui_outputs; /* UI visible outputs */ - GHashTable *ui_inputs; /* UI visible inputs */ - - /* When we change profile on a device that is not the server default sink, - * it will jump back to the default sink set by the server to prevent the - * audio setup from being 'outputless'. - * - * All well and good but then when we get the new stream created for the - * new profile how do we know that this is the intended default or selected - * device the user wishes to use. */ - guint profile_swapping_device_id; - - GvcMixerControlState state; -}; - -enum { - STATE_CHANGED, - STREAM_ADDED, - STREAM_REMOVED, - CARD_ADDED, - CARD_REMOVED, - DEFAULT_SINK_CHANGED, - DEFAULT_SOURCE_CHANGED, - ACTIVE_OUTPUT_UPDATE, - ACTIVE_INPUT_UPDATE, - OUTPUT_ADDED, - INPUT_ADDED, - OUTPUT_REMOVED, - INPUT_REMOVED, - LAST_SIGNAL -}; - -static guint signals [LAST_SIGNAL] = { 0, }; - -static void gvc_mixer_control_class_init (GvcMixerControlClass *klass); -static void gvc_mixer_control_init (GvcMixerControl *mixer_control); -static void gvc_mixer_control_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerControl, gvc_mixer_control, G_TYPE_OBJECT) - -pa_context * -gvc_mixer_control_get_pa_context (GvcMixerControl *control) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - return control->priv->pa_context; -} - -/** - * gvc_mixer_control_get_event_sink_input: - * - * @control: - * - * Returns: (transfer none): - */ -GvcMixerStream * -gvc_mixer_control_get_event_sink_input (GvcMixerControl *control) -{ - GvcMixerStream *stream; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - stream = g_hash_table_lookup (control->priv->all_streams, - GUINT_TO_POINTER (control->priv->event_sink_input_id)); - - return stream; -} - -static void -gvc_mixer_control_stream_restore_cb (pa_context *c, - GvcMixerStream *new_stream, - const pa_ext_stream_restore_info *info, - GvcMixerControl *control) -{ - pa_operation *o; - pa_ext_stream_restore_info new_info; - - if (new_stream == NULL) - return; - - new_info.name = info->name; - new_info.channel_map = info->channel_map; - new_info.volume = info->volume; - new_info.mute = info->mute; - - new_info.device = gvc_mixer_stream_get_name (new_stream); - - o = pa_ext_stream_restore_write (control->priv->pa_context, - PA_UPDATE_REPLACE, - &new_info, 1, - TRUE, NULL, NULL); - - if (o == NULL) { - g_warning ("pa_ext_stream_restore_write() failed: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - return; - } - - g_debug ("Changed default device for %s to %s", info->name, new_info.device); - - pa_operation_unref (o); -} - -static void -gvc_mixer_control_stream_restore_sink_cb (pa_context *c, - const pa_ext_stream_restore_info *info, - int eol, - void *userdata) -{ - GvcMixerControl *control = (GvcMixerControl *) userdata; - if (eol || info == NULL || !g_str_has_prefix(info->name, "sink-input-by")) - return; - gvc_mixer_control_stream_restore_cb (c, control->priv->new_default_sink_stream, info, control); -} - -static void -gvc_mixer_control_stream_restore_source_cb (pa_context *c, - const pa_ext_stream_restore_info *info, - int eol, - void *userdata) -{ - GvcMixerControl *control = (GvcMixerControl *) userdata; - if (eol || info == NULL || !g_str_has_prefix(info->name, "source-output-by")) - return; - gvc_mixer_control_stream_restore_cb (c, control->priv->new_default_source_stream, info, control); -} - -/** - * gvc_mixer_control_lookup_device_from_stream: - * @control: - * @stream: - * Returns: (transfer none): a #GvcUIDevice or %NULL - */ -GvcMixerUIDevice * -gvc_mixer_control_lookup_device_from_stream (GvcMixerControl *control, - GvcMixerStream *stream) -{ - GList *devices, *d; - gboolean is_network_stream; - const GList *ports; - GvcMixerUIDevice *ret; - - if (GVC_IS_MIXER_SOURCE (stream)) - devices = g_hash_table_get_values (control->priv->ui_inputs); - else - devices = g_hash_table_get_values (control->priv->ui_outputs); - - ret = NULL; - ports = gvc_mixer_stream_get_ports (stream); - is_network_stream = (ports == NULL); - - for (d = devices; d != NULL; d = d->next) { - GvcMixerUIDevice *device = d->data; - gint stream_id = G_MAXINT; - - g_object_get (G_OBJECT (device), - "stream-id", &stream_id, - NULL); - - if (is_network_stream && - stream_id == gvc_mixer_stream_get_id (stream)) { - g_debug ("lookup device from stream - %s - it is a network_stream ", - gvc_mixer_ui_device_get_description (device)); - ret = device; - break; - } else if (!is_network_stream) { - const GvcMixerStreamPort *port; - port = gvc_mixer_stream_get_port (stream); - - if (stream_id == gvc_mixer_stream_get_id (stream) && - g_strcmp0 (gvc_mixer_ui_device_get_port (device), - port->port) == 0) { - g_debug ("lookup-device-from-stream found device: device description '%s', device port = '%s', device stream id %i AND stream port = '%s' stream id '%u' and stream description '%s'", - gvc_mixer_ui_device_get_description (device), - gvc_mixer_ui_device_get_port (device), - stream_id, - port->port, - gvc_mixer_stream_get_id (stream), - gvc_mixer_stream_get_description (stream)); - ret = device; - break; - } - } - } - - g_debug ("gvc_mixer_control_lookup_device_from_stream - Could not find a device for stream '%s'",gvc_mixer_stream_get_description (stream)); - - g_list_free (devices); - - return ret; -} - -gboolean -gvc_mixer_control_set_default_sink (GvcMixerControl *control, - GvcMixerStream *stream) -{ - pa_operation *o; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_debug ("about to set default sink on server"); - o = pa_context_set_default_sink (control->priv->pa_context, - gvc_mixer_stream_get_name (stream), - NULL, - NULL); - if (o == NULL) { - g_warning ("pa_context_set_default_sink() failed: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - return FALSE; - } - - pa_operation_unref (o); - - control->priv->new_default_sink_stream = stream; - g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_sink_stream); - - o = pa_ext_stream_restore_read (control->priv->pa_context, - gvc_mixer_control_stream_restore_sink_cb, - control); - - if (o == NULL) { - g_warning ("pa_ext_stream_restore_read() failed: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - return FALSE; - } - - pa_operation_unref (o); - - return TRUE; -} - -gboolean -gvc_mixer_control_set_default_source (GvcMixerControl *control, - GvcMixerStream *stream) -{ - GvcMixerUIDevice* input; - pa_operation *o; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - o = pa_context_set_default_source (control->priv->pa_context, - gvc_mixer_stream_get_name (stream), - NULL, - NULL); - if (o == NULL) { - g_warning ("pa_context_set_default_source() failed"); - return FALSE; - } - - pa_operation_unref (o); - - control->priv->new_default_source_stream = stream; - g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_source_stream); - - o = pa_ext_stream_restore_read (control->priv->pa_context, - gvc_mixer_control_stream_restore_source_cb, - control); - - if (o == NULL) { - g_warning ("pa_ext_stream_restore_read() failed: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - return FALSE; - } - - pa_operation_unref (o); - - /* source change successful, update the UI. */ - input = gvc_mixer_control_lookup_device_from_stream (control, stream); - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_INPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (input)); - - return TRUE; -} - -/** - * gvc_mixer_control_get_default_sink: - * - * @control: - * - * Returns: (transfer none): - */ -GvcMixerStream * -gvc_mixer_control_get_default_sink (GvcMixerControl *control) -{ - GvcMixerStream *stream; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - if (control->priv->default_sink_is_set) { - stream = g_hash_table_lookup (control->priv->all_streams, - GUINT_TO_POINTER (control->priv->default_sink_id)); - } else { - stream = NULL; - } - - return stream; -} - -/** - * gvc_mixer_control_get_default_source: - * - * @control: - * - * Returns: (transfer none): - */ -GvcMixerStream * -gvc_mixer_control_get_default_source (GvcMixerControl *control) -{ - GvcMixerStream *stream; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - if (control->priv->default_source_is_set) { - stream = g_hash_table_lookup (control->priv->all_streams, - GUINT_TO_POINTER (control->priv->default_source_id)); - } else { - stream = NULL; - } - - return stream; -} - -static gpointer -gvc_mixer_control_lookup_id (GHashTable *hash_table, - guint id) -{ - return g_hash_table_lookup (hash_table, - GUINT_TO_POINTER (id)); -} - -/** - * gvc_mixer_control_lookup_stream_id: - * - * @control: - * @id: - * - * Returns: (transfer none): - */ -GvcMixerStream * -gvc_mixer_control_lookup_stream_id (GvcMixerControl *control, - guint id) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - return gvc_mixer_control_lookup_id (control->priv->all_streams, id); -} - -/** - * gvc_mixer_control_lookup_card_id: - * - * @control: - * @id: - * - * Returns: (transfer none): - */ -GvcMixerCard * -gvc_mixer_control_lookup_card_id (GvcMixerControl *control, - guint id) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - return gvc_mixer_control_lookup_id (control->priv->cards, id); -} - -/** - * gvc_mixer_control_lookup_output_id: - * @control: - * @id: - * Returns: (transfer none): - */ -GvcMixerUIDevice * -gvc_mixer_control_lookup_output_id (GvcMixerControl *control, - guint id) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - return gvc_mixer_control_lookup_id (control->priv->ui_outputs, id); -} - -/** - * gvc_mixer_control_lookup_input_id: - * @control: - * @id: - * Returns: (transfer none): - */ -GvcMixerUIDevice * -gvc_mixer_control_lookup_input_id (GvcMixerControl *control, - guint id) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - return gvc_mixer_control_lookup_id (control->priv->ui_inputs, id); -} - -/** - * gvc_mixer_control_get_stream_from_device: - * @control: - * @device: - * Returns: (transfer none): - */ -GvcMixerStream * -gvc_mixer_control_get_stream_from_device (GvcMixerControl *control, - GvcMixerUIDevice *device) -{ - gint stream_id; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - stream_id = gvc_mixer_ui_device_get_stream_id (device); - - if (stream_id == GVC_MIXER_UI_DEVICE_INVALID) { - g_debug ("gvc_mixer_control_get_stream_from_device - device has a null stream"); - return NULL; - } - return gvc_mixer_control_lookup_stream_id (control, stream_id); -} - -/** - * gvc_mixer_control_change_profile_on_selected_device: - * @control: - * @device: - * @profile: Can be null if any profile present on this port is okay - * Returns: This method will attempt to swap the profile on the card of - * the device with given profile name. If successfull it will set the - * preferred profile on that device so as we know the next time the user - * moves to that device it should have this profile active. - */ -gboolean -gvc_mixer_control_change_profile_on_selected_device (GvcMixerControl *control, - GvcMixerUIDevice *device, - const gchar *profile) -{ - const gchar *best_profile; - GvcMixerCardProfile *current_profile; - GvcMixerCard *card; - - g_object_get (G_OBJECT (device), "card", &card, NULL); - current_profile = gvc_mixer_card_get_profile (card); - - if (current_profile) - best_profile = gvc_mixer_ui_device_get_best_profile (device, profile, current_profile->profile); - else - best_profile = profile; - - g_assert (best_profile); - - g_debug ("Selected '%s', moving to profile '%s' on card '%s' on stream id %i", - profile ? profile : "(any)", best_profile, - gvc_mixer_card_get_name (card), - gvc_mixer_ui_device_get_stream_id (device)); - - g_debug ("default sink name = %s and default sink id %u", - control->priv->default_sink_name, - control->priv->default_sink_id); - - control->priv->profile_swapping_device_id = gvc_mixer_ui_device_get_id (device); - - if (gvc_mixer_card_change_profile (card, best_profile)) { - gvc_mixer_ui_device_set_user_preferred_profile (device, best_profile); - return TRUE; - } - return FALSE; -} - -/** - * gvc_mixer_control_change_output: - * @control: - * @output: - * This method is called from the UI when the user selects a previously unselected device. - * - Firstly it queries the stream from the device. - * - It assumes that if the stream is null that it cannot be a bluetooth or network stream (they never show unless they have valid sinks and sources) - * In the scenario of a NULL stream on the device - * - It fetches the device's preferred profile or if NUll the profile with the highest priority on that device. - * - It then caches this device in control->priv->cached_desired_output_id so that when the update_sink triggered - * from when we attempt to change profile we will know exactly what device to highlight on that stream. - * - It attempts to swap the profile on the card from that device and returns. - * - Next, it handles network or bluetooth streams that only require their stream to be made the default. - * - Next it deals with port changes so if the stream's active port is not the same as the port on the device - * it will attempt to change the port on that stream to be same as the device. If this fails it will return. - * - Finally it will set this new stream to be the default stream and emit a signal for the UI confirming the active output device. - */ -void -gvc_mixer_control_change_output (GvcMixerControl *control, - GvcMixerUIDevice* output) -{ - GvcMixerStream *stream; - GvcMixerStream *default_stream; - const GvcMixerStreamPort *active_port; - const gchar *output_port; - - g_debug ("control change output"); - - stream = gvc_mixer_control_get_stream_from_device (control, output); - if (stream == NULL) { - gvc_mixer_control_change_profile_on_selected_device (control, - output, NULL); - return; - } - - /* Handle a network sink as a portless or cardless device */ - if (!gvc_mixer_ui_device_has_ports (output)) { - g_debug ("Did we try to move to a software/bluetooth sink ?"); - if (gvc_mixer_control_set_default_sink (control, stream)) { - /* sink change was successful, update the UI.*/ - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_OUTPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (output)); - } - else { - g_warning ("Failed to set default sink with stream from output %s", - gvc_mixer_ui_device_get_description (output)); - } - return; - } - - active_port = gvc_mixer_stream_get_port (stream); - output_port = gvc_mixer_ui_device_get_port (output); - /* First ensure the correct port is active on the sink */ - if (g_strcmp0 (active_port->port, output_port) != 0) { - g_debug ("Port change, switch to = %s", output_port); - if (gvc_mixer_stream_change_port (stream, output_port) == FALSE) { - g_warning ("Could not change port !"); - return; - } - } - - default_stream = gvc_mixer_control_get_default_sink (control); - - /* Finally if we are not on the correct stream, swap over. */ - if (stream != default_stream) { - GvcMixerUIDevice* output; - - g_debug ("Attempting to swap over to stream %s ", - gvc_mixer_stream_get_description (stream)); - if (gvc_mixer_control_set_default_sink (control, stream)) { - output = gvc_mixer_control_lookup_device_from_stream (control, stream); - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_OUTPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (output)); - } else { - /* If the move failed for some reason reset the UI. */ - output = gvc_mixer_control_lookup_device_from_stream (control, default_stream); - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_OUTPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (output)); - } - } -} - - -/** - * gvc_mixer_control_change_input: - * @control: - * @input: - * This method is called from the UI when the user selects a previously unselected device. - * - Firstly it queries the stream from the device. - * - It assumes that if the stream is null that it cannot be a bluetooth or network stream (they never show unless they have valid sinks and sources) - * In the scenario of a NULL stream on the device - * - It fetches the device's preferred profile or if NUll the profile with the highest priority on that device. - * - It then caches this device in control->priv->cached_desired_input_id so that when the update_source triggered - * from when we attempt to change profile we will know exactly what device to highlight on that stream. - * - It attempts to swap the profile on the card from that device and returns. - * - Next, it handles network or bluetooth streams that only require their stream to be made the default. - * - Next it deals with port changes so if the stream's active port is not the same as the port on the device - * it will attempt to change the port on that stream to be same as the device. If this fails it will return. - * - Finally it will set this new stream to be the default stream and emit a signal for the UI confirming the active input device. - */ -void -gvc_mixer_control_change_input (GvcMixerControl *control, - GvcMixerUIDevice* input) -{ - GvcMixerStream *stream; - GvcMixerStream *default_stream; - const GvcMixerStreamPort *active_port; - const gchar *input_port; - - stream = gvc_mixer_control_get_stream_from_device (control, input); - if (stream == NULL) { - gvc_mixer_control_change_profile_on_selected_device (control, - input, NULL); - return; - } - - /* Handle a network sink as a portless/cardless device */ - if (!gvc_mixer_ui_device_has_ports (input)) { - g_debug ("Did we try to move to a software/bluetooth source ?"); - if (! gvc_mixer_control_set_default_source (control, stream)) { - g_warning ("Failed to set default source with stream from input %s", - gvc_mixer_ui_device_get_description (input)); - } - return; - } - - active_port = gvc_mixer_stream_get_port (stream); - input_port = gvc_mixer_ui_device_get_port (input); - /* First ensure the correct port is active on the sink */ - if (g_strcmp0 (active_port->port, input_port) != 0) { - g_debug ("Port change, switch to = %s", input_port); - if (gvc_mixer_stream_change_port (stream, input_port) == FALSE) { - g_warning ("Could not change port!"); - return; - } - } - - default_stream = gvc_mixer_control_get_default_source (control); - - /* Finally if we are not on the correct stream, swap over. */ - if (stream != default_stream) { - g_debug ("change-input - attempting to swap over to stream %s", - gvc_mixer_stream_get_description (stream)); - gvc_mixer_control_set_default_source (control, stream); - } -} - - -static void -listify_hash_values_hfunc (gpointer key, - gpointer value, - gpointer user_data) -{ - GSList **list = user_data; - - *list = g_slist_prepend (*list, value); -} - -static int -gvc_name_collate (const char *namea, - const char *nameb) -{ - if (nameb == NULL && namea == NULL) - return 0; - if (nameb == NULL) - return 1; - if (namea == NULL) - return -1; - - return g_utf8_collate (namea, nameb); -} - -static int -gvc_card_collate (GvcMixerCard *a, - GvcMixerCard *b) -{ - const char *namea; - const char *nameb; - - g_return_val_if_fail (a == NULL || GVC_IS_MIXER_CARD (a), 0); - g_return_val_if_fail (b == NULL || GVC_IS_MIXER_CARD (b), 0); - - namea = gvc_mixer_card_get_name (a); - nameb = gvc_mixer_card_get_name (b); - - return gvc_name_collate (namea, nameb); -} - -/** - * gvc_mixer_control_get_cards: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerCard): - */ -GSList * -gvc_mixer_control_get_cards (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->cards, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_card_collate); -} - -static int -gvc_stream_collate (GvcMixerStream *a, - GvcMixerStream *b) -{ - const char *namea; - const char *nameb; - - g_return_val_if_fail (a == NULL || GVC_IS_MIXER_STREAM (a), 0); - g_return_val_if_fail (b == NULL || GVC_IS_MIXER_STREAM (b), 0); - - namea = gvc_mixer_stream_get_name (a); - nameb = gvc_mixer_stream_get_name (b); - - return gvc_name_collate (namea, nameb); -} - -/** - * gvc_mixer_control_get_streams: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerStream): - */ -GSList * -gvc_mixer_control_get_streams (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->all_streams, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); -} - -/** - * gvc_mixer_control_get_sinks: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerSink): - */ -GSList * -gvc_mixer_control_get_sinks (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->sinks, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); -} - -/** - * gvc_mixer_control_get_sources: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerSource): - */ -GSList * -gvc_mixer_control_get_sources (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->sources, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); -} - -/** - * gvc_mixer_control_get_sink_inputs: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerSinkInput): - */ -GSList * -gvc_mixer_control_get_sink_inputs (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->sink_inputs, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); -} - -/** - * gvc_mixer_control_get_source_outputs: - * - * @control: - * - * Returns: (transfer container) (element-type Gvc.MixerSourceOutput): - */ -GSList * -gvc_mixer_control_get_source_outputs (GvcMixerControl *control) -{ - GSList *retval; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), NULL); - - retval = NULL; - g_hash_table_foreach (control->priv->source_outputs, - listify_hash_values_hfunc, - &retval); - return g_slist_sort (retval, (GCompareFunc) gvc_stream_collate); -} - -static void -dec_outstanding (GvcMixerControl *control) -{ - if (control->priv->n_outstanding <= 0) { - return; - } - - if (--control->priv->n_outstanding <= 0) { - control->priv->state = GVC_STATE_READY; - g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_READY); - } -} - -GvcMixerControlState -gvc_mixer_control_get_state (GvcMixerControl *control) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); - - return control->priv->state; -} - -static void -on_default_source_port_notify (GObject *object, - GParamSpec *pspec, - GvcMixerControl *control) -{ - char *port; - GvcMixerUIDevice *input; - - g_object_get (object, "port", &port, NULL); - input = gvc_mixer_control_lookup_device_from_stream (control, - GVC_MIXER_STREAM (object)); - - g_debug ("on_default_source_port_notify - moved to port '%s' which SHOULD ?? correspond to output '%s'", - port, - gvc_mixer_ui_device_get_description (input)); - - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_INPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (input)); - - g_free (port); -} - - -static void -_set_default_source (GvcMixerControl *control, - GvcMixerStream *stream) -{ - guint new_id; - - if (stream == NULL) { - control->priv->default_source_id = 0; - control->priv->default_source_is_set = FALSE; - g_signal_emit (control, - signals[DEFAULT_SOURCE_CHANGED], - 0, - PA_INVALID_INDEX); - return; - } - - new_id = gvc_mixer_stream_get_id (stream); - - if (control->priv->default_source_id != new_id) { - GvcMixerUIDevice *input; - control->priv->default_source_id = new_id; - control->priv->default_source_is_set = TRUE; - g_signal_emit (control, - signals[DEFAULT_SOURCE_CHANGED], - 0, - new_id); - - if (control->priv->default_source_is_set) { - g_signal_handlers_disconnect_by_func (gvc_mixer_control_get_default_source (control), - on_default_source_port_notify, - control); - } - - g_signal_connect (stream, - "notify::port", - G_CALLBACK (on_default_source_port_notify), - control); - - input = gvc_mixer_control_lookup_device_from_stream (control, stream); - - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_INPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (input)); - } -} - -static void -on_default_sink_port_notify (GObject *object, - GParamSpec *pspec, - GvcMixerControl *control) -{ - char *port; - GvcMixerUIDevice *output; - - g_object_get (object, "port", &port, NULL); - - output = gvc_mixer_control_lookup_device_from_stream (control, - GVC_MIXER_STREAM (object)); - if (output != NULL) { - g_debug ("on_default_sink_port_notify - moved to port %s - which SHOULD correspond to output %s", - port, - gvc_mixer_ui_device_get_description (output)); - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_OUTPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (output)); - } - g_free (port); -} - -static void -_set_default_sink (GvcMixerControl *control, - GvcMixerStream *stream) -{ - guint new_id; - - if (stream == NULL) { - /* Don't tell front-ends about an unset default - * sink if it's already unset */ - if (control->priv->default_sink_is_set == FALSE) - return; - control->priv->default_sink_id = 0; - control->priv->default_sink_is_set = FALSE; - g_signal_emit (control, - signals[DEFAULT_SINK_CHANGED], - 0, - PA_INVALID_INDEX); - return; - } - - new_id = gvc_mixer_stream_get_id (stream); - - if (control->priv->default_sink_id != new_id) { - GvcMixerUIDevice *output; - if (control->priv->default_sink_is_set) { - g_signal_handlers_disconnect_by_func (gvc_mixer_control_get_default_sink (control), - on_default_sink_port_notify, - control); - } - - control->priv->default_sink_id = new_id; - - control->priv->default_sink_is_set = TRUE; - g_signal_emit (control, - signals[DEFAULT_SINK_CHANGED], - 0, - new_id); - - g_signal_connect (stream, - "notify::port", - G_CALLBACK (on_default_sink_port_notify), - control); - - output = gvc_mixer_control_lookup_device_from_stream (control, stream); - - g_debug ("active_sink change"); - - g_signal_emit (G_OBJECT (control), - signals[ACTIVE_OUTPUT_UPDATE], - 0, - gvc_mixer_ui_device_get_id (output)); - } -} - -static gboolean -_stream_has_name (gpointer key, - GvcMixerStream *stream, - const char *name) -{ - const char *t_name; - - t_name = gvc_mixer_stream_get_name (stream); - - if (t_name != NULL - && name != NULL - && strcmp (t_name, name) == 0) { - return TRUE; - } - - return FALSE; -} - -static GvcMixerStream * -find_stream_for_name (GvcMixerControl *control, - const char *name) -{ - GvcMixerStream *stream; - - stream = g_hash_table_find (control->priv->all_streams, - (GHRFunc)_stream_has_name, - (char *)name); - return stream; -} - -static void -update_default_source_from_name (GvcMixerControl *control, - const char *name) -{ - gboolean changed = FALSE; - - if ((control->priv->default_source_name == NULL - && name != NULL) - || (control->priv->default_source_name != NULL - && name == NULL) - || (name != NULL && strcmp (control->priv->default_source_name, name) != 0)) { - changed = TRUE; - } - - if (changed) { - GvcMixerStream *stream; - - g_free (control->priv->default_source_name); - control->priv->default_source_name = g_strdup (name); - - stream = find_stream_for_name (control, name); - _set_default_source (control, stream); - } -} - -static void -update_default_sink_from_name (GvcMixerControl *control, - const char *name) -{ - gboolean changed = FALSE; - - if ((control->priv->default_sink_name == NULL - && name != NULL) - || (control->priv->default_sink_name != NULL - && name == NULL) - || (name != NULL && strcmp (control->priv->default_sink_name, name) != 0)) { - changed = TRUE; - } - - if (changed) { - GvcMixerStream *stream; - g_free (control->priv->default_sink_name); - control->priv->default_sink_name = g_strdup (name); - - stream = find_stream_for_name (control, name); - _set_default_sink (control, stream); - } -} - -static void -update_server (GvcMixerControl *control, - const pa_server_info *info) -{ - if (info->default_source_name != NULL) { - update_default_source_from_name (control, info->default_source_name); - } - if (info->default_sink_name != NULL) { - g_debug ("update server"); - update_default_sink_from_name (control, info->default_sink_name); - } -} - -static void -remove_stream (GvcMixerControl *control, - GvcMixerStream *stream) -{ - guint id; - - g_object_ref (stream); - - id = gvc_mixer_stream_get_id (stream); - - if (id == control->priv->default_sink_id) { - _set_default_sink (control, NULL); - } else if (id == control->priv->default_source_id) { - _set_default_source (control, NULL); - } - - g_hash_table_remove (control->priv->all_streams, - GUINT_TO_POINTER (id)); - g_signal_emit (G_OBJECT (control), - signals[STREAM_REMOVED], - 0, - gvc_mixer_stream_get_id (stream)); - g_object_unref (stream); -} - -static void -add_stream (GvcMixerControl *control, - GvcMixerStream *stream) -{ - g_hash_table_insert (control->priv->all_streams, - GUINT_TO_POINTER (gvc_mixer_stream_get_id (stream)), - stream); - g_signal_emit (G_OBJECT (control), - signals[STREAM_ADDED], - 0, - gvc_mixer_stream_get_id (stream)); -} - -/* This method will match individual stream ports against its corresponding device - * It does this by: - * - iterates through our devices and finds the one where the card-id on the device is the same as the card-id on the stream - * and the port-name on the device is the same as the streamport-name. - * This should always find a match and is used exclusively by sync_devices(). - */ -static gboolean -match_stream_with_devices (GvcMixerControl *control, - GvcMixerStreamPort *stream_port, - GvcMixerStream *stream) -{ - GList *devices, *d; - guint stream_card_id; - guint stream_id; - gboolean in_possession = FALSE; - - stream_id = gvc_mixer_stream_get_id (stream); - stream_card_id = gvc_mixer_stream_get_card_index (stream); - - devices = g_hash_table_get_values (GVC_IS_MIXER_SOURCE (stream) ? control->priv->ui_inputs : control->priv->ui_outputs); - - for (d = devices; d != NULL; d = d->next) { - GvcMixerUIDevice *device; - gint device_stream_id; - gchar *device_port_name; - gchar *origin; - gchar *description; - GvcMixerCard *card; - gint card_id; - - device = d->data; - g_object_get (G_OBJECT (device), - "stream-id", &device_stream_id, - "card", &card, - "origin", &origin, - "description", &description, - "port-name", &device_port_name, - NULL); - - card_id = gvc_mixer_card_get_index (card); - - g_debug ("Attempt to match_stream update_with_existing_outputs - Try description : '%s', origin : '%s', device port name : '%s', card : %p, AGAINST stream port: '%s', sink card id %i", - description, - origin, - device_port_name, - card, - stream_port->port, - stream_card_id); - - if (stream_card_id == card_id && - g_strcmp0 (device_port_name, stream_port->port) == 0) { - g_debug ("Match device with stream: We have a match with description: '%s', origin: '%s', cached already with device id %u, so set stream id to %i", - description, - origin, - gvc_mixer_ui_device_get_id (device), - stream_id); - - g_object_set (G_OBJECT (device), - "stream-id", (gint)stream_id, - NULL); - in_possession = TRUE; - } - - g_free (device_port_name); - g_free (origin); - g_free (description); - - if (in_possession == TRUE) - break; - } - - g_list_free (devices); - return in_possession; -} - -/* - * This method attempts to match a sink or source with its relevant UI device. - * GvcMixerStream can represent both a sink or source. - * Using static card port introspection implies that we know beforehand what - * outputs and inputs are available to the user. - * But that does not mean that all of these inputs and outputs are available to be used. - * For instance we might be able to see that there is a HDMI port available but if - * we are on the default analog stereo output profile there is no valid sink for - * that HDMI device. We first need to change profile and when update_sink() is called - * only then can we match the new hdmi sink with its corresponding device. - * - * Firstly it checks to see if the incoming stream has no ports. - * - If a stream has no ports but has a valid card ID (bluetooth), it will attempt - * to match the device with the stream using the card id. - * - If a stream has no ports and no valid card id, it goes ahead and makes a new - * device (software/network devices are only detectable at the sink/source level) - * If the stream has ports it will match each port against the stream using match_stream_with_devices(). - * - * This method should always find a match. - */ -static void -sync_devices (GvcMixerControl *control, - GvcMixerStream* stream) -{ - /* Go through ports to see what outputs can be created. */ - const GList *stream_ports; - const GList *n = NULL; - gboolean is_output = !GVC_IS_MIXER_SOURCE (stream); - gint stream_port_count = 0; - - stream_ports = gvc_mixer_stream_get_ports (stream); - - if (stream_ports == NULL) { - GvcMixerUIDevice *device; - /* Bluetooth, no ports but a valid card */ - if (gvc_mixer_stream_get_card_index (stream) != PA_INVALID_INDEX) { - GList *devices, *d; - gboolean in_possession = FALSE; - - devices = g_hash_table_get_values (is_output ? control->priv->ui_outputs : control->priv->ui_inputs); - - for (d = devices; d != NULL; d = d->next) { - GvcMixerCard *card; - gint card_id; - - device = d->data; - - g_object_get (G_OBJECT (device), - "card", &card, - NULL); - card_id = gvc_mixer_card_get_index (card); - g_debug ("sync devices, device description - '%s', device card id - %i, stream description - %s, stream card id - %i", - gvc_mixer_ui_device_get_description (device), - card_id, - gvc_mixer_stream_get_description (stream), - gvc_mixer_stream_get_card_index (stream)); - if (card_id == gvc_mixer_stream_get_card_index (stream)) { - in_possession = TRUE; - break; - } - } - g_list_free (devices); - - if (!in_possession) { - g_warning ("Couldn't match the portless stream (with card) - '%s' is it an input ? -> %i, streams card id -> %i", - gvc_mixer_stream_get_description (stream), - GVC_IS_MIXER_SOURCE (stream), - gvc_mixer_stream_get_card_index (stream)); - return; - } - - g_object_set (G_OBJECT (device), - "stream-id", (gint)gvc_mixer_stream_get_id (stream), - "description", gvc_mixer_stream_get_description (stream), - "origin", "", /*Leave it empty for these special cases*/ - "port-name", NULL, - "port-available", TRUE, - NULL); - } else { /* Network sink/source has no ports and no card. */ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, - "stream-id", (gint)gvc_mixer_stream_get_id (stream), - "description", gvc_mixer_stream_get_description (stream), - "origin", "", /* Leave it empty for these special cases */ - "port-name", NULL, - "port-available", TRUE, - NULL); - device = GVC_MIXER_UI_DEVICE (object); - - g_hash_table_insert (is_output ? control->priv->ui_outputs : control->priv->ui_inputs, - GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (device)), - g_object_ref (device)); - - } - g_signal_emit (G_OBJECT (control), - signals[is_output ? OUTPUT_ADDED : INPUT_ADDED], - 0, - gvc_mixer_ui_device_get_id (device)); - - return; - } - - /* Go ahead and make sure to match each port against a previously created device */ - for (n = stream_ports; n != NULL; n = n->next) { - - GvcMixerStreamPort *stream_port; - stream_port = n->data; - stream_port_count ++; - - if (match_stream_with_devices (control, stream_port, stream)) - continue; - - g_warning ("Sync_devices: Failed to match stream id: %u, description: '%s', origin: '%s'", - gvc_mixer_stream_get_id (stream), - stream_port->human_port, - gvc_mixer_stream_get_description (stream)); - } -} - -static void -set_icon_name_from_proplist (GvcMixerStream *stream, - pa_proplist *l, - const char *default_icon_name) -{ - const char *t; - - if ((t = pa_proplist_gets (l, PA_PROP_DEVICE_ICON_NAME))) { - goto finish; - } - - if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ICON_NAME))) { - goto finish; - } - - if ((t = pa_proplist_gets (l, PA_PROP_WINDOW_ICON_NAME))) { - goto finish; - } - - if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ICON_NAME))) { - goto finish; - } - - if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) { - - if (strcmp (t, "video") == 0 || - strcmp (t, "phone") == 0) { - goto finish; - } - - if (strcmp (t, "music") == 0) { - t = "audio"; - goto finish; - } - - if (strcmp (t, "game") == 0) { - t = "applications-games"; - goto finish; - } - - if (strcmp (t, "event") == 0) { - t = "dialog-information"; - goto finish; - } - } - - t = default_icon_name; - - finish: - gvc_mixer_stream_set_icon_name (stream, t); -} - -/* - * Called when anything changes with a sink. - */ -static void -update_sink (GvcMixerControl *control, - const pa_sink_info *info) -{ - GvcMixerStream *stream; - gboolean is_new; - pa_volume_t max_volume; - GvcChannelMap *map; - char map_buff[PA_CHANNEL_MAP_SNPRINT_MAX]; - - pa_channel_map_snprint (map_buff, PA_CHANNEL_MAP_SNPRINT_MAX, &info->channel_map); -#if 1 - g_debug ("Updating sink: index=%u name='%s' description='%s' map='%s'", - info->index, - info->name, - info->description, - map_buff); -#endif - - map = NULL; - is_new = FALSE; - stream = g_hash_table_lookup (control->priv->sinks, - GUINT_TO_POINTER (info->index)); - - if (stream == NULL) { - GList *list = NULL; - guint i; - - map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); - stream = gvc_mixer_sink_new (control->priv->pa_context, - info->index, - map); - - for (i = 0; i < info->n_ports; i++) { - GvcMixerStreamPort *port; - - port = g_new0 (GvcMixerStreamPort, 1); - port->port = g_strdup (info->ports[i]->name); - port->human_port = g_strdup (info->ports[i]->description); - port->priority = info->ports[i]->priority; - port->available = info->ports[i]->available != PA_PORT_AVAILABLE_NO; - - list = g_list_prepend (list, port); - } - gvc_mixer_stream_set_ports (stream, list); - - g_object_unref (map); - is_new = TRUE; - - } else if (gvc_mixer_stream_is_running (stream)) { - /* Ignore events if volume changes are outstanding */ - g_debug ("Ignoring event, volume changes are outstanding"); - return; - } - - max_volume = pa_cvolume_max (&info->volume); - gvc_mixer_stream_set_name (stream, info->name); - gvc_mixer_stream_set_card_index (stream, info->card); - gvc_mixer_stream_set_description (stream, info->description); - set_icon_name_from_proplist (stream, info->proplist, "audio-card"); - gvc_mixer_stream_set_sysfs_path (stream, pa_proplist_gets (info->proplist, "sysfs.path")); - gvc_mixer_stream_set_volume (stream, (guint)max_volume); - gvc_mixer_stream_set_is_muted (stream, info->mute); - gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SINK_DECIBEL_VOLUME)); - gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume); - - /* Messy I know but to set the port everytime regardless of whether it has changed will cost us a - * port change notify signal which causes the frontend to resync. - * Only update the UI when something has changed. */ - if (info->active_port != NULL) { - if (is_new) - gvc_mixer_stream_set_port (stream, info->active_port->name); - else { - const GvcMixerStreamPort *active_port; - active_port = gvc_mixer_stream_get_port (stream); - if (active_port == NULL || - g_strcmp0 (active_port->port, info->active_port->name) != 0) { - g_debug ("update sink - apparently a port update"); - gvc_mixer_stream_set_port (stream, info->active_port->name); - } - } - } - - if (is_new) { - g_debug ("update sink - is new"); - - g_hash_table_insert (control->priv->sinks, - GUINT_TO_POINTER (info->index), - g_object_ref (stream)); - add_stream (control, stream); - /* Always sink on a new stream to able to assign the right stream id - * to the appropriate outputs (multiple potential outputs per stream). */ - sync_devices (control, stream); - } - - /* - * When we change profile on a device that is not the server default sink, - * it will jump back to the default sink set by the server to prevent the audio setup from being 'outputless'. - * All well and good but then when we get the new stream created for the new profile how do we know - * that this is the intended default or selected device the user wishes to use. - * This is messy but it's the only reliable way that it can be done without ripping the whole thing apart. - */ - if (control->priv->profile_swapping_device_id != GVC_MIXER_UI_DEVICE_INVALID) { - GvcMixerUIDevice *dev = NULL; - dev = gvc_mixer_control_lookup_output_id (control, control->priv->profile_swapping_device_id); - if (dev != NULL) { - /* now check to make sure this new stream is the same stream just matched and set on the device object */ - if (gvc_mixer_ui_device_get_stream_id (dev) == gvc_mixer_stream_get_id (stream)) { - g_debug ("Looks like we profile swapped on a non server default sink"); - gvc_mixer_control_set_default_sink (control, stream); - } - } - control->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; - } - - if (control->priv->default_sink_name != NULL - && info->name != NULL - && strcmp (control->priv->default_sink_name, info->name) == 0) { - _set_default_sink (control, stream); - } - - if (map == NULL) - map = (GvcChannelMap *) gvc_mixer_stream_get_channel_map (stream); - - gvc_channel_map_volume_changed (map, &info->volume, FALSE); -} - -static void -update_source (GvcMixerControl *control, - const pa_source_info *info) -{ - GvcMixerStream *stream; - gboolean is_new; - pa_volume_t max_volume; - -#if 1 - g_debug ("Updating source: index=%u name='%s' description='%s'", - info->index, - info->name, - info->description); -#endif - - /* completely ignore monitors, they're not real sources */ - if (info->monitor_of_sink != PA_INVALID_INDEX) { - return; - } - - is_new = FALSE; - - stream = g_hash_table_lookup (control->priv->sources, - GUINT_TO_POINTER (info->index)); - if (stream == NULL) { - GList *list = NULL; - guint i; - GvcChannelMap *map; - - map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); - stream = gvc_mixer_source_new (control->priv->pa_context, - info->index, - map); - - for (i = 0; i < info->n_ports; i++) { - GvcMixerStreamPort *port; - - port = g_new0 (GvcMixerStreamPort, 1); - port->port = g_strdup (info->ports[i]->name); - port->human_port = g_strdup (info->ports[i]->description); - port->priority = info->ports[i]->priority; - list = g_list_prepend (list, port); - } - gvc_mixer_stream_set_ports (stream, list); - - g_object_unref (map); - is_new = TRUE; - } else if (gvc_mixer_stream_is_running (stream)) { - /* Ignore events if volume changes are outstanding */ - g_debug ("Ignoring event, volume changes are outstanding"); - return; - } - - max_volume = pa_cvolume_max (&info->volume); - - gvc_mixer_stream_set_name (stream, info->name); - gvc_mixer_stream_set_card_index (stream, info->card); - gvc_mixer_stream_set_description (stream, info->description); - set_icon_name_from_proplist (stream, info->proplist, "audio-input-microphone"); - gvc_mixer_stream_set_volume (stream, (guint)max_volume); - gvc_mixer_stream_set_is_muted (stream, info->mute); - gvc_mixer_stream_set_can_decibel (stream, !!(info->flags & PA_SOURCE_DECIBEL_VOLUME)); - gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume); - g_debug ("update source"); - - if (info->active_port != NULL) { - if (is_new) - gvc_mixer_stream_set_port (stream, info->active_port->name); - else { - const GvcMixerStreamPort *active_port; - active_port = gvc_mixer_stream_get_port (stream); - if (active_port == NULL || - g_strcmp0 (active_port->port, info->active_port->name) != 0) { - g_debug ("update source - apparently a port update"); - gvc_mixer_stream_set_port (stream, info->active_port->name); - } - } - } - - if (is_new) { - g_hash_table_insert (control->priv->sources, - GUINT_TO_POINTER (info->index), - g_object_ref (stream)); - add_stream (control, stream); - sync_devices (control, stream); - } - - if (control->priv->profile_swapping_device_id != GVC_MIXER_UI_DEVICE_INVALID) { - GvcMixerUIDevice *dev = NULL; - - dev = gvc_mixer_control_lookup_input_id (control, control->priv->profile_swapping_device_id); - - if (dev != NULL) { - /* now check to make sure this new stream is the same stream just matched and set on the device object */ - if (gvc_mixer_ui_device_get_stream_id (dev) == gvc_mixer_stream_get_id (stream)) { - g_debug ("Looks like we profile swapped on a non server default sink"); - gvc_mixer_control_set_default_source (control, stream); - } - } - control->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; - } - if (control->priv->default_source_name != NULL - && info->name != NULL - && strcmp (control->priv->default_source_name, info->name) == 0) { - _set_default_source (control, stream); - } -} - -static void -set_is_event_stream_from_proplist (GvcMixerStream *stream, - pa_proplist *l) -{ - const char *t; - gboolean is_event_stream; - - is_event_stream = FALSE; - - if ((t = pa_proplist_gets (l, PA_PROP_MEDIA_ROLE))) { - if (g_str_equal (t, "event")) - is_event_stream = TRUE; - } - - gvc_mixer_stream_set_is_event_stream (stream, is_event_stream); -} - -static void -set_application_id_from_proplist (GvcMixerStream *stream, - pa_proplist *l) -{ - const char *t; - - if ((t = pa_proplist_gets (l, PA_PROP_APPLICATION_ID))) { - gvc_mixer_stream_set_application_id (stream, t); - } -} - -static void -update_sink_input (GvcMixerControl *control, - const pa_sink_input_info *info) -{ - GvcMixerStream *stream; - gboolean is_new; - pa_volume_t max_volume; - const char *name; - -#if 0 - g_debug ("Updating sink input: index=%u name='%s' client=%u sink=%u", - info->index, - info->name, - info->client, - info->sink); -#endif - - is_new = FALSE; - - stream = g_hash_table_lookup (control->priv->sink_inputs, - GUINT_TO_POINTER (info->index)); - if (stream == NULL) { - GvcChannelMap *map; - map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); - stream = gvc_mixer_sink_input_new (control->priv->pa_context, - info->index, - map); - g_object_unref (map); - is_new = TRUE; - } else if (gvc_mixer_stream_is_running (stream)) { - /* Ignore events if volume changes are outstanding */ - g_debug ("Ignoring event, volume changes are outstanding"); - return; - } - - max_volume = pa_cvolume_max (&info->volume); - - name = (const char *)g_hash_table_lookup (control->priv->clients, - GUINT_TO_POINTER (info->client)); - gvc_mixer_stream_set_name (stream, name); - gvc_mixer_stream_set_description (stream, info->name); - - set_application_id_from_proplist (stream, info->proplist); - set_is_event_stream_from_proplist (stream, info->proplist); - set_icon_name_from_proplist (stream, info->proplist, "applications-multimedia"); - gvc_mixer_stream_set_volume (stream, (guint)max_volume); - gvc_mixer_stream_set_is_muted (stream, info->mute); - gvc_mixer_stream_set_is_virtual (stream, info->client == PA_INVALID_INDEX); - - if (is_new) { - g_hash_table_insert (control->priv->sink_inputs, - GUINT_TO_POINTER (info->index), - g_object_ref (stream)); - add_stream (control, stream); - } -} - -static void -update_source_output (GvcMixerControl *control, - const pa_source_output_info *info) -{ - GvcMixerStream *stream; - gboolean is_new; - const char *name; - -#if 1 - g_debug ("Updating source output: index=%u name='%s' client=%u source=%u", - info->index, - info->name, - info->client, - info->source); -#endif - - is_new = FALSE; - stream = g_hash_table_lookup (control->priv->source_outputs, - GUINT_TO_POINTER (info->index)); - if (stream == NULL) { - GvcChannelMap *map; - map = gvc_channel_map_new_from_pa_channel_map (&info->channel_map); - stream = gvc_mixer_source_output_new (control->priv->pa_context, - info->index, - map); - g_object_unref (map); - is_new = TRUE; - } - - name = (const char *)g_hash_table_lookup (control->priv->clients, - GUINT_TO_POINTER (info->client)); - - gvc_mixer_stream_set_name (stream, name); - gvc_mixer_stream_set_description (stream, info->name); - set_application_id_from_proplist (stream, info->proplist); - set_is_event_stream_from_proplist (stream, info->proplist); - set_icon_name_from_proplist (stream, info->proplist, "audio-input-microphone"); - - if (is_new) { - g_hash_table_insert (control->priv->source_outputs, - GUINT_TO_POINTER (info->index), - g_object_ref (stream)); - add_stream (control, stream); - } -} - -static void -update_client (GvcMixerControl *control, - const pa_client_info *info) -{ -#if 1 - g_debug ("Updating client: index=%u name='%s'", - info->index, - info->name); -#endif - g_hash_table_insert (control->priv->clients, - GUINT_TO_POINTER (info->index), - g_strdup (info->name)); -} - -static char * -card_num_streams_to_status (guint sinks, - guint sources) -{ - char *sinks_str; - char *sources_str; - char *ret; - - if (sinks == 0 && sources == 0) { - /* translators: - * The device has been disabled */ - return g_strdup (_("Disabled")); - } - if (sinks == 0) { - sinks_str = NULL; - } else { - /* translators: - * The number of sound outputs on a particular device */ - sinks_str = g_strdup_printf (ngettext ("%u Output", - "%u Outputs", - sinks), - sinks); - } - if (sources == 0) { - sources_str = NULL; - } else { - /* translators: - * The number of sound inputs on a particular device */ - sources_str = g_strdup_printf (ngettext ("%u Input", - "%u Inputs", - sources), - sources); - } - if (sources_str == NULL) - return sinks_str; - if (sinks_str == NULL) - return sources_str; - ret = g_strdup_printf ("%s / %s", sinks_str, sources_str); - g_free (sinks_str); - g_free (sources_str); - return ret; -} - -/** - * A utility method to gather which card profiles are relevant to the port . - */ -static GList * -determine_profiles_for_port (pa_card_port_info *port, - GList* card_profiles) -{ - gint i; - GList *supported_profiles = NULL; - GList *p; - for (i = 0; i < port->n_profiles; i++) { - for (p = card_profiles; p != NULL; p = p->next) { - GvcMixerCardProfile *prof; - prof = p->data; - if (g_strcmp0 (port->profiles[i]->name, prof->profile) == 0) - supported_profiles = g_list_append (supported_profiles, prof); - } - } - g_debug ("%i profiles supported on port %s", - g_list_length (supported_profiles), - port->description); - return g_list_sort (supported_profiles, (GCompareFunc) gvc_mixer_card_profile_compare); -} - -static gboolean -is_card_port_an_output (GvcMixerCardPort* port) -{ - return port->direction == PA_DIRECTION_OUTPUT ? TRUE : FALSE; -} - -/* - * This method will create a ui device for the given port. - */ -static void -create_ui_device_from_port (GvcMixerControl* control, - GvcMixerCardPort* port, - GvcMixerCard* card) -{ - GvcMixerUIDeviceDirection direction; - GObject *object; - GvcMixerUIDevice *uidevice; - gboolean available = port->available != PA_PORT_AVAILABLE_NO; - - direction = (is_card_port_an_output (port) == TRUE) ? UIDeviceOutput : UIDeviceInput; - - object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, - "type", (uint)direction, - "card", card, - "port-name", port->port, - "description", port->human_port, - "origin", gvc_mixer_card_get_name (card), - "port-available", available, - NULL); - - uidevice = GVC_MIXER_UI_DEVICE (object); - gvc_mixer_ui_device_set_profiles (uidevice, port->profiles); - - g_hash_table_insert (is_card_port_an_output (port) ? control->priv->ui_outputs : control->priv->ui_inputs, - GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (uidevice)), - g_object_ref (uidevice)); - - - if (available) { - g_signal_emit (G_OBJECT (control), - signals[is_card_port_an_output (port) ? OUTPUT_ADDED : INPUT_ADDED], - 0, - gvc_mixer_ui_device_get_id (uidevice)); - } - - g_debug ("create_ui_device_from_port, direction %u, description '%s', origin '%s', port available %i", - direction, - port->human_port, - gvc_mixer_card_get_name (card), - available); -} - -/* - * This method will match up GvcMixerCardPorts with existing devices. - * A match is achieved if the device's card-id and the port's card-id are the same - * && the device's port-name and the card-port's port member are the same. - * A signal is then sent adding or removing that device from the UI depending on the availability of the port. - */ -static void -match_card_port_with_existing_device (GvcMixerControl *control, - GvcMixerCardPort *card_port, - GvcMixerCard *card, - gboolean available) -{ - GList *d; - GList *devices; - GvcMixerUIDevice *device; - gboolean is_output = is_card_port_an_output (card_port); - - devices = g_hash_table_get_values (is_output ? control->priv->ui_outputs : control->priv->ui_inputs); - - for (d = devices; d != NULL; d = d->next) { - GvcMixerCard *device_card; - gchar *device_port_name; - - device = d->data; - g_object_get (G_OBJECT (device), - "card", &device_card, - "port-name", &device_port_name, - NULL); - - if (g_strcmp0 (card_port->port, device_port_name) == 0 && - device_card == card) { - g_debug ("Found the relevant device %s, update its port availability flag to %i, is_output %i", - device_port_name, - available, - is_output); - g_object_set (G_OBJECT (device), - "port-available", available, NULL); - g_signal_emit (G_OBJECT (control), - is_output ? signals[available ? OUTPUT_ADDED : OUTPUT_REMOVED] : signals[available ? INPUT_ADDED : INPUT_REMOVED], - 0, - gvc_mixer_ui_device_get_id (device)); - } - g_free (device_port_name); - } - - g_list_free (devices); -} - -static void -create_ui_device_from_card (GvcMixerControl *control, - GvcMixerCard *card) -{ - GObject *object; - GvcMixerUIDevice *in; - GvcMixerUIDevice *out; - const GList *profiles; - - /* For now just create two devices and presume this device is multi directional - * Ensure to remove both on card removal (available to false by default) */ - profiles = gvc_mixer_card_get_profiles (card); - - g_debug ("Portless card just registered - %i", gvc_mixer_card_get_index (card)); - - object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, - "type", UIDeviceInput, - "description", gvc_mixer_card_get_name (card), - "origin", "", /* Leave it empty for these special cases */ - "port-name", NULL, - "port-available", FALSE, - "card", card, - NULL); - in = GVC_MIXER_UI_DEVICE (object); - gvc_mixer_ui_device_set_profiles (in, profiles); - - g_hash_table_insert (control->priv->ui_inputs, - GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (in)), - g_object_ref (in)); - object = g_object_new (GVC_TYPE_MIXER_UI_DEVICE, - "type", UIDeviceOutput, - "description", gvc_mixer_card_get_name (card), - "origin", "", /* Leave it empty for these special cases */ - "port-name", NULL, - "port-available", FALSE, - "card", card, - NULL); - out = GVC_MIXER_UI_DEVICE (object); - gvc_mixer_ui_device_set_profiles (out, profiles); - - g_hash_table_insert (control->priv->ui_outputs, - GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (out)), - g_object_ref (out)); -} - -/* - * At this point we can determine all devices available to us (besides network 'ports') - * This is done by the following: - * - * - gvc_mixer_card and gvc_mixer_card_ports are created and relevant setters are called. - * - First it checks to see if it's a portless card. Bluetooth devices are portless AFAIHS. - * If so it creates two devices, an input and an output. - * - If it's a 'normal' card with ports it will create a new ui-device or - * synchronise port availability with the existing device cached for that port on this card. */ - -static void -update_card (GvcMixerControl *control, - const pa_card_info *info) -{ - const GList *card_ports = NULL; - const GList *m = NULL; - GvcMixerCard *card; - gboolean is_new = FALSE; -#if 1 - guint i; - const char *key; - void *state; - - g_debug ("Udpating card %s (index: %u driver: %s):", - info->name, info->index, info->driver); - - for (i = 0; i < info->n_profiles; i++) { - struct pa_card_profile_info pi = info->profiles[i]; - gboolean is_default; - - is_default = (g_strcmp0 (pi.name, info->active_profile->name) == 0); - g_debug ("\tProfile '%s': %d sources %d sinks%s", - pi.name, pi.n_sources, pi.n_sinks, - is_default ? " (Current)" : ""); - } - state = NULL; - key = pa_proplist_iterate (info->proplist, &state); - while (key != NULL) { - g_debug ("\tProperty: '%s' = '%s'", - key, pa_proplist_gets (info->proplist, key)); - key = pa_proplist_iterate (info->proplist, &state); - } -#endif - card = g_hash_table_lookup (control->priv->cards, - GUINT_TO_POINTER (info->index)); - if (card == NULL) { - GList *profile_list = NULL; - GList *port_list = NULL; - - for (i = 0; i < info->n_profiles; i++) { - GvcMixerCardProfile *profile; - struct pa_card_profile_info pi = info->profiles[i]; - - profile = g_new0 (GvcMixerCardProfile, 1); - profile->profile = g_strdup (pi.name); - profile->human_profile = g_strdup (pi.description); - profile->status = card_num_streams_to_status (pi.n_sinks, pi.n_sources); - profile->n_sinks = pi.n_sinks; - profile->n_sources = pi.n_sources; - profile->priority = pi.priority; - profile_list = g_list_prepend (profile_list, profile); - } - card = gvc_mixer_card_new (control->priv->pa_context, - info->index); - gvc_mixer_card_set_profiles (card, profile_list); - - for (i = 0; i < info->n_ports; i++) { - GvcMixerCardPort *port; - port = g_new0 (GvcMixerCardPort, 1); - port->port = g_strdup (info->ports[i]->name); - port->human_port = g_strdup (info->ports[i]->description); - port->priority = info->ports[i]->priority; - port->available = info->ports[i]->available; - port->direction = info->ports[i]->direction; - port->profiles = determine_profiles_for_port (info->ports[i], profile_list); - port_list = g_list_prepend (port_list, port); - } - gvc_mixer_card_set_ports (card, port_list); - is_new = TRUE; - } - - gvc_mixer_card_set_name (card, pa_proplist_gets (info->proplist, "device.description")); - gvc_mixer_card_set_icon_name (card, pa_proplist_gets (info->proplist, "device.icon_name")); - gvc_mixer_card_set_profile (card, info->active_profile->name); - - if (is_new) { - g_hash_table_insert (control->priv->cards, - GUINT_TO_POINTER (info->index), - g_object_ref (card)); - } - - card_ports = gvc_mixer_card_get_ports (card); - - if (card_ports == NULL && is_new) { - g_debug ("Portless card just registered - %s", gvc_mixer_card_get_name (card)); - create_ui_device_from_card (control, card); - } - - for (m = card_ports; m != NULL; m = m->next) { - GvcMixerCardPort *card_port; - card_port = m->data; - if (is_new) - create_ui_device_from_port (control, card_port, card); - else { - for (i = 0; i < info->n_ports; i++) { - if (g_strcmp0 (card_port->port, info->ports[i]->name) == 0) { - if (card_port->available != info->ports[i]->available) { - card_port->available = info->ports[i]->available; - g_debug ("sync port availability on card %i, card port name '%s', new available value %i", - gvc_mixer_card_get_index (card), - card_port->port, - card_port->available); - match_card_port_with_existing_device (control, - card_port, - card, - card_port->available != PA_PORT_AVAILABLE_NO); - } - } - } - } - } - g_signal_emit (G_OBJECT (control), - signals[CARD_ADDED], - 0, - info->index); -} - -static void -_pa_context_get_sink_info_cb (pa_context *context, - const pa_sink_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) { - return; - } - - g_warning ("Sink callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_sink (control, i); -} - -static void -_pa_context_get_source_info_cb (pa_context *context, - const pa_source_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) { - return; - } - - g_warning ("Source callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_source (control, i); -} - -static void -_pa_context_get_sink_input_info_cb (pa_context *context, - const pa_sink_input_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) { - return; - } - - g_warning ("Sink input callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_sink_input (control, i); -} - -static void -_pa_context_get_source_output_info_cb (pa_context *context, - const pa_source_output_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) { - return; - } - - g_warning ("Source output callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_source_output (control, i); -} - -static void -_pa_context_get_client_info_cb (pa_context *context, - const pa_client_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) { - return; - } - - g_warning ("Client callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_client (control, i); -} - -static void -_pa_context_get_card_info_by_index_cb (pa_context *context, - const pa_card_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - if (pa_context_errno (context) == PA_ERR_NOENTITY) - return; - - g_warning ("Card callback failure"); - return; - } - - if (eol > 0) { - dec_outstanding (control); - return; - } - - update_card (control, i); -} - -static void -_pa_context_get_server_info_cb (pa_context *context, - const pa_server_info *i, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (i == NULL) { - g_warning ("Server info callback failure"); - return; - } - g_debug ("get server info"); - update_server (control, i); - dec_outstanding (control); -} - -static void -remove_event_role_stream (GvcMixerControl *control) -{ - g_debug ("Removing event role"); -} - -static void -update_event_role_stream (GvcMixerControl *control, - const pa_ext_stream_restore_info *info) -{ - GvcMixerStream *stream; - gboolean is_new; - pa_volume_t max_volume; - - if (strcmp (info->name, "sink-input-by-media-role:event") != 0) { - return; - } - -#if 0 - g_debug ("Updating event role: name='%s' device='%s'", - info->name, - info->device); -#endif - - is_new = FALSE; - - if (!control->priv->event_sink_input_is_set) { - pa_channel_map pa_map; - GvcChannelMap *map; - - pa_map.channels = 1; - pa_map.map[0] = PA_CHANNEL_POSITION_MONO; - map = gvc_channel_map_new_from_pa_channel_map (&pa_map); - - stream = gvc_mixer_event_role_new (control->priv->pa_context, - info->device, - map); - control->priv->event_sink_input_id = gvc_mixer_stream_get_id (stream); - control->priv->event_sink_input_is_set = TRUE; - - is_new = TRUE; - } else { - stream = g_hash_table_lookup (control->priv->all_streams, - GUINT_TO_POINTER (control->priv->event_sink_input_id)); - } - - max_volume = pa_cvolume_max (&info->volume); - - gvc_mixer_stream_set_name (stream, _("System Sounds")); - gvc_mixer_stream_set_icon_name (stream, "multimedia-volume-control"); - gvc_mixer_stream_set_volume (stream, (guint)max_volume); - gvc_mixer_stream_set_is_muted (stream, info->mute); - - if (is_new) { - add_stream (control, stream); - } -} - -static void -_pa_ext_stream_restore_read_cb (pa_context *context, - const pa_ext_stream_restore_info *i, - int eol, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - if (eol < 0) { - g_debug ("Failed to initialized stream_restore extension: %s", - pa_strerror (pa_context_errno (context))); - remove_event_role_stream (control); - return; - } - - if (eol > 0) { - dec_outstanding (control); - /* If we don't have an event stream to restore, then - * set one up with a default 100% volume */ - if (!control->priv->event_sink_input_is_set) { - pa_ext_stream_restore_info info; - - memset (&info, 0, sizeof(info)); - info.name = "sink-input-by-media-role:event"; - info.volume.channels = 1; - info.volume.values[0] = PA_VOLUME_NORM; - update_event_role_stream (control, &info); - } - return; - } - - update_event_role_stream (control, i); -} - -static void -_pa_ext_stream_restore_subscribe_cb (pa_context *context, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - pa_operation *o; - - o = pa_ext_stream_restore_read (context, - _pa_ext_stream_restore_read_cb, - control); - if (o == NULL) { - g_warning ("pa_ext_stream_restore_read() failed"); - return; - } - - pa_operation_unref (o); -} - -static void -req_update_server_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - o = pa_context_get_server_info (control->priv->pa_context, - _pa_context_get_server_info_cb, - control); - if (o == NULL) { - g_warning ("pa_context_get_server_info() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_client_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_client_info_list (control->priv->pa_context, - _pa_context_get_client_info_cb, - control); - } else { - o = pa_context_get_client_info (control->priv->pa_context, - index, - _pa_context_get_client_info_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_client_info_list() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_card (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_card_info_list (control->priv->pa_context, - _pa_context_get_card_info_by_index_cb, - control); - } else { - o = pa_context_get_card_info_by_index (control->priv->pa_context, - index, - _pa_context_get_card_info_by_index_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_get_card_info_by_index() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_sink_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_sink_info_list (control->priv->pa_context, - _pa_context_get_sink_info_cb, - control); - } else { - o = pa_context_get_sink_info_by_index (control->priv->pa_context, - index, - _pa_context_get_sink_info_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_get_sink_info_list() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_source_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_source_info_list (control->priv->pa_context, - _pa_context_get_source_info_cb, - control); - } else { - o = pa_context_get_source_info_by_index(control->priv->pa_context, - index, - _pa_context_get_source_info_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_get_source_info_list() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_sink_input_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_sink_input_info_list (control->priv->pa_context, - _pa_context_get_sink_input_info_cb, - control); - } else { - o = pa_context_get_sink_input_info (control->priv->pa_context, - index, - _pa_context_get_sink_input_info_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_get_sink_input_info_list() failed"); - return; - } - pa_operation_unref (o); -} - -static void -req_update_source_output_info (GvcMixerControl *control, - int index) -{ - pa_operation *o; - - if (index < 0) { - o = pa_context_get_source_output_info_list (control->priv->pa_context, - _pa_context_get_source_output_info_cb, - control); - } else { - o = pa_context_get_source_output_info (control->priv->pa_context, - index, - _pa_context_get_source_output_info_cb, - control); - } - - if (o == NULL) { - g_warning ("pa_context_get_source_output_info_list() failed"); - return; - } - pa_operation_unref (o); -} - -static void -remove_client (GvcMixerControl *control, - guint index) -{ - g_hash_table_remove (control->priv->clients, - GUINT_TO_POINTER (index)); -} - -static void -remove_card (GvcMixerControl *control, - guint index) -{ - - GList *devices, *d; - - devices = g_list_concat (g_hash_table_get_values (control->priv->ui_inputs), - g_hash_table_get_values (control->priv->ui_outputs)); - - for (d = devices; d != NULL; d = d->next) { - GvcMixerCard *card; - GvcMixerUIDevice *device = d->data; - - g_object_get (G_OBJECT (device), "card", &card, NULL); - - if (gvc_mixer_card_get_index (card) == index) { - g_signal_emit (G_OBJECT (control), - signals[gvc_mixer_ui_device_is_output (device) ? OUTPUT_REMOVED : INPUT_REMOVED], - 0, - gvc_mixer_ui_device_get_id (device)); - g_debug ("Card removal remove device %s", - gvc_mixer_ui_device_get_description (device)); - g_hash_table_remove (gvc_mixer_ui_device_is_output (device) ? control->priv->ui_outputs : control->priv->ui_inputs, - GUINT_TO_POINTER (gvc_mixer_ui_device_get_id (device))); - } - } - - g_list_free (devices); - - g_hash_table_remove (control->priv->cards, - GUINT_TO_POINTER (index)); - - g_signal_emit (G_OBJECT (control), - signals[CARD_REMOVED], - 0, - index); -} - -static void -remove_sink (GvcMixerControl *control, - guint index) -{ - GvcMixerStream *stream; - GvcMixerUIDevice *device; - - g_debug ("Removing sink: index=%u", index); - - stream = g_hash_table_lookup (control->priv->sinks, - GUINT_TO_POINTER (index)); - if (stream == NULL) - return; - - device = gvc_mixer_control_lookup_device_from_stream (control, stream); - - if (device != NULL) { - gvc_mixer_ui_device_invalidate_stream (device); - if (!gvc_mixer_ui_device_has_ports (device)) { - g_signal_emit (G_OBJECT (control), - signals[OUTPUT_REMOVED], - 0, - gvc_mixer_ui_device_get_id (device)); - } else { - GList *devices, *d; - - devices = g_hash_table_get_values (control->priv->ui_outputs); - - for (d = devices; d != NULL; d = d->next) { - gint stream_id = GVC_MIXER_UI_DEVICE_INVALID; - device = d->data; - g_object_get (G_OBJECT (device), - "stream-id", &stream_id, - NULL); - if (stream_id == gvc_mixer_stream_get_id (stream)) - gvc_mixer_ui_device_invalidate_stream (device); - } - - g_list_free (devices); - } - } - - g_hash_table_remove (control->priv->sinks, - GUINT_TO_POINTER (index)); - - remove_stream (control, stream); -} - -static void -remove_source (GvcMixerControl *control, - guint index) -{ - GvcMixerStream *stream; - GvcMixerUIDevice *device; - - g_debug ("Removing source: index=%u", index); - - stream = g_hash_table_lookup (control->priv->sources, - GUINT_TO_POINTER (index)); - if (stream == NULL) - return; - - device = gvc_mixer_control_lookup_device_from_stream (control, stream); - - if (device != NULL) { - gvc_mixer_ui_device_invalidate_stream (device); - if (!gvc_mixer_ui_device_has_ports (device)) { - g_signal_emit (G_OBJECT (control), - signals[INPUT_REMOVED], - 0, - gvc_mixer_ui_device_get_id (device)); - } else { - GList *devices, *d; - - devices = g_hash_table_get_values (control->priv->ui_inputs); - - for (d = devices; d != NULL; d = d->next) { - gint stream_id = GVC_MIXER_UI_DEVICE_INVALID; - device = d->data; - g_object_get (G_OBJECT (device), - "stream-id", &stream_id, - NULL); - if (stream_id == gvc_mixer_stream_get_id (stream)) - gvc_mixer_ui_device_invalidate_stream (device); - } - - g_list_free (devices); - } - } - - g_hash_table_remove (control->priv->sources, - GUINT_TO_POINTER (index)); - - remove_stream (control, stream); -} - -static void -remove_sink_input (GvcMixerControl *control, - guint index) -{ - GvcMixerStream *stream; - - g_debug ("Removing sink input: index=%u", index); - - stream = g_hash_table_lookup (control->priv->sink_inputs, - GUINT_TO_POINTER (index)); - if (stream == NULL) { - return; - } - g_hash_table_remove (control->priv->sink_inputs, - GUINT_TO_POINTER (index)); - - remove_stream (control, stream); -} - -static void -remove_source_output (GvcMixerControl *control, - guint index) -{ - GvcMixerStream *stream; - - g_debug ("Removing source output: index=%u", index); - - stream = g_hash_table_lookup (control->priv->source_outputs, - GUINT_TO_POINTER (index)); - if (stream == NULL) { - return; - } - g_hash_table_remove (control->priv->source_outputs, - GUINT_TO_POINTER (index)); - - remove_stream (control, stream); -} - -static void -_pa_context_subscribe_cb (pa_context *context, - pa_subscription_event_type_t t, - uint32_t index, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { - case PA_SUBSCRIPTION_EVENT_SINK: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_sink (control, index); - } else { - req_update_sink_info (control, index); - } - break; - - case PA_SUBSCRIPTION_EVENT_SOURCE: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_source (control, index); - } else { - req_update_source_info (control, index); - } - break; - - case PA_SUBSCRIPTION_EVENT_SINK_INPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_sink_input (control, index); - } else { - req_update_sink_input_info (control, index); - } - break; - - case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_source_output (control, index); - } else { - req_update_source_output_info (control, index); - } - break; - - case PA_SUBSCRIPTION_EVENT_CLIENT: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_client (control, index); - } else { - req_update_client_info (control, index); - } - break; - - case PA_SUBSCRIPTION_EVENT_SERVER: - req_update_server_info (control, index); - break; - - case PA_SUBSCRIPTION_EVENT_CARD: - if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { - remove_card (control, index); - } else { - req_update_card (control, index); - } - break; - } -} - -static void -gvc_mixer_control_ready (GvcMixerControl *control) -{ - pa_operation *o; - - pa_context_set_subscribe_callback (control->priv->pa_context, - _pa_context_subscribe_cb, - control); - o = pa_context_subscribe (control->priv->pa_context, - (pa_subscription_mask_t) - (PA_SUBSCRIPTION_MASK_SINK| - PA_SUBSCRIPTION_MASK_SOURCE| - PA_SUBSCRIPTION_MASK_SINK_INPUT| - PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT| - PA_SUBSCRIPTION_MASK_CLIENT| - PA_SUBSCRIPTION_MASK_SERVER| - PA_SUBSCRIPTION_MASK_CARD), - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_subscribe() failed"); - return; - } - pa_operation_unref (o); - - req_update_server_info (control, -1); - req_update_card (control, -1); - req_update_client_info (control, -1); - req_update_sink_info (control, -1); - req_update_source_info (control, -1); - req_update_sink_input_info (control, -1); - req_update_source_output_info (control, -1); - - - control->priv->n_outstanding = 6; - - /* This call is not always supported */ - o = pa_ext_stream_restore_read (control->priv->pa_context, - _pa_ext_stream_restore_read_cb, - control); - if (o != NULL) { - pa_operation_unref (o); - control->priv->n_outstanding++; - - pa_ext_stream_restore_set_subscribe_cb (control->priv->pa_context, - _pa_ext_stream_restore_subscribe_cb, - control); - - o = pa_ext_stream_restore_subscribe (control->priv->pa_context, - 1, - NULL, - NULL); - if (o != NULL) { - pa_operation_unref (o); - } - - } else { - g_debug ("Failed to initialized stream_restore extension: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - } -} - -static void -gvc_mixer_new_pa_context (GvcMixerControl *self) -{ - pa_proplist *proplist; - - g_return_if_fail (self); - g_return_if_fail (!self->priv->pa_context); - - proplist = pa_proplist_new (); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_NAME, - self->priv->name); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_ID, - "org.gnome.VolumeControl"); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_ICON_NAME, - "multimedia-volume-control"); - pa_proplist_sets (proplist, - PA_PROP_APPLICATION_VERSION, - PACKAGE_VERSION); - - self->priv->pa_context = pa_context_new_with_proplist (self->priv->pa_api, NULL, proplist); - - pa_proplist_free (proplist); - g_assert (self->priv->pa_context); -} - -static void -remove_all_streams (GvcMixerControl *control, GHashTable *hash_table) -{ - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, hash_table); - while (g_hash_table_iter_next (&iter, &key, &value)) { - remove_stream (control, value); - g_hash_table_iter_remove (&iter); - } -} - -static gboolean -idle_reconnect (gpointer data) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (data); - GHashTableIter iter; - gpointer key, value; - - g_return_val_if_fail (control, FALSE); - - if (control->priv->pa_context) { - pa_context_unref (control->priv->pa_context); - control->priv->pa_context = NULL; - gvc_mixer_new_pa_context (control); - } - - remove_all_streams (control, control->priv->sinks); - remove_all_streams (control, control->priv->sources); - remove_all_streams (control, control->priv->sink_inputs); - remove_all_streams (control, control->priv->source_outputs); - - g_hash_table_iter_init (&iter, control->priv->clients); - while (g_hash_table_iter_next (&iter, &key, &value)) - g_hash_table_iter_remove (&iter); - - gvc_mixer_control_open (control); /* cannot fail */ - - control->priv->reconnect_id = 0; - return FALSE; -} - -static void -_pa_context_state_cb (pa_context *context, - void *userdata) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (userdata); - - switch (pa_context_get_state (context)) { - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; - - case PA_CONTEXT_READY: - gvc_mixer_control_ready (control); - break; - - case PA_CONTEXT_FAILED: - control->priv->state = GVC_STATE_FAILED; - g_signal_emit (control, signals[STATE_CHANGED], 0, GVC_STATE_FAILED); - if (control->priv->reconnect_id == 0) - control->priv->reconnect_id = g_timeout_add_seconds (RECONNECT_DELAY, idle_reconnect, control); - break; - - case PA_CONTEXT_TERMINATED: - default: - /* FIXME: */ - break; - } -} - -gboolean -gvc_mixer_control_open (GvcMixerControl *control) -{ - int res; - - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); - g_return_val_if_fail (control->priv->pa_context != NULL, FALSE); - g_return_val_if_fail (pa_context_get_state (control->priv->pa_context) == PA_CONTEXT_UNCONNECTED, FALSE); - - pa_context_set_state_callback (control->priv->pa_context, - _pa_context_state_cb, - control); - - control->priv->state = GVC_STATE_CONNECTING; - g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_CONNECTING); - res = pa_context_connect (control->priv->pa_context, NULL, (pa_context_flags_t) PA_CONTEXT_NOFAIL, NULL); - if (res < 0) { - g_warning ("Failed to connect context: %s", - pa_strerror (pa_context_errno (control->priv->pa_context))); - } - - return res; -} - -gboolean -gvc_mixer_control_close (GvcMixerControl *control) -{ - g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); - g_return_val_if_fail (control->priv->pa_context != NULL, FALSE); - - pa_context_disconnect (control->priv->pa_context); - - control->priv->state = GVC_STATE_CLOSED; - g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_CLOSED); - return TRUE; -} - -static void -gvc_mixer_control_dispose (GObject *object) -{ - GvcMixerControl *control = GVC_MIXER_CONTROL (object); - - if (control->priv->reconnect_id != 0) { - g_source_remove (control->priv->reconnect_id); - control->priv->reconnect_id = 0; - } - - if (control->priv->pa_context != NULL) { - pa_context_unref (control->priv->pa_context); - control->priv->pa_context = NULL; - } - - if (control->priv->default_source_name != NULL) { - g_free (control->priv->default_source_name); - control->priv->default_source_name = NULL; - } - if (control->priv->default_sink_name != NULL) { - g_free (control->priv->default_sink_name); - control->priv->default_sink_name = NULL; - } - - if (control->priv->pa_mainloop != NULL) { - pa_glib_mainloop_free (control->priv->pa_mainloop); - control->priv->pa_mainloop = NULL; - } - - if (control->priv->all_streams != NULL) { - g_hash_table_destroy (control->priv->all_streams); - control->priv->all_streams = NULL; - } - - if (control->priv->sinks != NULL) { - g_hash_table_destroy (control->priv->sinks); - control->priv->sinks = NULL; - } - if (control->priv->sources != NULL) { - g_hash_table_destroy (control->priv->sources); - control->priv->sources = NULL; - } - if (control->priv->sink_inputs != NULL) { - g_hash_table_destroy (control->priv->sink_inputs); - control->priv->sink_inputs = NULL; - } - if (control->priv->source_outputs != NULL) { - g_hash_table_destroy (control->priv->source_outputs); - control->priv->source_outputs = NULL; - } - if (control->priv->clients != NULL) { - g_hash_table_destroy (control->priv->clients); - control->priv->clients = NULL; - } - if (control->priv->cards != NULL) { - g_hash_table_destroy (control->priv->cards); - control->priv->cards = NULL; - } - if (control->priv->ui_outputs != NULL) { - g_hash_table_destroy (control->priv->ui_outputs); - control->priv->ui_outputs = NULL; - } - if (control->priv->ui_inputs != NULL) { - g_hash_table_destroy (control->priv->ui_inputs); - control->priv->ui_inputs = NULL; - } - - G_OBJECT_CLASS (gvc_mixer_control_parent_class)->dispose (object); -} - -static void -gvc_mixer_control_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerControl *self = GVC_MIXER_CONTROL (object); - - switch (prop_id) { - case PROP_NAME: - g_free (self->priv->name); - self->priv->name = g_value_dup_string (value); - g_object_notify (G_OBJECT (self), "name"); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_control_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerControl *self = GVC_MIXER_CONTROL (object); - - switch (prop_id) { - case PROP_NAME: - g_value_set_string (value, self->priv->name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static GObject * -gvc_mixer_control_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GvcMixerControl *self; - - object = G_OBJECT_CLASS (gvc_mixer_control_parent_class)->constructor (type, n_construct_properties, construct_params); - - self = GVC_MIXER_CONTROL (object); - - gvc_mixer_new_pa_context (self); - self->priv->profile_swapping_device_id = GVC_MIXER_UI_DEVICE_INVALID; - - return object; -} - -static void -gvc_mixer_control_class_init (GvcMixerControlClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructor = gvc_mixer_control_constructor; - object_class->dispose = gvc_mixer_control_dispose; - object_class->finalize = gvc_mixer_control_finalize; - object_class->set_property = gvc_mixer_control_set_property; - object_class->get_property = gvc_mixer_control_get_property; - - g_object_class_install_property (object_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "Name to display for this mixer control", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - - signals [STATE_CHANGED] = - g_signal_new ("state-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, state_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [STREAM_ADDED] = - g_signal_new ("stream-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, stream_added), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [STREAM_REMOVED] = - g_signal_new ("stream-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, stream_removed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [CARD_ADDED] = - g_signal_new ("card-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, card_added), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [CARD_REMOVED] = - g_signal_new ("card-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, card_removed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [DEFAULT_SINK_CHANGED] = - g_signal_new ("default-sink-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, default_sink_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [DEFAULT_SOURCE_CHANGED] = - g_signal_new ("default-source-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, default_source_changed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [ACTIVE_OUTPUT_UPDATE] = - g_signal_new ("active-output-update", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, active_output_update), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [ACTIVE_INPUT_UPDATE] = - g_signal_new ("active-input-update", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, active_input_update), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [OUTPUT_ADDED] = - g_signal_new ("output-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, output_added), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [INPUT_ADDED] = - g_signal_new ("input-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, input_added), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [OUTPUT_REMOVED] = - g_signal_new ("output-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, output_removed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals [INPUT_REMOVED] = - g_signal_new ("input-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GvcMixerControlClass, input_removed), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - g_type_class_add_private (klass, sizeof (GvcMixerControlPrivate)); -} - - -static void -gvc_mixer_control_init (GvcMixerControl *control) -{ - control->priv = GVC_MIXER_CONTROL_GET_PRIVATE (control); - - control->priv->pa_mainloop = pa_glib_mainloop_new (g_main_context_default ()); - g_assert (control->priv->pa_mainloop); - - control->priv->pa_api = pa_glib_mainloop_get_api (control->priv->pa_mainloop); - g_assert (control->priv->pa_api); - - control->priv->all_streams = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->sinks = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->sources = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->sink_inputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->source_outputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->cards = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->ui_outputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - control->priv->ui_inputs = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref); - - control->priv->clients = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free); - - control->priv->state = GVC_STATE_CLOSED; -} - -static void -gvc_mixer_control_finalize (GObject *object) -{ - GvcMixerControl *mixer_control; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_CONTROL (object)); - - mixer_control = GVC_MIXER_CONTROL (object); - g_free (mixer_control->priv->name); - mixer_control->priv->name = NULL; - - g_return_if_fail (mixer_control->priv != NULL); - G_OBJECT_CLASS (gvc_mixer_control_parent_class)->finalize (object); -} - -GvcMixerControl * -gvc_mixer_control_new (const char *name) -{ - GObject *control; - control = g_object_new (GVC_TYPE_MIXER_CONTROL, - "name", name, - NULL); - return GVC_MIXER_CONTROL (control); -} - -gdouble -gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control) -{ - return (gdouble) PA_VOLUME_NORM; -} - -gdouble -gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control) -{ - return (gdouble) PA_VOLUME_UI_MAX; -} diff --git a/panels/sound/gvc-mixer-control.h b/panels/sound/gvc-mixer-control.h deleted file mode 100644 index e5e2f74d8..000000000 --- a/panels/sound/gvc-mixer-control.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_CONTROL_H -#define __GVC_MIXER_CONTROL_H - -#include -#include "gvc-mixer-stream.h" -#include "gvc-mixer-card.h" -#include "gvc-mixer-ui-device.h" - -G_BEGIN_DECLS - -typedef enum -{ - GVC_STATE_CLOSED, - GVC_STATE_READY, - GVC_STATE_CONNECTING, - GVC_STATE_FAILED -} GvcMixerControlState; - -#define GVC_TYPE_MIXER_CONTROL (gvc_mixer_control_get_type ()) -#define GVC_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControl)) -#define GVC_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass)) -#define GVC_IS_MIXER_CONTROL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_CONTROL)) -#define GVC_IS_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_CONTROL)) -#define GVC_MIXER_CONTROL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass)) - -typedef struct GvcMixerControlPrivate GvcMixerControlPrivate; - -typedef struct -{ - GObject parent; - GvcMixerControlPrivate *priv; -} GvcMixerControl; - -typedef struct -{ - GObjectClass parent_class; - - void (*state_changed) (GvcMixerControl *control, - GvcMixerControlState new_state); - void (*stream_added) (GvcMixerControl *control, - guint id); - void (*stream_removed) (GvcMixerControl *control, - guint id); - void (*card_added) (GvcMixerControl *control, - guint id); - void (*card_removed) (GvcMixerControl *control, - guint id); - void (*default_sink_changed) (GvcMixerControl *control, - guint id); - void (*default_source_changed) (GvcMixerControl *control, - guint id); - void (*active_output_update) (GvcMixerControl *control, - guint id); - void (*active_input_update) (GvcMixerControl *control, - guint id); - void (*output_added) (GvcMixerControl *control, - guint id); - void (*input_added) (GvcMixerControl *control, - guint id); - void (*output_removed) (GvcMixerControl *control, - guint id); - void (*input_removed) (GvcMixerControl *control, - guint id); -} GvcMixerControlClass; - -GType gvc_mixer_control_get_type (void); - -GvcMixerControl * gvc_mixer_control_new (const char *name); - -gboolean gvc_mixer_control_open (GvcMixerControl *control); -gboolean gvc_mixer_control_close (GvcMixerControl *control); - -GSList * gvc_mixer_control_get_cards (GvcMixerControl *control); -GSList * gvc_mixer_control_get_streams (GvcMixerControl *control); -GSList * gvc_mixer_control_get_sinks (GvcMixerControl *control); -GSList * gvc_mixer_control_get_sources (GvcMixerControl *control); -GSList * gvc_mixer_control_get_sink_inputs (GvcMixerControl *control); -GSList * gvc_mixer_control_get_source_outputs (GvcMixerControl *control); - -GvcMixerStream * gvc_mixer_control_lookup_stream_id (GvcMixerControl *control, - guint id); -GvcMixerCard * gvc_mixer_control_lookup_card_id (GvcMixerControl *control, - guint id); -GvcMixerUIDevice * gvc_mixer_control_lookup_output_id (GvcMixerControl *control, - guint id); -GvcMixerUIDevice * gvc_mixer_control_lookup_input_id (GvcMixerControl *control, - guint id); -GvcMixerUIDevice * gvc_mixer_control_lookup_device_from_stream (GvcMixerControl *control, - GvcMixerStream *stream); - -GvcMixerStream * gvc_mixer_control_get_default_sink (GvcMixerControl *control); -GvcMixerStream * gvc_mixer_control_get_default_source (GvcMixerControl *control); -GvcMixerStream * gvc_mixer_control_get_event_sink_input (GvcMixerControl *control); - -gboolean gvc_mixer_control_set_default_sink (GvcMixerControl *control, - GvcMixerStream *stream); -gboolean gvc_mixer_control_set_default_source (GvcMixerControl *control, - GvcMixerStream *stream); - -gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control); -gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control); -void gvc_mixer_control_change_output (GvcMixerControl *control, - GvcMixerUIDevice* output); -void gvc_mixer_control_change_input (GvcMixerControl *control, - GvcMixerUIDevice* input); -GvcMixerStream* gvc_mixer_control_get_stream_from_device (GvcMixerControl *control, - GvcMixerUIDevice *dev); -gboolean gvc_mixer_control_change_profile_on_selected_device (GvcMixerControl *control, - GvcMixerUIDevice *device, - const gchar* profile); - -GvcMixerControlState gvc_mixer_control_get_state (GvcMixerControl *control); - -G_END_DECLS - -#endif /* __GVC_MIXER_CONTROL_H */ diff --git a/panels/sound/gvc-mixer-event-role.c b/panels/sound/gvc-mixer-event-role.c deleted file mode 100644 index 3646df292..000000000 --- a/panels/sound/gvc-mixer-event-role.c +++ /dev/null @@ -1,235 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include -#include - -#include "gvc-mixer-event-role.h" -#include "gvc-mixer-stream-private.h" -#include "gvc-channel-map-private.h" - -#define GVC_MIXER_EVENT_ROLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRolePrivate)) - -struct GvcMixerEventRolePrivate -{ - char *device; -}; - -enum -{ - PROP_0, - PROP_DEVICE -}; - -static void gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass); -static void gvc_mixer_event_role_init (GvcMixerEventRole *mixer_event_role); -static void gvc_mixer_event_role_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM) - -static gboolean -update_settings (GvcMixerEventRole *role, - gboolean is_muted, - gpointer *op) -{ - pa_operation *o; - const GvcChannelMap *map; - pa_context *context; - pa_ext_stream_restore_info info; - - map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role)); - - info.volume = *gvc_channel_map_get_cvolume(map); - info.name = "sink-input-by-media-role:event"; - info.channel_map = *gvc_channel_map_get_pa_channel_map(map); - info.device = role->priv->device; - info.mute = is_muted; - - context = gvc_mixer_stream_get_pa_context (GVC_MIXER_STREAM (role)); - - o = pa_ext_stream_restore_write (context, - PA_UPDATE_REPLACE, - &info, - 1, - TRUE, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_ext_stream_restore_write() failed"); - return FALSE; - } - - if (op != NULL) - *op = o; - - return TRUE; -} - -static gboolean -gvc_mixer_event_role_push_volume (GvcMixerStream *stream, gpointer *op) -{ - return update_settings (GVC_MIXER_EVENT_ROLE (stream), - gvc_mixer_stream_get_is_muted (stream), op); -} - -static gboolean -gvc_mixer_event_role_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - /* Apply change straight away so that we don't get a race with - * gvc_mixer_event_role_push_volume(). - * See https://bugs.freedesktop.org/show_bug.cgi?id=51413 */ - gvc_mixer_stream_set_is_muted (stream, is_muted); - return update_settings (GVC_MIXER_EVENT_ROLE (stream), - is_muted, NULL); -} - -static gboolean -gvc_mixer_event_role_set_device (GvcMixerEventRole *role, - const char *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_EVENT_ROLE (role), FALSE); - - g_free (role->priv->device); - role->priv->device = g_strdup (device); - g_object_notify (G_OBJECT (role), "device"); - - return TRUE; -} - -static void -gvc_mixer_event_role_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object); - - switch (prop_id) { - case PROP_DEVICE: - gvc_mixer_event_role_set_device (self, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_event_role_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerEventRole *self = GVC_MIXER_EVENT_ROLE (object); - - switch (prop_id) { - case PROP_DEVICE: - g_value_set_string (value, self->priv->device); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); - - object_class->finalize = gvc_mixer_event_role_finalize; - object_class->set_property = gvc_mixer_event_role_set_property; - object_class->get_property = gvc_mixer_event_role_get_property; - - stream_class->push_volume = gvc_mixer_event_role_push_volume; - stream_class->change_is_muted = gvc_mixer_event_role_change_is_muted; - - g_object_class_install_property (object_class, - PROP_DEVICE, - g_param_spec_string ("device", - "Device", - "Device", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - - g_type_class_add_private (klass, sizeof (GvcMixerEventRolePrivate)); -} - -static void -gvc_mixer_event_role_init (GvcMixerEventRole *event_role) -{ - event_role->priv = GVC_MIXER_EVENT_ROLE_GET_PRIVATE (event_role); - -} - -static void -gvc_mixer_event_role_finalize (GObject *object) -{ - GvcMixerEventRole *mixer_event_role; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_EVENT_ROLE (object)); - - mixer_event_role = GVC_MIXER_EVENT_ROLE (object); - - g_return_if_fail (mixer_event_role->priv != NULL); - - g_free (mixer_event_role->priv->device); - - G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->finalize (object); -} - -/** - * gvc_mixer_event_role_new: (skip) - * - * @context: - * @index: - * @channel_map: - * - * Returns: - */ -GvcMixerStream * -gvc_mixer_event_role_new (pa_context *context, - const char *device, - GvcChannelMap *channel_map) -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_EVENT_ROLE, - "pa-context", context, - "index", 0, - "device", device, - "channel-map", channel_map, - NULL); - - return GVC_MIXER_STREAM (object); -} diff --git a/panels/sound/gvc-mixer-event-role.h b/panels/sound/gvc-mixer-event-role.h deleted file mode 100644 index ab4c509e5..000000000 --- a/panels/sound/gvc-mixer-event-role.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_EVENT_ROLE_H -#define __GVC_MIXER_EVENT_ROLE_H - -#include -#include "gvc-mixer-stream.h" - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_EVENT_ROLE (gvc_mixer_event_role_get_type ()) -#define GVC_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRole)) -#define GVC_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass)) -#define GVC_IS_MIXER_EVENT_ROLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_EVENT_ROLE)) -#define GVC_IS_MIXER_EVENT_ROLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_EVENT_ROLE)) -#define GVC_MIXER_EVENT_ROLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_EVENT_ROLE, GvcMixerEventRoleClass)) - -typedef struct GvcMixerEventRolePrivate GvcMixerEventRolePrivate; - -typedef struct -{ - GvcMixerStream parent; - GvcMixerEventRolePrivate *priv; -} GvcMixerEventRole; - -typedef struct -{ - GvcMixerStreamClass parent_class; -} GvcMixerEventRoleClass; - -GType gvc_mixer_event_role_get_type (void); - -GvcMixerStream * gvc_mixer_event_role_new (pa_context *context, - const char *device, - GvcChannelMap *channel_map); - -G_END_DECLS - -#endif /* __GVC_MIXER_EVENT_ROLE_H */ diff --git a/panels/sound/gvc-mixer-sink-input.c b/panels/sound/gvc-mixer-sink-input.c deleted file mode 100644 index 03ba3b2f2..000000000 --- a/panels/sound/gvc-mixer-sink-input.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-sink-input.h" -#include "gvc-mixer-stream-private.h" -#include "gvc-channel-map-private.h" - -#define GVC_MIXER_SINK_INPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputPrivate)) - -struct GvcMixerSinkInputPrivate -{ - gpointer dummy; -}; - -static void gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass); -static void gvc_mixer_sink_input_init (GvcMixerSinkInput *mixer_sink_input); -static void gvc_mixer_sink_input_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM) - -static gboolean -gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op) -{ - pa_operation *o; - guint index; - const GvcChannelMap *map; - pa_context *context; - const pa_cvolume *cv; - - index = gvc_mixer_stream_get_index (stream); - - map = gvc_mixer_stream_get_channel_map (stream); - - cv = gvc_channel_map_get_cvolume(map); - - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_sink_input_volume (context, - index, - cv, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_sink_input_volume() failed"); - return FALSE; - } - - *op = o; - - return TRUE; -} - -static gboolean -gvc_mixer_sink_input_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - pa_operation *o; - guint index; - pa_context *context; - - index = gvc_mixer_stream_get_index (stream); - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_sink_input_mute (context, - index, - is_muted, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_sink_input_mute_by_index() failed"); - return FALSE; - } - - pa_operation_unref(o); - - return TRUE; -} - -static void -gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); - - object_class->finalize = gvc_mixer_sink_input_finalize; - - stream_class->push_volume = gvc_mixer_sink_input_push_volume; - stream_class->change_is_muted = gvc_mixer_sink_input_change_is_muted; - - g_type_class_add_private (klass, sizeof (GvcMixerSinkInputPrivate)); -} - -static void -gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input) -{ - sink_input->priv = GVC_MIXER_SINK_INPUT_GET_PRIVATE (sink_input); -} - -static void -gvc_mixer_sink_input_finalize (GObject *object) -{ - GvcMixerSinkInput *mixer_sink_input; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object)); - - mixer_sink_input = GVC_MIXER_SINK_INPUT (object); - - g_return_if_fail (mixer_sink_input->priv != NULL); - G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->finalize (object); -} - -/** - * gvc_mixer_sink_input_new: (skip) - * - * @context: - * @index: - * @channel_map: - * - * Returns: - */ -GvcMixerStream * -gvc_mixer_sink_input_new (pa_context *context, - guint index, - GvcChannelMap *channel_map) -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_SINK_INPUT, - "pa-context", context, - "index", index, - "channel-map", channel_map, - NULL); - - return GVC_MIXER_STREAM (object); -} diff --git a/panels/sound/gvc-mixer-sink-input.h b/panels/sound/gvc-mixer-sink-input.h deleted file mode 100644 index 8a4b71454..000000000 --- a/panels/sound/gvc-mixer-sink-input.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_SINK_INPUT_H -#define __GVC_MIXER_SINK_INPUT_H - -#include -#include "gvc-mixer-stream.h" - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_SINK_INPUT (gvc_mixer_sink_input_get_type ()) -#define GVC_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInput)) -#define GVC_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass)) -#define GVC_IS_MIXER_SINK_INPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK_INPUT)) -#define GVC_IS_MIXER_SINK_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK_INPUT)) -#define GVC_MIXER_SINK_INPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK_INPUT, GvcMixerSinkInputClass)) - -typedef struct GvcMixerSinkInputPrivate GvcMixerSinkInputPrivate; - -typedef struct -{ - GvcMixerStream parent; - GvcMixerSinkInputPrivate *priv; -} GvcMixerSinkInput; - -typedef struct -{ - GvcMixerStreamClass parent_class; -} GvcMixerSinkInputClass; - -GType gvc_mixer_sink_input_get_type (void); - -GvcMixerStream * gvc_mixer_sink_input_new (pa_context *context, - guint index, - GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_MIXER_SINK_INPUT_H */ diff --git a/panels/sound/gvc-mixer-sink.c b/panels/sound/gvc-mixer-sink.c deleted file mode 100644 index 78c3c680b..000000000 --- a/panels/sound/gvc-mixer-sink.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-sink.h" -#include "gvc-mixer-stream-private.h" -#include "gvc-channel-map-private.h" - -#define GVC_MIXER_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkPrivate)) - -struct GvcMixerSinkPrivate -{ - gpointer dummy; -}; - -static void gvc_mixer_sink_class_init (GvcMixerSinkClass *klass); -static void gvc_mixer_sink_init (GvcMixerSink *mixer_sink); -static void gvc_mixer_sink_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM) - -static gboolean -gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op) -{ - pa_operation *o; - guint index; - const GvcChannelMap *map; - pa_context *context; - const pa_cvolume *cv; - - index = gvc_mixer_stream_get_index (stream); - - map = gvc_mixer_stream_get_channel_map (stream); - - /* set the volume */ - cv = gvc_channel_map_get_cvolume(map); - - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_sink_volume_by_index (context, - index, - cv, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - *op = o; - - return TRUE; -} - -static gboolean -gvc_mixer_sink_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - pa_operation *o; - guint index; - pa_context *context; - - index = gvc_mixer_stream_get_index (stream); - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_sink_mute_by_index (context, - index, - is_muted, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - pa_operation_unref(o); - - return TRUE; -} - -static gboolean -gvc_mixer_sink_change_port (GvcMixerStream *stream, - const char *port) -{ - pa_operation *o; - guint index; - pa_context *context; - - index = gvc_mixer_stream_get_index (stream); - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_sink_port_by_index (context, - index, - port, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_sink_port_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - pa_operation_unref(o); - - return TRUE; -} - -static void -gvc_mixer_sink_class_init (GvcMixerSinkClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); - - object_class->finalize = gvc_mixer_sink_finalize; - - stream_class->push_volume = gvc_mixer_sink_push_volume; - stream_class->change_port = gvc_mixer_sink_change_port; - stream_class->change_is_muted = gvc_mixer_sink_change_is_muted; - - g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate)); -} - -static void -gvc_mixer_sink_init (GvcMixerSink *sink) -{ - sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink); -} - -static void -gvc_mixer_sink_finalize (GObject *object) -{ - GvcMixerSink *mixer_sink; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_SINK (object)); - - mixer_sink = GVC_MIXER_SINK (object); - - g_return_if_fail (mixer_sink->priv != NULL); - G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->finalize (object); -} - -/** - * gvc_mixer_sink_new: (skip) - * - * @context: - * @index: - * @channel_map: - * - * Returns: - */ -GvcMixerStream * -gvc_mixer_sink_new (pa_context *context, - guint index, - GvcChannelMap *channel_map) - -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_SINK, - "pa-context", context, - "index", index, - "channel-map", channel_map, - NULL); - - return GVC_MIXER_STREAM (object); -} diff --git a/panels/sound/gvc-mixer-sink.h b/panels/sound/gvc-mixer-sink.h deleted file mode 100644 index 2a4a4badb..000000000 --- a/panels/sound/gvc-mixer-sink.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_SINK_H -#define __GVC_MIXER_SINK_H - -#include -#include "gvc-mixer-stream.h" - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_SINK (gvc_mixer_sink_get_type ()) -#define GVC_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SINK, GvcMixerSink)) -#define GVC_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass)) -#define GVC_IS_MIXER_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SINK)) -#define GVC_IS_MIXER_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SINK)) -#define GVC_MIXER_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SINK, GvcMixerSinkClass)) - -typedef struct GvcMixerSinkPrivate GvcMixerSinkPrivate; - -typedef struct -{ - GvcMixerStream parent; - GvcMixerSinkPrivate *priv; -} GvcMixerSink; - -typedef struct -{ - GvcMixerStreamClass parent_class; -} GvcMixerSinkClass; - -GType gvc_mixer_sink_get_type (void); - -GvcMixerStream * gvc_mixer_sink_new (pa_context *context, - guint index, - GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_MIXER_SINK_H */ diff --git a/panels/sound/gvc-mixer-source-output.c b/panels/sound/gvc-mixer-source-output.c deleted file mode 100644 index 536487b70..000000000 --- a/panels/sound/gvc-mixer-source-output.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-source-output.h" - -#define GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputPrivate)) - -struct GvcMixerSourceOutputPrivate -{ - gpointer dummy; -}; - -static void gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass); -static void gvc_mixer_source_output_init (GvcMixerSourceOutput *mixer_source_output); -static void gvc_mixer_source_output_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerSourceOutput, gvc_mixer_source_output, GVC_TYPE_MIXER_STREAM) - -static gboolean -gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op) -{ - /* FIXME: */ - *op = NULL; - return TRUE; -} - -static gboolean -gvc_mixer_source_output_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - /* FIXME: */ - return TRUE; -} - -static void -gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); - - object_class->finalize = gvc_mixer_source_output_finalize; - - stream_class->push_volume = gvc_mixer_source_output_push_volume; - stream_class->change_is_muted = gvc_mixer_source_output_change_is_muted; - - g_type_class_add_private (klass, sizeof (GvcMixerSourceOutputPrivate)); -} - -static void -gvc_mixer_source_output_init (GvcMixerSourceOutput *source_output) -{ - source_output->priv = GVC_MIXER_SOURCE_OUTPUT_GET_PRIVATE (source_output); - -} - -static void -gvc_mixer_source_output_finalize (GObject *object) -{ - GvcMixerSourceOutput *mixer_source_output; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_SOURCE_OUTPUT (object)); - - mixer_source_output = GVC_MIXER_SOURCE_OUTPUT (object); - - g_return_if_fail (mixer_source_output->priv != NULL); - G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->finalize (object); -} - -/** - * gvc_mixer_source_output_new: (skip) - * - * @context: - * @index: - * @channel_map: - * - * Returns: - */ -GvcMixerStream * -gvc_mixer_source_output_new (pa_context *context, - guint index, - GvcChannelMap *channel_map) -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_SOURCE_OUTPUT, - "pa-context", context, - "index", index, - "channel-map", channel_map, - NULL); - - return GVC_MIXER_STREAM (object); -} diff --git a/panels/sound/gvc-mixer-source-output.h b/panels/sound/gvc-mixer-source-output.h deleted file mode 100644 index 2283e3b67..000000000 --- a/panels/sound/gvc-mixer-source-output.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_SOURCE_OUTPUT_H -#define __GVC_MIXER_SOURCE_OUTPUT_H - -#include -#include "gvc-mixer-stream.h" - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_SOURCE_OUTPUT (gvc_mixer_source_output_get_type ()) -#define GVC_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutput)) -#define GVC_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass)) -#define GVC_IS_MIXER_SOURCE_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT)) -#define GVC_IS_MIXER_SOURCE_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE_OUTPUT)) -#define GVC_MIXER_SOURCE_OUTPUT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE_OUTPUT, GvcMixerSourceOutputClass)) - -typedef struct GvcMixerSourceOutputPrivate GvcMixerSourceOutputPrivate; - -typedef struct -{ - GvcMixerStream parent; - GvcMixerSourceOutputPrivate *priv; -} GvcMixerSourceOutput; - -typedef struct -{ - GvcMixerStreamClass parent_class; -} GvcMixerSourceOutputClass; - -GType gvc_mixer_source_output_get_type (void); - -GvcMixerStream * gvc_mixer_source_output_new (pa_context *context, - guint index, - GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_MIXER_SOURCE_OUTPUT_H */ diff --git a/panels/sound/gvc-mixer-source.c b/panels/sound/gvc-mixer-source.c deleted file mode 100644 index dd2d0b408..000000000 --- a/panels/sound/gvc-mixer-source.c +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-source.h" -#include "gvc-mixer-stream-private.h" -#include "gvc-channel-map-private.h" - -#define GVC_MIXER_SOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourcePrivate)) - -struct GvcMixerSourcePrivate -{ - gpointer dummy; -}; - -static void gvc_mixer_source_class_init (GvcMixerSourceClass *klass); -static void gvc_mixer_source_init (GvcMixerSource *mixer_source); -static void gvc_mixer_source_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM) - -static gboolean -gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op) -{ - pa_operation *o; - guint index; - const GvcChannelMap *map; - pa_context *context; - const pa_cvolume *cv; - - index = gvc_mixer_stream_get_index (stream); - - map = gvc_mixer_stream_get_channel_map (stream); - - /* set the volume */ - cv = gvc_channel_map_get_cvolume (map); - - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_source_volume_by_index (context, - index, - cv, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - *op = o; - - return TRUE; -} - -static gboolean -gvc_mixer_source_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - pa_operation *o; - guint index; - pa_context *context; - - index = gvc_mixer_stream_get_index (stream); - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_source_mute_by_index (context, - index, - is_muted, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - pa_operation_unref(o); - - return TRUE; -} - -static gboolean -gvc_mixer_source_change_port (GvcMixerStream *stream, - const char *port) -{ - pa_operation *o; - guint index; - pa_context *context; - - index = gvc_mixer_stream_get_index (stream); - context = gvc_mixer_stream_get_pa_context (stream); - - o = pa_context_set_source_port_by_index (context, - index, - port, - NULL, - NULL); - - if (o == NULL) { - g_warning ("pa_context_set_source_port_by_index() failed: %s", pa_strerror(pa_context_errno(context))); - return FALSE; - } - - pa_operation_unref(o); - - return TRUE; -} - -static void -gvc_mixer_source_class_init (GvcMixerSourceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass); - - object_class->finalize = gvc_mixer_source_finalize; - - stream_class->push_volume = gvc_mixer_source_push_volume; - stream_class->change_is_muted = gvc_mixer_source_change_is_muted; - stream_class->change_port = gvc_mixer_source_change_port; - - g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate)); -} - -static void -gvc_mixer_source_init (GvcMixerSource *source) -{ - source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source); -} - -static void -gvc_mixer_source_finalize (GObject *object) -{ - GvcMixerSource *mixer_source; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_SOURCE (object)); - - mixer_source = GVC_MIXER_SOURCE (object); - - g_return_if_fail (mixer_source->priv != NULL); - G_OBJECT_CLASS (gvc_mixer_source_parent_class)->finalize (object); -} - -/** - * gvc_mixer_source_new: (skip) - * - * @context: - * @index: - * @channel_map: - * - * Returns: - */ -GvcMixerStream * -gvc_mixer_source_new (pa_context *context, - guint index, - GvcChannelMap *channel_map) - -{ - GObject *object; - - object = g_object_new (GVC_TYPE_MIXER_SOURCE, - "pa-context", context, - "index", index, - "channel-map", channel_map, - NULL); - - return GVC_MIXER_STREAM (object); -} diff --git a/panels/sound/gvc-mixer-source.h b/panels/sound/gvc-mixer-source.h deleted file mode 100644 index 503f1b54d..000000000 --- a/panels/sound/gvc-mixer-source.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_SOURCE_H -#define __GVC_MIXER_SOURCE_H - -#include -#include "gvc-mixer-stream.h" - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_SOURCE (gvc_mixer_source_get_type ()) -#define GVC_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSource)) -#define GVC_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass)) -#define GVC_IS_MIXER_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_SOURCE)) -#define GVC_IS_MIXER_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_SOURCE)) -#define GVC_MIXER_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_SOURCE, GvcMixerSourceClass)) - -typedef struct GvcMixerSourcePrivate GvcMixerSourcePrivate; - -typedef struct -{ - GvcMixerStream parent; - GvcMixerSourcePrivate *priv; -} GvcMixerSource; - -typedef struct -{ - GvcMixerStreamClass parent_class; -} GvcMixerSourceClass; - -GType gvc_mixer_source_get_type (void); - -GvcMixerStream * gvc_mixer_source_new (pa_context *context, - guint index, - GvcChannelMap *map); - -G_END_DECLS - -#endif /* __GVC_MIXER_SOURCE_H */ diff --git a/panels/sound/gvc-mixer-stream.c b/panels/sound/gvc-mixer-stream.c deleted file mode 100644 index 0a5663edc..000000000 --- a/panels/sound/gvc-mixer-stream.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 William Jon McCann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include - -#include -#include - -#include - -#include "gvc-mixer-stream.h" -#include "gvc-mixer-stream-private.h" -#include "gvc-channel-map-private.h" - -#define GVC_MIXER_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamPrivate)) - -static guint32 stream_serial = 1; - -struct GvcMixerStreamPrivate -{ - pa_context *pa_context; - guint id; - guint index; - gint card_index; - GvcChannelMap *channel_map; - char *name; - char *description; - char *application_id; - char *icon_name; - char *sysfs_path; - gboolean is_muted; - gboolean can_decibel; - gboolean is_event_stream; - gboolean is_virtual; - pa_volume_t base_volume; - pa_operation *change_volume_op; - char *port; - char *human_port; - GList *ports; -}; - -enum -{ - PROP_0, - PROP_ID, - PROP_PA_CONTEXT, - PROP_CHANNEL_MAP, - PROP_INDEX, - PROP_NAME, - PROP_DESCRIPTION, - PROP_APPLICATION_ID, - PROP_ICON_NAME, - PROP_SYSFS_PATH, - PROP_VOLUME, - PROP_DECIBEL, - PROP_IS_MUTED, - PROP_CAN_DECIBEL, - PROP_IS_EVENT_STREAM, - PROP_IS_VIRTUAL, - PROP_CARD_INDEX, - PROP_PORT, -}; - -static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass); -static void gvc_mixer_stream_init (GvcMixerStream *mixer_stream); -static void gvc_mixer_stream_finalize (GObject *object); - -G_DEFINE_ABSTRACT_TYPE (GvcMixerStream, gvc_mixer_stream, G_TYPE_OBJECT) - -static guint32 -get_next_stream_serial (void) -{ - guint32 serial; - - serial = stream_serial++; - - if ((gint32)stream_serial < 0) { - stream_serial = 1; - } - - return serial; -} - -pa_context * -gvc_mixer_stream_get_pa_context (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - return stream->priv->pa_context; -} - -guint -gvc_mixer_stream_get_index (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - return stream->priv->index; -} - -guint -gvc_mixer_stream_get_id (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - return stream->priv->id; -} - -const GvcChannelMap * -gvc_mixer_stream_get_channel_map (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->channel_map; -} - -/** - * gvc_mixer_stream_get_volume: - * - * @stream: - * - * Returns: (type guint32) (transfer none): - */ -pa_volume_t -gvc_mixer_stream_get_volume (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - - return (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]; -} - -gdouble -gvc_mixer_stream_get_decibel (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - - return pa_sw_volume_to_dB( - (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]); -} - -/** - * gvc_mixer_stream_set_volume: - * - * @stream: - * @volume: (type guint32): - * - * Returns: - */ -gboolean -gvc_mixer_stream_set_volume (GvcMixerStream *stream, - pa_volume_t volume) -{ - pa_cvolume cv; - - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map); - pa_cvolume_scale(&cv, volume); - - if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) { - gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE); - g_object_notify (G_OBJECT (stream), "volume"); - return TRUE; - } - - return FALSE; -} - -gboolean -gvc_mixer_stream_set_decibel (GvcMixerStream *stream, - gdouble db) -{ - pa_cvolume cv; - - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - cv = *gvc_channel_map_get_cvolume(stream->priv->channel_map); - pa_cvolume_scale(&cv, pa_sw_volume_from_dB(db)); - - if (!pa_cvolume_equal(gvc_channel_map_get_cvolume(stream->priv->channel_map), &cv)) { - gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE); - g_object_notify (G_OBJECT (stream), "volume"); - } - - return TRUE; -} - -gboolean -gvc_mixer_stream_get_is_muted (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - return stream->priv->is_muted; -} - -gboolean -gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - return stream->priv->can_decibel; -} - -gboolean -gvc_mixer_stream_set_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - if (is_muted != stream->priv->is_muted) { - stream->priv->is_muted = is_muted; - g_object_notify (G_OBJECT (stream), "is-muted"); - } - - return TRUE; -} - -gboolean -gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream, - gboolean can_decibel) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - if (can_decibel != stream->priv->can_decibel) { - stream->priv->can_decibel = can_decibel; - g_object_notify (G_OBJECT (stream), "can-decibel"); - } - - return TRUE; -} - -const char * -gvc_mixer_stream_get_name (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->name; -} - -const char * -gvc_mixer_stream_get_description (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->description; -} - -gboolean -gvc_mixer_stream_set_name (GvcMixerStream *stream, - const char *name) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_free (stream->priv->name); - stream->priv->name = g_strdup (name); - g_object_notify (G_OBJECT (stream), "name"); - - return TRUE; -} - -gboolean -gvc_mixer_stream_set_description (GvcMixerStream *stream, - const char *description) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_free (stream->priv->description); - stream->priv->description = g_strdup (description); - g_object_notify (G_OBJECT (stream), "description"); - - return TRUE; -} - -gboolean -gvc_mixer_stream_is_event_stream (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - return stream->priv->is_event_stream; -} - -gboolean -gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream, - gboolean is_event_stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - stream->priv->is_event_stream = is_event_stream; - g_object_notify (G_OBJECT (stream), "is-event-stream"); - - return TRUE; -} - -gboolean -gvc_mixer_stream_is_virtual (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - return stream->priv->is_virtual; -} - -gboolean -gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream, - gboolean is_virtual) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - stream->priv->is_virtual = is_virtual; - g_object_notify (G_OBJECT (stream), "is-virtual"); - - return TRUE; -} - -const char * -gvc_mixer_stream_get_application_id (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->application_id; -} - -gboolean -gvc_mixer_stream_set_application_id (GvcMixerStream *stream, - const char *application_id) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_free (stream->priv->application_id); - stream->priv->application_id = g_strdup (application_id); - g_object_notify (G_OBJECT (stream), "application-id"); - - return TRUE; -} - -static void -on_channel_map_volume_changed (GvcChannelMap *channel_map, - gboolean set, - GvcMixerStream *stream) -{ - if (set == TRUE) - gvc_mixer_stream_push_volume (stream); - - g_object_notify (G_OBJECT (stream), "volume"); -} - -static gboolean -gvc_mixer_stream_set_channel_map (GvcMixerStream *stream, - GvcChannelMap *channel_map) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - if (channel_map != NULL) { - g_object_ref (channel_map); - } - - if (stream->priv->channel_map != NULL) { - g_signal_handlers_disconnect_by_func (stream->priv->channel_map, - on_channel_map_volume_changed, - stream); - g_object_unref (stream->priv->channel_map); - } - - stream->priv->channel_map = channel_map; - - if (stream->priv->channel_map != NULL) { - g_signal_connect (stream->priv->channel_map, - "volume-changed", - G_CALLBACK (on_channel_map_volume_changed), - stream); - - g_object_notify (G_OBJECT (stream), "channel-map"); - } - - return TRUE; -} - -const char * -gvc_mixer_stream_get_icon_name (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->icon_name; -} - -const char * -gvc_mixer_stream_get_sysfs_path (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->sysfs_path; -} - -/** - * gvc_mixer_stream_get_gicon: - * @stream: a #GvcMixerStream - * - * Returns: (transfer full): a new #GIcon - */ -GIcon * -gvc_mixer_stream_get_gicon (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - if (stream->priv->icon_name == NULL) - return NULL; - return g_themed_icon_new_with_default_fallbacks (stream->priv->icon_name); -} - -gboolean -gvc_mixer_stream_set_icon_name (GvcMixerStream *stream, - const char *icon_name) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_free (stream->priv->icon_name); - stream->priv->icon_name = g_strdup (icon_name); - g_object_notify (G_OBJECT (stream), "icon-name"); - - return TRUE; -} - -gboolean -gvc_mixer_stream_set_sysfs_path (GvcMixerStream *stream, - const char *sysfs_path) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - g_free (stream->priv->sysfs_path); - stream->priv->sysfs_path = g_strdup (sysfs_path); - g_object_notify (G_OBJECT (stream), "sysfs-path"); - - return TRUE; -} - -/** - * gvc_mixer_stream_get_base_volume: - * - * @stream: - * - * Returns: (type guint32) (transfer none): - */ -pa_volume_t -gvc_mixer_stream_get_base_volume (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0); - - return stream->priv->base_volume; -} - -/** - * gvc_mixer_stream_set_base_volume: - * - * @stream: - * @base_volume: (type guint32): - * - * Returns: - */ -gboolean -gvc_mixer_stream_set_base_volume (GvcMixerStream *stream, - pa_volume_t base_volume) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - stream->priv->base_volume = base_volume; - - return TRUE; -} - -const GvcMixerStreamPort * -gvc_mixer_stream_get_port (GvcMixerStream *stream) -{ - GList *l; - - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - g_return_val_if_fail (stream->priv->ports != NULL, NULL); - - for (l = stream->priv->ports; l != NULL; l = l->next) { - GvcMixerStreamPort *p = l->data; - if (g_strcmp0 (stream->priv->port, p->port) == 0) { - return p; - } - } - - g_assert_not_reached (); - - return NULL; -} - -gboolean -gvc_mixer_stream_set_port (GvcMixerStream *stream, - const char *port) -{ - GList *l; - - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - g_return_val_if_fail (stream->priv->ports != NULL, FALSE); - - g_free (stream->priv->port); - stream->priv->port = g_strdup (port); - - g_free (stream->priv->human_port); - stream->priv->human_port = NULL; - - for (l = stream->priv->ports; l != NULL; l = l->next) { - GvcMixerStreamPort *p = l->data; - if (g_str_equal (stream->priv->port, p->port)) { - stream->priv->human_port = g_strdup (p->human_port); - break; - } - } - - g_object_notify (G_OBJECT (stream), "port"); - - return TRUE; -} - -gboolean -gvc_mixer_stream_change_port (GvcMixerStream *stream, - const char *port) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - return GVC_MIXER_STREAM_GET_CLASS (stream)->change_port (stream, port); -} - -/** - * gvc_mixer_stream_get_ports: - * - * Return value: (transfer none) (element-type GvcMixerStreamPort): - */ -const GList * -gvc_mixer_stream_get_ports (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), NULL); - return stream->priv->ports; -} - -static int -sort_ports (GvcMixerStreamPort *a, - GvcMixerStreamPort *b) -{ - if (a->priority == b->priority) - return 0; - if (a->priority > b->priority) - return 1; - return -1; -} - -/** - * gvc_mixer_stream_set_ports: - * @ports: (transfer full) (element-type GvcMixerStreamPort): - */ -gboolean -gvc_mixer_stream_set_ports (GvcMixerStream *stream, - GList *ports) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - g_return_val_if_fail (stream->priv->ports == NULL, FALSE); - - stream->priv->ports = g_list_sort (ports, (GCompareFunc) sort_ports); - - return TRUE; -} - -gint -gvc_mixer_stream_get_card_index (GvcMixerStream *stream) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), PA_INVALID_INDEX); - return stream->priv->card_index; -} - -gboolean -gvc_mixer_stream_set_card_index (GvcMixerStream *stream, - gint card_index) -{ - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - stream->priv->card_index = card_index; - g_object_notify (G_OBJECT (stream), "card-index"); - - return TRUE; -} - -static void -gvc_mixer_stream_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerStream *self = GVC_MIXER_STREAM (object); - - switch (prop_id) { - case PROP_PA_CONTEXT: - self->priv->pa_context = g_value_get_pointer (value); - break; - case PROP_INDEX: - self->priv->index = g_value_get_ulong (value); - break; - case PROP_ID: - self->priv->id = g_value_get_ulong (value); - break; - case PROP_CHANNEL_MAP: - gvc_mixer_stream_set_channel_map (self, g_value_get_object (value)); - break; - case PROP_NAME: - gvc_mixer_stream_set_name (self, g_value_get_string (value)); - break; - case PROP_DESCRIPTION: - gvc_mixer_stream_set_description (self, g_value_get_string (value)); - break; - case PROP_APPLICATION_ID: - gvc_mixer_stream_set_application_id (self, g_value_get_string (value)); - break; - case PROP_ICON_NAME: - gvc_mixer_stream_set_icon_name (self, g_value_get_string (value)); - break; - case PROP_SYSFS_PATH: - gvc_mixer_stream_set_sysfs_path (self, g_value_get_string (value)); - break; - case PROP_VOLUME: - gvc_mixer_stream_set_volume (self, g_value_get_ulong (value)); - break; - case PROP_DECIBEL: - gvc_mixer_stream_set_decibel (self, g_value_get_double (value)); - break; - case PROP_IS_MUTED: - gvc_mixer_stream_set_is_muted (self, g_value_get_boolean (value)); - break; - case PROP_IS_EVENT_STREAM: - gvc_mixer_stream_set_is_event_stream (self, g_value_get_boolean (value)); - break; - case PROP_IS_VIRTUAL: - gvc_mixer_stream_set_is_virtual (self, g_value_get_boolean (value)); - break; - case PROP_CAN_DECIBEL: - gvc_mixer_stream_set_can_decibel (self, g_value_get_boolean (value)); - break; - case PROP_PORT: - gvc_mixer_stream_set_port (self, g_value_get_string (value)); - break; - case PROP_CARD_INDEX: - self->priv->card_index = g_value_get_long (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gvc_mixer_stream_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerStream *self = GVC_MIXER_STREAM (object); - - switch (prop_id) { - case PROP_PA_CONTEXT: - g_value_set_pointer (value, self->priv->pa_context); - break; - case PROP_INDEX: - g_value_set_ulong (value, self->priv->index); - break; - case PROP_ID: - g_value_set_ulong (value, self->priv->id); - break; - case PROP_CHANNEL_MAP: - g_value_set_object (value, self->priv->channel_map); - break; - case PROP_NAME: - g_value_set_string (value, self->priv->name); - break; - case PROP_DESCRIPTION: - g_value_set_string (value, self->priv->description); - break; - case PROP_APPLICATION_ID: - g_value_set_string (value, self->priv->application_id); - break; - case PROP_ICON_NAME: - g_value_set_string (value, self->priv->icon_name); - break; - case PROP_SYSFS_PATH: - g_value_set_string (value, self->priv->sysfs_path); - break; - case PROP_VOLUME: - g_value_set_ulong (value, - pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map))); - break; - case PROP_DECIBEL: - g_value_set_double (value, - pa_sw_volume_to_dB(pa_cvolume_max(gvc_channel_map_get_cvolume(self->priv->channel_map)))); - break; - case PROP_IS_MUTED: - g_value_set_boolean (value, self->priv->is_muted); - break; - case PROP_IS_EVENT_STREAM: - g_value_set_boolean (value, self->priv->is_event_stream); - break; - case PROP_IS_VIRTUAL: - g_value_set_boolean (value, self->priv->is_virtual); - break; - case PROP_CAN_DECIBEL: - g_value_set_boolean (value, self->priv->can_decibel); - break; - case PROP_PORT: - g_value_set_string (value, self->priv->port); - break; - case PROP_CARD_INDEX: - g_value_set_long (value, self->priv->card_index); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GObject * -gvc_mixer_stream_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GvcMixerStream *self; - - object = G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->constructor (type, n_construct_properties, construct_params); - - self = GVC_MIXER_STREAM (object); - - self->priv->id = get_next_stream_serial (); - - return object; -} - -static gboolean -gvc_mixer_stream_real_change_port (GvcMixerStream *stream, - const char *port) -{ - return FALSE; -} - -static gboolean -gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op) -{ - return FALSE; -} - -static gboolean -gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - return FALSE; -} - -gboolean -gvc_mixer_stream_push_volume (GvcMixerStream *stream) -{ - pa_operation *op; - gboolean ret; - - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - - if (stream->priv->is_event_stream != FALSE) - return TRUE; - - g_debug ("Pushing new volume to stream '%s' (%s)", - stream->priv->description, stream->priv->name); - - ret = GVC_MIXER_STREAM_GET_CLASS (stream)->push_volume (stream, (gpointer *) &op); - if (ret) { - if (stream->priv->change_volume_op != NULL) - pa_operation_unref (stream->priv->change_volume_op); - stream->priv->change_volume_op = op; - } - return ret; -} - -gboolean -gvc_mixer_stream_change_is_muted (GvcMixerStream *stream, - gboolean is_muted) -{ - gboolean ret; - g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE); - ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_is_muted (stream, is_muted); - return ret; -} - -gboolean -gvc_mixer_stream_is_running (GvcMixerStream *stream) -{ - if (stream->priv->change_volume_op == NULL) - return FALSE; - - if ((pa_operation_get_state(stream->priv->change_volume_op) == PA_OPERATION_RUNNING)) - return TRUE; - - pa_operation_unref(stream->priv->change_volume_op); - stream->priv->change_volume_op = NULL; - - return FALSE; -} - -static void -gvc_mixer_stream_class_init (GvcMixerStreamClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->constructor = gvc_mixer_stream_constructor; - gobject_class->finalize = gvc_mixer_stream_finalize; - gobject_class->set_property = gvc_mixer_stream_set_property; - gobject_class->get_property = gvc_mixer_stream_get_property; - - klass->push_volume = gvc_mixer_stream_real_push_volume; - klass->change_port = gvc_mixer_stream_real_change_port; - klass->change_is_muted = gvc_mixer_stream_real_change_is_muted; - - g_object_class_install_property (gobject_class, - PROP_INDEX, - g_param_spec_ulong ("index", - "Index", - "The index for this stream", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_ID, - g_param_spec_ulong ("id", - "id", - "The id for this stream", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_CHANNEL_MAP, - g_param_spec_object ("channel-map", - "channel map", - "The channel map for this stream", - GVC_TYPE_CHANNEL_MAP, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_PA_CONTEXT, - g_param_spec_pointer ("pa-context", - "PulseAudio context", - "The PulseAudio context for this stream", - G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (gobject_class, - PROP_VOLUME, - g_param_spec_ulong ("volume", - "Volume", - "The volume for this stream", - 0, G_MAXULONG, 0, - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_DECIBEL, - g_param_spec_double ("decibel", - "Decibel", - "The decibel level for this stream", - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "Name to display for this stream", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_DESCRIPTION, - g_param_spec_string ("description", - "Description", - "Description to display for this stream", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_APPLICATION_ID, - g_param_spec_string ("application-id", - "Application identifier", - "Application identifier for this stream", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_ICON_NAME, - g_param_spec_string ("icon-name", - "Icon Name", - "Name of icon to display for this stream", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_SYSFS_PATH, - g_param_spec_string ("sysfs-path", - "Sysfs path", - "Sysfs path for the device associated with this stream", - NULL, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_IS_MUTED, - g_param_spec_boolean ("is-muted", - "is muted", - "Whether stream is muted", - FALSE, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_CAN_DECIBEL, - g_param_spec_boolean ("can-decibel", - "can decibel", - "Whether stream volume can be converted to decibel units", - FALSE, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_IS_EVENT_STREAM, - g_param_spec_boolean ("is-event-stream", - "is event stream", - "Whether stream's role is to play an event", - FALSE, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_IS_VIRTUAL, - g_param_spec_boolean ("is-virtual", - "is virtual stream", - "Whether the stream is virtual", - FALSE, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, - PROP_PORT, - g_param_spec_string ("port", - "Port", - "The name of the current port for this stream", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_CARD_INDEX, - g_param_spec_long ("card-index", - "Card index", - "The index of the card for this stream", - PA_INVALID_INDEX, G_MAXLONG, PA_INVALID_INDEX, - G_PARAM_READWRITE|G_PARAM_CONSTRUCT)); - g_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate)); -} - -static void -gvc_mixer_stream_init (GvcMixerStream *stream) -{ - stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream); -} - -static void -free_port (GvcMixerStreamPort *p) -{ - g_free (p->port); - g_free (p->human_port); - g_free (p); -} - -static void -gvc_mixer_stream_finalize (GObject *object) -{ - GvcMixerStream *mixer_stream; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_IS_MIXER_STREAM (object)); - - mixer_stream = GVC_MIXER_STREAM (object); - - g_return_if_fail (mixer_stream->priv != NULL); - - g_object_unref (mixer_stream->priv->channel_map); - mixer_stream->priv->channel_map = NULL; - - g_free (mixer_stream->priv->name); - mixer_stream->priv->name = NULL; - - g_free (mixer_stream->priv->description); - mixer_stream->priv->description = NULL; - - g_free (mixer_stream->priv->application_id); - mixer_stream->priv->application_id = NULL; - - g_free (mixer_stream->priv->icon_name); - mixer_stream->priv->icon_name = NULL; - - g_free (mixer_stream->priv->sysfs_path); - mixer_stream->priv->sysfs_path = NULL; - - g_free (mixer_stream->priv->port); - mixer_stream->priv->port = NULL; - - g_free (mixer_stream->priv->human_port); - mixer_stream->priv->human_port = NULL; - - g_list_foreach (mixer_stream->priv->ports, (GFunc) free_port, NULL); - g_list_free (mixer_stream->priv->ports); - mixer_stream->priv->ports = NULL; - - if (mixer_stream->priv->change_volume_op) { - pa_operation_unref(mixer_stream->priv->change_volume_op); - mixer_stream->priv->change_volume_op = NULL; - } - - G_OBJECT_CLASS (gvc_mixer_stream_parent_class)->finalize (object); -} diff --git a/panels/sound/gvc-mixer-stream.h b/panels/sound/gvc-mixer-stream.h deleted file mode 100644 index 846f2e03a..000000000 --- a/panels/sound/gvc-mixer-stream.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_MIXER_STREAM_H -#define __GVC_MIXER_STREAM_H - -#include -#include "gvc-pulseaudio-fake.h" -#include "gvc-channel-map.h" -#include - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_STREAM (gvc_mixer_stream_get_type ()) -#define GVC_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStream)) -#define GVC_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass)) -#define GVC_IS_MIXER_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GVC_TYPE_MIXER_STREAM)) -#define GVC_IS_MIXER_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GVC_TYPE_MIXER_STREAM)) -#define GVC_MIXER_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GVC_TYPE_MIXER_STREAM, GvcMixerStreamClass)) - -typedef struct GvcMixerStreamPrivate GvcMixerStreamPrivate; - -typedef struct -{ - GObject parent; - GvcMixerStreamPrivate *priv; -} GvcMixerStream; - -typedef struct -{ - GObjectClass parent_class; - - /* vtable */ - gboolean (*push_volume) (GvcMixerStream *stream, - gpointer *operation); - gboolean (*change_is_muted) (GvcMixerStream *stream, - gboolean is_muted); - gboolean (*change_port) (GvcMixerStream *stream, - const char *port); -} GvcMixerStreamClass; - -typedef struct -{ - char *port; - char *human_port; - guint priority; - gboolean available; -} GvcMixerStreamPort; - -GType gvc_mixer_stream_get_type (void); - -guint gvc_mixer_stream_get_index (GvcMixerStream *stream); -guint gvc_mixer_stream_get_id (GvcMixerStream *stream); -const GvcChannelMap *gvc_mixer_stream_get_channel_map(GvcMixerStream *stream); -const GvcMixerStreamPort *gvc_mixer_stream_get_port (GvcMixerStream *stream); -const GList * gvc_mixer_stream_get_ports (GvcMixerStream *stream); -gboolean gvc_mixer_stream_change_port (GvcMixerStream *stream, - const char *port); - -pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream); -gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream); -gboolean gvc_mixer_stream_push_volume (GvcMixerStream *stream); -pa_volume_t gvc_mixer_stream_get_base_volume (GvcMixerStream *stream); - -gboolean gvc_mixer_stream_get_is_muted (GvcMixerStream *stream); -gboolean gvc_mixer_stream_get_can_decibel (GvcMixerStream *stream); -gboolean gvc_mixer_stream_change_is_muted (GvcMixerStream *stream, - gboolean is_muted); -gboolean gvc_mixer_stream_is_running (GvcMixerStream *stream); -const char * gvc_mixer_stream_get_name (GvcMixerStream *stream); -const char * gvc_mixer_stream_get_icon_name (GvcMixerStream *stream); -const char * gvc_mixer_stream_get_sysfs_path (GvcMixerStream *stream); -GIcon * gvc_mixer_stream_get_gicon (GvcMixerStream *stream); -const char * gvc_mixer_stream_get_description (GvcMixerStream *stream); -const char * gvc_mixer_stream_get_application_id (GvcMixerStream *stream); -gboolean gvc_mixer_stream_is_event_stream (GvcMixerStream *stream); -gboolean gvc_mixer_stream_is_virtual (GvcMixerStream *stream); -gint gvc_mixer_stream_get_card_index (GvcMixerStream *stream); - -/* private */ -gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream, - pa_volume_t volume); -gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream, - gdouble db); -gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream, - gboolean is_muted); -gboolean gvc_mixer_stream_set_can_decibel (GvcMixerStream *stream, - gboolean can_decibel); -gboolean gvc_mixer_stream_set_name (GvcMixerStream *stream, - const char *name); -gboolean gvc_mixer_stream_set_description (GvcMixerStream *stream, - const char *description); -gboolean gvc_mixer_stream_set_icon_name (GvcMixerStream *stream, - const char *name); -gboolean gvc_mixer_stream_set_sysfs_path (GvcMixerStream *stream, - const char *sysfs_path); -gboolean gvc_mixer_stream_set_is_event_stream (GvcMixerStream *stream, - gboolean is_event_stream); -gboolean gvc_mixer_stream_set_is_virtual (GvcMixerStream *stream, - gboolean is_event_stream); -gboolean gvc_mixer_stream_set_application_id (GvcMixerStream *stream, - const char *application_id); -gboolean gvc_mixer_stream_set_base_volume (GvcMixerStream *stream, - pa_volume_t base_volume); -gboolean gvc_mixer_stream_set_port (GvcMixerStream *stream, - const char *port); -gboolean gvc_mixer_stream_set_ports (GvcMixerStream *stream, - GList *ports); -gboolean gvc_mixer_stream_set_card_index (GvcMixerStream *stream, - gint card_index); - -G_END_DECLS - -#endif /* __GVC_MIXER_STREAM_H */ diff --git a/panels/sound/gvc-mixer-ui-device.c b/panels/sound/gvc-mixer-ui-device.c deleted file mode 100644 index 6f3599043..000000000 --- a/panels/sound/gvc-mixer-ui-device.c +++ /dev/null @@ -1,656 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ -/* - * gvc-mixer-ui-device.c - * Copyright (C) Conor Curran 2011 - * Copyright (C) 2012 David Henningsson, Canonical Ltd. - * - * gvc-mixer-ui-device.c is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * gvc-mixer-ui-device.c is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#include - -#include "gvc-mixer-ui-device.h" -#include "gvc-mixer-card.h" - -#define GVC_MIXER_UI_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDevicePrivate)) - -struct GvcMixerUIDevicePrivate -{ - gchar *first_line_desc; - gchar *second_line_desc; - - GvcMixerCard *card; - gchar *port_name; - gint stream_id; - guint id; - gboolean port_available; - - /* These two lists contain pointers to GvcMixerCardProfile objects. Those objects are owned by GvcMixerCard. * - * TODO: Do we want to add a weak reference to the GvcMixerCard for this reason? */ - GList *supported_profiles; /* all profiles supported by this port.*/ - GList *profiles; /* profiles to be added to combobox, subset of supported_profiles. */ - GvcMixerUIDeviceDirection type; - gboolean disable_profile_swapping; - gchar *user_preferred_profile; -}; - -enum -{ - PROP_0, - PROP_DESC_LINE_1, - PROP_DESC_LINE_2, - PROP_CARD, - PROP_PORT_NAME, - PROP_STREAM_ID, - PROP_UI_DEVICE_TYPE, - PROP_PORT_AVAILABLE, -}; - -static void gvc_mixer_ui_device_class_init (GvcMixerUIDeviceClass *klass); -static void gvc_mixer_ui_device_init (GvcMixerUIDevice *device); -static void gvc_mixer_ui_device_finalize (GObject *object); - -G_DEFINE_TYPE (GvcMixerUIDevice, gvc_mixer_ui_device, G_TYPE_OBJECT); - -static guint32 -get_next_output_serial (void) -{ - static guint32 output_serial = 1; - guint32 serial; - - serial = output_serial++; - - if ((gint32)output_serial < 0) - output_serial = 1; - - return serial; -} - -static void -gvc_mixer_ui_device_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GvcMixerUIDevice *self = GVC_MIXER_UI_DEVICE (object); - - switch (property_id) { - case PROP_DESC_LINE_1: - g_value_set_string (value, self->priv->first_line_desc); - break; - case PROP_DESC_LINE_2: - g_value_set_string (value, self->priv->second_line_desc); - break; - case PROP_CARD: - g_value_set_pointer (value, self->priv->card); - break; - case PROP_PORT_NAME: - g_value_set_string (value, self->priv->port_name); - break; - case PROP_STREAM_ID: - g_value_set_int (value, self->priv->stream_id); - break; - case PROP_UI_DEVICE_TYPE: - g_value_set_uint (value, (guint)self->priv->type); - break; - case PROP_PORT_AVAILABLE: - g_value_set_boolean (value, self->priv->port_available); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gvc_mixer_ui_device_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GvcMixerUIDevice *self = GVC_MIXER_UI_DEVICE (object); - - switch (property_id) { - case PROP_DESC_LINE_1: - g_free (self->priv->first_line_desc); - self->priv->first_line_desc = g_value_dup_string (value); - g_debug ("gvc-mixer-output-set-property - 1st line: %s\n", - self->priv->first_line_desc); - break; - case PROP_DESC_LINE_2: - g_free (self->priv->second_line_desc); - self->priv->second_line_desc = g_value_dup_string (value); - g_debug ("gvc-mixer-output-set-property - 2nd line: %s\n", - self->priv->second_line_desc); - break; - case PROP_CARD: - self->priv->card = g_value_get_pointer (value); - g_debug ("gvc-mixer-output-set-property - card: %p\n", - self->priv->card); - break; - case PROP_PORT_NAME: - g_free (self->priv->port_name); - self->priv->port_name = g_value_dup_string (value); - g_debug ("gvc-mixer-output-set-property - card port name: %s\n", - self->priv->port_name); - break; - case PROP_STREAM_ID: - self->priv->stream_id = g_value_get_int (value); - g_debug ("gvc-mixer-output-set-property - sink/source id: %i\n", - self->priv->stream_id); - break; - case PROP_UI_DEVICE_TYPE: - self->priv->type = (GvcMixerUIDeviceDirection) g_value_get_uint (value); - break; - case PROP_PORT_AVAILABLE: - self->priv->port_available = g_value_get_boolean (value); - g_debug ("gvc-mixer-output-set-property - port available %i, value passed in %i \n", - self->priv->port_available, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static GObject * -gvc_mixer_ui_device_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_params) -{ - GObject *object; - GvcMixerUIDevice *self; - - object = G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->constructor (type, n_construct_properties, construct_params); - - self = GVC_MIXER_UI_DEVICE (object); - self->priv->id = get_next_output_serial (); - self->priv->stream_id = GVC_MIXER_UI_DEVICE_INVALID; - return object; -} - -static void -gvc_mixer_ui_device_init (GvcMixerUIDevice *device) -{ - device->priv = GVC_MIXER_UI_DEVICE_GET_PRIVATE (device); -} - -static void -gvc_mixer_ui_device_dispose (GObject *object) -{ - GvcMixerUIDevice *device; - - g_return_if_fail (object != NULL); - g_return_if_fail (GVC_MIXER_UI_DEVICE (object)); - - device = GVC_MIXER_UI_DEVICE (object); - - g_clear_pointer (&device->priv->port_name, g_free); - g_clear_pointer (&device->priv->first_line_desc, g_free); - g_clear_pointer (&device->priv->second_line_desc, g_free); - g_clear_pointer (&device->priv->profiles, g_list_free); - g_clear_pointer (&device->priv->supported_profiles, g_list_free); - g_clear_pointer (&device->priv->user_preferred_profile, g_free); - - G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->dispose (object); -} - -static void -gvc_mixer_ui_device_finalize (GObject *object) -{ - G_OBJECT_CLASS (gvc_mixer_ui_device_parent_class)->finalize (object); -} - -static void -gvc_mixer_ui_device_class_init (GvcMixerUIDeviceClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->constructor = gvc_mixer_ui_device_constructor; - object_class->dispose = gvc_mixer_ui_device_dispose; - object_class->finalize = gvc_mixer_ui_device_finalize; - object_class->set_property = gvc_mixer_ui_device_set_property; - object_class->get_property = gvc_mixer_ui_device_get_property; - - pspec = g_param_spec_string ("description", - "Description construct prop", - "Set first line description", - "no-name-set", - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_DESC_LINE_1, pspec); - - pspec = g_param_spec_string ("origin", - "origin construct prop", - "Set second line description name", - "no-name-set", - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_DESC_LINE_2, pspec); - - pspec = g_param_spec_pointer ("card", - "Card from pulse", - "Set/Get card", - G_PARAM_READWRITE); - - g_object_class_install_property (object_class, PROP_CARD, pspec); - - pspec = g_param_spec_string ("port-name", - "port-name construct prop", - "Set port-name", - NULL, - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_PORT_NAME, pspec); - - pspec = g_param_spec_int ("stream-id", - "stream id assigned by gvc-stream", - "Set/Get stream id", - -1, - G_MAXINT, - GVC_MIXER_UI_DEVICE_INVALID, - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_STREAM_ID, pspec); - - pspec = g_param_spec_uint ("type", - "ui-device type", - "determine whether its an input and output", - 0, 1, 0, G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_UI_DEVICE_TYPE, pspec); - - pspec = g_param_spec_boolean ("port-available", - "available", - "determine whether this port is available", - FALSE, - G_PARAM_READWRITE); - g_object_class_install_property (object_class, PROP_PORT_AVAILABLE, pspec); - - g_type_class_add_private (klass, sizeof (GvcMixerUIDevicePrivate)); -} - -/* Removes the part of the string that starts with skip_prefix - * ie. corresponding to the other direction. - * Normally either "input:" or "output:" - * - * Example: if given the input string "output:hdmi-stereo+input:analog-stereo" and - * skip_prefix "input:", the resulting string is "output:hdmi-stereo". - * - * The returned string must be freed with g_free(). - */ -static gchar * -get_profile_canonical_name (const gchar *profile_name, const gchar *skip_prefix) -{ - gchar *result = NULL; - gchar **s; - int i; - - /* optimisation for the simple case. */ - if (strstr (profile_name, skip_prefix) == NULL) - return g_strdup (profile_name); - - s = g_strsplit (profile_name, "+", 0); - for (i = 0; i < g_strv_length (s); i++) { - if (g_str_has_prefix (s[i], skip_prefix)) - continue; - if (result == NULL) - result = g_strdup (s[i]); - else { - gchar *c = g_strdup_printf("%s+%s", result, s[i]); - g_free(result); - result = c; - } - } - - g_strfreev(s); - - if (!result) - return g_strdup("off"); - - return result; -} - -const gchar * -gvc_mixer_ui_device_get_matching_profile (GvcMixerUIDevice *device, const gchar *profile) -{ - gchar *skip_prefix = device->priv->type == UIDeviceInput ? "output:" : "input:"; - gchar *target_cname = get_profile_canonical_name (profile, skip_prefix); - GList *l; - gchar *result = NULL; - - for (l = device->priv->profiles; l != NULL; l = l->next) { - gchar *canonical_name; - GvcMixerCardProfile* p = l->data; - canonical_name = get_profile_canonical_name (p->profile, skip_prefix); - if (strcmp (canonical_name, target_cname) == 0) - result = p->profile; - g_free (canonical_name); - } - - g_free (target_cname); - g_debug ("Matching profile for '%s' is '%s'", profile, result ? result : "(null)"); - return result; -} - - -static void -add_canonical_names_of_profiles (GvcMixerUIDevice *device, - const GList *in_profiles, - GHashTable *added_profiles, - const gchar *skip_prefix, - gboolean only_canonical) -{ - const GList *l; - - for (l = in_profiles; l != NULL; l = l->next) { - gchar *canonical_name; - GvcMixerCardProfile* p = l->data; - - canonical_name = get_profile_canonical_name (p->profile, skip_prefix); - g_debug ("The canonical name for '%s' is '%s'", p->profile, canonical_name); - - /* Have we already added the canonical version of this profile? */ - if (g_hash_table_contains (added_profiles, canonical_name)) { - g_free (canonical_name); - continue; - } - - if (only_canonical && strcmp (p->profile, canonical_name) != 0) { - g_free (canonical_name); - continue; - } - - g_free (canonical_name); - - g_debug ("Adding profile to combobox: '%s' - '%s'", p->profile, p->human_profile); - g_hash_table_insert (added_profiles, g_strdup (p->profile), p); - device->priv->profiles = g_list_append (device->priv->profiles, p); - } -} - -/** - * gvc_mixer_ui_device_set_profiles: - * - * @in_profiles: a list of GvcMixerCardProfile - * - * Assigns value to - * - device->priv->profiles (profiles to be added to combobox) - * - device->priv->supported_profiles (all profiles of this port) - * - device->priv->disable_profile_swapping (whether to show the combobox) - * - * This method attempts to reduce the list of profiles visible to the user by figuring out - * from the context of that device (whether it's an input or an output) what profiles - * actually provide an alternative. - * - * It does this by the following. - * - It ignores off profiles. - * - It takes the canonical name of the profile. That name is what you get when you - * ignore the other direction. - * - In the first iteration, it only adds the names of canonical profiles - i e - * when the other side is turned off. - * - Normally the first iteration covers all cases, but sometimes (e g bluetooth) - * it doesn't, so add other profiles whose canonical name isn't already added - * in a second iteration. - */ -void -gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device, - const GList *in_profiles) -{ - GHashTable *added_profiles; - gchar *skip_prefix = device->priv->type == UIDeviceInput ? "output:" : "input:"; - - g_debug ("Set profiles for '%s'", gvc_mixer_ui_device_get_description(device)); - - if (in_profiles == NULL) - return; - - device->priv->supported_profiles = g_list_copy ((GList*) in_profiles); - - added_profiles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - /* Run two iterations: First, add profiles which are canonical themselves, - * Second, add profiles for which the canonical name is not added already. */ - - add_canonical_names_of_profiles(device, in_profiles, added_profiles, skip_prefix, TRUE); - add_canonical_names_of_profiles(device, in_profiles, added_profiles, skip_prefix, FALSE); - - /* TODO: Consider adding the "Off" profile here */ - - device->priv->disable_profile_swapping = g_hash_table_size (added_profiles) <= 1; - g_hash_table_destroy (added_profiles); -} - -/** - * gvc_mixer_ui_device_get_best_profile: - * - * @selected: The selected profile or its canonical name or %NULL for any profile - * @current: The currently selected profile - * - * Returns: (transfer none): a profile name, valid as long as the UI device profiles are. - */ -const gchar * -gvc_mixer_ui_device_get_best_profile (GvcMixerUIDevice *device, - const gchar *selected, - const gchar *current) -{ - GList *candidates, *l; - const gchar *result; - gchar *skip_prefix; - gchar *canonical_name_selected; - - if (device->priv->type == UIDeviceInput) - skip_prefix = "output:"; - else - skip_prefix = "input:"; - - /* First make a list of profiles acceptable to switch to */ - canonical_name_selected = NULL; - if (selected) - canonical_name_selected = get_profile_canonical_name (selected, skip_prefix); - - candidates = NULL; - for (l = device->priv->supported_profiles; l != NULL; l = l->next) { - gchar *canonical_name; - GvcMixerCardProfile* p = l->data; - canonical_name = get_profile_canonical_name (p->profile, skip_prefix); - if (!canonical_name_selected || strcmp (canonical_name, canonical_name_selected) == 0) { - candidates = g_list_append (candidates, p); - g_debug ("Candidate for profile switching: '%s'", p->profile); - } - } - - if (!candidates) { - g_warning ("No suitable profile candidates for '%s'", selected ? selected : "(null)"); - g_free (canonical_name_selected); - return current; - } - - /* 1) Maybe we can skip profile switching altogether? */ - result = NULL; - for (l = candidates; (result == NULL) && (l != NULL); l = l->next) { - GvcMixerCardProfile* p = l->data; - if (strcmp (current, p->profile) == 0) - result = p->profile; - } - - /* 2) Try to keep the other side unchanged if possible */ - if (result == NULL) { - guint prio = 0; - gchar *skip_prefix_reverse = device->priv->type == UIDeviceInput ? "input:" : "output:"; - gchar *current_reverse = get_profile_canonical_name (current, skip_prefix_reverse); - for (l = candidates; l != NULL; l = l->next) { - gchar *p_reverse; - GvcMixerCardProfile* p = l->data; - p_reverse = get_profile_canonical_name (p->profile, skip_prefix_reverse); - g_debug ("Comparing '%s' (from '%s') with '%s', prio %d", p_reverse, p->profile, current_reverse, p->priority); - if (strcmp (p_reverse, current_reverse) == 0 && (!result || p->priority > prio)) { - result = p->profile; - prio = p->priority; - } - g_free (p_reverse); - } - g_free (current_reverse); - } - - /* 3) All right, let's just pick the profile with highest priority. - * TODO: We could consider asking a GUI question if this stops streams - * in the other direction */ - if (result == NULL) { - guint prio = 0; - for (l = candidates; l != NULL; l = l->next) { - GvcMixerCardProfile* p = l->data; - if ((p->priority > prio) || !result) { - result = p->profile; - prio = p->priority; - } - } - } - - g_list_free (candidates); - g_free (canonical_name_selected); - return result; -} - -const gchar * -gvc_mixer_ui_device_get_active_profile (GvcMixerUIDevice* device) -{ - GvcMixerCardProfile *profile; - - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - if (device->priv->card == NULL) { - g_warning ("Device did not have an appropriate card"); - return NULL; - } - - profile = gvc_mixer_card_get_profile (device->priv->card); - return gvc_mixer_ui_device_get_matching_profile (device, profile->profile); -} - -gboolean -gvc_mixer_ui_device_should_profiles_be_hidden (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); - - return device->priv->disable_profile_swapping; -} - -GList* -gvc_mixer_ui_device_get_profiles (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->profiles; -} - -GList* -gvc_mixer_ui_device_get_supported_profiles (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->supported_profiles; -} - -guint -gvc_mixer_ui_device_get_id (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), 0); - - return device->priv->id; -} - -gint -gvc_mixer_ui_device_get_stream_id (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), 0); - - return device->priv->stream_id; -} - -void -gvc_mixer_ui_device_invalidate_stream (GvcMixerUIDevice *self) -{ - g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (self)); - - self->priv->stream_id = GVC_MIXER_UI_DEVICE_INVALID; -} - -const gchar * -gvc_mixer_ui_device_get_description (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->first_line_desc; -} - -const gchar * -gvc_mixer_ui_device_get_origin (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->second_line_desc; -} - -const gchar* -gvc_mixer_ui_device_get_user_preferred_profile (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->user_preferred_profile; -} - -const gchar * -gvc_mixer_ui_device_get_top_priority_profile (GvcMixerUIDevice *device) -{ - GList *last; - GvcMixerCardProfile *profile; - - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - last = g_list_last (device->priv->supported_profiles); - profile = last->data; - - return profile->profile; -} - -void -gvc_mixer_ui_device_set_user_preferred_profile (GvcMixerUIDevice *device, - const gchar *profile) -{ - g_return_if_fail (GVC_IS_MIXER_UI_DEVICE (device)); - - g_free (device->priv->user_preferred_profile); - device->priv->user_preferred_profile = g_strdup (profile); -} - -const gchar * -gvc_mixer_ui_device_get_port (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), NULL); - - return device->priv->port_name; -} - -gboolean -gvc_mixer_ui_device_has_ports (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); - - return (device->priv->port_name != NULL); -} - -gboolean -gvc_mixer_ui_device_is_output (GvcMixerUIDevice *device) -{ - g_return_val_if_fail (GVC_IS_MIXER_UI_DEVICE (device), FALSE); - - return (device->priv->type == UIDeviceOutput); -} diff --git a/panels/sound/gvc-mixer-ui-device.h b/panels/sound/gvc-mixer-ui-device.h deleted file mode 100644 index fbf3b9ce8..000000000 --- a/panels/sound/gvc-mixer-ui-device.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ -/* - * Copyright (C) Conor Curran 2011 - * - * This is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * gvc-mixer-ui-device.h is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -#ifndef _GVC_MIXER_UI_DEVICE_H_ -#define _GVC_MIXER_UI_DEVICE_H_ - -#include - -G_BEGIN_DECLS - -#define GVC_TYPE_MIXER_UI_DEVICE (gvc_mixer_ui_device_get_type ()) -#define GVC_MIXER_UI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDevice)) -#define GVC_MIXER_UI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDeviceClass)) -#define GVC_IS_MIXER_UI_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GVC_TYPE_MIXER_UI_DEVICE)) -#define GVC_IS_MIXER_UI_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GVC_TYPE_MIXER_UI_DEVICE)) -#define GVC_MIXER_UI_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GVC_TYPE_MIXER_UI_DEVICE, GvcMixerUIDeviceClass)) - -#define GVC_MIXER_UI_DEVICE_INVALID -1 - -typedef struct GvcMixerUIDevicePrivate GvcMixerUIDevicePrivate; - -typedef struct -{ - GObjectClass parent_class; -} GvcMixerUIDeviceClass; - -typedef struct -{ - GObject parent_instance; - GvcMixerUIDevicePrivate *priv; -} GvcMixerUIDevice; - -typedef enum -{ - UIDeviceInput, - UIDeviceOutput, -} GvcMixerUIDeviceDirection; - -GType gvc_mixer_ui_device_get_type (void) G_GNUC_CONST; - -guint gvc_mixer_ui_device_get_id (GvcMixerUIDevice *dev); -gint gvc_mixer_ui_device_get_stream_id (GvcMixerUIDevice *dev); -const gchar * gvc_mixer_ui_device_get_description (GvcMixerUIDevice *dev); -const gchar * gvc_mixer_ui_device_get_origin (GvcMixerUIDevice *dev); -const gchar * gvc_mixer_ui_device_get_port (GvcMixerUIDevice *dev); -const gchar * gvc_mixer_ui_device_get_best_profile (GvcMixerUIDevice *dev, - const gchar *selected, - const gchar *current); -const gchar * gvc_mixer_ui_device_get_active_profile (GvcMixerUIDevice* device); -const gchar * gvc_mixer_ui_device_get_matching_profile (GvcMixerUIDevice *dev, - const gchar *profile); -const gchar * gvc_mixer_ui_device_get_user_preferred_profile (GvcMixerUIDevice *dev); -const gchar * gvc_mixer_ui_device_get_top_priority_profile (GvcMixerUIDevice *dev); -GList * gvc_mixer_ui_device_get_profiles (GvcMixerUIDevice *dev); -GList * gvc_mixer_ui_device_get_supported_profiles (GvcMixerUIDevice *device); -gboolean gvc_mixer_ui_device_should_profiles_be_hidden (GvcMixerUIDevice *device); -void gvc_mixer_ui_device_set_profiles (GvcMixerUIDevice *device, - const GList *profiles); -void gvc_mixer_ui_device_set_user_preferred_profile (GvcMixerUIDevice *device, - const gchar *profile); -void gvc_mixer_ui_device_invalidate_stream (GvcMixerUIDevice *dev); -gboolean gvc_mixer_ui_device_has_ports (GvcMixerUIDevice *dev); -gboolean gvc_mixer_ui_device_is_output (GvcMixerUIDevice *dev); - -G_END_DECLS - -#endif /* _GVC_MIXER_UI_DEVICE_H_ */ diff --git a/panels/sound/gvc-pulseaudio-fake.h b/panels/sound/gvc-pulseaudio-fake.h deleted file mode 100644 index ab8f6b415..000000000 --- a/panels/sound/gvc-pulseaudio-fake.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GVC_PULSEAUDIO_FAKE_H -#define __GVC_PULSEAUDIO_FAKE_H - -#ifdef WITH_INTROSPECTION - -#ifndef PA_API_VERSION -#define pa_channel_position_t int -#define pa_volume_t guint32 -#define pa_context gpointer -#endif /* PA_API_VERSION */ - -#endif /* WITH_INTROSPECTION */ - -#endif /* __GVC_PULSEAUDIO_FAKE_H */