GnomeVolumeControl: track PulseAudio connection state and expose it

Adds get_state() and ::state-changed signals, that replace connecting
and ready, as well as providing indication of when the object was closed
or the connection to PulseAudio failed.

https://bugzilla.gnome.org/show_bug.cgi?id=645708
This commit is contained in:
Giovanni Campagna 2011-03-26 17:59:22 +01:00
parent 8f4a4d93f2
commit 270e82e3db
2 changed files with 34 additions and 24 deletions

View File

@ -81,11 +81,12 @@ struct GvcMixerControlPrivate
GHashTable *cards; GHashTable *cards;
GvcMixerStream *new_default_stream; /* new default stream, used in gvc_mixer_control_set_default_sink () */ GvcMixerStream *new_default_stream; /* new default stream, used in gvc_mixer_control_set_default_sink () */
GvcMixerControlState state;
}; };
enum { enum {
CONNECTING, STATE_CHANGED,
READY,
STREAM_ADDED, STREAM_ADDED,
STREAM_REMOVED, STREAM_REMOVED,
CARD_ADDED, CARD_ADDED,
@ -508,16 +509,17 @@ dec_outstanding (GvcMixerControl *control)
} }
if (--control->priv->n_outstanding <= 0) { if (--control->priv->n_outstanding <= 0) {
g_signal_emit (G_OBJECT (control), signals[READY], 0); control->priv->state = GVC_STATE_READY;
g_signal_emit (G_OBJECT (control), signals[STATE_CHANGED], 0, GVC_STATE_READY);
} }
} }
gboolean GvcMixerControlState
gvc_mixer_control_is_ready (GvcMixerControl *control) gvc_mixer_control_get_state (GvcMixerControl *control)
{ {
g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE); g_return_val_if_fail (GVC_IS_MIXER_CONTROL (control), FALSE);
return (control->priv->n_outstanding == 0); return control->priv->state;
} }
@ -1943,7 +1945,8 @@ _pa_context_state_cb (pa_context *context,
break; break;
case PA_CONTEXT_FAILED: case PA_CONTEXT_FAILED:
g_warning ("Connection failed, reconnecting..."); control->priv->state = GVC_STATE_FAILED;
g_signal_emit (control, signals[STATE_CHANGED], 0, GVC_STATE_FAILED);
if (control->priv->reconnect_id == 0) if (control->priv->reconnect_id == 0)
control->priv->reconnect_id = g_timeout_add_seconds (RECONNECT_DELAY, idle_reconnect, control); control->priv->reconnect_id = g_timeout_add_seconds (RECONNECT_DELAY, idle_reconnect, control);
break; break;
@ -1968,7 +1971,8 @@ gvc_mixer_control_open (GvcMixerControl *control)
_pa_context_state_cb, _pa_context_state_cb,
control); control);
g_signal_emit (G_OBJECT (control), signals[CONNECTING], 0); 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); res = pa_context_connect (control->priv->pa_context, NULL, (pa_context_flags_t) PA_CONTEXT_NOFAIL, NULL);
if (res < 0) { if (res < 0) {
g_warning ("Failed to connect context: %s", g_warning ("Failed to connect context: %s",
@ -1985,6 +1989,9 @@ gvc_mixer_control_close (GvcMixerControl *control)
g_return_val_if_fail (control->priv->pa_context != NULL, FALSE); g_return_val_if_fail (control->priv->pa_context != NULL, FALSE);
pa_context_disconnect (control->priv->pa_context); 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; return TRUE;
} }
@ -2125,22 +2132,14 @@ gvc_mixer_control_class_init (GvcMixerControlClass *klass)
NULL, NULL,
G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY)); G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
signals [CONNECTING] = signals [STATE_CHANGED] =
g_signal_new ("connecting", g_signal_new ("state-changed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GvcMixerControlClass, connecting), G_STRUCT_OFFSET (GvcMixerControlClass, state_changed),
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 0); G_TYPE_NONE, 1, G_TYPE_UINT);
signals [READY] =
g_signal_new ("ready",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GvcMixerControlClass, ready),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals [STREAM_ADDED] = signals [STREAM_ADDED] =
g_signal_new ("stream-added", g_signal_new ("stream-added",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
@ -2212,6 +2211,8 @@ gvc_mixer_control_init (GvcMixerControl *control)
control->priv->cards = 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->clients = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free); control->priv->clients = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_free);
control->priv->state = GVC_STATE_CLOSED;
} }
static void static void

View File

@ -27,6 +27,14 @@
G_BEGIN_DECLS 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_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(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_MIXER_CONTROL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GVC_TYPE_MIXER_CONTROL, GvcMixerControlClass))
@ -46,8 +54,8 @@ typedef struct
{ {
GObjectClass parent_class; GObjectClass parent_class;
void (*connecting) (GvcMixerControl *control); void (*state_changed) (GvcMixerControl *control,
void (*ready) (GvcMixerControl *control); GvcMixerControlState new_state);
void (*stream_added) (GvcMixerControl *control, void (*stream_added) (GvcMixerControl *control,
guint id); guint id);
void (*stream_removed) (GvcMixerControl *control, void (*stream_removed) (GvcMixerControl *control,
@ -68,7 +76,6 @@ GvcMixerControl * gvc_mixer_control_new (const char *name);
gboolean gvc_mixer_control_open (GvcMixerControl *control); gboolean gvc_mixer_control_open (GvcMixerControl *control);
gboolean gvc_mixer_control_close (GvcMixerControl *control); gboolean gvc_mixer_control_close (GvcMixerControl *control);
gboolean gvc_mixer_control_is_ready (GvcMixerControl *control);
GSList * gvc_mixer_control_get_cards (GvcMixerControl *control); GSList * gvc_mixer_control_get_cards (GvcMixerControl *control);
GSList * gvc_mixer_control_get_streams (GvcMixerControl *control); GSList * gvc_mixer_control_get_streams (GvcMixerControl *control);
@ -94,6 +101,8 @@ gboolean gvc_mixer_control_set_default_source (GvcMixerControl *con
gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control); gdouble gvc_mixer_control_get_vol_max_norm (GvcMixerControl *control);
gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control); gdouble gvc_mixer_control_get_vol_max_amplified (GvcMixerControl *control);
GvcMixerControlState gvc_mixer_control_get_state (GvcMixerControl *control);
G_END_DECLS G_END_DECLS
#endif /* __GVC_MIXER_CONTROL_H */ #endif /* __GVC_MIXER_CONTROL_H */