[Telepathy-commits] [telepathy-mission-control/master] Partially implement the client side of channel requests

Alberto Mardegan alberto.mardegan at nokia.com
Mon Nov 17 00:05:22 PST 2008


Implement the client side of the channel requests; only the cancel function is
still unimplemented.
---
 libmcclient/account.xml          |    1 +
 libmcclient/mc-account-priv.h    |    6 +
 libmcclient/mc-account-request.c |  223 ++++++++++++++++++++++++++++++++++++--
 libmcclient/mc-account.c         |    5 +
 4 files changed, 226 insertions(+), 9 deletions(-)

diff --git a/libmcclient/account.xml b/libmcclient/account.xml
index eac5604..71d2f5c 100644
--- a/libmcclient/account.xml
+++ b/libmcclient/account.xml
@@ -4,6 +4,7 @@
 
 <xi:include href="../xml/Account.xml"/>
 <xi:include href="../xml/Account_Interface_Avatar.xml"/>
+<xi:include href="../xml/Account_Interface_ChannelRequests.xml"/>
 <xi:include href="../xml/Account_Interface_Compat.xml"/>
 <xi:include href="../xml/Account_Interface_Conditions.xml"/>
 
diff --git a/libmcclient/mc-account-priv.h b/libmcclient/mc-account-priv.h
index 4f40ca6..dc4d6bb 100644
--- a/libmcclient/mc-account-priv.h
+++ b/libmcclient/mc-account-priv.h
@@ -44,12 +44,14 @@ extern guint _mc_account_signals[LAST_SIGNAL];
 
 typedef struct _McAccountProps McAccountProps;
 typedef struct _McAccountAvatarProps McAccountAvatarProps;
+typedef struct _McAccountChannelrequestsProps McAccountChannelrequestsProps;
 typedef struct _McAccountCompatProps McAccountCompatProps;
 typedef struct _McAccountConditionsProps McAccountConditionsProps;
 
 struct _McAccountPrivate {
     McAccountProps *props;
     McAccountAvatarProps *avatar_props;
+    McAccountChannelrequestsProps *request_props;
     McAccountCompatProps *compat_props;
     McAccountConditionsProps *conditions_props;
 };
