[Telepathy-commits] [telepathy-mission-control/master] Invoke AddRequest and RemoveFailedRequest

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


Notify the McdDispatcher of new channel requests, and let it invoke the
AddRequest and (if needed) RemoveFailedRequest client methods.
Move the creation of an object path for the channel request into mcd-channel.c
---
 src/mcd-account-requests.c |   31 +++-------
 src/mcd-channel.c          |   44 ++++++++++++++
 src/mcd-channel.h          |    2 +
 src/mcd-dispatcher.c       |  141 ++++++++++++++++++++++++++++++++++++++++++++
 src/mcd-dispatcher.h       |    4 +
 src/mcd-master.c           |   14 ++++
 src/mcd-master.h           |    1 +
 7 files changed, 216 insertions(+), 21 deletions(-)

diff --git a/src/mcd-account-requests.c b/src/mcd-account-requests.c
index 373bb05..c52ec19 100644
--- a/src/mcd-account-requests.c
+++ b/src/mcd-account-requests.c
@@ -40,16 +40,11 @@
 #include "mcd-misc.h"
 #include "_gen/interfaces.h"
 
-#define REQUEST_OBJ_BASE "/com/nokia/MissionControl/requests/r"
-
 typedef struct
 {
-    gchar *id;
     gchar *requestor_client_id;
 } McdRequestData;
 
-static guint last_prop_id = 1;
-
 #define REQUEST_DATA "request_data"
 
 static inline McdRequestData *
@@ -59,15 +54,6 @@ get_request_data (McdChannel *channel)
     return g_object_get_data ((GObject *)channel, REQUEST_DATA);
 }
 
-static const gchar *
-get_request_id (McdChannel *channel)
-{
-    McdRequestData *rd;
-
-    rd = get_request_data (channel);
-    return rd->id;
-}
-
 static void
 online_request_cb (McdAccount *account, gpointer userdata, const GError *error)
 {
@@ -97,7 +83,6 @@ online_request_cb (McdAccount *account, gpointer userdata, const GError *error)
 static void
 request_data_free (McdRequestData *rd)
 {
-    g_free (rd->id);
     g_free (rd->requestor_client_id);
     g_slice_free (McdRequestData, rd);
 }
@@ -113,18 +98,19 @@ on_channel_status_changed (McdChannel *channel, McdChannelStatus status,
         const gchar *err_string;
         error = _mcd_channel_get_error (channel);
         g_warning ("Channel request %s failed, error: %s",
-                   get_request_id (channel), error->message);
+                   _mcd_channel_get_request_path (channel), error->message);
 
         err_string = _mcd_get_error_string (error);
         mc_svc_account_interface_channelrequests_emit_failed (account,
-            get_request_id (channel), err_string, error->message);
+            _mcd_channel_get_request_path (channel),
+            err_string, error->message);
 
         g_object_unref (channel);
     }
     else if (status == MCD_CHANNEL_DISPATCHED)
     {
         mc_svc_account_interface_channelrequests_emit_succeeded (account,
-            get_request_id (channel));
+            _mcd_channel_get_request_path (channel));
 
         /* free the request data, it's no longer useful */
         g_object_set_data ((GObject *)channel, REQUEST_DATA, NULL);
