/*
* telepathy-example-client-extended - use an extended connection manager
*
* Usage:
*
* telepathy-example-client-extended
*
* Copyright (C) 2007-2008 Collabora Ltd.
* Copyright (C) 2007-2008 Nokia Corporation
*
* Copying and distribution of this file, with or without modification,
* are permitted in any medium without royalty provided the copyright
* notice and this notice are preserved.
*/
#include "config.h"
#include
#include
/* Usually this'd be a top-level extensions/ directory in practice */
#include "examples/extensions/extensions.h"
static guint timer;
static int main_ret = 1;
static GMainLoop *mainloop;
static gboolean
die_if (const GError *error, const gchar *context)
{
if (error != NULL)
{
g_warning ("%s: %s", context, error->message);
g_main_loop_quit (mainloop);
return TRUE;
}
return FALSE;
}
static void
disconnect_cb (TpConnection *conn,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
if (die_if (error, "Disconnect()"))
return;
main_ret = 0;
g_main_loop_quit (mainloop);
}
typedef struct {
TpContact *contacts[2];
} ContactPair;
static void
got_hats_cb (TpConnection *conn,
const GPtrArray *hats,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
guint i;
if (die_if (error, "GetHats()"))
return;
for (i = 0; i < hats->len; i++)
{
GValueArray *vals = g_ptr_array_index (hats, i);
guint handle;
const gchar *color;
guint style;
GHashTable *details;
tp_value_array_unpack (vals, 4,
&handle, &color, &style, &details);
g_message ("Contact #%u has hat style %u, color \"%s\", with %u "
"properties", handle, style, color, g_hash_table_size (details));
}
tp_cli_connection_call_disconnect (conn, -1, disconnect_cb,
NULL, NULL, NULL);
}
static void
set_hat_cb (TpConnection *conn,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
ContactPair *pair = user_data;
GArray *handles = NULL;
TpHandle handle;
if (die_if (error, "SetHat()"))
return;
handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 2);
handle = tp_contact_get_handle (pair->contacts[0]);
g_array_append_val (handles, handle);
handle = tp_contact_get_handle (pair->contacts[1]);
g_array_append_val (handles, handle);
example_cli_connection_interface_hats_call_get_hats (conn, -1,
handles, got_hats_cb, NULL, NULL, NULL);
}
static void
contact_pair_free (gpointer p)
{
ContactPair *pair = p;
g_object_unref (pair->contacts[0]);
g_object_unref (pair->contacts[1]);
g_slice_free (ContactPair, pair);
}
static void
contact_ready_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
TpConnection *conn = (TpConnection *) object;
GHashTable *asv;
ContactPair *pair;
GError *error = NULL;
pair = g_slice_new0 (ContactPair);
pair->contacts[0] = tp_connection_dup_contact_by_id_finish (conn,
result, &error);
pair->contacts[1] = g_object_ref (tp_connection_get_self_contact (conn));
if (die_if (error, "tp_connection_dup_contact_by_id_async()"))
{
g_clear_error (&error);
contact_pair_free (pair);
return;
}
asv = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
(GDestroyNotify) tp_g_value_slice_free);
g_hash_table_insert (asv, "previous-owner",
tp_g_value_slice_new_static_string ("Shadowman"));
example_cli_connection_interface_hats_call_set_hat (conn, -1,
"red", EXAMPLE_HAT_STYLE_FEDORA, asv,
set_hat_cb, pair, contact_pair_free, NULL);
g_hash_table_unref (asv);
}
static void
conn_ready (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
GError *error = NULL;
TpConnection *conn = TP_CONNECTION (source);
if (!tp_proxy_prepare_finish (conn, result, &error))
{
g_warning ("%s", error->message);
g_main_loop_quit (mainloop);
g_clear_error (&error);
return;
}
if (!tp_proxy_has_interface_by_id (conn,
EXAMPLE_IFACE_QUARK_CONNECTION_INTERFACE_HATS))
{
g_warning ("Connection does not support Hats interface");
g_main_loop_quit (mainloop);
return;
}
/* Get contact object for someone else */
tp_connection_dup_contact_by_id_async (conn, "other@server", 0, NULL,
contact_ready_cb, NULL);
}
static void
conn_status_changed (TpConnection *conn,
guint status,
guint reason,
gpointer user_data,
GObject *weak_object)
{
g_message ("Connection status changed to %u because %u", status, reason);
if (status == TP_CONNECTION_STATUS_DISCONNECTED)
{
g_message ("Disconnected - exiting");
g_main_loop_quit (mainloop);
}
}
static void
cm_requested_connection (TpConnectionManager *manager,
const gchar *bus_name,
const gchar *object_path,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
TpSimpleClientFactory *factory;
GError *e = NULL;
TpConnection *conn;
if (die_if (error, "RequestConnection()"))
return;
/* Because we don't have an AccountManager, we have to do more work here. */
factory = tp_simple_client_factory_new (NULL);
conn = tp_simple_client_factory_ensure_connection (factory, object_path, NULL,
&e);
g_object_unref (factory);
if (conn == NULL)
{
g_warning ("tp_connection_new(): %s", error->message);
g_main_loop_quit (mainloop);
return;
}
/* the connection hasn't had a chance to become invalid yet, so we can
* assume that this signal connection will work */
tp_cli_connection_connect_to_status_changed (conn, conn_status_changed,
NULL, NULL, NULL, NULL);
tp_proxy_prepare_async (conn, NULL, conn_ready, NULL);
tp_cli_connection_call_connect (conn, -1, NULL, NULL, NULL, NULL);
}
static void
connection_manager_got_info (TpConnectionManager *cm,
guint source,
gpointer unused)
{
g_message ("Emitted got-info (source=%d)", source);
if (source > 0)
{
GHashTable *params;
GValue value = { 0 };
if (timer != 0)
{
g_source_remove (timer);
timer = 0;
}
params = g_hash_table_new (g_str_hash, g_str_equal);
g_value_init (&value, G_TYPE_STRING);
g_value_set_static_string (&value, "myself@server");
g_hash_table_insert (params, "account", &value);
/* This example is rather lower-level than most: it's
* "going behind the account manager's back". This is not recommended
* in real applications. */
tp_cli_connection_manager_call_request_connection (cm,
-1, "example", params, cm_requested_connection, NULL, NULL, NULL);
g_hash_table_unref (params);
}
}
static gboolean
time_out (gpointer unused)
{
g_warning ("Timed out trying to get CM info");
g_main_loop_quit (mainloop);
return FALSE;
}
int
main (int argc,
char **argv)
{
TpConnectionManager *cm = NULL;
GError *error = NULL;
TpDBusDaemon *dbus = NULL;
g_type_init ();
tp_debug_set_flags (g_getenv ("EXAMPLE_DEBUG"));
example_cli_init ();
dbus = tp_dbus_daemon_dup (&error);
if (dbus == NULL)
{
g_warning ("%s", error->message);
g_error_free (error);
goto out;
}
mainloop = g_main_loop_new (NULL, FALSE);
cm = tp_connection_manager_new (dbus, "example_extended", NULL, &error);
if (cm == NULL)
{
g_warning ("%s", error->message);
goto out;
}
g_signal_connect (cm, "got-info",
G_CALLBACK (connection_manager_got_info), NULL);
timer = g_timeout_add (5000, time_out, NULL);
g_main_loop_run (mainloop);
out:
if (cm != NULL)
g_object_unref (cm);
if (dbus != NULL)
g_object_unref (dbus);
if (mainloop != NULL)
g_main_loop_unref (mainloop);
return main_ret;
}