]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-tube.c
Merge branch 'master' into tp-tube
[empathy.git] / libempathy / empathy-tp-tube.c
index c2a2e0c773ca69aa89049877fd15d140849f4162..7d22f6b783cae6d7d16faedb99e8a8246f4b0f9d 100644 (file)
 #include <config.h>
 
 #include <telepathy-glib/connection.h>
+#include <telepathy-glib/proxy.h>
 #include <telepathy-glib/util.h>
 #include <extensions/extensions.h>
 
-#include "empathy-contact-factory.h"
 #include "empathy-enum-types.h"
 #include "empathy-tp-tube.h"
 #include "empathy-utils.h"
@@ -60,18 +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;
-  guint initiator;
-  guint type;
-  gchar *service;
-  /* FIXME readd support for parameters.. */
-  GHashTable *parameters;
   EmpTubeChannelState state;
-  EmpathyContact *initiator_contact;
-  EmpathyContactFactory *factory;
+  gboolean ready;
+  GSList *ready_callbacks;
 } EmpathyTpTubePriv;
 
 enum
@@ -99,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;
@@ -167,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,
@@ -182,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);
 
@@ -204,15 +322,16 @@ tp_tube_finalize (GObject *object)
         "closing tube", NULL, NULL);
       g_object_unref (priv->channel);
     }
-  if (priv->initiator_contact)
-      g_object_unref (priv->initiator_contact);
-  if (priv->factory)
-      g_object_unref (priv->factory);
 
-  g_free (priv->service);
+  for (l = priv->ready_callbacks; l != NULL; l = g_slist_next (l))
+    {
+      ReadyCbData *d = (ReadyCbData *) l->data;
 
-  if (priv->parameters != NULL)
-  g_hash_table_destroy (priv->parameters);
+      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);
 }
@@ -232,7 +351,8 @@ empathy_tp_tube_class_init (EmpathyTpTubeClass *klass)
       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
   g_object_class_install_property (object_class, PROP_STATE,
-      g_param_spec_uint ("state", "state", "state", 0, G_MAXUINT, 0,
+      g_param_spec_uint ("state", "state", "state",
+        0, NUM_EMP_TUBE_CHANNEL_STATES, 0,
         G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_STRINGS));
 
   signals[DESTROY] = g_signal_new ("destroy",
@@ -252,8 +372,6 @@ empathy_tp_tube_init (EmpathyTpTube *tube)
                EMPATHY_TYPE_TP_TUBE, EmpathyTpTubePriv);
 
   tube->priv = priv;
-
-  priv->factory = empathy_contact_factory_dup_singleton ();
 }
 
 EmpathyTpTube *
@@ -272,8 +390,6 @@ empathy_tp_tube_new_stream_tube (EmpathyContact *contact,
                                  const gchar *service,
                                  GHashTable *parameters)
 {
-  MissionControl *mc;
-  McAccount *account;
   TpConnection *connection;
   TpChannel *channel;
   gchar *object_path;
@@ -290,12 +406,7 @@ empathy_tp_tube_new_stream_tube (EmpathyContact *contact,
   g_return_val_if_fail (hostname != NULL, NULL);
   g_return_val_if_fail (service != NULL, NULL);
 
-  mc = empathy_mission_control_dup_singleton ();
-  account = empathy_contact_get_account (contact);
-  connection = mission_control_get_tpconnection (mc, account, NULL);
-  g_object_unref (mc);
-
-  tp_connection_run_until_ready (connection, FALSE, NULL, NULL);
+  connection = empathy_contact_get_connection (contact);
 
   request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
       (GDestroyNotify) tp_g_value_slice_free);
@@ -439,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));
+    }
+}