@@ -142,6 +128,7 @@ create_request (McdAccount *account, GHashTable *properties,
     McdRequestData *rd;
     GError *error = NULL;
     GHashTable *props;
+    McdDispatcher *dispatcher;
 
     /* TODO: handle use_existing */
 
@@ -153,7 +140,6 @@ create_request (McdAccount *account, GHashTable *properties,
     g_hash_table_unref (props);
 
     rd = g_slice_new (McdRequestData);
-    rd->id = g_strdup_printf (REQUEST_OBJ_BASE "%u", last_prop_id++);
     rd->requestor_client_id = dbus_g_method_get_sender (context);
     g_object_set_data_full ((GObject *)channel, REQUEST_DATA, rd,
                             (GDestroyNotify)request_data_free);
@@ -161,6 +147,9 @@ create_request (McdAccount *account, GHashTable *properties,
     g_signal_connect (channel, "status-changed",
                       G_CALLBACK (on_channel_status_changed), account);
 
+    dispatcher = mcd_master_get_dispatcher (mcd_master_get_default ());
+    _mcd_dispatcher_add_request (dispatcher, channel);
+
     _mcd_account_online_request (account, online_request_cb, channel, &error);
     if (error)
     {
@@ -195,7 +184,7 @@ account_request_create (McSvcAccountInterfaceChannelRequests *self,
         g_error_free (error);
         return;
     }
-    request_id = get_request_id (channel);
+    request_id = _mcd_channel_get_request_path (channel);
     mc_svc_account_interface_channelrequests_return_from_create (context,
                                                                  request_id);
 }
@@ -219,7 +208,7 @@ account_request_ensure_channel (McSvcAccountInterfaceChannelRequests *self,
         g_error_free (error);
         return;
     }
-    request_id = get_request_id (channel);
+    request_id = _mcd_channel_get_request_path (channel);
     mc_svc_account_interface_channelrequests_return_from_ensure_channel
         (context, request_id);
 }
diff --git a/src/mcd-channel.c b/src/mcd-channel.c
index 8e2cdde..cee1214 100644
--- a/src/mcd-channel.c
+++ b/src/mcd-channel.c
@@ -90,6 +90,8 @@ typedef struct
 
 typedef struct
 {
+    gchar *path;
+
     GHashTable *properties;
     guint64 user_time;
     gchar *preferred_handler;
@@ -131,6 +133,10 @@ enum _McdChannelPropertyType
 
 static guint mcd_channel_signals[LAST_SIGNAL] = { 0 };
 
+#define REQUEST_OBJ_BASE "/com/nokia/MissionControl/requests/r"
+static guint last_req_id = 1;
+
+
 static void _mcd_channel_release_tp_channel (McdChannel *channel,
 					     gboolean close_channel);
 
@@ -140,6 +146,7 @@ channel_request_data_free (McdChannelRequestData *crd)
     g_debug ("%s called for %p", G_STRFUNC, crd);
     g_hash_table_unref (crd->properties);
     g_free (crd->preferred_handler);
+    g_free (crd->path);
     g_slice_free (McdChannelRequestData, crd);
 }
 
@@ -1258,6 +1265,7 @@ mcd_channel_new_request (GHashTable *properties, guint64 user_time,
     /* TODO: these data could be freed when the channel status becomes
      * MCD_CHANNEL_DISPATCHED */
     crd = g_slice_new (McdChannelRequestData);
+    crd->path = g_strdup_printf (REQUEST_OBJ_BASE "%u", last_req_id++);
     crd->properties = g_hash_table_ref (properties);
     crd->user_time = user_time;
     crd->preferred_handler = g_strdup (preferred_handler);
@@ -1286,3 +1294,39 @@ _mcd_channel_get_requested_properties (McdChannel *channel)
     return crd->properties;
 }
 
+/*
+ * _mcd_channel_get_request_path:
+ * @channel: the #McdChannel.
+ *
+ * Returns: the object path of the channel request, if the channel is in
+ * MCD_CHANNEL_REQUEST status.
+ */
+const gchar *
+_mcd_channel_get_request_path (McdChannel *channel)
+{
+    McdChannelRequestData *crd;
+
+    g_return_val_if_fail (MCD_IS_CHANNEL (channel), NULL);
+    crd = g_object_get_data ((GObject *)channel, CD_REQUEST);
+    if (G_UNLIKELY (!crd)) return NULL;
+    return crd->path;
+}
+
+/*
+ * _mcd_channel_get_request_user_action_time:
+ * @channel: the #McdChannel.
+ *
+ * Returns: UserActionTime of the channel request, if the channel is in
+ * MCD_CHANNEL_REQUEST status.
+ */
+guint64
+_mcd_channel_get_request_user_action_time (McdChannel *channel)
+{
+    McdChannelRequestData *crd;
+
+    g_return_val_if_fail (MCD_IS_CHANNEL (channel), 0);
+    crd = g_object_get_data ((GObject *)channel, CD_REQUEST);
+    if (G_UNLIKELY (!crd)) return 0;
+    return crd->user_time;
+}
+
diff --git a/src/mcd-channel.h b/src/mcd-channel.h
index adc7d04..f38057b 100644
--- a/src/mcd-channel.h
+++ b/src/mcd-channel.h
@@ -122,6 +122,8 @@ void _mcd_channel_details_free (GPtrArray *channels);
 
 const gchar *_mcd_channel_get_target_id (McdChannel *channel);
 GHashTable *_mcd_channel_get_requested_properties (McdChannel *channel);
+const gchar *_mcd_channel_get_request_path (McdChannel *channel);
+guint64 _mcd_channel_get_request_user_action_time (McdChannel *channel);
 
 void _mcd_channel_set_error (McdChannel *channel, GError *error);
 const GError *_mcd_channel_get_error (McdChannel *channel);
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 8acc9ff..c02907b 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -164,6 +164,12 @@ typedef struct
     GList *channels;
 } McdHandlerCallData;
 
+typedef struct
+{
+    TpProxy *handler;
+    gchar *request_path;
+} McdRemoveRequestData;
+
 enum
 {
     PROP_0,
@@ -1947,3 +1953,138 @@ mcd_dispatcher_context_get_protocol_name (McdDispatcherContext *context)
     return context->protocol;
 }
 
+static void
+remove_request_data_free (McdRemoveRequestData *rrd)
+{
+    g_object_unref (rrd->handler);
+    g_free (rrd->request_path);
+    g_slice_free (McdRemoveRequestData, rrd);
+}
+
+static void
+on_request_status_changed (McdChannel *channel, McdChannelStatus status,
+                           McdRemoveRequestData *rrd)
+{
+    if (status != MCD_CHANNEL_FAILED && status != MCD_CHANNEL_DISPATCHED)
+        return;
+
+    g_debug ("%s called, %u", G_STRFUNC, status);
+    if (status == MCD_CHANNEL_FAILED)
+    {
+        const GError *error;
+        const gchar *err_string;
+        error = _mcd_channel_get_error (channel);
+        err_string = _mcd_get_error_string (error);
+        /* no callback, as we don't really care */
+        mc_cli_client_handler_call_remove_failed_request
+            (rrd->handler, -1, rrd->request_path, err_string, error->message,
+             NULL, NULL, NULL, NULL);
+    }
+
+    /* we don't need the McdRemoveRequestData anymore */
+    remove_request_data_free (rrd);
+    g_signal_handlers_disconnect_by_func (channel, on_request_status_changed,
+                                          rrd);
+}
+
+static void
+add_request_cb (TpProxy *proxy, const GError *error, gpointer user_data,
+                GObject *weak_object)
+{
+    McdChannel *channel = MCD_CHANNEL (user_data);
+    McdRemoveRequestData *rrd;
+
+    if (error)
+    {
+        g_warning ("AddRequest %s failed: %s",
+                   _mcd_channel_get_request_path (channel), error->message);
+        return;
+    }
+
+    rrd = g_slice_new (McdRemoveRequestData);
+    /* store the request path, because it might not be available when the
+     * channel status changes */
+    rrd->request_path = g_strdup (_mcd_channel_get_request_path (channel));
+    rrd->handler = proxy;
+    g_object_ref (proxy);
+    /* we must watch whether the request fails and in that case call
+     * RemoveFailedRequest */
+    g_signal_connect (channel, "status-changed",
+                      G_CALLBACK (on_request_status_changed), rrd);
+}
+
+/*
+ * _mcd_dispatcher_add_request:
+ * @context: the #McdDispatcherContext.
+ * @channels: a #McdChannel in MCD_CHANNEL_REQUEST state.
+ *
+ * Add a request; this basically means invoking AddRequest (and maybe
+ * RemoveRequest) on the channel handler.
+ */
+void
+_mcd_dispatcher_add_request (McdDispatcher *dispatcher, McdChannel *channel)
+{
+    McdDispatcherPrivate *priv;
+    McdClient *handler = NULL;
+    GHashTable *properties;
+    GValue v_user_time = { 0, };
+    GValue v_requests = { 0, };
+    GPtrArray *requests;
+    GList *list;
+
+    g_return_if_fail (MCD_IS_DISPATCHER (dispatcher));
+    g_return_if_fail (MCD_IS_CHANNEL (channel));
+    g_return_if_fail (mcd_channel_get_status (channel) == MCD_CHANNEL_REQUEST);
+
+    priv = dispatcher->priv;
+
+    for (list = priv->clients; list != NULL; list = list->next)
+    {
+        McdClient *client = list->data;
+
+        if (!client->proxy ||
+            !(client->interfaces & MCD_CLIENT_HANDLER))
+            continue;
+
+        if (match_filters (channel, client->handler_filters))
+        {
+            handler = client;
+            break;
+        }
+    }
+
+    if (!handler)
+    {
+        /* No handler found. But it's possible that by the time that the
+         * channel will be created some handler will have popped up, so we
+         * must not destroy it. */
+        g_debug ("No handler for request %s",
+                 _mcd_channel_get_request_path (channel));
+        return;
+    }
+
+    properties = g_hash_table_new (g_str_hash, g_str_equal);
+
+    g_value_init (&v_user_time, G_TYPE_UINT64);
+    g_value_set_uint64 (&v_user_time,
+                        _mcd_channel_get_request_user_action_time (channel));
+
+    requests = g_ptr_array_sized_new (1);
+    g_ptr_array_add (requests,
+                     _mcd_channel_get_requested_properties (channel));
+    g_value_init (&v_requests, dbus_g_type_get_collection ("GPtrArray",
+         MC_HASH_TYPE_QUALIFIED_PROPERTY_VALUE_MAP));
+    g_value_set_static_boxed (&v_requests, requests);
+
+    g_hash_table_insert (properties, "org.freedesktop.Telepathy.ChannelRequest" ".UserActionTime", &v_user_time);
+    g_hash_table_insert (properties, "org.freedesktop.Telepathy.ChannelRequest" ".Requests", &v_requests);
+
+    g_object_ref (channel);
+    mc_cli_client_handler_call_add_request (handler->proxy, -1,
+        _mcd_channel_get_request_path (channel), properties,
+        add_request_cb, channel, g_object_unref, (GObject *)dispatcher);
+
+    g_hash_table_unref (properties);
+    g_ptr_array_free (requests, TRUE);
+}
+
diff --git a/src/mcd-dispatcher.h b/src/mcd-dispatcher.h
index 29a4e89..9bf0de5 100644
--- a/src/mcd-dispatcher.h
+++ b/src/mcd-dispatcher.h
@@ -86,6 +86,10 @@ gint mcd_dispatcher_get_channel_type_usage (McdDispatcher * dispatcher,
 GPtrArray *mcd_dispatcher_get_channel_capabilities (McdDispatcher * dispatcher,
 						    const gchar *protocol);
 
+/* not exported */
+void _mcd_dispatcher_add_request (McdDispatcher *dispatcher,
+                                  McdChannel *channel);
+
 G_END_DECLS
 
 #endif /* MCD_DISPATCHER_H */
diff --git a/src/mcd-master.c b/src/mcd-master.c
index 9fdffd6..faeea0e 100644
--- a/src/mcd-master.c
+++ b/src/mcd-master.c
@@ -1160,6 +1160,20 @@ mcd_master_lookup_manager (McdMaster *master,
 }
 
 /**
+ * mcd_master_get_dispatcher:
+ * @master: the #McdMaster.
+ *
+ * Returns: the #McdDispatcher. It will go away when @master is disposed,
+ * unless you keep a reference to it.
+ */
+McdDispatcher *
+mcd_master_get_dispatcher (McdMaster *master)
+{
+    g_return_val_if_fail (MCD_IS_MASTER (master), NULL);
+    return MCD_MASTER_PRIV (master)->dispatcher;
+}
+
+/**
  * mcd_plugin_get_dispatcher:
  * @plugin: the #McdPlugin
  * 
diff --git a/src/mcd-master.h b/src/mcd-master.h
index 6a23f62..d50389e 100644
--- a/src/mcd-master.h
+++ b/src/mcd-master.h
@@ -63,6 +63,7 @@ McdMaster *mcd_master_get_default (void);
 
 McdManager *mcd_master_lookup_manager (McdMaster *master,
 				       const gchar *unique_name);
+McdDispatcher *mcd_master_get_dispatcher (McdMaster *master);
 
 void mcd_master_request_presence (McdMaster * master,
 				  TpConnectionPresenceType presence,
-- 
1.5.6.5




More information about the Telepathy-commits mailing list