diff options
-rw-r--r-- | telepathy-logger/action-chain-internal.h | 5 | ||||
-rw-r--r-- | telepathy-logger/action-chain.c | 39 | ||||
-rw-r--r-- | telepathy-logger/channel-internal.h | 51 | ||||
-rw-r--r-- | telepathy-logger/channel.c | 262 | ||||
-rw-r--r-- | telepathy-logger/dbus-service.c | 24 | ||||
-rw-r--r-- | telepathy-logger/observer.c | 18 | ||||
-rw-r--r-- | telepathy-logger/text-channel-internal.h | 31 | ||||
-rw-r--r-- | telepathy-logger/text-channel.c | 154 |
8 files changed, 222 insertions, 362 deletions
diff --git a/telepathy-logger/action-chain-internal.h b/telepathy-logger/action-chain-internal.h index f0a75f4..c2c072f 100644 --- a/telepathy-logger/action-chain-internal.h +++ b/telepathy-logger/action-chain-internal.h @@ -40,8 +40,9 @@ void _tpl_action_chain_append (TplActionChain *self, TplPendingAction func, void _tpl_action_chain_prepend (TplActionChain *self, TplPendingAction func, gpointer user_data); void _tpl_action_chain_continue (TplActionChain *self); -void _tpl_action_chain_terminate (TplActionChain *self); +void _tpl_action_chain_terminate (TplActionChain *self, const GError *error); gpointer _tpl_action_chain_get_object (TplActionChain *self); -gboolean _tpl_action_chain_new_finish (GAsyncResult *result); +gboolean _tpl_action_chain_new_finish (GObject *source, + GAsyncResult *result, GError **error); #endif // __TPL_ACTION_CHAIN_H__ diff --git a/telepathy-logger/action-chain.c b/telepathy-logger/action-chain.c index f68a770..0999885 100644 --- a/telepathy-logger/action-chain.c +++ b/telepathy-logger/action-chain.c @@ -110,12 +110,7 @@ void _tpl_action_chain_continue (TplActionChain *self) { if (g_queue_is_empty (self->chain)) - { - GSimpleAsyncResult *simple = self->simple; - - g_simple_async_result_set_op_res_gboolean (simple, TRUE); - g_simple_async_result_complete (simple); - } + g_simple_async_result_complete (self->simple); else { TplActionLink *l = g_queue_pop_head (self->chain); @@ -127,35 +122,49 @@ _tpl_action_chain_continue (TplActionChain *self) void -_tpl_action_chain_terminate (TplActionChain *self) +_tpl_action_chain_terminate (TplActionChain *self, + const GError *error) { GSimpleAsyncResult *simple = self->simple; - g_simple_async_result_set_op_res_gboolean (simple, FALSE); + g_assert (error != NULL); + + g_simple_async_result_set_from_error (simple, error); g_simple_async_result_complete (simple); } /** * _tpl_action_chain_new_finish: + * @source: the #GObject pass to _tpl_action_chain_new_async() + * @result: the #GAsyncResult pass in callback + * @error: a pointer to a #GError that will be set on error, or NULL to ignore * * Get the result from running the action chain (%TRUE if the chain completed - * successfully, %FALSE if it was terminated). + * successfully, %FALSE with @error set if it was terminated). * * This function also frees the chain. + * + * Returns: %TRUE on success, %FALSE with @error set on error. */ gboolean -_tpl_action_chain_new_finish (GAsyncResult *result) +_tpl_action_chain_new_finish (GObject *source, + GAsyncResult *result, + GError **error) { TplActionChain *chain; - gboolean retval; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, source, + _tpl_action_chain_new_async), FALSE); chain = g_object_get_data (G_OBJECT (result), "chain"); - retval = g_simple_async_result_get_op_res_gboolean ( - G_SIMPLE_ASYNC_RESULT (result)); + g_return_val_if_fail (chain != NULL, FALSE); - _tpl_action_chain_free (chain); + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; - return retval; + _tpl_action_chain_free (chain); + return TRUE; } diff --git a/telepathy-logger/channel-internal.h b/telepathy-logger/channel-internal.h index 7c5ec5e..9da0f61 100644 --- a/telepathy-logger/channel-internal.h +++ b/telepathy-logger/channel-internal.h @@ -30,40 +30,35 @@ #include <telepathy-glib/channel.h> G_BEGIN_DECLS -#define TPL_TYPE_CHANNEL (_tpl_channel_get_type ()) -#define TPL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TPL_TYPE_CHANNEL, TplChannel)) -#define TPL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TPL_TYPE_CHANNEL, TplChannelClass)) -#define TPL_IS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TPL_TYPE_CHANNEL)) -#define TPL_IS_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TPL_TYPE_CHANNEL)) -#define TPL_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TPL_TYPE_CHANNEL, TplChannelClass)) -typedef struct _TplChannelPriv TplChannelPriv; +#define TPL_TYPE_CHANNEL (_tpl_channel_get_type ()) +#define TPL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TPL_TYPE_CHANNEL, TplChannel)) +#define TPL_IS_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TPL_TYPE_CHANNEL)) +#define TPL_CHANNEL_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TPL_TYPE_CHANNEL, TplChannelInterface)) -typedef struct -{ - TpChannel parent; - - /* private */ - TplChannelPriv *priv; -} TplChannel; +typedef struct _TplChannel TplChannel; +typedef struct _TplChannelInterface TplChannelInterface; -typedef struct +struct _TplChannelInterface { - TpChannelClass parent_class; - /* Virtual method, to be implemented by subclasses */ - void (*call_when_ready) (TplChannel *self, GAsyncReadyCallback cb, - gpointer user_data); - /* Protected method, should be called only by subclasses to prepare - * TplChannel */ - void (*call_when_ready_protected) (TplChannel *self, GAsyncReadyCallback cb, - gpointer user_data); -} TplChannelClass; + GTypeInterface g_iface; + + void (*prepare_async) (TplChannel *self, + GAsyncReadyCallback cb, + gpointer user_data); + gboolean (*prepare_finish) (TplChannel *self, + GAsyncResult *result, + GError **error); +}; -GType _tpl_channel_get_type (void); +GType _tpl_channel_get_type (void) G_GNUC_CONST; -TpAccount *_tpl_channel_get_account (TplChannel *self); -void _tpl_channel_call_when_ready (TplChannel *self, GAsyncReadyCallback cb, - gpointer user_data); +void _tpl_channel_prepare_async (TplChannel *self, + GAsyncReadyCallback cb, + gpointer user_data); +gboolean _tpl_channel_prepare_finish (TplChannel *self, + GAsyncResult *result, + GError **error); G_END_DECLS #endif // __TPL_CHANNEL_H__ diff --git a/telepathy-logger/channel.c b/telepathy-logger/channel.c index a098e46..fe5309c 100644 --- a/telepathy-logger/channel.c +++ b/telepathy-logger/channel.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2009 Collabora Ltd. + * Copyright (C) 2009-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,168 +17,25 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk> + * Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> */ #include "config.h" #include "channel-internal.h" -#include <string.h> - #include <glib.h> -#include <telepathy-glib/util.h> - -#include <telepathy-logger/text-channel-internal.h> -#include <telepathy-logger/observer-internal.h> - -#define DEBUG_FLAG TPL_DEBUG_CHANNEL -#include <telepathy-logger/action-chain-internal.h> -#include <telepathy-logger/debug-internal.h> -#include <telepathy-logger/util-internal.h> - -#define TPCHAN_PROP_PREFIX "org.freedesktop.Telepathy.Channel." -#define TPCHAN_PROP_PREFIX_LEN strlen(TPCHAN_PROP_PREFIX) - -static void tpl_channel_set_account (TplChannel *self, TpAccount *data); -static void call_when_ready_protected (TplChannel *self, - GAsyncReadyCallback cb, gpointer user_data); -static void pendingproc_get_ready_tp_connection (TplActionChain *ctx, - gpointer user_data); -static void pendingproc_get_ready_tp_channel (TplActionChain *ctx, - gpointer user_data); - -G_DEFINE_ABSTRACT_TYPE (TplChannel, _tpl_channel, TP_TYPE_CHANNEL) - -struct _TplChannelPriv -{ - TpAccount *account; -}; - -enum -{ - PROP0, - PROP_ACCOUNT -}; - -static void -tpl_channel_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TplChannelPriv *priv = TPL_CHANNEL (object)->priv; - - switch (param_id) - { - case PROP_ACCOUNT: - g_value_set_object (value, priv->account); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -tpl_channel_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TplChannel *self = TPL_CHANNEL (object); - - switch (param_id) { - case PROP_ACCOUNT: - tpl_channel_set_account (self, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - - -static void -tpl_channel_dispose (GObject *obj) -{ - TplChannelPriv *priv = TPL_CHANNEL (obj)->priv; - - if (priv->account != NULL) - { - g_object_unref (priv->account); - priv->account = NULL; - } - - G_OBJECT_CLASS (_tpl_channel_parent_class)->dispose (obj); -} - - -static void -_tpl_channel_class_init (TplChannelClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *param_spec; - - object_class->dispose = tpl_channel_dispose; - object_class->get_property = tpl_channel_get_property; - object_class->set_property = tpl_channel_set_property; - - klass->call_when_ready_protected = call_when_ready_protected; - - /** - * TplChannel:account: - * - * the TpAccount instance associated with TplChannel - */ - param_spec = g_param_spec_object ("account", - "Account", "TpAccount instance associated with TplChannel", - TP_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); - - g_type_class_add_private (object_class, sizeof (TplChannelPriv)); -} - - -static void -_tpl_channel_init (TplChannel *self) -{ - TplChannelPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TPL_TYPE_CHANNEL, - TplChannelPriv); - self->priv = priv; -} - - -TpAccount * -_tpl_channel_get_account (TplChannel *self) -{ - TplChannelPriv *priv; - - g_return_val_if_fail (TPL_IS_CHANNEL (self), NULL); - - priv = self->priv; - return priv->account; -} +G_DEFINE_INTERFACE (TplChannel, _tpl_channel, TP_TYPE_CHANNEL) static void -tpl_channel_set_account (TplChannel *self, - TpAccount *data) +_tpl_channel_default_init (TplChannelInterface *iface) { - TplChannelPriv *priv; - - g_return_if_fail (TPL_IS_CHANNEL (self)); - g_return_if_fail (TP_IS_ACCOUNT (data)); - - priv = self->priv; - g_return_if_fail (priv->account == NULL); - - priv->account = g_object_ref (data); } /** - * tpl_channel_call_when_ready + * tpl_channel_prepare_async * @self: a TplChannel instance * @cb: a callback * @user_data: user's data passed to the callback @@ -186,116 +43,29 @@ tpl_channel_set_account (TplChannel *self, * The TplObserver has no idea of what TplChannel subclass instance it's * dealing with. * In order to prepare the subclass instance this method has to - * be called, which will call #TplChannelClass.call_when_ready + * be called, which will call #TplChannelClass.prepare_async * virtual method, implemented (mandatory) by #TplChannel subclasses. - * Such method has to call, internally, - * #TplChannelClass.call_when_ready_protected in order to prepare also the - * #TplChannel instance. */ void -_tpl_channel_call_when_ready (TplChannel *self, +_tpl_channel_prepare_async (TplChannel *self, GAsyncReadyCallback cb, gpointer user_data) { g_return_if_fail (TPL_IS_CHANNEL (self)); - /* Subclasses have to implement it */ - g_return_if_fail (TPL_CHANNEL_GET_CLASS (self)->call_when_ready != NULL); - - TPL_CHANNEL_GET_CLASS (self)->call_when_ready (self, cb, user_data); -} - - -/** - * call_when_ready_protected - * @self: a TplChannel instance - * @cb: a callback - * @user_data: user's data passed to the callback - * - * This static method is called from #TplChannelClass.call_when_ready, implemented by - * #TplChannel subclasses. - * - * See also: %tpl_channel_call_when_ready - */ -static void -call_when_ready_protected (TplChannel *self, - GAsyncReadyCallback cb, - gpointer user_data) -{ - TplActionChain *actions; - - actions = _tpl_action_chain_new_async (G_OBJECT (self), cb, user_data); - _tpl_action_chain_append (actions, pendingproc_get_ready_tp_connection, NULL); - _tpl_action_chain_append (actions, pendingproc_get_ready_tp_channel, NULL); - _tpl_action_chain_continue (actions); -} - -static void -conn_prepared_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TplActionChain *ctx = user_data; - GError *error = NULL; - - if (!tp_proxy_prepare_finish (source, result, &error)) - { - TplChannel *tpl_chan; - - tpl_chan = _tpl_action_chain_get_object (ctx); - PATH_DEBUG (tpl_chan, "Giving up channel observation: %s", - error->message); + g_return_if_fail (TPL_CHANNEL_GET_IFACE (self)->prepare_async != NULL); - _tpl_action_chain_terminate (ctx); - g_error_free (error); - return; - } - - _tpl_action_chain_continue (ctx); + TPL_CHANNEL_GET_IFACE (self)->prepare_async (self, cb, user_data); } -static void -pendingproc_get_ready_tp_connection (TplActionChain *ctx, - gpointer user_data) -{ - TplChannel *tpl_chan = _tpl_action_chain_get_object (ctx); - TpConnection *tp_conn = tp_channel_borrow_connection (TP_CHANNEL ( - tpl_chan)); - GQuark features[] = { TP_CONNECTION_FEATURE_CORE, 0 }; - - tp_proxy_prepare_async (tp_conn, features, conn_prepared_cb, ctx); -} -static void -channel_prepared_cb (GObject *source, +gboolean +_tpl_channel_prepare_finish (TplChannel *self, GAsyncResult *result, - gpointer user_data) -{ - TplActionChain *ctx = user_data; - TplChannel *tpl_chan = _tpl_action_chain_get_object (ctx); - GError *error = NULL; - - if (!tp_proxy_prepare_finish (source, result, &error)) - { - PATH_DEBUG (tpl_chan, "Giving up channel observation: %s", - error->message); - - _tpl_action_chain_terminate (ctx); - g_error_free (error); - return; - - } - - _tpl_action_chain_continue (ctx); -} - -static void -pendingproc_get_ready_tp_channel (TplActionChain *ctx, - gpointer user_data) + GError **error) { - TplChannel *tpl_chan = _tpl_action_chain_get_object (ctx); - GQuark features[] = { TP_CHANNEL_FEATURE_CORE, TP_CHANNEL_FEATURE_GROUP, 0 }; + g_return_val_if_fail (TPL_IS_CHANNEL (self), FALSE); + g_return_val_if_fail (TPL_CHANNEL_GET_IFACE (self)->prepare_finish != NULL, + FALSE); - /* user_data is a TplChannel instance */ - tp_proxy_prepare_async (TP_CHANNEL (tpl_chan), features, channel_prepared_cb, - ctx); + return TPL_CHANNEL_GET_IFACE (self)->prepare_finish (self, result, error); } diff --git a/telepathy-logger/dbus-service.c b/telepathy-logger/dbus-service.c index 536733d..22561ad 100644 --- a/telepathy-logger/dbus-service.c +++ b/telepathy-logger/dbus-service.c @@ -214,9 +214,9 @@ favourite_contacts_file_read_line_cb (GObject *object, if (error != NULL) { - DEBUG ("failed to open favourite contacts file: %s", error->message); + g_prefix_error (&error, "failed to open favourite contacts file: "); + _tpl_action_chain_terminate (action_chain, error); g_clear_error (&error); - _tpl_action_chain_terminate (action_chain); } else if (line != NULL) { @@ -260,9 +260,9 @@ favourite_contacts_file_open_cb (GObject *object, } else { - DEBUG ("Failed to open the favourite contacts file: %s", error->message); + g_prefix_error (&error, "Failed to open the favourite contacts file: "); + _tpl_action_chain_terminate (action_chain, error); g_clear_error (&error); - _tpl_action_chain_terminate (action_chain); } } @@ -309,11 +309,13 @@ favourite_contacts_file_parsed_cb (GObject *object, { TplDBusService *self = TPL_DBUS_SERVICE (object); TplDBusServicePriv *priv = self->priv; + GError *error = NULL; - if (!_tpl_action_chain_new_finish (result)) + if (!_tpl_action_chain_new_finish (object, result, &error)) { DEBUG ("Failed to parse the favourite contacts file and/or execute " - "subsequent queued method calls"); + "subsequent queued method calls: %s", error->message); + g_error_free (error); } priv->favourite_contacts_actions = NULL; @@ -602,9 +604,10 @@ pendingproc_add_favourite_contact (TplActionChain *action_chain, return; pendingproc_add_favourite_contact_ERROR: - g_clear_error (&error); if (action_chain != NULL) - _tpl_action_chain_terminate (action_chain); + _tpl_action_chain_terminate (action_chain, error); + + g_clear_error (&error); } @@ -702,9 +705,10 @@ pendingproc_remove_favourite_contact (TplActionChain *action_chain, return; pendingproc_remove_favourite_contact_ERROR: - g_clear_error (&error); if (action_chain != NULL) - _tpl_action_chain_terminate (action_chain); + _tpl_action_chain_terminate (action_chain, error); + + g_clear_error (&error); } static void diff --git a/telepathy-logger/observer.c b/telepathy-logger/observer.c index a2bd40b..2645e08 100644 --- a/telepathy-logger/observer.c +++ b/telepathy-logger/observer.c @@ -82,7 +82,8 @@ */ static void tpl_observer_dispose (GObject * obj); -static void got_tpl_text_channel_ready_cb (GObject *obj, GAsyncResult *result, +static void channel_prepared_cb (GObject *obj, + GAsyncResult *result, gpointer user_data); static TplChannelFactory tpl_observer_get_channel_factory (TplObserver *self); @@ -181,7 +182,7 @@ tpl_observer_observe_channels (TpBaseClient *client, g_hash_table_insert (self->priv->preparing_channels, (gchar *) tp_proxy_get_object_path (tpl_chan), tpl_chan); - _tpl_channel_call_when_ready (tpl_chan, got_tpl_text_channel_ready_cb, + _tpl_channel_prepare_async (tpl_chan, channel_prepared_cb, observing_ctx); } @@ -227,23 +228,24 @@ _tpl_observer_register_channel (TplObserver *self, return TRUE; } + static void -got_tpl_text_channel_ready_cb (GObject *obj, +channel_prepared_cb (GObject *obj, GAsyncResult *result, gpointer user_data) { ObservingContext *observing_ctx = user_data; - gboolean success = _tpl_action_chain_new_finish (result); + GError *error = NULL; - if (success) + if (_tpl_action_chain_new_finish (obj, result, &error)) { - PATH_DEBUG (obj, "prepared channel"); - + PATH_DEBUG (obj, "channel prepared"); _tpl_observer_register_channel (observing_ctx->self, TPL_CHANNEL (obj)); } else { - PATH_DEBUG (obj, "failed to prepare"); + PATH_DEBUG (obj, "failed to prepare channel: %s", error->message); + g_error_free (error); } g_hash_table_remove (observing_ctx->self->priv->preparing_channels, diff --git a/telepathy-logger/text-channel-internal.h b/telepathy-logger/text-channel-internal.h index 2b71a01..00f4d87 100644 --- a/telepathy-logger/text-channel-internal.h +++ b/telepathy-logger/text-channel-internal.h @@ -31,21 +31,34 @@ #include <telepathy-glib/channel.h> #include <telepathy-glib/connection.h> #include <telepathy-glib/contact.h> +#include <telepathy-glib/text-channel.h> -#include <telepathy-logger/channel-internal.h> +#include "channel-internal.h" G_BEGIN_DECLS -#define TPL_TYPE_TEXT_CHANNEL (_tpl_text_channel_get_type ()) -#define TPL_TEXT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TPL_TYPE_TEXT_CHANNEL, TplTextChannel)) -#define TPL_TEXT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TPL_TYPE_TEXT_CHANNEL, TplTextChannelClass)) -#define TPL_IS_TEXT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TPL_TYPE_TEXT_CHANNEL)) -#define TPL_IS_TEXT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TPL_TYPE_TEXT_CHANNEL)) -#define TPL_TEXT_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TPL_TYPE_TEXT_CHANNEL, TplTextChannelClass)) + +#define TPL_TYPE_TEXT_CHANNEL (_tpl_text_channel_get_type ()) +#define TPL_TEXT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TPL_TYPE_TEXT_CHANNEL, TplTextChannel)) +#define TPL_TEXT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TPL_TYPE_TEXT_CHANNEL, TplTextChannelClass)) +#define TPL_IS_TEXT_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TPL_TYPE_TEXT_CHANNEL)) +#define TPL_IS_TEXT_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TPL_TYPE_TEXT_CHANNEL)) +#define TPL_TEXT_CHANNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TPL_TYPE_TEXT_CHANNEL, TplTextChannelClass)) + + +#define TPL_TEXT_CHANNEL_ERROR \ + g_quark_from_static_string ("tpl-text-channel-error-quark") + +typedef enum +{ + /* generic error */ + TPL_TEXT_CHANNEL_ERROR_FAILED, + TPL_TEXT_CHANNEL_ERROR_NEED_MESSAGE_INTERFACE, +} TplTextChannelError; typedef struct _TplTextChannelPriv TplTextChannelPriv; typedef struct { - TplChannel parent; + TpTextChannel parent; /* private */ TplTextChannelPriv *priv; @@ -53,7 +66,7 @@ typedef struct typedef struct { - TplChannelClass parent_class; + TpTextChannelClass parent_class; } TplTextChannelClass; GType _tpl_text_channel_get_type (void); diff --git a/telepathy-logger/text-channel.c b/telepathy-logger/text-channel.c index 6b2f054..58114bd 100644 --- a/telepathy-logger/text-channel.c +++ b/telepathy-logger/text-channel.c @@ -43,6 +43,7 @@ struct _TplTextChannelPriv { + TpAccount *account; TplEntity *self; gboolean is_chatroom; TplEntity *chatroom; /* only set if is_chatroom==TRUE */ @@ -62,36 +63,86 @@ static TpContactFeature features[3] = { TP_CONTACT_FEATURE_AVATAR_TOKEN }; -G_DEFINE_TYPE (TplTextChannel, _tpl_text_channel, TPL_TYPE_CHANNEL) +static void tpl_text_channel_iface_init (TplChannelInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (TplTextChannel, _tpl_text_channel, + TP_TYPE_TEXT_CHANNEL, + G_IMPLEMENT_INTERFACE (TPL_TYPE_CHANNEL, tpl_text_channel_iface_init)) static void -got_tpl_chan_ready_cb (GObject *obj, +connection_prepared_cb (GObject *source, GAsyncResult *result, gpointer user_data) { - TpProxy *proxy = TP_PROXY (obj); TplActionChain *ctx = user_data; + GError *error = NULL; - /* if TplChannel preparation is OK (and support Message interface, - * keep on with the TplTextChannel */ - if (_tpl_action_chain_new_finish (result) - && tp_proxy_has_interface_by_id (proxy, - TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES)) - _tpl_action_chain_continue (ctx); - else - _tpl_action_chain_terminate (ctx); + if (!tp_proxy_prepare_finish (source, result, &error)) + { + _tpl_action_chain_terminate (ctx, error); + g_error_free (error); + return; + } + + _tpl_action_chain_continue (ctx); } static void -pendingproc_prepare_tpl_channel (TplActionChain *ctx, +pendingproc_prepare_tp_connection (TplActionChain *ctx, gpointer user_data) { - TplChannel *tpl_chan = TPL_CHANNEL (_tpl_action_chain_get_object (ctx)); + TplChannel *chan = _tpl_action_chain_get_object (ctx); + TpConnection *conn = tp_channel_borrow_connection (TP_CHANNEL (chan)); + GQuark conn_features[] = { TP_CONNECTION_FEATURE_CORE, 0 }; - TPL_CHANNEL_GET_CLASS (tpl_chan)->call_when_ready_protected (tpl_chan, - got_tpl_chan_ready_cb, ctx); + tp_proxy_prepare_async (conn, conn_features, connection_prepared_cb, ctx); +} + + +static void +channel_prepared_cb (GObject *source, + GAsyncResult *result, + gpointer ctx) +{ + TplChannel *chan = _tpl_action_chain_get_object (ctx); + GError *error = NULL; + + if (!tp_proxy_prepare_finish (source, result, &error)) + { + _tpl_action_chain_terminate (ctx, error); + g_error_free (error); + return; + } + else if (!tp_proxy_has_interface_by_id (TP_PROXY (chan), + TP_IFACE_QUARK_CHANNEL_INTERFACE_MESSAGES)) + { + error = g_error_new (TPL_TEXT_CHANNEL_ERROR, + TPL_TEXT_CHANNEL_ERROR_NEED_MESSAGE_INTERFACE, + "The text channel does not implement Message interface."); + _tpl_action_chain_terminate (ctx, error); + g_error_free (error); + } + + _tpl_action_chain_continue (ctx); +} + + +static void +pendingproc_prepare_tp_text_channel (TplActionChain *ctx, + gpointer user_data) +{ + TplChannel *chan = _tpl_action_chain_get_object (ctx); + GQuark chan_features[] = { + TP_CHANNEL_FEATURE_CORE, + TP_CHANNEL_FEATURE_GROUP, + TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES, + 0 + }; + + /* user_data is a TplChannel instance */ + tp_proxy_prepare_async (chan, chan_features, channel_prepared_cb, ctx); } @@ -116,13 +167,16 @@ get_self_contact_cb (TpConnection *connection, { TpConnection *tp_conn = tp_channel_borrow_connection (tp_chan); const gchar *conn_path; + GError *new_error = NULL; conn_path = tp_proxy_get_object_path (TP_PROXY (tp_conn)); - PATH_DEBUG (tpl_text, "Error resolving self handle for connection %s." - " Aborting channel observation", conn_path); + new_error = g_error_new (error->domain, error->code, + "Error resolving self handle for connection %s: %s)", + conn_path, error->message); - _tpl_action_chain_terminate (ctx); + _tpl_action_chain_terminate (ctx, new_error); + g_error_free (new_error); return; } @@ -168,10 +222,13 @@ get_remote_contacts_cb (TpConnection *connection, if (error != NULL) { - DEBUG ("Failed to get remote contacts: %s", error->message); - if (ctx != NULL) - _tpl_action_chain_terminate (ctx); + { + GError *new_error = NULL; + new_error = g_error_new (error->domain, error->code, + "Failed to get remote contacts: %s", error->message); + _tpl_action_chain_terminate (ctx, error); + } return; } @@ -444,7 +501,7 @@ tpl_text_channel_store_message (TplTextChannel *self, /* Initialise TplTextEvent */ event = g_object_new (TPL_TYPE_TEXT_EVENT, /* TplEvent */ - "account", _tpl_channel_get_account (TPL_CHANNEL (self)), + "account", priv->account, "channel-path", tp_proxy_get_object_path (TP_PROXY (self)), "receiver", receiver, "sender", sender, @@ -538,33 +595,34 @@ pendingproc_connect_message_signals (TplActionChain *ctx, return; disaster: - DEBUG ("couldn't connect to signals: %s", error->message); - g_clear_error (&error); - _tpl_action_chain_terminate (ctx); + g_prefix_error (&error, "Couldn't connect to signals: "); + _tpl_action_chain_terminate (ctx, error); + g_error_free (error); +} + +static gboolean +tpl_text_channel_prepare_finish (TplChannel *chan, + GAsyncResult *result, + GError **error) +{ + return _tpl_action_chain_new_finish (G_OBJECT (chan), result, error); } static void -tpl_text_channel_call_when_ready (TplChannel *chan, - GAsyncReadyCallback cb, gpointer user_data) +tpl_text_channel_prepare_async (TplChannel *chan, + GAsyncReadyCallback cb, + gpointer user_data) { TplActionChain *actions; - /* first: connect signals, so none are lost - * second: prepare all TplChannel - * third: cache my contact and the remote one. - * last: connect to Message signals - * - * If for any reason, the order is changed, it's needed to check what objects - * are unreferenced by g_object_unref but used by a next action AND what - * object are actually not prepared but used anyway */ actions = _tpl_action_chain_new_async (G_OBJECT (chan), cb, user_data); - _tpl_action_chain_append (actions, pendingproc_prepare_tpl_channel, NULL); + _tpl_action_chain_append (actions, pendingproc_prepare_tp_connection, NULL); + _tpl_action_chain_append (actions, pendingproc_prepare_tp_text_channel, NULL); _tpl_action_chain_append (actions, pendingproc_get_my_contact, NULL); _tpl_action_chain_append (actions, pendingproc_get_remote_contacts, NULL); _tpl_action_chain_append (actions, pendingproc_connect_message_signals, NULL); - /* start the chain consuming */ _tpl_action_chain_continue (actions); } @@ -595,18 +653,23 @@ static void _tpl_text_channel_class_init (TplTextChannelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - TplChannelClass *tpl_chan_class = TPL_CHANNEL_CLASS (klass); object_class->dispose = tpl_text_channel_dispose; object_class->finalize = tpl_text_channel_finalize; - tpl_chan_class->call_when_ready = tpl_text_channel_call_when_ready; - g_type_class_add_private (object_class, sizeof (TplTextChannelPriv)); } static void +tpl_text_channel_iface_init (TplChannelInterface *iface) +{ + iface->prepare_async = tpl_text_channel_prepare_async; + iface->prepare_finish = tpl_text_channel_prepare_finish; +} + + +static void _tpl_text_channel_init (TplTextChannel *self) { TplTextChannelPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, @@ -652,8 +715,9 @@ _tpl_text_channel_new (TpConnection *conn, GError **error) { TpProxy *conn_proxy = TP_PROXY (conn); + TplTextChannel *self; - /* Do what tpl_channel_new does + set TplTextChannel specific properties */ + /* Do what tpl_channel_new does + set TplTextChannel specific */ g_return_val_if_fail (TP_IS_CONNECTION (conn), NULL); g_return_val_if_fail (TP_IS_ACCOUNT (account), NULL); @@ -663,9 +727,7 @@ _tpl_text_channel_new (TpConnection *conn, if (!tp_dbus_check_valid_object_path (object_path, error)) return NULL; - return g_object_new (TPL_TYPE_TEXT_CHANNEL, - /* TplChannel properties */ - "account", account, + self = g_object_new (TPL_TYPE_TEXT_CHANNEL, /* TpChannel properties */ "connection", conn, "dbus-daemon", conn_proxy->dbus_daemon, @@ -674,4 +736,8 @@ _tpl_text_channel_new (TpConnection *conn, "handle-type", (guint) TP_UNKNOWN_HANDLE_TYPE, "channel-properties", tp_chan_props, NULL); + + self->priv->account = g_object_ref (account); + + return self; } |