diff options
author | Danielle Madeley <danielle.madeley@collabora.co.uk> | 2010-09-24 12:37:11 +1000 |
---|---|---|
committer | Danielle Madeley <danielle.madeley@collabora.co.uk> | 2010-09-24 12:37:11 +1000 |
commit | db9a512277ccdd6da9aa2d694ff2d1175f21a7ff (patch) | |
tree | f03c2aa3bda153046d5f7e48f6a2c474ce250be0 | |
parent | 9039634166dbc99076ead871186c7573b8bb6ac8 (diff) |
Beginning of a contact monitor example
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | docs/examples/Makefile.am | 1 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/.gitignore | 2 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/Makefile.am | 26 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/connections-monitor.c | 249 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/connections-monitor.h | 37 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/example.c | 35 | ||||
-rw-r--r-- | docs/examples/glib_mc5_presence_app/marshallers.list | 1 |
8 files changed, 352 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 05b6a3f..2f0ec40 100644 --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,7 @@ AC_OUTPUT([ docs/examples/glib_mc5_observer/Makefile docs/examples/glib_blinkenlight_observer/Makefile docs/examples/glib_mc5_ft_handler/Makefile + docs/examples/glib_mc5_presence_app/Makefile docs/examples/gtk_presence_app/Makefile docs/examples/pygtk_chat_client/Makefile docs/examples/python_get_parameters/Makefile diff --git a/docs/examples/Makefile.am b/docs/examples/Makefile.am index cb5d90f..af0bc26 100644 --- a/docs/examples/Makefile.am +++ b/docs/examples/Makefile.am @@ -13,6 +13,7 @@ example_dirs = \ glib_mc5_observer \ glib_blinkenlight_observer \ glib_mc5_ft_handler \ + glib_mc5_presence_app \ gtk_presence_app \ pygtk_chat_client \ python_get_parameters \ diff --git a/docs/examples/glib_mc5_presence_app/.gitignore b/docs/examples/glib_mc5_presence_app/.gitignore new file mode 100644 index 0000000..e7e60f0 --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/.gitignore @@ -0,0 +1,2 @@ +marshallers.c +marshallers.h diff --git a/docs/examples/glib_mc5_presence_app/Makefile.am b/docs/examples/glib_mc5_presence_app/Makefile.am new file mode 100644 index 0000000..88522af --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/Makefile.am @@ -0,0 +1,26 @@ +INCLUDES = $(TELEPATHY_GLIB_CFLAGS) +LDADD = $(TELEPATHY_GLIB_LIBS) + +noinst_PROGRAMS = example + +example_SOURCES = \ + connections-monitor.c connections-monitor.h \ + example.c \ + $(BUILT_SOURCES) + +BUILT_SOURCES = \ + marshallers.c marshallers.h + +marshallers.h: marshallers.list + glib-genmarshal --header --prefix=_example $< > $@ + +marshallers.c: marshallers.list + glib-genmarshal --body --prefix=_example $< > $@ + +CLEANFILES = \ + $(BUILT_SOURCES) + +EXTRA_DIST = \ + marshallers.list + +include $(top_srcdir)/docs/rsync-dist.make diff --git a/docs/examples/glib_mc5_presence_app/connections-monitor.c b/docs/examples/glib_mc5_presence_app/connections-monitor.c new file mode 100644 index 0000000..f0af4d4 --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/connections-monitor.c @@ -0,0 +1,249 @@ +#include <string.h> + +#include "connections-monitor.h" +#include "marshallers.h" + +#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_CONNECTIONS_MONITOR, ConnectionsMonitorPrivate)) + +G_DEFINE_TYPE (ConnectionsMonitor, connections_monitor, G_TYPE_OBJECT); + +enum /* signals */ +{ + CONNECTION, + LAST_SIGNAL +}; + +static guint _signals[LAST_SIGNAL] = { 0, }; + +typedef struct _ConnectionsMonitorPrivate ConnectionsMonitorPrivate; +struct _ConnectionsMonitorPrivate +{ + TpAccountManager *am; +}; + + +static const char * +shorten_account_name (TpAccount *account) +{ + return tp_proxy_get_object_path (account) + + strlen (TP_ACCOUNT_OBJECT_PATH_BASE); +} + + +static void +_object_destroyed (gpointer data, + GObject *ptr) +{ + g_debug ("Object finalized: %s: %p", (char *) data, ptr); +} + + +static void +_connection_invalidated (TpConnection *conn, + guint domain, + int code, + char *message, + gpointer user_data) +{ + g_debug ("Unreffing connection: %s", tp_proxy_get_object_path (conn)); + + g_object_unref (conn); +} + + +static void +_connection_prepared (GObject *conn, + GAsyncResult *res, + gpointer user_data) +{ + ConnectionsMonitor *self = user_data; + TpAccount *account; + GError *error = NULL; + + if (!tp_proxy_prepare_finish (conn, res, &error)) + g_error ("%s", error->message); + + g_debug ("Prepared connection: %s", tp_proxy_get_object_path (conn)); + + g_signal_connect (conn, "invalidated", + G_CALLBACK (_connection_invalidated), self); + + account = g_object_get_data (conn, "account"); + + g_signal_emit (self, _signals[CONNECTION], 0, account, conn); +} + + +static void +account_prepare_connection (ConnectionsMonitor *self, + TpAccount *account) +{ + TpConnection *conn; + + conn = tp_account_get_connection (account); + + if (conn == NULL) + return; + + g_debug ("Preparing connection: %s", tp_proxy_get_object_path (conn)); + + /* reference released when the connection is invalidated */ + g_object_ref (conn); + g_object_weak_ref (G_OBJECT (conn), _object_destroyed, "Connection"); + + /* connection doesn't hold a ref to the account, it shouldn't outlive + * the account */ + g_object_set_data (G_OBJECT (conn), "account", account); + + tp_proxy_prepare_async (conn, NULL, _connection_prepared, self); +} + + +static void +_account_notify_connection (GObject *account, + GParamSpec *pspec, + gpointer user_data) +{ + ConnectionsMonitor *self = user_data; + + account_prepare_connection (self, TP_ACCOUNT (account)); +} + + +static void +_account_prepared (GObject *account, + GAsyncResult *res, + gpointer user_data) +{ + ConnectionsMonitor *self = user_data; + GError *error = NULL; + + if (!tp_proxy_prepare_finish (account, res, &error)) + g_error ("%s", error->message); + + g_debug ("Prepared account %s", shorten_account_name (TP_ACCOUNT (account))); + + account_prepare_connection (self, TP_ACCOUNT (account)); + + /* disconnect any old handlers */ + g_signal_handlers_disconnect_by_func (account, + _account_notify_connection, self); + + g_signal_connect (account, "notify::connection", + G_CALLBACK (_account_notify_connection), self); +} + + +static void +prepare_account (ConnectionsMonitor *self, + TpAccount *account) +{ + g_debug ("Preparing account %s", shorten_account_name (account)); + + /* reference released when the account is diabled */ + g_object_ref (account); + g_object_weak_ref (G_OBJECT (account), _object_destroyed, "Account"); + + tp_proxy_prepare_async (account, NULL, _account_prepared, self); +} + + +static void +_am_account_enabled (TpAccountManager *am, + TpAccount *account, + gpointer user_data) +{ + ConnectionsMonitor *self = user_data; + + prepare_account (self, account); +} + + +static void +_am_account_disabled (TpAccountManager *am, + TpAccount *account, + gpointer user_data) +{ + g_debug ("Unreffing account: %s", shorten_account_name (account)); + + /* release the reference to the account acquired when we prepared it */ + g_object_unref (account); +} + + +static void +_am_prepared (GObject *am, + GAsyncResult *res, + gpointer user_data) +{ + ConnectionsMonitor *self = user_data; + GList *accounts, *ptr; + GError *error = NULL; + + if (!tp_proxy_prepare_finish (am, res, &error)) + g_error ("%s", error->message); + + g_debug ("AM prepared"); + + /* prepare the valid accounts */ + accounts = tp_account_manager_get_valid_accounts (TP_ACCOUNT_MANAGER (am)); + + for (ptr = accounts; ptr != NULL; ptr = ptr->next) + prepare_account (self, ptr->data); + + g_signal_connect (am, "account-enabled", + G_CALLBACK (_am_account_enabled), self); + g_signal_connect (am, "account-disabled", + G_CALLBACK (_am_account_disabled), self); + + g_list_free (accounts); +} + + +static void +connections_monitor_finalize (GObject *self) +{ + ConnectionsMonitorPrivate *priv = GET_PRIVATE (self); + + tp_clear_object (&priv->am); + + G_OBJECT_CLASS (connections_monitor_parent_class)->finalize (self); +} + + +static void +connections_monitor_class_init (ConnectionsMonitorClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = connections_monitor_finalize; + + _signals[CONNECTION] = g_signal_new ("connection", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ConnectionsMonitorClass, connection), + NULL, NULL, + _example_VOID__OBJECT_OBJECT, + G_TYPE_NONE, + 2, TP_TYPE_ACCOUNT, TP_TYPE_CONNECTION); + + g_type_class_add_private (gobject_class, sizeof (ConnectionsMonitorPrivate)); +} + + +static void +connections_monitor_init (ConnectionsMonitor *self) +{ + ConnectionsMonitorPrivate *priv = GET_PRIVATE (self); + + /* prepare the Account Manager */ + priv->am = tp_account_manager_dup (); + + tp_proxy_prepare_async (priv->am, NULL, _am_prepared, self); +} + +ConnectionsMonitor * +connections_monitor_new (void) +{ + return g_object_new (TYPE_CONNECTIONS_MONITOR, NULL); +} diff --git a/docs/examples/glib_mc5_presence_app/connections-monitor.h b/docs/examples/glib_mc5_presence_app/connections-monitor.h new file mode 100644 index 0000000..3046ba7 --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/connections-monitor.h @@ -0,0 +1,37 @@ +#ifndef __CONNECTIONS_MONITOR_H__ +#define __CONNECTIONS_MONITOR_H__ + +#include <telepathy-glib/telepathy-glib.h> + +G_BEGIN_DECLS + +#define TYPE_CONNECTIONS_MONITOR (connections_monitor_get_type ()) +#define CONNECTIONS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_CONNECTIONS_MONITOR, ConnectionsMonitor)) +#define CONNECTIONS_MONITOR_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), TYPE_CONNECTIONS_MONITOR, ConnectionsMonitorClass)) +#define IS_CONNECTIONS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_CONNECTIONS_MONITOR)) +#define IS_CONNECTIONS_MONITOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), TYPE_CONNECTIONS_MONITOR)) +#define CONNECTIONS_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_CONNECTIONS_MONITOR, ConnectionsMonitorClass)) + +typedef struct _ConnectionsMonitor ConnectionsMonitor; +typedef struct _ConnectionsMonitorClass ConnectionsMonitorClass; + +struct _ConnectionsMonitor +{ + GObject parent; +}; + +struct _ConnectionsMonitorClass +{ + GObjectClass parent_class; + + void (* connection) (ConnectionsMonitor *self, + TpAccount *account, + TpConnection *connection); +}; + +GType connections_monitor_get_type (void); +ConnectionsMonitor *connections_monitor_new (void); + +G_END_DECLS + +#endif diff --git a/docs/examples/glib_mc5_presence_app/example.c b/docs/examples/glib_mc5_presence_app/example.c new file mode 100644 index 0000000..d708a7e --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/example.c @@ -0,0 +1,35 @@ +#include "connections-monitor.h" + + +static void +_got_connection (ConnectionsMonitor *monitor, + TpAccount *account, + TpConnection *conn) +{ + g_debug ("GOT CONNECTION:\n\t%s\n\t%s", + tp_proxy_get_object_path (account), + tp_proxy_get_object_path (conn)); +} + + +int +main (int argc, + const char **argv) +{ + ConnectionsMonitor *monitor; + GMainLoop *loop; + + g_type_init (); + + monitor = connections_monitor_new (); + g_signal_connect (monitor, "connection", + G_CALLBACK (_got_connection), NULL); + + loop = g_main_loop_new (NULL, FALSE); + + /* run the program */ + g_main_loop_run (loop); + + g_main_loop_unref (loop); + g_object_unref (monitor); +} diff --git a/docs/examples/glib_mc5_presence_app/marshallers.list b/docs/examples/glib_mc5_presence_app/marshallers.list new file mode 100644 index 0000000..38076d6 --- /dev/null +++ b/docs/examples/glib_mc5_presence_app/marshallers.list @@ -0,0 +1 @@ +VOID:OBJECT,OBJECT |