[gnome-media/nofail] Bug 564311 – "Connection failed" when PA drops off
- From: Marc-Andre Lureau <malureau src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-media/nofail] Bug 564311 – "Connection failed" when PA drops off
- Date: Sun, 14 Jun 2009 18:08:13 -0400 (EDT)
commit 73fd870018f28089fc311cb7f88a972a6a453d38
Author: Marc-André Lureau <marcandre lureau gmail com>
Date: Sun Jun 14 23:25:14 2009 +0300
Bug 564311 â?? "Connection failed" when PA drops off
gnome-volume-control/src/dialog-main.c | 25 ++++-
gnome-volume-control/src/gvc-applet.c | 11 ++
gnome-volume-control/src/gvc-mixer-control.c | 129 ++++++++++++++++++++------
gnome-volume-control/src/gvc-mixer-control.h | 1 +
4 files changed, 132 insertions(+), 34 deletions(-)
---
diff --git a/gnome-volume-control/src/dialog-main.c b/gnome-volume-control/src/dialog-main.c
index dddc281..dd24472 100644
--- a/gnome-volume-control/src/dialog-main.c
+++ b/gnome-volume-control/src/dialog-main.c
@@ -85,6 +85,9 @@ on_control_ready (GvcMixerControl *control,
warning_dialog = NULL;
}
+ if (dialog)
+ return;
+
dialog = GTK_WIDGET (gvc_mixer_dialog_new (control));
g_signal_connect (dialog,
"response",
@@ -115,7 +118,7 @@ warning_dialog_answered (GtkDialog *d,
static gboolean
dialog_popup_timeout (gpointer data)
{
- warning_dialog = gtk_message_dialog_new (NULL,
+ warning_dialog = gtk_message_dialog_new (GTK_WINDOW(dialog),
0,
GTK_MESSAGE_INFO,
GTK_BUTTONS_CANCEL,
@@ -130,6 +133,18 @@ dialog_popup_timeout (gpointer data)
return FALSE;
}
+static void
+on_control_connecting (GvcMixerControl *control,
+ UniqueApp *app)
+{
+ if (popup_id != 0)
+ return;
+
+ popup_id = g_timeout_add_seconds (DIALOG_POPUP_TIMEOUT,
+ dialog_popup_timeout,
+ NULL);
+}
+
int
main (int argc, char **argv)
{
@@ -177,15 +192,15 @@ main (int argc, char **argv)
control = gvc_mixer_control_new ();
g_signal_connect (control,
+ "connecting",
+ G_CALLBACK (on_control_connecting),
+ app);
+ g_signal_connect (control,
"ready",
G_CALLBACK (on_control_ready),
app);
gvc_mixer_control_open (control);
- popup_id = g_timeout_add_seconds (DIALOG_POPUP_TIMEOUT,
- dialog_popup_timeout,
- NULL);
-
gtk_main ();
if (control != NULL) {
diff --git a/gnome-volume-control/src/gvc-applet.c b/gnome-volume-control/src/gvc-applet.c
index e11818b..82e3765 100644
--- a/gnome-volume-control/src/gvc-applet.c
+++ b/gnome-volume-control/src/gvc-applet.c
@@ -167,6 +167,13 @@ on_control_ready (GvcMixerControl *control,
}
static void
+on_control_connecting (GvcMixerControl *control,
+ GvcApplet *applet)
+{
+ g_debug ("Connecting..");
+}
+
+static void
on_control_default_sink_changed (GvcMixerControl *control,
guint id,
GvcApplet *applet)
@@ -216,6 +223,10 @@ gvc_applet_constructor (GType type,
G_CALLBACK (on_control_ready),
self);
g_signal_connect (self->priv->control,
+ "connecting",
+ G_CALLBACK (on_control_connecting),
+ self);
+ g_signal_connect (self->priv->control,
"default-sink-changed",
G_CALLBACK (on_control_default_sink_changed),
self);
diff --git a/gnome-volume-control/src/gvc-mixer-control.c b/gnome-volume-control/src/gvc-mixer-control.c
index fc72fb4..21f56f7 100644
--- a/gnome-volume-control/src/gvc-mixer-control.c
+++ b/gnome-volume-control/src/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;
@@ -70,6 +71,7 @@ struct GvcMixerControlPrivate
};
enum {
+ CONNECTING,
READY,
STREAM_ADDED,
STREAM_REMOVED,
@@ -381,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;
@@ -403,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;
@@ -1461,6 +1467,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)
{
@@ -1478,7 +1556,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:
@@ -1501,7 +1581,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)));
@@ -1580,30 +1661,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;
}
@@ -1617,6 +1680,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/gnome-volume-control/src/gvc-mixer-control.h b/gnome-volume-control/src/gvc-mixer-control.h
index 33e745a..3de9e62 100644
--- a/gnome-volume-control/src/gvc-mixer-control.h
+++ b/gnome-volume-control/src/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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]