summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extensions/Logger.xml83
-rw-r--r--telepathy-logger/Makefile.am2
-rw-r--r--telepathy-logger/action-chain.c42
-rw-r--r--telepathy-logger/action-chain.h8
-rw-r--r--telepathy-logger/channel-text.c56
-rw-r--r--telepathy-logger/channel.c24
-rw-r--r--telepathy-logger/dbus-service.c856
-rw-r--r--telepathy-logger/dbus-service.h6
-rw-r--r--tests/tpl-channel-test.c8
9 files changed, 970 insertions, 115 deletions
diff --git a/extensions/Logger.xml b/extensions/Logger.xml
index 1695690..a377829 100644
--- a/extensions/Logger.xml
+++ b/extensions/Logger.xml
@@ -91,6 +91,89 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</
</tp:docstring>
</method>
+ <method name="GetFavouriteContacts"
+ tp:name-for-bindings="Get_Favourite_Contacts">
+ <arg direction="out" name="Favourite_Contacts" type="a(oas)">
+ <tp:docstring>
+ The favourite contacts, as an array of TpAccounts and their contact
+ identifiers.
+ </tp:docstring>
+ </arg>
+
+ <tp:docstring>
+ Returns the favourite contacts.
+ </tp:docstring>
+ </method>
+
+ <method name="AddFavouriteContact"
+ tp:name-for-bindings="Add_Favourite_Contact">
+ <arg direction="in" name="Account" type="o" tp:type="Account">
+ <tp:docstring>
+ The object path for the TpAccount to which the contact belongs
+ </tp:docstring>
+ </arg>
+
+ <arg direction="in" name="Identifier" type="s">
+ <tp:docstring>
+ The favourite contact's identifier
+ </tp:docstring>
+ </arg>
+
+ <tp:docstring>
+ Add a contact's designation as a favourite. This method may not be
+ called until the service is ready. See the <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Logger.DRAFT">FavouriteContactsReady</tp:dbus-ref> signal and <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Logger.DRAFT">FavouriteContactsIsReady</tp:dbus-ref> property.
+ </tp:docstring>
+ </method>
+
+ <method name="RemoveFavouriteContact"
+ tp:name-for-bindings="Remove_Favourite_Contact">
+ <arg direction="in" name="Account" type="o" tp:type="Account">
+ <tp:docstring>
+ The object path for the TpAccount to which the contact belongs
+ </tp:docstring>
+ </arg>
+
+ <arg direction="in" name="Identifier" type="s">
+ <tp:docstring>
+ The favourite contact's identifier
+ </tp:docstring>
+ </arg>
+
+ <tp:docstring>
+ Remove a contact's designation as a favourite. This method may not be
+ called until the service is ready. See the <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Logger.DRAFT">FavouriteContactsReady</tp:dbus-ref> signal and <tp:dbus-ref
+ namespace="org.freedesktop.Telepathy.Logger.DRAFT">FavouriteContactsIsReady</tp:dbus-ref> property.
+ </tp:docstring>
+ </method>
+
+ <signal name="FavouriteContactsChanged"
+ tp:name-for-bindings="Favourite_Contacts_Changed">
+ <tp:docstring>
+ The set of favourite contacts has changed.
+ </tp:docstring>
+
+ <arg name="Account" type="o" tp:type="Account">
+ <tp:docstring>
+ An account associated with the contact.
+ </tp:docstring>
+ </arg>
+
+ <arg name="Added" type="as">
+ <tp:docstring>
+ List of contact identifiers of contacts which are now favourites.
+ </tp:docstring>
+ </arg>
+
+ <arg name="Removed" type="as">
+ <tp:docstring>
+ List of contact identifiers of contacts which are no longer favourites.
+ </tp:docstring>
+ </arg>
+ </signal>
+
</interface>
</node>
<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/telepathy-logger/Makefile.am b/telepathy-logger/Makefile.am
index 3f2021c..3892482 100644
--- a/telepathy-logger/Makefile.am
+++ b/telepathy-logger/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir) \
$(ERROR_CFLAGS) \
-DG_LOG_DOMAIN=\"tp-logger\" \
+ -DTPL_DATA_DIR=\"$(PACKAGE_NAME)\" \
$(LIBTPL_CFLAGS) \
$(DISABLE_DEPRECATED) \
$(WARN_CFLAGS)
@@ -38,7 +39,6 @@ LIBTPL_HEADERS = \
observer.h \
util.h
-
libtelepathy_logger_la_SOURCES = \
action-chain.c \
channel.c \
diff --git a/telepathy-logger/action-chain.c b/telepathy-logger/action-chain.c
index 7d4af57..f29a9c5 100644
--- a/telepathy-logger/action-chain.c
+++ b/telepathy-logger/action-chain.c
@@ -22,6 +22,12 @@
#include "config.h"
#include "action-chain.h"
+typedef struct {
+ TplPendingAction action;
+ gpointer user_data;
+} TplActionLink;
+
+
TplActionChain *
tpl_actionchain_new (GObject *obj,
GAsyncReadyCallback cb,
@@ -37,9 +43,17 @@ tpl_actionchain_new (GObject *obj,
}
+static void
+link_free (TplActionLink *link)
+{
+ g_slice_free (TplActionLink, link);
+}
+
+
void
tpl_actionchain_free (TplActionChain *self)
{
+ g_queue_foreach (self->chain, (GFunc) link_free, NULL);
g_queue_free (self->chain);
/* TODO free self->simple, I canont understand how */
g_slice_free (TplActionChain, self);
@@ -57,17 +71,31 @@ tpl_actionchain_get_object (TplActionChain *self)
void
tpl_actionchain_prepend (TplActionChain *self,
- TplPendingAction func)
+ TplPendingAction func,
+ gpointer user_data)
{
- g_queue_push_head (self->chain, func);
+ TplActionLink *link;
+
+ link = g_slice_new0 (TplActionLink);
+ link->action = func;
+ link->user_data = user_data;
+
+ g_queue_push_head (self->chain, link);
}
void
tpl_actionchain_append (TplActionChain *self,
- TplPendingAction func)
+ TplPendingAction func,
+ gpointer user_data)
{
- g_queue_push_tail (self->chain, func);
+ TplActionLink *link;
+
+ link = g_slice_new0 (TplActionLink);
+ link->action = func;
+ link->user_data = user_data;
+
+ g_queue_push_tail (self->chain, link);
}
@@ -83,8 +111,10 @@ tpl_actionchain_continue (TplActionChain *self)
}
else
{
- TplPendingAction next_action = g_queue_pop_head (self->chain);
- next_action (self);
+ TplActionLink *link = g_queue_pop_head (self->chain);
+
+ link->action (self, link->user_data);
+ link_free (link);
}
}
diff --git a/telepathy-logger/action-chain.h b/telepathy-logger/action-chain.h
index f5027e1..75621fc 100644
--- a/telepathy-logger/action-chain.h
+++ b/telepathy-logger/action-chain.h
@@ -33,9 +33,11 @@ typedef struct {
TplActionChain *tpl_actionchain_new (GObject *obj, GAsyncReadyCallback cb,
gpointer user_data);
void tpl_actionchain_free (TplActionChain *self);
-typedef void (*TplPendingAction) (TplActionChain *ctx);
-void tpl_actionchain_append (TplActionChain *self, TplPendingAction func);
-void tpl_actionchain_prepend (TplActionChain *self, TplPendingAction func);
+typedef void (*TplPendingAction) (TplActionChain *ctx, gpointer user_data);
+void tpl_actionchain_append (TplActionChain *self, TplPendingAction func,
+ gpointer user_data);
+void tpl_actionchain_prepend (TplActionChain *self, TplPendingAction func,
+ gpointer user_data);
void tpl_actionchain_continue (TplActionChain *self);
void tpl_actionchain_terminate (TplActionChain *self);
gpointer tpl_actionchain_get_object (TplActionChain *self);
diff --git a/telepathy-logger/channel-text.c b/telepathy-logger/channel-text.c
index ee62527..159e237 100644
--- a/telepathy-logger/channel-text.c
+++ b/telepathy-logger/channel-text.c
@@ -78,16 +78,23 @@ static void on_sent_signal_cb (TpChannel *proxy, guint arg_Timestamp,
static void on_send_error_cb (TpChannel *proxy, guint arg_Error,
guint arg_Timestamp, guint arg_Type, const gchar *arg_Text,
gpointer user_data, GObject *weak_object);
-static void pendingproc_connect_signals (TplActionChain *ctx);
-static void pendingproc_get_pending_messages (TplActionChain *ctx);
-static void pendingproc_prepare_tpl_channel (TplActionChain *ctx);
-static void pendingproc_get_chatroom_id (TplActionChain *ctx);
+static void pendingproc_connect_signals (TplActionChain *ctx,
+ gpointer user_data);
+static void pendingproc_get_pending_messages (TplActionChain *ctx,
+ gpointer user_data);
+static void pendingproc_prepare_tpl_channel (TplActionChain *ctx,
+ gpointer user_data);
+static void pendingproc_get_chatroom_id (TplActionChain *ctx,
+ gpointer user_data);
static void get_chatroom_id_cb (TpConnection *proxy,
const gchar **identifiers, const GError *error, gpointer user_data,
GObject *weak_object);
-static void pendingproc_get_my_contact (TplActionChain *ctx);
-static void pendingproc_get_remote_contact (TplActionChain *ctx);
-static void pendingproc_get_remote_handle_type (TplActionChain *ctx);
+static void pendingproc_get_my_contact (TplActionChain *ctx,
+ gpointer user_data);
+static void pendingproc_get_remote_contact (TplActionChain *ctx,
+ gpointer user_data);
+static void pendingproc_get_remote_handle_type (TplActionChain *ctx,
+ gpointer user_data);
static void keepon_on_receiving_signal (TplLogEntryText *log);
@@ -157,7 +164,8 @@ got_contact_cb (TpConnection *connection,
static void
-pendingproc_get_remote_contact (TplActionChain *ctx)
+pendingproc_get_remote_contact (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *tpl_text = tpl_actionchain_get_object (ctx);
TplChannel *tpl_chan = TPL_CHANNEL (tpl_text);
@@ -174,7 +182,8 @@ pendingproc_get_remote_contact (TplActionChain *ctx)
static void
-pendingproc_get_my_contact (TplActionChain *ctx)
+pendingproc_get_my_contact (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *tpl_text = tpl_actionchain_get_object (ctx);
TpConnection *tp_conn = tp_channel_borrow_connection (
@@ -188,7 +197,8 @@ pendingproc_get_my_contact (TplActionChain *ctx)
static void
-pendingproc_get_remote_handle_type (TplActionChain *ctx)
+pendingproc_get_remote_handle_type (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *tpl_text = tpl_actionchain_get_object (ctx);
TpHandleType remote_handle_type;
@@ -198,10 +208,10 @@ pendingproc_get_remote_handle_type (TplActionChain *ctx)
switch (remote_handle_type)
{
case TP_HANDLE_TYPE_CONTACT:
- tpl_actionchain_prepend (ctx, pendingproc_get_remote_contact);
+ tpl_actionchain_prepend (ctx, pendingproc_get_remote_contact, NULL);
break;
case TP_HANDLE_TYPE_ROOM:
- tpl_actionchain_prepend (ctx, pendingproc_get_chatroom_id);
+ tpl_actionchain_prepend (ctx, pendingproc_get_chatroom_id, NULL);
break;
case TP_HANDLE_TYPE_NONE:
PATH_DEBUG (tpl_text, "HANDLE_TYPE_NONE received, probably an anonymous "
@@ -472,18 +482,19 @@ tpl_channel_text_call_when_ready (TplChannelText *self,
* are unreferenced by g_object_unref but used by a next action AND what object are actually not
* prepared but used anyway */
actions = tpl_actionchain_new (G_OBJECT (self), cb, user_data);
- tpl_actionchain_append (actions, pendingproc_connect_signals);
- tpl_actionchain_append (actions, pendingproc_prepare_tpl_channel);
- tpl_actionchain_append (actions, pendingproc_get_my_contact);
- tpl_actionchain_append (actions, pendingproc_get_remote_handle_type);
- tpl_actionchain_append (actions, pendingproc_get_pending_messages);
+ tpl_actionchain_append (actions, pendingproc_connect_signals, NULL);
+ tpl_actionchain_append (actions, pendingproc_prepare_tpl_channel, NULL);
+ tpl_actionchain_append (actions, pendingproc_get_my_contact, NULL);
+ tpl_actionchain_append (actions, pendingproc_get_remote_handle_type, NULL);
+ tpl_actionchain_append (actions, pendingproc_get_pending_messages, NULL);
/* start the chain consuming */
tpl_actionchain_continue (actions);
}
static void
-pendingproc_prepare_tpl_channel (TplActionChain *ctx)
+pendingproc_prepare_tpl_channel (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannel *tpl_chan = TPL_CHANNEL (tpl_actionchain_get_object (ctx));
@@ -509,7 +520,8 @@ got_tpl_chan_ready_cb (GObject *obj,
static void
-pendingproc_get_pending_messages (TplActionChain *ctx)
+pendingproc_get_pending_messages (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *chan_text = tpl_actionchain_get_object (ctx);
@@ -567,7 +579,8 @@ got_pending_messages_cb (TpChannel *proxy,
static void
-pendingproc_get_chatroom_id (TplActionChain *ctx)
+pendingproc_get_chatroom_id (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *tpl_text = tpl_actionchain_get_object (ctx);
TplChannel *tpl_chan = TPL_CHANNEL (tpl_text);
@@ -612,7 +625,8 @@ get_chatroom_id_cb (TpConnection *proxy,
static void
-pendingproc_connect_signals (TplActionChain *ctx)
+pendingproc_connect_signals (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannelText *tpl_text = tpl_actionchain_get_object (ctx);
GError *error = NULL;
diff --git a/telepathy-logger/channel.c b/telepathy-logger/channel.c
index 7772f4c..814d73e 100644
--- a/telepathy-logger/channel.c
+++ b/telepathy-logger/channel.c
@@ -41,13 +41,16 @@
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);
+static void pendingproc_get_ready_tp_connection (TplActionChain *ctx,
+ gpointer user_data);
static void got_ready_tp_connection_cb (TpConnection *connection,
const GError *error, gpointer user_data);
-static void pendingproc_get_ready_tp_channel (TplActionChain *ctx);
+static void pendingproc_get_ready_tp_channel (TplActionChain *ctx,
+ gpointer user_data);
static void got_ready_tp_channel_cb (TpChannel *channel,
const GError *error, gpointer user_data);
-static void pendingproc_register_tpl_channel (TplActionChain *ctx);
+static void pendingproc_register_tpl_channel (TplActionChain *ctx,
+ gpointer user_data);
G_DEFINE_ABSTRACT_TYPE (TplChannel, tpl_channel, TP_TYPE_CHANNEL)
@@ -229,15 +232,16 @@ call_when_ready_protected (TplChannel *self,
TplActionChain *actions;
actions = tpl_actionchain_new (G_OBJECT (self), cb, user_data);
- tpl_actionchain_append (actions, pendingproc_get_ready_tp_connection);
- tpl_actionchain_append (actions, pendingproc_get_ready_tp_channel);
- tpl_actionchain_append (actions, pendingproc_register_tpl_channel);
+ tpl_actionchain_append (actions, pendingproc_get_ready_tp_connection, NULL);
+ tpl_actionchain_append (actions, pendingproc_get_ready_tp_channel, NULL);
+ tpl_actionchain_append (actions, pendingproc_register_tpl_channel, NULL);
tpl_actionchain_continue (actions);
}
static void
-pendingproc_get_ready_tp_connection (TplActionChain *ctx)
+pendingproc_get_ready_tp_connection (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannel *tpl_chan = tpl_actionchain_get_object (ctx);
TpConnection *tp_conn = tp_channel_borrow_connection (TP_CHANNEL (
@@ -272,7 +276,8 @@ got_ready_tp_connection_cb (TpConnection *connection,
}
static void
-pendingproc_get_ready_tp_channel (TplActionChain *ctx)
+pendingproc_get_ready_tp_channel (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannel *tpl_chan = tpl_actionchain_get_object (ctx);
@@ -311,7 +316,8 @@ got_ready_tp_channel_cb (TpChannel *channel,
static void
-pendingproc_register_tpl_channel (TplActionChain *ctx)
+pendingproc_register_tpl_channel (TplActionChain *ctx,
+ gpointer user_data)
{
/* singleton */
TplObserver *observer = tpl_observer_new ();
diff --git a/telepathy-logger/dbus-service.c b/telepathy-logger/dbus-service.c
index 6f00c44..fa000b6 100644
--- a/telepathy-logger/dbus-service.c
+++ b/telepathy-logger/dbus-service.c
@@ -22,11 +22,16 @@
#include "config.h"
#include "dbus-service.h"
+#include <string.h>
+#include <sys/stat.h>
+
#include <glib.h>
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/account.h>
#include <telepathy-glib/util.h>
+#include <telepathy-glib/svc-generic.h>
+#include <telepathy-logger/action-chain.h>
#include <telepathy-logger/log-entry-text.h>
#include <telepathy-logger/log-manager.h>
#include <telepathy-logger/util.h>
@@ -36,22 +41,306 @@
#define DEBUG_FLAG TPL_DEBUG_DBUS_SERVICE
#include <telepathy-logger/debug.h>
+#define FAVOURITE_CONTACTS_FILENAME "favourite-contacts.txt"
+
static void tpl_logger_iface_init (gpointer iface, gpointer iface_data);
#define GET_PRIV(obj) TPL_GET_PRIV (obj, TplDBusService)
struct _TplDBusServicePriv
{
TplLogManager *manager;
+ /* map of (string) account name -> (string set) contact ID */
+ /* (the set is implemented as a hash table) */
+ GHashTable *accounts_contacts_map;
+ TplActionChain *favourite_contacts_actions;
};
G_DEFINE_TYPE_WITH_CODE (TplDBusService, tpl_dbus_service, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (TPL_TYPE_SVC_LOGGER, tpl_logger_iface_init));
+typedef struct _FavouriteContactClosure FavouriteContactClosure;
+typedef void (*FavouriteContactCallback) (gboolean success,
+ FavouriteContactClosure *closure);
+
+
+struct _FavouriteContactClosure {
+ TplDBusService *service;
+ gchar *account;
+ gchar *contact_id;
+ gchar *file_contents;
+ DBusGMethodInvocation *context;
+ FavouriteContactCallback cb;
+};
+
+
+static void
+favourite_contact_closure_free (FavouriteContactClosure *closure)
+{
+ if (closure == NULL)
+ return;
+
+ if (closure->service != NULL)
+ g_object_unref (closure->service);
+
+ g_free (closure->account);
+ g_free (closure->contact_id);
+ g_free (closure->file_contents);
+ g_slice_free (FavouriteContactClosure, closure);
+}
+
+
+static FavouriteContactClosure *
+favourite_contact_closure_new (TplDBusService *self,
+ const gchar *account,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context)
+{
+ FavouriteContactClosure *closure;
+
+ closure = g_slice_new0 (FavouriteContactClosure);
+ closure->service = g_object_ref (G_OBJECT (self));
+ closure->account = g_strdup (account);
+ closure->contact_id = g_strdup (contact_id);
+ /* XXX: ideally we'd up the ref count or duplicate this */
+ closure->context = context;
+
+ return closure;
+}
+
+
+static gboolean
+favourite_contacts_add_entry (TplDBusService *self,
+ const gchar *account,
+ const gchar *contact_id)
+{
+ GHashTable *contacts;
+ gboolean new_entry = FALSE;
+ TplDBusServicePriv *priv;
+
+ g_return_val_if_fail (TPL_IS_DBUS_SERVICE (self), FALSE);
+ g_return_val_if_fail (account != NULL, FALSE);
+ g_return_val_if_fail (contact_id != NULL, FALSE);
+
+ priv = GET_PRIV (self);
+
+ DEBUG ("adding favourite contact: account '%s', ID '%s'",
+ account, contact_id);
+
+ contacts = g_hash_table_lookup (priv->accounts_contacts_map, account);
+ if (contacts == NULL)
+ {
+ contacts = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, NULL);
+ g_hash_table_insert (priv->accounts_contacts_map, g_strdup (account),
+ contacts);
+ new_entry = TRUE;
+ }
+ else if (g_hash_table_lookup (contacts, contact_id) == NULL)
+ {
+ new_entry = TRUE;
+ }
+
+ if (new_entry)
+ {
+ /* add dummy string for the value just for the convenience of looking up
+ * whether the key already exists */
+ g_hash_table_insert (contacts, g_strdup (contact_id),
+ GINT_TO_POINTER (TRUE));
+ }
+
+ return new_entry;
+}
+
+
+static const gchar *
+favourite_contacts_get_filename (void)
+{
+ static gchar *filename = NULL;
+
+ if (filename == NULL)
+ {
+ filename = g_build_filename (g_get_user_data_dir (), TPL_DATA_DIR,
+ FAVOURITE_CONTACTS_FILENAME, NULL);
+ }
+
+ return filename;
+}
+
+
+static gboolean
+favourite_contacts_parse_line (TplDBusService *self,
+ const gchar *line)
+{
+ gboolean success = TRUE;
+ gchar **elements;
+
+ if (line == NULL || line[0] == '\0')
+ return TRUE;
+
+ /* this works on the assumption that account names can't have spaces in them
+ */
+ elements = g_strsplit (line, " ", 2);
+ if (g_strv_length (elements) < 2)
+ {
+ DEBUG ("invalid number of elements on favourite contacts file line:\n"
+ "%s\n", line);
+ success = FALSE;
+ }
+ else
+ favourite_contacts_add_entry (self, elements[0], elements[1]);
+
+ g_strfreev (elements);
+
+ return success;
+}
+
+
+static void
+favourite_contacts_file_read_line_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GDataInputStream *data_stream = G_DATA_INPUT_STREAM (object);
+ TplActionChain *action_chain = (TplActionChain *) (user_data);
+ TplDBusService *self = tpl_actionchain_get_object (action_chain);
+ TplDBusServicePriv *priv;
+ gchar *line;
+ GError *error = NULL;
+
+ priv = GET_PRIV (self);
+
+ line = g_data_input_stream_read_line_finish (data_stream, result, NULL, &error);
+
+ if (error != NULL)
+ {
+ DEBUG ("failed to open favourite contacts file: %s", error->message);
+ g_clear_error (&error);
+ tpl_actionchain_terminate (action_chain);
+ }
+ else if (line != NULL)
+ {
+ favourite_contacts_parse_line (self, line);
+
+ g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
+ NULL, favourite_contacts_file_read_line_cb, action_chain);
+ }
+ else
+ tpl_actionchain_continue (action_chain);
+}
+
+
+static void
+favourite_contacts_file_open_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = G_FILE (object);
+ TplActionChain *action_chain = (TplActionChain *) user_data;
+ GFileInputStream *stream;
+ GError *error = NULL;
+
+ if ((stream = g_file_read_finish (file, result, &error)))
+ {
+ GDataInputStream *data_stream = g_data_input_stream_new (
+ G_INPUT_STREAM (stream));
+
+ g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
+ NULL, favourite_contacts_file_read_line_cb, action_chain);
+
+ g_object_unref (stream);
+ }
+ else if (error->code == G_IO_ERROR_NOT_FOUND)
+ {
+ DEBUG ("Favourite contacts file doesn't exist yet. Will create as "
+ "necessary.");
+
+ g_clear_error (&error);
+ tpl_actionchain_continue (action_chain);
+ }
+ else
+ {
+ DEBUG ("Failed to open the favourite contacts file: %s", error->message);
+ g_clear_error (&error);
+ tpl_actionchain_terminate (action_chain);
+ }
+}
+
+
+static void
+pendingproc_favourite_contacts_file_open (TplActionChain *action_chain,
+ gpointer user_data)
+{
+ const gchar *filename;
+ GFile *file;
+
+ filename = favourite_contacts_get_filename ();
+ file = g_file_new_for_path (filename);
+
+ g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
+ favourite_contacts_file_open_cb, action_chain);
+
+ g_object_unref (G_OBJECT (file));
+}
+
+
+static void
+tpl_dbus_service_dispose (GObject *obj)
+{
+ TplDBusServicePriv *priv = GET_PRIV (obj);
+
+ if (priv->accounts_contacts_map != NULL)
+ {
+ g_hash_table_destroy (priv->accounts_contacts_map);
+ priv->accounts_contacts_map = NULL;
+ }
+
+ if (priv->favourite_contacts_actions != NULL)
+ priv->favourite_contacts_actions = NULL;
+
+ G_OBJECT_CLASS (tpl_dbus_service_parent_class)->dispose (obj);
+}
+
+
+static void
+favourite_contacts_file_parsed_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TplDBusService *self = TPL_DBUS_SERVICE (object);
+ TplDBusServicePriv *priv = GET_PRIV (self);
+
+ if (!tpl_actionchain_finish (result))
+ {
+ DEBUG ("Failed to parse the favourite contacts file and/or execute "
+ "subsequent queued method calls");
+ }
+
+ priv->favourite_contacts_actions = NULL;
+}
+
+
+static void
+tpl_dbus_service_constructed (GObject *object)
+{
+ TplDBusServicePriv *priv = GET_PRIV (object);
+
+ priv->favourite_contacts_actions = tpl_actionchain_new (object,
+ favourite_contacts_file_parsed_cb, object);
+
+ tpl_actionchain_append (priv->favourite_contacts_actions,
+ pendingproc_favourite_contacts_file_open, NULL);
+ tpl_actionchain_continue (priv->favourite_contacts_actions);
+}
+
+
static void
tpl_dbus_service_class_init (TplDBusServiceClass *klass)
{
GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = tpl_dbus_service_constructed;
+ object_class->dispose = tpl_dbus_service_dispose;
+
g_type_class_add_private (object_class, sizeof (TplDBusServicePriv));
}
@@ -66,6 +355,9 @@ tpl_dbus_service_init (TplDBusService *self)
self->priv = priv;
priv->manager = tpl_log_manager_dup_singleton ();
+ priv->accounts_contacts_map = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free, (GDestroyNotify) g_hash_table_destroy);
+ priv->favourite_contacts_actions = NULL;
}
@@ -76,39 +368,134 @@ tpl_dbus_service_new (void)
}
-static GPtrArray *
-tpl_chat_message_marshal (GList *data)
+typedef struct
+{
+ TplDBusService *self;
+ TpAccount *account;
+ char *identifier;
+ gboolean is_chatroom;
+ guint lines;
+ DBusGMethodInvocation *context;
+ GPtrArray *packed;
+ GList *dates, *ptr;
+} RecentMessagesContext;
+
+static void _lookup_next_date (RecentMessagesContext *ctx);
+
+static void
+_get_messages_return (GObject *manager,
+ GAsyncResult *res,
+ gpointer user_data)
{
- guint idx;
- GList *data_ptr;
- GPtrArray *retval;
+ RecentMessagesContext *ctx = user_data;
+ GList *messages, *ptr;
+ GError *error = NULL;
- retval = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free);
+ messages = tpl_log_manager_get_messages_for_date_async_finish (res, &error);
+ if (error != NULL)
+ {
+ DEBUG ("Failed to get messages: %s", error->message);
- DEBUG ("Marshalled a(ssx) data:");
+ g_clear_error (&error);
+ messages = NULL; /* just to be sure */
+ }
- for (idx = 0, data_ptr = data;
- data_ptr != NULL;
- data_ptr = g_list_next (data_ptr), ++idx)
+ /* from the most recent message, backward */
+ for (ptr = g_list_last (messages);
+ ptr != NULL && ctx->lines > 0;
+ ptr = g_list_previous (ptr))
{
- TplLogEntry *log = data_ptr->data;
- const gchar *message = tpl_log_entry_text_get_message (
+ TplLogEntry *log = ptr->data;
+ const char *message = tpl_log_entry_text_get_message (
TPL_LOG_ENTRY_TEXT (log));
- const gchar *sender = tpl_contact_get_identifier (
+ const char *sender = tpl_contact_get_identifier (
tpl_log_entry_text_get_sender (TPL_LOG_ENTRY_TEXT (log)));
gint64 timestamp = tpl_log_entry_get_timestamp (log);
- g_ptr_array_add (retval, tp_value_array_build (3,
+ DEBUG ("Message: %" G_GINT64_FORMAT " <%s> %s",
+ timestamp, sender, message);
+
+ g_ptr_array_add (ctx->packed, tp_value_array_build (3,
G_TYPE_STRING, sender,
G_TYPE_STRING, message,
G_TYPE_INT64, timestamp,
G_TYPE_INVALID));
- DEBUG ("%d = %s / %s / %" G_GINT64_FORMAT, idx, sender, message,
- timestamp);
+ ctx->lines--;
}
- return retval;
+ g_list_foreach (messages, (GFunc) g_object_unref, NULL);
+ g_list_free (messages);
+
+ _lookup_next_date (ctx);
+}
+
+
+static void
+_lookup_next_date (RecentMessagesContext *ctx)
+{
+ TplDBusServicePriv *priv = GET_PRIV (ctx->self);
+
+ if (ctx->ptr != NULL && ctx->lines > 0)
+ {
+ char *date = ctx->ptr->data;
+
+ DEBUG ("Looking up date %s", date);
+
+ tpl_log_manager_get_messages_for_date_async (priv->manager,
+ ctx->account, ctx->identifier, ctx->is_chatroom, date,
+ _get_messages_return, ctx);
+
+ ctx->ptr = g_list_previous (ctx->ptr);
+ }
+ else
+ {
+ /* return and release */
+ DEBUG ("complete, returning");
+
+ g_list_foreach (ctx->dates, (GFunc) g_free, NULL);
+ g_list_free (ctx->dates);
+
+ tpl_svc_logger_return_from_get_recent_messages (ctx->context,
+ ctx->packed);
+
+ g_ptr_array_free (ctx->packed, TRUE);
+ g_free (ctx->identifier);
+ g_object_unref (ctx->account);
+ g_slice_free (RecentMessagesContext, ctx);
+ }
+}
+
+
+static void
+_get_dates_return (GObject *manager,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ RecentMessagesContext *ctx = user_data;
+ GError *error = NULL;
+
+ ctx->dates = tpl_log_manager_get_dates_async_finish (res, &error);
+ if (ctx->dates == NULL)
+ {
+ DEBUG ("Failed to get dates: %s", error->message);
+
+ dbus_g_method_return_error (ctx->context, error);
+
+ g_clear_error (&error);
+
+ g_free (ctx->identifier);
+ g_object_unref (ctx->account);
+ g_slice_free (RecentMessagesContext, ctx);
+
+ return;
+ }
+
+ ctx->ptr = g_list_last (ctx->dates);
+ ctx->packed = g_ptr_array_new_with_free_func (
+ (GDestroyNotify) g_value_array_free);
+
+ _lookup_next_date (ctx);
}
@@ -121,14 +508,10 @@ tpl_dbus_service_get_recent_messages (TplSvcLogger *self,
DBusGMethodInvocation *context)
{
TplDBusServicePriv *priv = GET_PRIV (self);
- TpAccount *account = NULL;
- TpDBusDaemon *tp_dbus = NULL;
- GList *ret = NULL;
- GPtrArray *packed = NULL;
- GList *dates = NULL;
- GList *dates_ptr = NULL;
+ TpDBusDaemon *tp_dbus;
+ TpAccount *account;
+ RecentMessagesContext *ctx;
GError *error = NULL;
- guint left_lines = lines;
g_return_if_fail (TPL_IS_DBUS_SERVICE (self));
g_return_if_fail (context != NULL);
@@ -150,56 +533,19 @@ tpl_dbus_service_get_recent_messages (TplSvcLogger *self,
goto out;
}
- dates = tpl_log_manager_get_dates (priv->manager, account, identifier,
- is_chatroom);
- if (dates == NULL)
- {
- error = g_error_new_literal (TPL_DBUS_SERVICE_ERROR,
- TPL_DBUS_SERVICE_ERROR_FAILED, "Error during date list retrieving, "
- "probably the account path or the identifier does not exist");
- dbus_g_method_return_error (context, error);
- goto out;
- }
+ ctx = g_slice_new (RecentMessagesContext);
+ ctx->self = TPL_DBUS_SERVICE (self);
+ ctx->account = account;
+ ctx->identifier = g_strdup (identifier);
+ ctx->is_chatroom = is_chatroom;
+ ctx->lines = lines;
+ ctx->context = context;
- /* for each date returned, get at most <lines> lines, then if needed
- * check the previous date for the missing ones, and so on until
- * <lines> is reached, most recent date first */
- for (dates_ptr = g_list_last (dates);
- dates_ptr != NULL && left_lines > 0;
- dates_ptr = g_list_previous (dates_ptr))
- {
- gchar *date = dates_ptr->data;
- GList *messages = tpl_log_manager_get_messages_for_date (priv->manager,
- account, identifier, is_chatroom, date);
- GList *messages_ptr;
-
- /* from the most recent message, backward */
- for (messages_ptr = g_list_last (messages);
- messages_ptr != NULL && left_lines > 0;
- messages_ptr = g_list_previous (messages_ptr))
- {
- TplLogEntry *log = messages_ptr->data;
- /* keeps the reference and add to the result */
- ret = g_list_prepend (ret, g_object_ref (log));
- left_lines -= 1;
- }
- g_list_foreach (messages, (GFunc) g_object_unref, NULL);
- g_list_free (messages);
- }
- g_list_foreach (dates, (GFunc) g_free, NULL);
- g_list_free (dates);
-
- packed = tpl_chat_message_marshal (ret);
-
- tpl_svc_logger_return_from_get_recent_messages (context, packed);
-
- g_list_foreach (ret, (GFunc) g_object_unref, NULL);
- g_list_free (ret);
- g_ptr_array_free (packed, TRUE);
+ tpl_log_manager_get_dates_async (priv->manager,
+ account, identifier, is_chatroom,
+ _get_dates_return, ctx);
out:
- if (account != NULL)
- g_object_unref (account);
if (tp_dbus != NULL)
g_object_unref (tp_dbus);
@@ -209,6 +555,371 @@ out:
static void
+append_favourite_contacts_account_and_contacts (const gchar *account,
+ GHashTable *contacts,
+ GPtrArray *packed)
+{
+ GList *l;
+ gchar **contact_ids;
+ gint i;
+
+ /* this case shouldn't happen, but this is just some basic sanity checking */
+ if (g_hash_table_size (contacts) < 1)
+ return;
+
+ /* includes room for the terminal NULL */
+ contact_ids = g_new0 (gchar *, g_hash_table_size (contacts)+1);
+
+ for (i = 0, l = g_hash_table_get_keys (contacts);
+ l;
+ i++, l = g_list_delete_link (l, l))
+ {
+ contact_ids[i] = l->data;
+ }
+
+ g_ptr_array_add (packed, tp_value_array_build (2,
+ DBUS_TYPE_G_OBJECT_PATH, account,
+ G_TYPE_STRV, contact_ids,
+ G_TYPE_INVALID));
+
+ g_free (contact_ids);
+}
+
+
+static void
+pendingproc_get_favourite_contacts (TplActionChain *action_chain,
+ gpointer user_data)
+{
+ FavouriteContactClosure *closure = user_data;
+ TplDBusServicePriv *priv;
+ GPtrArray *packed;
+
+ g_return_if_fail (closure);
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (closure->service));
+ g_return_if_fail (closure->context != NULL);
+
+ priv = GET_PRIV (closure->service);
+
+ packed = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free);
+
+ g_hash_table_foreach (priv->accounts_contacts_map,
+ (GHFunc) append_favourite_contacts_account_and_contacts, packed);
+
+ tpl_svc_logger_return_from_get_favourite_contacts (closure->context, packed);
+
+ g_ptr_array_free (packed, TRUE);
+ favourite_contact_closure_free (closure);
+
+ if (action_chain != NULL)
+ tpl_actionchain_continue (action_chain);
+}
+
+
+static void
+tpl_dbus_service_get_favourite_contacts (TplSvcLogger *self,
+ DBusGMethodInvocation *context)
+{
+ TplDBusServicePriv *priv;
+ FavouriteContactClosure *closure;
+
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (self));
+ g_return_if_fail (context != NULL);
+
+ priv = GET_PRIV (self);
+
+ closure = favourite_contact_closure_new (TPL_DBUS_SERVICE (self), NULL, NULL,
+ context);
+
+ /* If we're still waiting on the contacts to finish being parsed from disk,
+ * queue this action */
+ if (priv->favourite_contacts_actions != NULL)
+ {
+ tpl_actionchain_append (priv->favourite_contacts_actions,
+ pendingproc_get_favourite_contacts, closure);
+ }
+ else
+ pendingproc_get_favourite_contacts (NULL, closure);
+}
+
+
+static void
+append_favourite_contacts_file_entries (const gchar *account,
+ GHashTable *contacts,
+ GString *string)
+{
+ GList *l;
+
+ for (l = g_hash_table_get_keys (contacts); l; l = g_list_delete_link (l, l))
+ g_string_append_printf (string, "%s %s\n", account, (const gchar*) l->data);
+}
+
+
+static gchar *
+favourite_contacts_to_string (TplDBusService *self)
+{
+ TplDBusServicePriv *priv = GET_PRIV (self);
+ GString *string;
+
+ string = g_string_new ("");
+
+ g_hash_table_foreach (priv->accounts_contacts_map,
+ (GHFunc) append_favourite_contacts_file_entries, string);
+
+ return g_string_free (string, FALSE);
+}
+
+
+static void
+favourite_contacts_file_replace_contents_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GFile *file = G_FILE (object);
+ GError *error = NULL;
+ FavouriteContactClosure *closure = user_data;
+ gboolean success;
+
+ if (g_file_replace_contents_finish (file, result, NULL, &error))
+ {
+ success = TRUE;
+ }
+ else
+ {
+ DEBUG ("Failed to save favourite contacts file: %s", error->message);
+ success = FALSE;
+ g_clear_error (&error);
+ }
+
+ ((FavouriteContactCallback) closure->cb) (success, closure);
+}
+
+
+static void
+favourite_contacts_file_save_async (TplDBusService *self,
+ FavouriteContactClosure *closure)
+{
+ gchar *dir;
+ const gchar *filename;
+ GFile *file;
+ gchar *file_contents;
+
+ g_return_if_fail (closure != NULL);
+
+ filename = favourite_contacts_get_filename ();
+ dir = g_path_get_dirname (filename);
+ g_mkdir_with_parents (dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_free (dir);
+
+ file = g_file_new_for_path (filename);
+
+ file_contents = favourite_contacts_to_string (self);
+
+ closure->file_contents = file_contents;
+
+ g_file_replace_contents_async (file,
+ file_contents, strlen (file_contents), NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION, NULL,
+ favourite_contacts_file_replace_contents_cb, closure);
+
+ g_object_unref (file);
+}
+
+
+static void
+add_favourite_contact_file_save_cb (gboolean added_favourite,
+ FavouriteContactClosure *closure)
+{
+ TplDBusServicePriv *priv = GET_PRIV (closure->service);
+ TplActionChain *action_chain = priv->favourite_contacts_actions;
+
+ if (added_favourite)
+ {
+ const gchar *added[] = { NULL, NULL };
+ const gchar *removed[] = { NULL };
+
+ added[0] = closure->contact_id;
+
+ tpl_svc_logger_emit_favourite_contacts_changed (closure->service,
+ closure->account, added, removed);
+ }
+
+ tpl_svc_logger_return_from_add_favourite_contact (closure->context);
+
+ favourite_contact_closure_free (closure);
+ if (action_chain != NULL)
+ tpl_actionchain_continue (action_chain);
+}
+
+
+static void
+pendingproc_add_favourite_contact (TplActionChain *action_chain,
+ gpointer user_data)
+{
+ FavouriteContactClosure *closure = user_data;
+ gboolean should_add = FALSE;
+ TplDBusServicePriv *priv;
+ GError *error = NULL;
+
+ g_return_if_fail (closure);
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (closure->service));
+ g_return_if_fail (closure->context != NULL);
+
+ priv = GET_PRIV (closure->service);
+
+ if (!tp_dbus_check_valid_object_path (closure->account, &error))
+ {
+ dbus_g_method_return_error (closure->context, error);
+
+ goto pendingproc_add_favourite_contact_ERROR;
+ }
+
+ should_add = favourite_contacts_add_entry (closure->service, closure->account,
+ closure->contact_id);
+
+ closure->cb = add_favourite_contact_file_save_cb;
+
+ if (should_add)
+ favourite_contacts_file_save_async (closure->service, closure);
+ else
+ add_favourite_contact_file_save_cb (FALSE, closure);
+
+ return;
+
+pendingproc_add_favourite_contact_ERROR:
+ g_clear_error (&error);
+ if (action_chain != NULL)
+ tpl_actionchain_terminate (action_chain);
+}
+
+
+static void
+tpl_dbus_service_add_favourite_contact (TplSvcLogger *self,
+ const gchar *account,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context)
+{
+ TplDBusServicePriv *priv;
+ FavouriteContactClosure *closure;
+
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (self));
+ g_return_if_fail (context != NULL);
+
+ priv = GET_PRIV (self);
+
+ closure = favourite_contact_closure_new (TPL_DBUS_SERVICE (self), account,
+ contact_id, context);
+
+ /* If we're still waiting on the contacts to finish being parsed from disk,
+ * queue this action */
+ if (priv->favourite_contacts_actions != NULL)
+ {
+ tpl_actionchain_append (priv->favourite_contacts_actions,
+ pendingproc_add_favourite_contact, closure);
+ }
+ else
+ pendingproc_add_favourite_contact (NULL, closure);
+}
+
+static void
+remove_favourite_contact_file_save_cb (gboolean removed_favourite,
+ FavouriteContactClosure *closure)
+{
+ TplDBusServicePriv *priv = GET_PRIV (closure->service);
+ TplActionChain *action_chain = priv->favourite_contacts_actions;
+
+ if (removed_favourite)
+ {
+ const gchar *added[] = { NULL };
+ const gchar *removed[] = { NULL, NULL };
+
+ removed[0] = closure->contact_id;
+
+ tpl_svc_logger_emit_favourite_contacts_changed (closure->service,
+ closure->account, added, removed);
+ }
+
+ tpl_svc_logger_return_from_remove_favourite_contact (closure->context);
+
+ favourite_contact_closure_free (closure);
+ if (action_chain != NULL)
+ tpl_actionchain_continue (action_chain);
+}
+
+
+static void
+pendingproc_remove_favourite_contact (TplActionChain *action_chain,
+ gpointer user_data)
+{
+ FavouriteContactClosure *closure = user_data;
+ GHashTable *contacts;
+ gboolean removed = FALSE;
+ GError *error = NULL;
+
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (closure->service));
+ g_return_if_fail (closure->context != NULL);
+
+ TplDBusServicePriv *priv = GET_PRIV (closure->service);
+
+ if (!tp_dbus_check_valid_object_path (closure->account, &error))
+ {
+ dbus_g_method_return_error (closure->context, error);
+
+ goto pendingproc_remove_favourite_contact_ERROR;
+ }
+
+ DEBUG ("removing favourite contact: account '%s', ID '%s'",
+ closure->account, closure->contact_id);
+
+ contacts = g_hash_table_lookup (priv->accounts_contacts_map,
+ closure->account);
+ if (contacts != NULL && g_hash_table_remove (contacts, closure->contact_id))
+ removed = TRUE;
+
+ closure->cb = remove_favourite_contact_file_save_cb;
+
+ if (removed)
+ favourite_contacts_file_save_async (closure->service, closure);
+ else
+ remove_favourite_contact_file_save_cb (FALSE, closure);
+
+ return;
+
+pendingproc_remove_favourite_contact_ERROR:
+ g_clear_error (&error);
+ if (action_chain != NULL)
+ tpl_actionchain_terminate (action_chain);
+}
+
+static void
+tpl_dbus_service_remove_favourite_contact (TplSvcLogger *self,
+ const gchar *account,
+ const gchar *contact_id,
+ DBusGMethodInvocation *context)
+{
+ TplDBusServicePriv *priv;
+ FavouriteContactClosure *closure;
+
+ g_return_if_fail (TPL_IS_DBUS_SERVICE (self));
+ g_return_if_fail (context != NULL);
+
+ priv = GET_PRIV (self);
+
+ closure = favourite_contact_closure_new (TPL_DBUS_SERVICE (self), account,
+ contact_id, context);
+
+ /* If we're still waiting on the contacts to finish being parsed from disk,
+ * queue this action */
+ if (priv->favourite_contacts_actions != NULL)
+ {
+ tpl_actionchain_append (priv->favourite_contacts_actions,
+ pendingproc_remove_favourite_contact, closure);
+ }
+ else
+ pendingproc_remove_favourite_contact (NULL, closure);
+}
+
+static void
tpl_logger_iface_init (gpointer iface,
gpointer iface_data)
{
@@ -216,5 +927,8 @@ tpl_logger_iface_init (gpointer iface,
#define IMPLEMENT(x) tpl_svc_logger_implement_##x (klass, tpl_dbus_service_##x)
IMPLEMENT (get_recent_messages);
+ IMPLEMENT (get_favourite_contacts);
+ IMPLEMENT (add_favourite_contact);
+ IMPLEMENT (remove_favourite_contact);
#undef IMPLEMENT
}
diff --git a/telepathy-logger/dbus-service.h b/telepathy-logger/dbus-service.h
index d0424a2..600c826 100644
--- a/telepathy-logger/dbus-service.h
+++ b/telepathy-logger/dbus-service.h
@@ -23,6 +23,7 @@
#define __TPL_DBUS_SERVICE_H__
#include <glib-object.h>
+#include <telepathy-glib/dbus-properties-mixin.h>
#include <telepathy-logger/log-manager.h>
@@ -44,7 +45,10 @@ G_BEGIN_DECLS
"tpl-dbus-service-error-quark")
typedef enum
{
- TPL_DBUS_SERVICE_ERROR_FAILED
+ TPL_DBUS_SERVICE_ERROR_FAILED,
+ /* >= 1 argument(s) is/are invalid */
+ TPL_DBUS_SERVICE_ERROR_INVALID_ARGS,
+ TPL_DBUS_SERVICE_ERROR_NOT_READY,
} TplDBusServiceError;
typedef struct _TplDBusServicePriv TplDBusServicePriv;
diff --git a/tests/tpl-channel-test.c b/tests/tpl-channel-test.c
index 31080a1..e87c154 100644
--- a/tests/tpl-channel-test.c
+++ b/tests/tpl-channel-test.c
@@ -32,7 +32,8 @@
static void call_when_ready_wrapper (TplChannel *tpl_chan, GAsyncReadyCallback
cb, gpointer user_data);
-static void pendingproc_prepare_tpl_channel (TplActionChain *ctx);
+static void pendingproc_prepare_tpl_channel (TplActionChain *ctx,
+ gpointer user_data);
static void got_tpl_chan_ready_cb (GObject *obj, GAsyncResult *result,
gpointer user_data);
@@ -133,14 +134,15 @@ tpl_channel_test_call_when_ready (TplChannelTest *self,
* are unreferenced by g_object_unref: after the order change, it might
* happend that an object still has to be created after the change */
actions = tpl_actionchain_new (G_OBJECT (self), cb, user_data);
- tpl_actionchain_append (actions, pendingproc_prepare_tpl_channel);
+ tpl_actionchain_append (actions, pendingproc_prepare_tpl_channel, NULL);
/* start the queue consuming */
tpl_actionchain_continue (actions);
}
static void
-pendingproc_prepare_tpl_channel (TplActionChain *ctx)
+pendingproc_prepare_tpl_channel (TplActionChain *ctx,
+ gpointer user_data)
{
TplChannel *tpl_chan = TPL_CHANNEL (tpl_actionchain_get_object (ctx));