rpms/gnome-settings-daemon/F-11 0001-Update-gnome-volume-control-code-from-master.patch, NONE, 1.1 0002-Bug-590073-gnome-settings-daemon-crashed-with-SI.patch, NONE, 1.1 0003-Update-gnome-volume-control-code.patch, NONE, 1.1 0004-Update-volume-control-code-for-new-API.patch, NONE, 1.1 gnome-settings-daemon.spec, 1.109, 1.110
Bastien Nocera
hadess at fedoraproject.org
Mon Sep 7 15:02:30 UTC 2009
Author: hadess
Update of /cvs/pkgs/rpms/gnome-settings-daemon/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv27258
Modified Files:
gnome-settings-daemon.spec
Added Files:
0001-Update-gnome-volume-control-code-from-master.patch
0002-Bug-590073-gnome-settings-daemon-crashed-with-SI.patch
0003-Update-gnome-volume-control-code.patch
0004-Update-volume-control-code-for-new-API.patch
Log Message:
* Mon Sep 07 2009 Bastien Nocera <bnocera at redhat.com> 2.26.1-10
- Update volume code from 2.27
0001-Update-gnome-volume-control-code-from-master.patch:
cut-n-paste/gvc-channel-map.c | 175 ++++++++++++++++++---
cut-n-paste/gvc-channel-map.h | 24 ++
cut-n-paste/gvc-mixer-control.c | 276 +++++++++++++++++++++++++++-------
cut-n-paste/gvc-mixer-control.h | 1
cut-n-paste/gvc-mixer-event-role.c | 29 +--
cut-n-paste/gvc-mixer-event-role.h | 5
cut-n-paste/gvc-mixer-sink-input.c | 40 ++--
cut-n-paste/gvc-mixer-sink.c | 53 +++---
cut-n-paste/gvc-mixer-source-output.c | 6
cut-n-paste/gvc-mixer-source.c | 48 ++---
cut-n-paste/gvc-mixer-stream.c | 225 ++++++++++++++++++++++++---
cut-n-paste/gvc-mixer-stream.h | 23 ++
gsd-media-keys-manager.c | 11 -
13 files changed, 708 insertions(+), 208 deletions(-)
--- NEW FILE 0001-Update-gnome-volume-control-code-from-master.patch ---
>From dffcd6f60cb6984b28d673d013b436de4ee54f4e Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess at hadess.net>
Date: Mon, 22 Jun 2009 15:40:19 +0100
Subject: [PATCH 1/4] Update gnome-volume-control code from master
And make slight changes to gsd-media-keys-manager.c to match
the new API.
---
plugins/media-keys/cut-n-paste/gvc-channel-map.c | 175 +++++++++++--
plugins/media-keys/cut-n-paste/gvc-channel-map.h | 24 ++-
plugins/media-keys/cut-n-paste/gvc-mixer-control.c | 276 ++++++++++++++++----
plugins/media-keys/cut-n-paste/gvc-mixer-control.h | 1 +
.../media-keys/cut-n-paste/gvc-mixer-event-role.c | 29 +-
.../media-keys/cut-n-paste/gvc-mixer-event-role.h | 5 +-
.../media-keys/cut-n-paste/gvc-mixer-sink-input.c | 40 ++--
plugins/media-keys/cut-n-paste/gvc-mixer-sink.c | 53 ++--
.../cut-n-paste/gvc-mixer-source-output.c | 6 +-
plugins/media-keys/cut-n-paste/gvc-mixer-source.c | 48 ++--
plugins/media-keys/cut-n-paste/gvc-mixer-stream.c | 225 ++++++++++++++---
plugins/media-keys/cut-n-paste/gvc-mixer-stream.h | 23 ++-
plugins/media-keys/gsd-media-keys-manager.c | 10 +-
13 files changed, 708 insertions(+), 207 deletions(-)
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.c b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
index e7c9b22..32750ef 100644
--- a/plugins/media-keys/cut-n-paste/gvc-channel-map.c
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
@@ -33,15 +33,26 @@
#define GVC_CHANNEL_MAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GVC_TYPE_CHANNEL_MAP, GvcChannelMapPrivate))
+#ifndef PA_CHECK_VERSION
+#define PA_CHECK_VERSION(major,minor,micro) \
+ ((PA_MAJOR > (major)) || \
+ (PA_MAJOR == (major) && PA_MINOR > (minor)) || \
+ (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro)))
+#endif
+
+
struct GvcChannelMapPrivate
{
- guint num_channels;
- pa_channel_position_t positions[PA_CHANNELS_MAX];
- gdouble gains[PA_CHANNELS_MAX];
+ pa_channel_map pa_map;
+ pa_cvolume pa_volume;
+ gdouble extern_volume[NUM_TYPES]; /* volume, balance, fade, lfe */
+ gboolean can_balance;
+ gboolean can_fade;
+ gboolean has_lfe;
};
enum {
- GAINS_CHANGED,
+ VOLUME_CHANGED,
LAST_SIGNAL
};
@@ -53,25 +64,135 @@ static void gvc_channel_map_finalize (GObject *object);
G_DEFINE_TYPE (GvcChannelMap, gvc_channel_map, G_TYPE_OBJECT)
+/* FIXME remove when we depend on a newer PA */
+static int
+gvc_pa_channel_map_has_position (const pa_channel_map *map, pa_channel_position_t p) {
+ unsigned c;
+
+ g_return_val_if_fail(pa_channel_map_valid(map), 0);
+ g_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == p)
+ return 1;
+
+ return 0;
+}
+
+#if !PA_CHECK_VERSION(0,9,16)
+/* The PulseAudio master increase version only when tagged, so let's avoid clashing with pa_ namespace */
+#define pa_cvolume_get_position gvc_cvolume_get_position
+static pa_volume_t
+gvc_cvolume_get_position (pa_cvolume *cv, const pa_channel_map *map, pa_channel_position_t t) {
+ unsigned c;
+ pa_volume_t v = PA_VOLUME_MUTED;
+
+ g_assert(cv);
+ g_assert(map);
+
+ g_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
+ g_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == t)
+ if (cv->values[c] > v)
+ v = cv->values[c];
+
+ return v;
+}
+#endif
+
guint
gvc_channel_map_get_num_channels (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), 0);
- return map->priv->num_channels;
+
+ 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 (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->can_balance;
+}
+
+gboolean
+gvc_channel_map_can_fade (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 (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);
}
-gdouble *
-gvc_channel_map_get_gains (GvcChannelMap *map)
+gboolean
+gvc_channel_map_has_lfe (GvcChannelMap *map)
+{
+ g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), FALSE);
+
+ return map->priv->has_lfe;
+}
+
+const pa_channel_map *
+gvc_channel_map_get_pa_channel_map (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
- return map->priv->gains;
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return &map->priv->pa_map;
}
-pa_channel_position_t *
-gvc_channel_map_get_positions (GvcChannelMap *map)
+const pa_cvolume *
+gvc_channel_map_get_cvolume (GvcChannelMap *map)
{
g_return_val_if_fail (GVC_IS_CHANNEL_MAP (map), NULL);
- return map->priv->positions;
+
+ if (!pa_channel_map_valid(&map->priv->pa_map))
+ return NULL;
+
+ return &map->priv->pa_volume;
}
static void
@@ -81,11 +202,11 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
gobject_class->finalize = gvc_channel_map_finalize;
- signals [GAINS_CHANGED] =
- g_signal_new ("gains-changed",
+ signals [VOLUME_CHANGED] =
+ g_signal_new ("volume-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GvcChannelMapClass, gains_changed),
+ G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
@@ -94,10 +215,19 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
}
void
-gvc_channel_map_gains_changed (GvcChannelMap *map)
+gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv)
{
g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
- g_signal_emit (map, signals[GAINS_CHANGED], 0);
+ 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;
+
+ g_signal_emit (map, signals[VOLUME_CHANGED], 0);
}
static void
@@ -133,13 +263,14 @@ static void
set_from_pa_map (GvcChannelMap *map,
const pa_channel_map *pa_map)
{
- guint i;
+ 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->has_lfe = gvc_pa_channel_map_has_position (pa_map, PA_CHANNEL_POSITION_LFE);
- map->priv->num_channels = pa_map->channels;
- for (i = 0; i < pa_map->channels; i++) {
- map->priv->positions[i] = pa_map->map[i];
- map->priv->gains[i] = 1.0;
- }
+ map->priv->pa_map = *pa_map;
+ pa_cvolume_set(&map->priv->pa_volume, pa_map->channels, PA_VOLUME_NORM);
}
GvcChannelMap *
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.h b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
index 963904f..b35c9cb 100644
--- a/plugins/media-keys/cut-n-paste/gvc-channel-map.h
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
@@ -44,19 +44,35 @@ typedef struct
typedef struct
{
GObjectClass parent_class;
- void (*gains_changed) (GvcChannelMap *channel_map);
+ void (*volume_changed) (GvcChannelMap *channel_map);
} GvcChannelMapClass;
+enum {
+ VOLUME,
+ BALANCE,
+ FADE,
+ LFE,
+};
+
+#define NUM_TYPES LFE + 1
+
GType gvc_channel_map_get_type (void);
GvcChannelMap * gvc_channel_map_new (void);
GvcChannelMap * gvc_channel_map_new_from_pa_channel_map (const pa_channel_map *map);
guint gvc_channel_map_get_num_channels (GvcChannelMap *map);
-pa_channel_position_t * gvc_channel_map_get_positions (GvcChannelMap *map);
-gdouble * gvc_channel_map_get_gains (GvcChannelMap *map);
+const gdouble * gvc_channel_map_get_volume (GvcChannelMap *map);
+gboolean gvc_channel_map_can_balance (GvcChannelMap *map);
+gboolean gvc_channel_map_can_fade (GvcChannelMap *map);
+gboolean gvc_channel_map_has_lfe (GvcChannelMap *map);
-void gvc_channel_map_gains_changed (GvcChannelMap *map);
+void gvc_channel_map_volume_changed (GvcChannelMap *map,
+ const pa_cvolume *cv);
+const char * gvc_channel_map_get_mapping (GvcChannelMap *map);
+/* private */
+const pa_cvolume * gvc_channel_map_get_cvolume (GvcChannelMap *map);
+const pa_channel_map * gvc_channel_map_get_pa_channel_map (GvcChannelMap *map);
G_END_DECLS
#endif /* __GVC_CHANNEL_MAP_H */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-control.c b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
index e7dd18b..92b0286 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
@@ -48,6 +48,7 @@ struct GvcMixerControlPrivate
pa_mainloop_api *pa_api;
pa_context *pa_context;
int n_outstanding;
+ guint reconnect_id;
gboolean default_sink_is_set;
guint default_sink_id;
@@ -65,9 +66,12 @@ struct GvcMixerControlPrivate
GHashTable *sink_inputs; /* routable output streams */
GHashTable *source_outputs; /* routable input streams */
GHashTable *clients;
+
+ GvcMixerStream *new_default_stream; /* new default stream, used in gvc_mixer_control_set_default_sink () */
};
enum {
+ CONNECTING,
READY,
STREAM_ADDED,
STREAM_REMOVED,
@@ -104,6 +108,42 @@ gvc_mixer_control_get_event_sink_input (GvcMixerControl *control)
return stream;
}
+static void
+gvc_mixer_control_stream_restore_cb (pa_context *c,
+ const pa_ext_stream_restore_info *info,
+ int eol,
+ void *userdata)
+{
+ pa_operation *o;
+ GvcMixerControl *control = (GvcMixerControl *) userdata;
+ pa_ext_stream_restore_info new_info;
+
+ if (eol || control->priv->new_default_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 (control->priv->new_default_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, info->device);
+
+ pa_operation_unref (o);
+}
+
gboolean
gvc_mixer_control_set_default_sink (GvcMixerControl *control,
GvcMixerStream *stream)
@@ -118,7 +158,23 @@ gvc_mixer_control_set_default_sink (GvcMixerControl *control,
NULL,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_default_sink() failed");
+ 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_stream = stream;
+ g_object_add_weak_pointer (G_OBJECT (stream), (gpointer *) &control->priv->new_default_stream);
+
+ o = pa_ext_stream_restore_read (control->priv->pa_context,
+ gvc_mixer_control_stream_restore_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;
}
@@ -220,6 +276,13 @@ gvc_stream_collate (GvcMixerStream *a,
namea = gvc_mixer_stream_get_name (a);
nameb = gvc_mixer_stream_get_name (b);
+ if (nameb == NULL && namea == NULL)
+ return 0;
+ if (nameb == NULL)
+ return 1;
+ if (namea == NULL)
+ return -1;
+
return g_utf8_collate (namea, nameb);
}
@@ -320,12 +383,14 @@ _set_default_source (GvcMixerControl *control,
{
guint new_id;
- new_id = 0;
-
- if (stream != NULL) {
- new_id = gvc_mixer_stream_get_id (stream);
+ if (stream == NULL) {
+ control->priv->default_source_id = 0;
+ control->priv->default_source_is_set = FALSE;
+ return;
}
+ new_id = gvc_mixer_stream_get_id (stream);
+
if (control->priv->default_source_id != new_id) {
control->priv->default_source_id = new_id;
control->priv->default_source_is_set = TRUE;
@@ -342,12 +407,14 @@ _set_default_sink (GvcMixerControl *control,
{
guint new_id;
- new_id = 0;
-
- if (stream != NULL) {
- new_id = gvc_mixer_stream_get_id (stream);
+ if (stream == NULL) {
+ control->priv->default_sink_id = 0;
+ control->priv->default_sink_is_set = FALSE;
+ return;
}
+ new_id = gvc_mixer_stream_get_id (stream);
+
if (control->priv->default_sink_id != new_id) {
control->priv->default_sink_id = new_id;
control->priv->default_sink_is_set = TRUE;
@@ -495,6 +562,7 @@ update_sink (GvcMixerControl *control,
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);
@@ -506,22 +574,21 @@ update_sink (GvcMixerControl *control,
map_buff);
#endif
- /* for now completely ignore virtual streams */
- if (!(info->flags & PA_SINK_HARDWARE)) {
- return;
- }
-
+ map = NULL;
is_new = FALSE;
stream = g_hash_table_lookup (control->priv->sinks,
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_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);
@@ -531,11 +598,6 @@ update_sink (GvcMixerControl *control,
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));
- if (!!(info->flags & PA_SINK_DECIBEL_VOLUME)) {
- gdouble db;
- db = pa_sw_volume_to_dB (max_volume);
- gvc_mixer_stream_set_decibel (stream, db);
- }
if (is_new) {
g_hash_table_insert (control->priv->sinks,
@@ -549,6 +611,10 @@ update_sink (GvcMixerControl *control,
&& strcmp (control->priv->default_sink_name, info->name) == 0) {
_set_default_sink (control, stream);
}
+
+ if (map == NULL)
+ map = gvc_mixer_stream_get_channel_map (stream);
+ gvc_channel_map_volume_changed (map, &info->volume);
}
static void
@@ -566,8 +632,8 @@ update_source (GvcMixerControl *control,
info->description);
#endif
- /* for now completely ignore virtual streams */
- if (!(info->flags & PA_SOURCE_HARDWARE)) {
+ /* completely ignore monitors, they're not real sources */
+ if (info->monitor_of_sink != PA_INVALID_INDEX) {
return;
}
@@ -583,6 +649,10 @@ update_source (GvcMixerControl *control,
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);
@@ -593,11 +663,7 @@ update_source (GvcMixerControl *control,
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));
- if (!!(info->flags & PA_SINK_DECIBEL_VOLUME)) {
- gdouble db;
- db = pa_sw_volume_to_dB (max_volume);
- gvc_mixer_stream_set_decibel (stream, db);
- }
+ gvc_mixer_stream_set_base_volume (stream, (guint32) info->base_volume);
if (is_new) {
g_hash_table_insert (control->priv->sources,
@@ -662,6 +728,34 @@ set_icon_name_from_proplist (GvcMixerStream *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)
{
@@ -690,6 +784,10 @@ update_sink_input (GvcMixerControl *control,
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);
@@ -699,9 +797,12 @@ update_sink_input (GvcMixerControl *control,
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,
@@ -745,7 +846,9 @@ update_source_output (GvcMixerControl *control,
gvc_mixer_stream_set_name (stream, name);
gvc_mixer_stream_set_description (stream, info->name);
- set_icon_name_from_proplist (stream, info->proplist, "applications-multimedia");
+ 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,
@@ -938,8 +1041,16 @@ update_event_role_stream (GvcMixerControl *control,
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);
+ info->device,
+ map);
control->priv->event_sink_input_id = gvc_mixer_stream_get_id (stream);
control->priv->event_sink_input_is_set = TRUE;
@@ -1346,6 +1457,78 @@ gvc_mixer_control_ready (GvcMixerControl *control)
}
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);
+
+ /* FIXME: read these from an object property */
+ proplist = pa_proplist_new ();
+ pa_proplist_sets (proplist,
+ PA_PROP_APPLICATION_NAME,
+ _("GNOME Volume Control"));
+ 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)
{
@@ -1363,7 +1546,9 @@ _pa_context_state_cb (pa_context *context,
break;
case PA_CONTEXT_FAILED:
- g_warning ("Connection failed");
+ g_warning ("Connection failed, reconnecting...");
+ if (control->priv->reconnect_id == 0)
+ control->priv->reconnect_id = g_idle_add (idle_reconnect, control);
break;
case PA_CONTEXT_TERMINATED:
@@ -1386,7 +1571,8 @@ gvc_mixer_control_open (GvcMixerControl *control)
_pa_context_state_cb,
control);
- res = pa_context_connect (control->priv->pa_context, NULL, (pa_context_flags_t) 0, NULL);
+ g_signal_emit (G_OBJECT (control), signals[CONNECTING], 0);
+ 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)));
@@ -1465,30 +1651,12 @@ gvc_mixer_control_constructor (GType type,
{
GObject *object;
GvcMixerControl *self;
- pa_proplist *proplist;
object = G_OBJECT_CLASS (gvc_mixer_control_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_CONTROL (object);
- /* FIXME: read these from an object property */
- proplist = pa_proplist_new ();
- pa_proplist_sets (proplist,
- PA_PROP_APPLICATION_NAME,
- _("GNOME Volume Control"));
- 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);
- g_assert (self->priv->pa_context);
- pa_proplist_free (proplist);
+ gvc_mixer_new_pa_context (self);
return object;
}
@@ -1502,6 +1670,14 @@ gvc_mixer_control_class_init (GvcMixerControlClass *klass)
object_class->dispose = gvc_mixer_control_dispose;
object_class->finalize = gvc_mixer_control_finalize;
+ signals [CONNECTING] =
+ g_signal_new ("connecting",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GvcMixerControlClass, connecting),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
signals [READY] =
g_signal_new ("ready",
G_TYPE_FROM_CLASS (klass),
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-control.h b/plugins/media-keys/cut-n-paste/gvc-mixer-control.h
index 33e745a..3de9e62 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-control.h
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-control.h
@@ -46,6 +46,7 @@ typedef struct
{
GObjectClass parent_class;
+ void (*connecting) (GvcMixerControl *control);
void (*ready) (GvcMixerControl *control);
void (*stream_added) (GvcMixerControl *control,
guint id);
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c
index b5469ca..69e38ce 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.c
@@ -53,21 +53,22 @@ G_DEFINE_TYPE (GvcMixerEventRole, gvc_mixer_event_role, GVC_TYPE_MIXER_STREAM)
static gboolean
update_settings (GvcMixerEventRole *role,
- guint volume,
- gboolean is_muted)
+ gboolean is_muted,
+ gpointer *op)
{
pa_operation *o;
guint index;
+ GvcChannelMap *map;
pa_context *context;
pa_ext_stream_restore_info info;
index = gvc_mixer_stream_get_index (GVC_MIXER_STREAM (role));
- pa_cvolume_set (&info.volume, 1, (pa_volume_t)volume);
+ 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.channels = 1;
- info.channel_map.map[0] = PA_CHANNEL_POSITION_MONO;
+ info.channel_map = *gvc_channel_map_get_pa_channel_map(map);
info.device = role->priv->device;
info.mute = is_muted;
@@ -86,18 +87,17 @@ update_settings (GvcMixerEventRole *role,
return FALSE;
}
- pa_operation_unref(o);
+ if (op != NULL)
+ *op = o;
return TRUE;
}
static gboolean
-gvc_mixer_event_role_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_event_role_push_volume (GvcMixerStream *stream, gpointer *op)
{
return update_settings (GVC_MIXER_EVENT_ROLE (stream),
- volume,
- gvc_mixer_stream_get_is_muted (stream));
+ gvc_mixer_stream_get_is_muted (stream), op);
}
static gboolean
@@ -105,8 +105,7 @@ gvc_mixer_event_role_change_is_muted (GvcMixerStream *stream,
gboolean is_muted)
{
return update_settings (GVC_MIXER_EVENT_ROLE (stream),
- gvc_mixer_stream_get_volume (stream),
- is_muted);
+ is_muted, NULL);
}
static gboolean
@@ -184,7 +183,7 @@ gvc_mixer_event_role_class_init (GvcMixerEventRoleClass *klass)
object_class->set_property = gvc_mixer_event_role_set_property;
object_class->get_property = gvc_mixer_event_role_get_property;
- stream_class->change_volume = gvc_mixer_event_role_change_volume;
+ 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,
@@ -224,7 +223,8 @@ gvc_mixer_event_role_finalize (GObject *object)
GvcMixerStream *
gvc_mixer_event_role_new (pa_context *context,
- const char *device)
+ const char *device,
+ GvcChannelMap *channel_map)
{
GObject *object;
@@ -232,6 +232,7 @@ gvc_mixer_event_role_new (pa_context *context,
"pa-context", context,
"index", 0,
"device", device,
+ "channel-map", channel_map,
NULL);
return GVC_MIXER_STREAM (object);
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h
index 280c597..ab4c509 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-event-role.h
@@ -48,8 +48,9 @@ typedef struct
GType gvc_mixer_event_role_get_type (void);
-GvcMixerStream * gvc_mixer_event_role_new (pa_context *context,
- const char *device);
+GvcMixerStream * gvc_mixer_event_role_new (pa_context *context,
+ const char *device,
+ GvcChannelMap *channel_map);
G_END_DECLS
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c
index b2c7172..35551bb 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink-input.c
@@ -40,44 +40,33 @@ struct GvcMixerSinkInputPrivate
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);
+static void gvc_mixer_sink_input_finalize (GObject *object);
+static void gvc_mixer_sink_input_dispose (GObject *object);
G_DEFINE_TYPE (GvcMixerSinkInput, gvc_mixer_sink_input, GVC_TYPE_MIXER_STREAM)
static gboolean
-gvc_mixer_sink_input_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint i;
+ const pa_cvolume *cv;
guint num_channels;
- gdouble *gains;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
-
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- cv.values[i] = v;
- }
+ 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,
+ cv,
NULL,
NULL);
@@ -86,7 +75,7 @@ gvc_mixer_sink_input_change_volume (GvcMixerStream *stream,
return FALSE;
}
- pa_operation_unref(o);
+ *op = o;
return TRUE;
}
@@ -140,9 +129,10 @@ gvc_mixer_sink_input_class_init (GvcMixerSinkInputClass *klass)
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->constructor = gvc_mixer_sink_input_constructor;
+ object_class->dispose = gvc_mixer_sink_input_dispose;
object_class->finalize = gvc_mixer_sink_input_finalize;
- stream_class->change_volume = gvc_mixer_sink_input_change_volume;
+ 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));
@@ -152,7 +142,19 @@ 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_dispose (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_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->dispose (object);
}
static void
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c
index 76eb3d7..06e5af6 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-sink.c
@@ -40,57 +40,41 @@ struct GvcMixerSinkPrivate
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);
+static void gvc_mixer_sink_finalize (GObject *object);
+static void gvc_mixer_sink_dispose (GObject *object);
G_DEFINE_TYPE (GvcMixerSink, gvc_mixer_sink, GVC_TYPE_MIXER_STREAM)
static gboolean
-gvc_mixer_sink_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_sink_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint i;
- guint num_channels;
- gdouble *gains;
+ const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
-
map = gvc_mixer_stream_get_channel_map (stream);
- num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
-
- g_debug ("Changing volume for sink: n=%d vol=%u", num_channels, (guint)volume);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
-
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- g_debug ("Channel %d v=%u", i, v);
- cv.values[i] = v;
- }
+ /* 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,
+ cv,
NULL,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_sink_volume_by_index() failed");
+ g_warning ("pa_context_set_sink_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
- pa_operation_unref(o);
+ *op = o;
return TRUE;
}
@@ -113,7 +97,7 @@ gvc_mixer_sink_change_is_muted (GvcMixerStream *stream,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_sink_mute_by_index() failed");
+ g_warning ("pa_context_set_sink_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
@@ -127,7 +111,7 @@ gvc_mixer_sink_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
- GObject *object;
+ GObject *object;
GvcMixerSink *self;
object = G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->constructor (type, n_construct_properties, construct_params);
@@ -144,9 +128,10 @@ gvc_mixer_sink_class_init (GvcMixerSinkClass *klass)
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->constructor = gvc_mixer_sink_constructor;
+ object_class->dispose = gvc_mixer_sink_dispose;
object_class->finalize = gvc_mixer_sink_finalize;
- stream_class->change_volume = gvc_mixer_sink_change_volume;
+ stream_class->push_volume = gvc_mixer_sink_push_volume;
stream_class->change_is_muted = gvc_mixer_sink_change_is_muted;
g_type_class_add_private (klass, sizeof (GvcMixerSinkPrivate));
@@ -156,7 +141,19 @@ static void
gvc_mixer_sink_init (GvcMixerSink *sink)
{
sink->priv = GVC_MIXER_SINK_GET_PRIVATE (sink);
+}
+
+static void
+gvc_mixer_sink_dispose (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_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object);
}
static void
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c
index b71ad23..b4cc34d 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source-output.c
@@ -45,10 +45,10 @@ 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_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_source_output_push_volume (GvcMixerStream *stream, gpointer *op)
{
/* FIXME: */
+ *op = NULL;
return TRUE;
}
@@ -84,7 +84,7 @@ gvc_mixer_source_output_class_init (GvcMixerSourceOutputClass *klass)
object_class->constructor = gvc_mixer_source_output_constructor;
object_class->finalize = gvc_mixer_source_output_finalize;
- stream_class->change_volume = gvc_mixer_source_output_change_volume;
+ 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));
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-source.c b/plugins/media-keys/cut-n-paste/gvc-mixer-source.c
index de1b09e..ae02d85 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-source.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-source.c
@@ -41,53 +41,40 @@ struct GvcMixerSourcePrivate
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);
+static void gvc_mixer_source_dispose (GObject *object);
G_DEFINE_TYPE (GvcMixerSource, gvc_mixer_source, GVC_TYPE_MIXER_STREAM)
static gboolean
-gvc_mixer_source_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_source_push_volume (GvcMixerStream *stream, gpointer *op)
{
pa_operation *o;
guint index;
GvcChannelMap *map;
pa_context *context;
- pa_cvolume cv;
- guint num_channels;
- guint i;
- gdouble *gains;
+ const pa_cvolume *cv;
index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream);
- num_channels = gvc_channel_map_get_num_channels (map);
- gains = gvc_channel_map_get_gains (map);
- /* set all values to nominal level */
- pa_cvolume_set (&cv, num_channels, (pa_volume_t)volume);
-
-
- /* apply channel gain mapping */
- for (i = 0; i < num_channels; i++) {
- pa_volume_t v;
- v = (double) volume * gains[i];
- cv.values[i] = v;
- }
+ /* 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,
+ cv,
NULL,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_source_volume_by_index() failed");
+ g_warning ("pa_context_set_source_volume_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
- pa_operation_unref(o);
+ *op = o;
return TRUE;
}
@@ -110,7 +97,7 @@ gvc_mixer_source_change_is_muted (GvcMixerStream *stream,
NULL);
if (o == NULL) {
- g_warning ("pa_context_set_source_mute_by_index() failed");
+ g_warning ("pa_context_set_source_mute_by_index() failed: %s", pa_strerror(pa_context_errno(context)));
return FALSE;
}
@@ -124,7 +111,7 @@ gvc_mixer_source_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
- GObject *object;
+ GObject *object;
GvcMixerSource *self;
object = G_OBJECT_CLASS (gvc_mixer_source_parent_class)->constructor (type, n_construct_properties, construct_params);
@@ -141,9 +128,10 @@ gvc_mixer_source_class_init (GvcMixerSourceClass *klass)
GvcMixerStreamClass *stream_class = GVC_MIXER_STREAM_CLASS (klass);
object_class->constructor = gvc_mixer_source_constructor;
+ object_class->dispose = gvc_mixer_source_dispose;
object_class->finalize = gvc_mixer_source_finalize;
- stream_class->change_volume = gvc_mixer_source_change_volume;
+ stream_class->push_volume = gvc_mixer_source_push_volume;
stream_class->change_is_muted = gvc_mixer_source_change_is_muted;
g_type_class_add_private (klass, sizeof (GvcMixerSourcePrivate));
@@ -153,7 +141,19 @@ static void
gvc_mixer_source_init (GvcMixerSource *source)
{
source->priv = GVC_MIXER_SOURCE_GET_PRIVATE (source);
+}
+
+static void
+gvc_mixer_source_dispose (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_OBJECT_CLASS (gvc_mixer_source_parent_class)->dispose (object);
}
static void
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
index 69d8598..e5cfb19 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
@@ -41,13 +41,16 @@ struct GvcMixerStreamPrivate
guint id;
guint index;
GvcChannelMap *channel_map;
- guint volume;
- gdouble decibel;
char *name;
char *description;
+ char *application_id;
char *icon_name;
gboolean is_muted;
gboolean can_decibel;
+ gboolean is_event_stream;
+ gboolean is_virtual;
+ pa_volume_t base_volume;
+ pa_operation *change_volume_op;
};
enum
@@ -59,11 +62,14 @@ enum
PROP_INDEX,
PROP_NAME,
PROP_DESCRIPTION,
+ PROP_APPLICATION_ID,
PROP_ICON_NAME,
PROP_VOLUME,
PROP_DECIBEL,
PROP_IS_MUTED,
- PROP_CAN_DECIBEL
+ PROP_CAN_DECIBEL,
+ PROP_IS_EVENT_STREAM,
+ PROP_IS_VIRTUAL,
};
static void gvc_mixer_stream_class_init (GvcMixerStreamClass *klass);
@@ -114,28 +120,36 @@ gvc_mixer_stream_get_channel_map (GvcMixerStream *stream)
return stream->priv->channel_map;
}
-guint
+pa_volume_t
gvc_mixer_stream_get_volume (GvcMixerStream *stream)
{
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), 0);
- return stream->priv->volume;
+
+ 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 stream->priv->decibel;
+
+ return pa_sw_volume_to_dB(
+ (pa_volume_t) gvc_channel_map_get_volume(stream->priv->channel_map)[VOLUME]);
}
gboolean
gvc_mixer_stream_set_volume (GvcMixerStream *stream,
- pa_volume_t volume)
+ pa_volume_t volume)
{
+ pa_cvolume cv;
+
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
- if (volume != stream->priv->volume) {
- stream->priv->volume = volume;
+ 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);
g_object_notify (G_OBJECT (stream), "volume");
}
@@ -146,11 +160,16 @@ gboolean
gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
gdouble db)
{
+ pa_cvolume cv;
+
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
- if (db != stream->priv->decibel) {
- stream->priv->decibel = db;
- g_object_notify (G_OBJECT (stream), "decibel");
+ 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);
+ g_object_notify (G_OBJECT (stream), "volume");
}
return TRUE;
@@ -238,12 +257,73 @@ gvc_mixer_stream_set_description (GvcMixerStream *stream,
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_gains_changed (GvcChannelMap *channel_map,
- GvcMixerStream *stream)
+on_channel_map_volume_changed (GvcChannelMap *channel_map,
+ GvcMixerStream *stream)
{
- g_debug ("Gains changed");
- gvc_mixer_stream_change_volume (stream, stream->priv->volume);
+ gvc_mixer_stream_push_volume (stream);
+
+ g_object_notify (G_OBJECT (stream), "volume");
}
static gboolean
@@ -258,7 +338,7 @@ gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
if (stream->priv->channel_map != NULL) {
g_signal_handlers_disconnect_by_func (stream->priv->channel_map,
- on_channel_map_gains_changed,
+ on_channel_map_volume_changed,
stream);
g_object_unref (stream->priv->channel_map);
}
@@ -267,8 +347,8 @@ gvc_mixer_stream_set_channel_map (GvcMixerStream *stream,
if (stream->priv->channel_map != NULL) {
g_signal_connect (stream->priv->channel_map,
- "gains-changed",
- G_CALLBACK (on_channel_map_gains_changed),
+ "volume-changed",
+ G_CALLBACK (on_channel_map_volume_changed),
stream);
g_object_notify (G_OBJECT (stream), "channel-map");
@@ -297,6 +377,25 @@ gvc_mixer_stream_set_icon_name (GvcMixerStream *stream,
return TRUE;
}
+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;
+}
+
+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;
+}
+
static void
gvc_mixer_stream_set_property (GObject *object,
guint prop_id,
@@ -324,6 +423,9 @@ gvc_mixer_stream_set_property (GObject *object,
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;
@@ -336,6 +438,12 @@ gvc_mixer_stream_set_property (GObject *object,
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;
@@ -372,18 +480,29 @@ gvc_mixer_stream_get_property (GObject *object,
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_VOLUME:
- g_value_set_ulong (value, self->priv->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, self->priv->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;
@@ -411,8 +530,7 @@ gvc_mixer_stream_constructor (GType type,
}
static gboolean
-gvc_mixer_stream_real_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_stream_real_push_volume (GvcMixerStream *stream, gpointer *op)
{
return FALSE;
}
@@ -425,12 +543,17 @@ gvc_mixer_stream_real_change_is_muted (GvcMixerStream *stream,
}
gboolean
-gvc_mixer_stream_change_volume (GvcMixerStream *stream,
- guint volume)
+gvc_mixer_stream_push_volume (GvcMixerStream *stream)
{
+ pa_operation *op;
gboolean ret;
g_return_val_if_fail (GVC_IS_MIXER_STREAM (stream), FALSE);
- ret = GVC_MIXER_STREAM_GET_CLASS (stream)->change_volume (stream, volume);
+ 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;
}
@@ -444,6 +567,21 @@ gvc_mixer_stream_change_is_muted (GvcMixerStream *stream,
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)
{
@@ -454,7 +592,7 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
gobject_class->set_property = gvc_mixer_stream_set_property;
gobject_class->get_property = gvc_mixer_stream_get_property;
- klass->change_volume = gvc_mixer_stream_real_change_volume;
+ klass->push_volume = gvc_mixer_stream_real_push_volume;
klass->change_is_muted = gvc_mixer_stream_real_change_is_muted;
g_object_class_install_property (gobject_class,
@@ -490,7 +628,7 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
"Volume",
"The volume for this stream",
0, G_MAXULONG, 0,
- G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+ G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DECIBEL,
g_param_spec_double ("decibel",
@@ -514,6 +652,13 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
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",
@@ -534,7 +679,20 @@ gvc_mixer_stream_class_init (GvcMixerStreamClass *klass)
"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_type_class_add_private (klass, sizeof (GvcMixerStreamPrivate));
}
@@ -542,7 +700,6 @@ static void
gvc_mixer_stream_init (GvcMixerStream *stream)
{
stream->priv = GVC_MIXER_STREAM_GET_PRIVATE (stream);
-
}
static void
@@ -563,8 +720,16 @@ gvc_mixer_stream_finalize (GObject *object)
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;
+ 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/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h
index 3dee03b..4171ca3 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.h
@@ -48,8 +48,7 @@ typedef struct
GObjectClass parent_class;
/* vtable */
- gboolean (*change_volume) (GvcMixerStream *stream,
- guint volume);
+ gboolean (*push_volume) (GvcMixerStream *stream, gpointer *operation);
gboolean (*change_is_muted) (GvcMixerStream *stream,
gboolean is_muted);
} GvcMixerStreamClass;
@@ -61,22 +60,26 @@ guint gvc_mixer_stream_get_index (GvcMixerStream *stream);
guint gvc_mixer_stream_get_id (GvcMixerStream *stream);
GvcChannelMap * gvc_mixer_stream_get_channel_map (GvcMixerStream *stream);
-guint gvc_mixer_stream_get_volume (GvcMixerStream *stream);
+pa_volume_t gvc_mixer_stream_get_volume (GvcMixerStream *stream);
gdouble gvc_mixer_stream_get_decibel (GvcMixerStream *stream);
-gboolean gvc_mixer_stream_change_volume (GvcMixerStream *stream,
- guint volume);
+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_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);
/* private */
gboolean gvc_mixer_stream_set_volume (GvcMixerStream *stream,
- guint volume);
+ pa_volume_t volume);
gboolean gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
gdouble db);
gboolean gvc_mixer_stream_set_is_muted (GvcMixerStream *stream,
@@ -89,6 +92,14 @@ 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_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);
G_END_DECLS
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index d35048c..3eeea71 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -687,17 +687,17 @@ do_sound_action (GsdMediaKeysManager *manager,
if (!muted && (vol <= norm_vol_step)) {
manager->priv->num_expected_update_signals = 2;
gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
- gvc_mixer_stream_change_volume (manager->priv->stream, 0);
+ gvc_mixer_stream_set_volume (manager->priv->stream, 0);
} else if (!muted) {
manager->priv->num_expected_update_signals = 1;
- gvc_mixer_stream_change_volume (manager->priv->stream, vol - norm_vol_step);
+ gvc_mixer_stream_set_volume (manager->priv->stream, vol - norm_vol_step);
}
break;
case VOLUME_UP_KEY:
if (muted) {
if (vol == 0) {
manager->priv->num_expected_update_signals = 2;
- gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step);
+ gvc_mixer_stream_set_volume (manager->priv->stream, vol + norm_vol_step);
gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
} else {
manager->priv->num_expected_update_signals = 1;
@@ -707,9 +707,9 @@ do_sound_action (GsdMediaKeysManager *manager,
if (vol < MAX_VOLUME) {
manager->priv->num_expected_update_signals = 1;
if (vol + norm_vol_step >= MAX_VOLUME) {
- gvc_mixer_stream_change_volume (manager->priv->stream, MAX_VOLUME);
+ gvc_mixer_stream_set_volume (manager->priv->stream, MAX_VOLUME);
} else {
- gvc_mixer_stream_change_volume (manager->priv->stream, vol + norm_vol_step);
+ gvc_mixer_stream_set_volume (manager->priv->stream, vol + norm_vol_step);
}
}
}
--
1.6.2.5
0002-Bug-590073-gnome-settings-daemon-crashed-with-SI.patch:
gsd-media-keys-manager.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- NEW FILE 0002-Bug-590073-gnome-settings-daemon-crashed-with-SI.patch ---
>From 604a1f534e703b9d492f886ffabdca879df824ef Mon Sep 17 00:00:00 2001
From: Chris Coulson <chrisccoulson at googlemail.com>
Date: Fri, 31 Jul 2009 16:59:36 +0100
Subject: [PATCH 2/4] =?utf-8?q?Bug=20590073=20=E2=80=93=20gnome-settings-daemon=20crashed=20with=20SIGSEGV=20in=20gvc=5Fmixer=5Fstream=5Fis=5Frunning()?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Fix crasher when the default sink changes, we were unref'ing
streams, when never ref'ing them.
---
plugins/media-keys/gsd-media-keys-manager.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 3eeea71..8438875 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -740,7 +740,7 @@ update_default_sink (GsdMediaKeysManager *manager)
}
if (stream != NULL) {
- manager->priv->stream = stream;
+ manager->priv->stream = g_object_ref (stream);
g_signal_connect (G_OBJECT (manager->priv->stream), "notify::volume",
G_CALLBACK (on_stream_event_notify), manager);
g_signal_connect (G_OBJECT (manager->priv->stream), "notify::is-muted",
--
1.6.2.5
0003-Update-gnome-volume-control-code.patch:
cut-n-paste/gvc-channel-map.c | 15 +++++++++++----
cut-n-paste/gvc-channel-map.h | 5 +++--
cut-n-paste/gvc-mixer-control.c | 2 +-
cut-n-paste/gvc-mixer-stream.c | 16 +++++++++++++---
gsd-media-keys-manager.c | 4 +++-
5 files changed, 31 insertions(+), 11 deletions(-)
--- NEW FILE 0003-Update-gnome-volume-control-code.patch ---
>From aec15023ea43ab636df75e7237a6452c90bc5eb3 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess at hadess.net>
Date: Fri, 14 Aug 2009 18:16:10 +0100
Subject: [PATCH 3/4] Update gnome-volume-control code
Should cut down on the feedback loops.
---
plugins/media-keys/cut-n-paste/gvc-channel-map.c | 15 +++++++++++----
plugins/media-keys/cut-n-paste/gvc-channel-map.h | 5 +++--
plugins/media-keys/cut-n-paste/gvc-mixer-control.c | 2 +-
plugins/media-keys/cut-n-paste/gvc-mixer-stream.c | 16 +++++++++++++---
plugins/media-keys/gsd-media-keys-manager.c | 3 +++
5 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.c b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
index 32750ef..ea3e5af 100644
--- a/plugins/media-keys/cut-n-paste/gvc-channel-map.c
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.c
@@ -44,6 +44,7 @@
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;
@@ -208,15 +209,16 @@ gvc_channel_map_class_init (GvcChannelMapClass *klass)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GvcChannelMapClass, volume_changed),
NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ 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)
+ const pa_cvolume *cv,
+ gboolean set)
{
g_return_if_fail (GVC_IS_CHANNEL_MAP (map));
g_return_if_fail (cv != NULL);
@@ -227,13 +229,18 @@ gvc_channel_map_volume_changed (GvcChannelMap *map,
map->priv->pa_volume = *cv;
- g_signal_emit (map, signals[VOLUME_CHANGED], 0);
+ 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
diff --git a/plugins/media-keys/cut-n-paste/gvc-channel-map.h b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
index b35c9cb..497ce69 100644
--- a/plugins/media-keys/cut-n-paste/gvc-channel-map.h
+++ b/plugins/media-keys/cut-n-paste/gvc-channel-map.h
@@ -44,7 +44,7 @@ typedef struct
typedef struct
{
GObjectClass parent_class;
- void (*volume_changed) (GvcChannelMap *channel_map);
+ void (*volume_changed) (GvcChannelMap *channel_map, gboolean set);
} GvcChannelMapClass;
enum {
@@ -67,7 +67,8 @@ gboolean gvc_channel_map_can_fade (GvcChannelMap
gboolean gvc_channel_map_has_lfe (GvcChannelMap *map);
void gvc_channel_map_volume_changed (GvcChannelMap *map,
- const pa_cvolume *cv);
+ const pa_cvolume *cv,
+ gboolean set);
const char * gvc_channel_map_get_mapping (GvcChannelMap *map);
/* private */
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-control.c b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
index 92b0286..6986202 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-control.c
@@ -614,7 +614,7 @@ update_sink (GvcMixerControl *control,
if (map == NULL)
map = gvc_mixer_stream_get_channel_map (stream);
- gvc_channel_map_volume_changed (map, &info->volume);
+ gvc_channel_map_volume_changed (map, &info->volume, TRUE);
}
static void
diff --git a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
index e5cfb19..0f8bea7 100644
--- a/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
+++ b/plugins/media-keys/cut-n-paste/gvc-mixer-stream.c
@@ -149,7 +149,7 @@ gvc_mixer_stream_set_volume (GvcMixerStream *stream,
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);
+ gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
g_object_notify (G_OBJECT (stream), "volume");
}
@@ -168,7 +168,7 @@ gvc_mixer_stream_set_decibel (GvcMixerStream *stream,
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);
+ gvc_channel_map_volume_changed(stream->priv->channel_map, &cv, FALSE);
g_object_notify (G_OBJECT (stream), "volume");
}
@@ -319,9 +319,11 @@ gvc_mixer_stream_set_application_id (GvcMixerStream *stream,
static void
on_channel_map_volume_changed (GvcChannelMap *channel_map,
+ gboolean set,
GvcMixerStream *stream)
{
- gvc_mixer_stream_push_volume (stream);
+ if (set == TRUE)
+ gvc_mixer_stream_push_volume (stream);
g_object_notify (G_OBJECT (stream), "volume");
}
@@ -547,7 +549,15 @@ 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)
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 8438875..2b14bcc 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -688,9 +688,11 @@ do_sound_action (GsdMediaKeysManager *manager,
manager->priv->num_expected_update_signals = 2;
gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
gvc_mixer_stream_set_volume (manager->priv->stream, 0);
+ gvc_mixer_stream_push_volume (manager->priv->stream);
} else if (!muted) {
manager->priv->num_expected_update_signals = 1;
gvc_mixer_stream_set_volume (manager->priv->stream, vol - norm_vol_step);
+ gvc_mixer_stream_push_volume (manager->priv->stream);
}
break;
case VOLUME_UP_KEY:
@@ -698,6 +700,7 @@ do_sound_action (GsdMediaKeysManager *manager,
if (vol == 0) {
manager->priv->num_expected_update_signals = 2;
gvc_mixer_stream_set_volume (manager->priv->stream, vol + norm_vol_step);
+ gvc_mixer_stream_push_volume (manager->priv->stream);
gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
} else {
manager->priv->num_expected_update_signals = 1;
--
1.6.2.5
0004-Update-volume-control-code-for-new-API.patch:
gsd-media-keys-manager.c | 89 ++++++++++++++---------------------------------
1 file changed, 27 insertions(+), 62 deletions(-)
--- NEW FILE 0004-Update-volume-control-code-for-new-API.patch ---
>From 98664ae573c2fb96ff2ff56294c2d69e4bfcc73b Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess at hadess.net>
Date: Tue, 18 Aug 2009 14:00:09 +0100
Subject: [PATCH 4/4] Update volume control code for new API
Only push volume changes if they are necessary, and
remove the "expected signals" crud.
We shouldn't be waiting for PA to actually do the changes
before displaying them, and we should always show feedback
to the user when they pressed a key.
---
plugins/media-keys/gsd-media-keys-manager.c | 88 ++++++++------------------
1 files changed, 27 insertions(+), 61 deletions(-)
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 2b14bcc..33b4675 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -87,9 +87,6 @@ struct GsdMediaKeysManagerPrivate
/* Volume bits */
GvcMixerControl *volume;
GvcMixerStream *stream;
- /* Number of expected update signals, zero meaning we
- * shouldn't be showing any update dialogues */
- guint num_expected_update_signals;
#endif /* HAVE_PULSE */
GtkWidget *dialog;
GConfClient *conf_client;
@@ -616,23 +613,10 @@ do_eject_action (GsdMediaKeysManager *manager)
#ifdef HAVE_PULSE
static void
-update_dialog (GsdMediaKeysManager *manager)
+update_dialog (GsdMediaKeysManager *manager,
+ guint vol,
+ gboolean muted)
{
- gboolean muted;
- guint vol;
-
- /* Not expecting a dialogue to show up */
- if (manager->priv->num_expected_update_signals == 0)
- return;
-
- /* If we aren't expecting any more updates, show the dialogue */
- manager->priv->num_expected_update_signals--;
- if (manager->priv->num_expected_update_signals != 0)
- return;
-
- vol = gvc_mixer_stream_get_volume (manager->priv->stream);
- muted = gvc_mixer_stream_get_is_muted (manager->priv->stream);
-
dialog_init (manager);
gsd_media_keys_window_set_volume_muted (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
muted);
@@ -644,14 +628,6 @@ update_dialog (GsdMediaKeysManager *manager)
}
static void
-on_stream_event_notify (GObject *object,
- GParamSpec *pspec,
- GsdMediaKeysManager *manager)
-{
- update_dialog (manager);
-}
-
-static void
do_sound_action (GsdMediaKeysManager *manager,
int type)
{
@@ -674,56 +650,52 @@ do_sound_action (GsdMediaKeysManager *manager,
/* FIXME: this is racy */
vol = gvc_mixer_stream_get_volume (manager->priv->stream);
muted = gvc_mixer_stream_get_is_muted (manager->priv->stream);
- /* By default, we would be showing a dialogue
- * based on the current values, eg. an unchanged dialogue */
- manager->priv->num_expected_update_signals = 0;
switch (type) {
case MUTE_KEY:
- manager->priv->num_expected_update_signals = 1;
- gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
+ muted = !muted;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
break;
case VOLUME_DOWN_KEY:
if (!muted && (vol <= norm_vol_step)) {
- manager->priv->num_expected_update_signals = 2;
- gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
- gvc_mixer_stream_set_volume (manager->priv->stream, 0);
- gvc_mixer_stream_push_volume (manager->priv->stream);
+ muted = !muted;
+ vol = 0;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE)
+ gvc_mixer_stream_push_volume (manager->priv->stream);
} else if (!muted) {
- manager->priv->num_expected_update_signals = 1;
- gvc_mixer_stream_set_volume (manager->priv->stream, vol - norm_vol_step);
- gvc_mixer_stream_push_volume (manager->priv->stream);
+ vol = vol - norm_vol_step;
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE)
+ gvc_mixer_stream_push_volume (manager->priv->stream);
}
break;
case VOLUME_UP_KEY:
if (muted) {
+ muted = !muted;
if (vol == 0) {
- manager->priv->num_expected_update_signals = 2;
- gvc_mixer_stream_set_volume (manager->priv->stream, vol + norm_vol_step);
- gvc_mixer_stream_push_volume (manager->priv->stream);
- gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
+ vol = vol + norm_vol_step;
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE)
+ gvc_mixer_stream_push_volume (manager->priv->stream);
} else {
- manager->priv->num_expected_update_signals = 1;
- gvc_mixer_stream_change_is_muted (manager->priv->stream, !muted);
+ gvc_mixer_stream_change_is_muted (manager->priv->stream, muted);
}
} else {
if (vol < MAX_VOLUME) {
- manager->priv->num_expected_update_signals = 1;
+ gboolean set;
if (vol + norm_vol_step >= MAX_VOLUME) {
- gvc_mixer_stream_set_volume (manager->priv->stream, MAX_VOLUME);
+ vol = MAX_VOLUME;
} else {
- gvc_mixer_stream_set_volume (manager->priv->stream, vol + norm_vol_step);
+ vol = vol + norm_vol_step;
}
+ if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE)
+ gvc_mixer_stream_push_volume (manager->priv->stream);
}
}
break;
}
- /* We didn't actually make any changes, so force showing the dialogue */
- if (manager->priv->num_expected_update_signals == 0) {
- manager->priv->num_expected_update_signals = 1;
- update_dialog (manager);
- }
+ update_dialog (manager, vol, muted);
}
static void
@@ -736,18 +708,12 @@ update_default_sink (GsdMediaKeysManager *manager)
return;
if (manager->priv->stream != NULL) {
- g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->stream),
- G_CALLBACK (on_stream_event_notify), manager);
g_object_unref (manager->priv->stream);
manager->priv->stream = NULL;
}
if (stream != NULL) {
manager->priv->stream = g_object_ref (stream);
- g_signal_connect (G_OBJECT (manager->priv->stream), "notify::volume",
- G_CALLBACK (on_stream_event_notify), manager);
- g_signal_connect (G_OBJECT (manager->priv->stream), "notify::is-muted",
- G_CALLBACK (on_stream_event_notify), manager);
} else {
g_warning ("Unable to get default sink");
}
@@ -755,7 +721,7 @@ update_default_sink (GsdMediaKeysManager *manager)
static void
on_control_ready (GvcMixerControl *control,
- GsdMediaKeysManager *manager)
+ GsdMediaKeysManager *manager)
{
update_default_sink (manager);
}
@@ -1081,7 +1047,7 @@ gsd_media_keys_manager_start (GsdMediaKeysManager *manager,
*/
gnome_settings_profile_start ("gvc_mixer_control_new");
- manager->priv->volume = gvc_mixer_control_new ();
+ manager->priv->volume = gvc_mixer_control_new ("GNOME Volume Control Media Keys");
g_signal_connect (manager->priv->volume,
"ready",
--
1.6.2.5
Index: gnome-settings-daemon.spec
===================================================================
RCS file: /cvs/pkgs/rpms/gnome-settings-daemon/F-11/gnome-settings-daemon.spec,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -p -r1.109 -r1.110
--- gnome-settings-daemon.spec 26 Aug 2009 04:00:05 -0000 1.109
+++ gnome-settings-daemon.spec 7 Sep 2009 15:02:29 -0000 1.110
@@ -1,6 +1,6 @@
Name: gnome-settings-daemon
Version: 2.26.1
-Release: 9%{?dist}
+Release: 10%{?dist}
Summary: The daemon sharing settings from GNOME to GTK+/KDE applications
Group: System Environment/Daemons
@@ -53,6 +53,12 @@ Patch16: there-can-be-only-one.patch
Patch17: syndaemon-k.patch
Patch18: buttonmapping.patch
+# Updated from 2.27 branch
+Patch90: 0001-Update-gnome-volume-control-code-from-master.patch
+Patch91: 0002-Bug-590073-gnome-settings-daemon-crashed-with-SI.patch
+Patch92: 0003-Update-gnome-volume-control-code.patch
+Patch93: 0004-Update-volume-control-code-for-new-API.patch
+
%description
A daemon to share settings from GNOME to other applications. It also
handles global keybindings, as well as a number of desktop-wide settings.
@@ -81,6 +87,11 @@ developing applications that use %{name}
%patch17 -p1 -b .syndaemon-k
%patch18 -p1 -b .buttonmapping
+%patch90 -p1
+%patch91 -p1
+%patch92 -p1
+%patch93 -p1
+
autoreconf -i -f
%build
@@ -192,6 +203,9 @@ fi
%{_libdir}/pkgconfig/gnome-settings-daemon.pc
%changelog
+* Mon Sep 07 2009 Bastien Nocera <bnocera at redhat.com> 2.26.1-10
+- Update volume code from 2.27
+
* Wed Aug 26 2009 Peter Hutterer <peter.hutterer at redhat.com> 2.26.1-9
- buttonmapping.patch: Don't check for IsXExtensionDevice, only skip button
mappings for core devices instead (#502129).
More information about the fedora-extras-commits
mailing list