From: Guillaume Desmottes Date: Fri, 24 Apr 2009 15:28:22 +0000 (+0100) Subject: Merge branch 'master' into tp-tube X-Git-Url: https://git.0d.be/?p=empathy.git;a=commitdiff_plain;h=f02d96379cb7043611d093921755d699e48689bb;hp=d696d6cc31f672884382d5b8949be504cdc718a5 Merge branch 'master' into tp-tube --- 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)); + } +} diff --git a/libempathy/empathy-tp-tube.h b/libempathy/empathy-tp-tube.h index 8e63945e..dd9ec4dc 100644 --- a/libempathy/empathy-tp-tube.h +++ b/libempathy/empathy-tp-tube.h @@ -81,6 +81,14 @@ void empathy_tp_tube_accept_stream_tube (EmpathyTpTube *tube, TpSocketAddressType type, EmpatyTpTubeAcceptStreamTubeCb *callback, gpointer user_data); +typedef void (EmpathyTpTubeReadyCb) + (EmpathyTpTube *tube, const GError *error, gpointer user_data, + GObject *weak_object); + +void empathy_tp_tube_call_when_ready (EmpathyTpTube *tube, + EmpathyTpTubeReadyCb *callback, gpointer user_data, GDestroyNotify destroy, + GObject *weak_object); + G_END_DECLS #endif /* __EMPATHY_TP_TUBE_H__ */ diff --git a/libempathy/empathy-tube-handler.c b/libempathy/empathy-tube-handler.c index 18cda18b..43e19fde 100644 --- a/libempathy/empathy-tube-handler.c +++ b/libempathy/empathy-tube-handler.c @@ -59,15 +59,38 @@ typedef struct gchar *channel; guint handle_type; guint handle; + EmpathyTpTube *tube; } IdleData; +static void +tube_ready_cb (EmpathyTpTube *tube, + const GError *error, + gpointer user_data, + GObject *weak_object) +{ + IdleData *idle_data = user_data; + + g_signal_emit (idle_data->thandler, signals[NEW_TUBE], 0, tube); +} + +static void +tube_ready_destroy_notify (gpointer data) +{ + IdleData *idle_data = data; + + g_object_unref (idle_data->tube); + g_free (idle_data->bus_name); + g_free (idle_data->connection); + g_free (idle_data->channel); + g_slice_free (IdleData, idle_data); +} + static gboolean tube_handler_handle_tube_idle_cb (gpointer data) { IdleData *idle_data = data; TpConnection *connection; TpChannel *channel; - EmpathyTpTube *tube; static TpDBusDaemon *daemon = NULL; DEBUG ("New tube to be handled"); @@ -82,16 +105,12 @@ tube_handler_handle_tube_idle_cb (gpointer data) idle_data->handle, NULL); tp_channel_run_until_ready (channel, NULL, NULL); - tube = empathy_tp_tube_new (channel); - g_signal_emit (idle_data->thandler, signals[NEW_TUBE], 0, tube); + idle_data->tube = empathy_tp_tube_new (channel); + empathy_tp_tube_call_when_ready (idle_data->tube, tube_ready_cb, idle_data, + tube_ready_destroy_notify, NULL); - g_object_unref (tube); g_object_unref (channel); g_object_unref (connection); - g_free (idle_data->bus_name); - g_free (idle_data->connection); - g_free (idle_data->channel); - g_slice_free (IdleData, idle_data); return FALSE; }