@@ -57,6 +59,10 @@ struct _McAccountPrivate {
 void _mc_account_avatar_props_free (McAccountAvatarProps *props);
 void _mc_account_avatar_class_init (McAccountClass *klass);
 
+void _mc_account_channelrequests_props_free
+    (McAccountChannelrequestsProps *props);
+void _mc_account_channelrequests_class_init (McAccountClass *klass);
+
 void _mc_account_compat_props_free (McAccountCompatProps *props);
 void _mc_account_compat_class_init (McAccountClass *klass);
 
diff --git a/libmcclient/mc-account-request.c b/libmcclient/mc-account-request.c
index d107e78..73866f6 100644
--- a/libmcclient/mc-account-request.c
+++ b/libmcclient/mc-account-request.c
@@ -27,9 +27,157 @@
 #include "mc-account.h"
 #include "mc-account-priv.h"
 #include "dbus-api.h"
+#include "mc-errors.h"
 
 #include <telepathy-glib/interfaces.h>
 
+struct _McAccountChannelrequestsProps {
+    GList *requests;
+};
+
+typedef struct
+{
+    McAccount *account;
+    gchar *request_path;
+    GError *error;
+
+    /* caller data */
+    McAccountChannelRequestCb callback;
+    gpointer user_data;
+    GDestroyNotify destroy;
+    GObject *weak_object;
+} McChannelRequest;
+
+
+static void mc_request_free (McChannelRequest *req);
+
+static void
+on_weak_object_destroy (McAccount *account, GObject *weak_object)
+{
+    McAccountChannelrequestsProps *props;
+    GList *list;
+
+    g_return_if_fail (MC_IS_ACCOUNT (account));
+
+    props = account->priv->request_props;
+    g_return_if_fail (props != NULL);
+
+    /* look for this request */
+    for (list = props->requests; list != NULL; list = list->next)
+    {
+        McChannelRequest *req = list->data;
+
+        if (req->weak_object == weak_object)
+        {
+            props->requests = g_list_delete_link (props->requests, list);
+            req->weak_object = NULL;
+            mc_request_free (req);
+            break;
+        }
+    }
+}
+
+static void
+mc_request_free (McChannelRequest *req)
+{
+    if (req->weak_object)
+        g_object_weak_unref (req->weak_object,
+                             (GWeakNotify)on_weak_object_destroy,
+                             req->account);
+    if (req->destroy)
+        req->destroy (req->user_data);
+    g_free (req->request_path);
+    if (req->error)
+        g_error_free (req->error);
+    g_slice_free (McChannelRequest, req);
+}
+
+static void
+emit_request_event (McChannelRequest *req, McAccountChannelRequestEvent event)
+{
+    if (req->callback)
+        req->callback (req->account, GPOINTER_TO_UINT (req), event,
+                       req->user_data, req->weak_object);
+
+    if (event == MC_ACCOUNT_CR_SUCCEEDED ||
+        event == MC_ACCOUNT_CR_FAILED ||
+        event == MC_ACCOUNT_CR_CANCELLED)
+    {
+        /* the request does no longer exist */
+        mc_request_free (req);
+    }
+}
+
+static void
+request_create_cb (TpProxy *proxy, const gchar *request_path,
+                   const GError *error, gpointer user_data,
+                   GObject *weak_object)
+{
+    McChannelRequest *req = user_data;
+
+    if (error)
+    {
+        /* the request hasn't even been created */
+        req->error = g_error_copy (error);
+        emit_request_event (req, MC_ACCOUNT_CR_FAILED);
+        return;
+    }
+    g_debug ("%s called with %s", G_STRFUNC, request_path);
+    req->request_path = g_strdup (request_path);
+}
+
+static void
+on_request_failed (TpProxy *proxy, const gchar *request_path,
+                   const gchar *error_name, const gchar *error_message,
+                   gpointer user_data, GObject *weak_object)
+{
+    McChannelRequest *req;
+
+    g_debug ("%s called for %s", G_STRFUNC, request_path);
+    req = GUINT_TO_POINTER (mc_account_channel_request_get_from_path
+                            (MC_ACCOUNT (proxy), request_path));
+    if (!req) /* not our request, ignore it */
+        return;
+
+    /* FIXME: map the error properly */
+    req->error = g_error_new (MC_ERROR, MC_CHANNEL_REQUEST_GENERIC_ERROR,
+                              error_message);
+    emit_request_event (req, MC_ACCOUNT_CR_FAILED);
+}
+
+static void
+on_request_succeeded (TpProxy *proxy, const gchar *request_path,
+                      gpointer user_data, GObject *weak_object)
+{
+    McChannelRequest *req;
+
+    g_debug ("%s called for %s", G_STRFUNC, request_path);
+    req = GUINT_TO_POINTER (mc_account_channel_request_get_from_path
+                            (MC_ACCOUNT (proxy), request_path));
+    if (!req) /* not our request, ignore it */
+        return;
+
+    emit_request_event (req, MC_ACCOUNT_CR_SUCCEEDED);
+}
+
+void
+_mc_account_channelrequests_props_free (McAccountChannelrequestsProps *props)
+{
+    GList *list;
+
+    for (list = props->requests; list != NULL; list = list->next)
+        mc_request_free (list->data);
+
+    g_list_free (props->requests);
+    g_slice_free (McAccountChannelrequestsProps, props);
+}
+
+void
+_mc_account_channelrequests_class_init (McAccountClass *klass)
+{
+    /* nothing here, as we don't have any properties on the interface */
+}
+
 /**
  * McAccountChannelRequestCb:
  * @account: the #McAccount.
@@ -108,7 +256,7 @@ mc_account_channel_request (McAccount *account,
                           MC_ACCOUNT_CRD_GET (req_data, target_handle));
         g_hash_table_insert (properties,
                              TP_IFACE_CHANNEL ".TargetHandle",
-                             &v_channel_type);
+                             &v_target_handle);
     }
 
     if (MC_ACCOUNT_CRD_IS_SET (req_data, target_handle_type))
@@ -119,7 +267,7 @@ mc_account_channel_request (McAccount *account,
                           MC_ACCOUNT_CRD_GET (req_data, target_handle_type));
         g_hash_table_insert (properties,
                              TP_IFACE_CHANNEL ".TargetHandleType",
-                             &v_channel_type);
+                             &v_target_handle_type);
     }
 
     if (MC_ACCOUNT_CRD_IS_SET (req_data, target_id))
@@ -181,8 +329,43 @@ mc_account_channel_request_ht (McAccount *account,
                                gpointer user_data, GDestroyNotify destroy,
                                GObject *weak_object)
 {
-    g_warning ("%s is not implemented yet", G_STRFUNC);
-    return 0;
+    McAccountChannelrequestsProps *props;
+    McChannelRequest *req;
+
+    g_return_val_if_fail (MC_IS_ACCOUNT (account), 0);
+    props = account->priv->request_props;
+    if (props == NULL)
+    {
+        account->priv->request_props = props =
+            g_slice_new0 (McAccountChannelrequestsProps);
+
+        mc_cli_account_interface_channelrequests_connect_to_failed (account,
+            on_request_failed, NULL, NULL, NULL, NULL);
+        mc_cli_account_interface_channelrequests_connect_to_succeeded (account,
+            on_request_succeeded, NULL, NULL, NULL, NULL);
+    }
+
+    req = g_slice_new0 (McChannelRequest);
+    req->account = account;
+    req->callback = callback;
+    req->user_data = user_data;
+    req->destroy = destroy;
+    if (weak_object)
+    {
+        req->weak_object = weak_object;
+        g_object_weak_ref (weak_object,
+                           (GWeakNotify)on_weak_object_destroy, account);
+    }
+    mc_cli_account_interface_channelrequests_call_create (account, -1,
+                                                          properties,
+                                                          user_action_time,
+                                                          handler,
+                                                          request_create_cb,
+                                                          req, NULL,
+                                                          NULL);
+
+    props->requests = g_list_prepend (props->requests, req);
+    return GPOINTER_TO_UINT (req);
 }
 
 /**
@@ -211,8 +394,12 @@ mc_account_channel_request_cancel (McAccount *account, guint request_id)
 const GError *
 mc_account_channel_request_get_error (McAccount *account, guint request_id)
 {
-    g_warning ("%s is not implemented yet", G_STRFUNC);
-    return NULL;
+    McChannelRequest *req;
+
+    g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+    g_return_val_if_fail (request_id != 0, NULL);
+    req = GUINT_TO_POINTER (request_id);
+    return req->error;
 }
 
 /**
@@ -230,8 +417,12 @@ mc_account_channel_request_get_error (McAccount *account, guint request_id)
 const gchar *
 mc_account_channel_request_get_path (McAccount *account, guint request_id)
 {
-    g_warning ("%s is not implemented yet", G_STRFUNC);
-    return NULL;
+    McChannelRequest *req;
+
+    g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+    g_return_val_if_fail (request_id != 0, NULL);
+    req = GUINT_TO_POINTER (request_id);
+    return req->request_path;
 }
 
 /**
@@ -248,7 +439,21 @@ guint
 mc_account_channel_request_get_from_path (McAccount *account,
                                           const gchar *object_path)
 {
-    g_warning ("%s is not implemented yet", G_STRFUNC);
+    McAccountChannelrequestsProps *props;
+    GList *list;
+
+    g_return_val_if_fail (MC_IS_ACCOUNT (account), 0);
+    g_return_val_if_fail (object_path != NULL, 0);
+    props = account->priv->request_props;
+    if (!props) return 0;
+
+    for (list = props->requests; list != NULL; list = list->next)
+    {
+        McChannelRequest *req = list->data;
+
+        if (req->request_path && strcmp (req->request_path, object_path) == 0)
+            return GPOINTER_TO_UINT (req);
+    }
     return 0;
 }
 
diff --git a/libmcclient/mc-account.c b/libmcclient/mc-account.c
index 23dda1b..0aee986 100644
--- a/libmcclient/mc-account.c
+++ b/libmcclient/mc-account.c
@@ -160,6 +160,8 @@ mc_account_init (McAccount *account)
     tp_proxy_add_interface_by_id ((TpProxy *)account,
 				  MC_IFACE_QUARK_ACCOUNT_INTERFACE_AVATAR);
     tp_proxy_add_interface_by_id ((TpProxy *)account,
+        MC_IFACE_QUARK_ACCOUNT_INTERFACE_CHANNELREQUESTS);
+    tp_proxy_add_interface_by_id ((TpProxy *)account,
 				  MC_IFACE_QUARK_ACCOUNT_INTERFACE_COMPAT);
     tp_proxy_add_interface_by_id ((TpProxy *)account,
 				  MC_IFACE_QUARK_ACCOUNT_INTERFACE_CONDITIONS);
@@ -215,6 +217,9 @@ finalize (GObject *object)
     if (account->priv->avatar_props)
 	_mc_account_avatar_props_free (account->priv->avatar_props);
 
+    if (account->priv->request_props)
+	_mc_account_channelrequests_props_free (account->priv->request_props);
+
     if (account->priv->compat_props)
 	_mc_account_compat_props_free (account->priv->compat_props);
 
-- 
1.5.6.5




More information about the Telepathy-commits mailing list