X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy%2Fempathy-tp-tube.c;h=7d22f6b783cae6d7d16faedb99e8a8246f4b0f9d;hp=5979615ef2c93f21f9f6ac74b2e210da0cf1dffe;hb=f02d96379cb7043611d093921755d699e48689bb;hpb=d696d6cc31f672884382d5b8949be504cdc718a5;ds=sidebyside diff --git a/libempathy/empathy-tp-tube.c b/libempathy/empathy-tp-tube.c index 5979615e..7d22f6b7 100644 --- a/libempathy/empathy-tp-tube.c +++ b/libempathy/empathy-tp-tube.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -59,11 +60,21 @@ free_empathy_tp_tube_accept_data (gpointer data) } +typedef struct { + EmpathyTpTubeReadyCb *callback; + gpointer user_data; + GDestroyNotify destroy; + GObject *weak_object; +} ReadyCbData; + + #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpTube) typedef struct { TpChannel *channel; EmpTubeChannelState state; + gboolean ready; + GSList *ready_callbacks; } EmpathyTpTubePriv; enum @@ -91,6 +102,10 @@ tp_tube_state_changed_cb (TpProxy *proxy, { EmpathyTpTubePriv *priv = GET_PRIV (tube); + if (!priv->ready) + /* We didn't get the state yet */ + return; + DEBUG ("Tube state changed"); priv->state = state; @@ -159,6 +174,109 @@ tp_tube_get_property (GObject *object, } } +static void weak_object_notify (gpointer data, + GObject *old_object); + +static ReadyCbData * +ready_cb_data_new (EmpathyTpTube *self, + EmpathyTpTubeReadyCb *callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object) +{ + ReadyCbData *d = g_slice_new0 (ReadyCbData); + d->callback = callback; + d->user_data = user_data; + d->destroy = destroy; + d->weak_object = weak_object; + + if (weak_object != NULL) + g_object_weak_ref (weak_object, weak_object_notify, self); + + return d; +} + +static void +ready_cb_data_free (ReadyCbData *data, + EmpathyTpTube *self) +{ + if (data->destroy != NULL) + data->destroy (data->user_data); + + if (data->weak_object != NULL) + g_object_weak_unref (data->weak_object, + weak_object_notify, self); + + g_slice_free (ReadyCbData, data); +} + +static void +weak_object_notify (gpointer data, + GObject *old_object) +{ + EmpathyTpTube *self = EMPATHY_TP_TUBE (data); + EmpathyTpTubePriv *priv = GET_PRIV (self); + GSList *l, *ln; + + for (l = priv->ready_callbacks ; l != NULL ; l = ln ) + { + ReadyCbData *d = (ReadyCbData *) l->data; + ln = g_slist_next (l); + + if (d->weak_object == old_object) + { + ready_cb_data_free (d, self); + priv->ready_callbacks = g_slist_delete_link (priv->ready_callbacks, + l); + } + } +} + + +static void +tube_is_ready (EmpathyTpTube *self, + const GError *error) +{ + EmpathyTpTubePriv *priv = GET_PRIV (self); + GSList *l; + + priv->ready = TRUE; + + for (l = priv->ready_callbacks ; l != NULL ; l = g_slist_next (l)) + { + ReadyCbData *data = (ReadyCbData *) l->data; + + data->callback (self, error, data->user_data, data->weak_object); + ready_cb_data_free (data, self); + } + + g_slist_free (priv->ready_callbacks); + priv->ready_callbacks = NULL; +} + +static void +got_tube_state_cb (TpProxy *proxy, + const GValue *out_value, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + EmpathyTpTube *self = EMPATHY_TP_TUBE (user_data); + EmpathyTpTubePriv *priv = GET_PRIV (self); + + if (error != NULL) + { + DEBUG ("Error getting State property: %s", error->message); + } + else + { + priv->state = g_value_get_uint (out_value); + g_object_notify (G_OBJECT (self), "state"); + } + + tube_is_ready (self, error); +} + static GObject * tp_tube_constructor (GType type, guint n_props, @@ -174,17 +292,25 @@ tp_tube_constructor (GType type, g_signal_connect (priv->channel, "invalidated", G_CALLBACK (tp_tube_invalidated_cb), self); + priv->ready = FALSE; + emp_cli_channel_interface_tube_connect_to_tube_channel_state_changed ( TP_PROXY (priv->channel), tp_tube_state_changed_cb, NULL, NULL, self, NULL); + tp_cli_dbus_properties_call_get (priv->channel, -1, + EMP_IFACE_CHANNEL_INTERFACE_TUBE, "State", got_tube_state_cb, + self, NULL, G_OBJECT (self)); + return self; } static void tp_tube_finalize (GObject *object) { + EmpathyTpTube *self = EMPATHY_TP_TUBE (object); EmpathyTpTubePriv *priv = GET_PRIV (object); + GSList *l; DEBUG ("Finalizing: %p", object); @@ -197,6 +323,16 @@ tp_tube_finalize (GObject *object) g_object_unref (priv->channel); } + for (l = priv->ready_callbacks; l != NULL; l = g_slist_next (l)) + { + ReadyCbData *d = (ReadyCbData *) l->data; + + ready_cb_data_free (d, self); + } + + g_slist_free (priv->ready_callbacks); + priv->ready_callbacks = NULL; + G_OBJECT_CLASS (empathy_tp_tube_parent_class)->finalize (object); } @@ -414,3 +550,28 @@ empathy_tp_tube_accept_stream_tube (EmpathyTpTube *tube, tp_g_value_slice_free (control_param); } + +void +empathy_tp_tube_call_when_ready (EmpathyTpTube *self, + EmpathyTpTubeReadyCb *callback, + gpointer user_data, + GDestroyNotify destroy, + GObject *weak_object) +{ + EmpathyTpTubePriv *priv = GET_PRIV (self); + + g_return_if_fail (self != NULL); + g_return_if_fail (callback != NULL); + + if (priv->ready) + { + callback (self, NULL, user_data, weak_object); + if (destroy != NULL) + destroy (user_data); + } + else + { + priv->ready_callbacks = g_slist_prepend (priv->ready_callbacks, + ready_cb_data_new (self, callback, user_data, destroy, weak_object)); + } +}