← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/indicator-messages/status-items into lp:indicator-messages

 

Ted Gould has proposed merging lp:~ted/indicator-messages/status-items into lp:indicator-messages.

Requested reviews:
  Indicator Applet Developers (indicator-applet-developers)

For more details, see:
https://code.launchpad.net/~ted/indicator-messages/status-items/+merge/67891

This moves the status providers and status menu items over from indicator-me to the messaging menu.  The status providers are *mostly* unchanged, the big difference is that they're now loadable modules instead of compiled in.  This should reduce the dep load of the messaging menu and help people refine the "Pidgin experience" outside of the messaging menu.
-- 
https://code.launchpad.net/~ted/indicator-messages/status-items/+merge/67891
Your team ayatana-commits is subscribed to branch lp:indicator-messages.
=== modified file '.bzrignore'
--- .bzrignore	2011-01-17 18:05:20 +0000
+++ .bzrignore	2011-07-13 20:27:12 +0000
@@ -25,3 +25,25 @@
 src/libmessaging_la-app-gtk-menu-item.lo
 src/gen-messages-service.xml.c
 src/gen-messages-service.xml.h
+src/libemesene.la
+src/libemesene_la-status-provider-emesene.lo
+src/libmc5.la
+src/libmc5_la-status-provider-mc5-marshal.lo
+src/libmc5_la-status-provider-mc5.lo
+src/libmessaging_la-gen-messages-service.xml.lo
+src/libpidgin.la
+src/libpidgin_la-status-provider-pidgin-marshal.lo
+src/libpidgin_la-status-provider-pidgin.lo
+src/libtelepathy.la
+src/libtelepathy_la-status-provider-telepathy-marshal.lo
+src/libtelepathy_la-status-provider-telepathy.lo
+src/status-provider-mc5-marshal.c
+src/status-provider-mc5-marshal.h
+src/status-provider-pidgin-marshal.c
+src/status-provider-pidgin-marshal.h
+src/status-provider-telepathy-marshal.c
+src/status-provider-telepathy-marshal.h
+src/libindicator-messages-status-provider.la
+src/libindicator_messages_status_provider_la-status-provider.lo
+indicator-messages-status-provider-0.5.pc
+indicator-messages-status-provider-0.5.pc.in

=== modified file 'configure.ac'
--- configure.ac	2011-07-08 14:13:51 +0000
+++ configure.ac	2011-07-13 20:27:12 +0000
@@ -69,6 +69,28 @@
 AC_SUBST(APPLET_LIBS)
 
 ###########################
+# Status Provider Deps
+###########################
+
+PKG_CHECK_MODULES(STATUS_PROVIDER_PIDGIN, dbus-glib-1)
+AC_SUBST(STATUS_PROVIDER_PIDGIN_CFLAGS)
+AC_SUBST(STATUS_PROVIDER_PIDGIN_LIBS)
+
+PKG_CHECK_MODULES(STATUS_PROVIDER_TELEPATHY, dbus-glib-1)
+AC_SUBST(STATUS_PROVIDER_TELEPATHY_CFLAGS)
+AC_SUBST(STATUS_PROVIDER_TELEPATHY_LIBS)
+
+TELEPATHYGLIB_REQUIRED_VERSION=0.9.0
+PKG_CHECK_MODULES(STATUS_PROVIDER_MC5, dbus-glib-1
+                                       telepathy-glib >= $TELEPATHYGLIB_REQUIRED_VERSION)
+AC_SUBST(STATUS_PROVIDER_MC5_CFLAGS)
+AC_SUBST(STATUS_PROVIDER_MC5_LIBS)
+
+PKG_CHECK_MODULES(STATUS_PROVIDER_EMESENE, dbus-glib-1)
+AC_SUBST(STATUS_PROVIDER_EMESENE_CFLAGS)
+AC_SUBST(STATUS_PROVIDER_EMESENE_LIBS)
+
+###########################
 # Check to see if we're local
 ###########################
 
@@ -137,6 +159,7 @@
 AC_OUTPUT([
 Makefile
 src/Makefile
+src/indicator-messages-status-provider-0.5.pc.in
 data/Makefile
 data/icons/Makefile
 data/icons/16x16/Makefile

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in	2010-03-04 06:35:22 +0000
+++ po/POTFILES.in	2011-07-13 20:27:12 +0000
@@ -6,3 +6,4 @@
 src/launcher-menu-item.c
 src/im-menu-item.c
 src/app-menu-item.c
+src/status-items.c

=== modified file 'src/Makefile.am'
--- src/Makefile.am	2011-01-17 18:04:11 +0000
+++ src/Makefile.am	2011-07-13 20:27:12 +0000
@@ -1,6 +1,12 @@
 
+BUILT_SOURCES = 
+EXTRA_DIST =
+CLEANFILES = 
+DISTCLEANFILES =
+
 libexec_PROGRAMS = indicator-messages-service
 
+
 ######################################
 # Building the messages indicator
 ######################################
@@ -44,7 +50,11 @@
 	seen-db.c \
 	seen-db.h \
 	dirs.h \
-	dbus-data.h
+	dbus-data.h \
+	\
+	status-items.c \
+	status-items.h
+
 indicator_messages_service_CFLAGS = \
 	$(APPLET_CFLAGS) \
 	-Wall \
@@ -52,8 +62,12 @@
 	-Wl,-z,defs \
 	-Wl,--as-needed \
 	-Werror \
-	-DG_LOG_DOMAIN=\"Indicator-Messages\"
-indicator_messages_service_LDADD = $(APPLET_LIBS)
+	-DG_LOG_DOMAIN=\"Indicator-Messages\" \
+	-DSTATUS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\"
+
+indicator_messages_service_LDADD = \
+	$(APPLET_LIBS) \
+	libindicator-messages-status-provider.la
 
 gen-%.xml.h: %.xml
 	@echo "Building $@ from $<"
@@ -65,13 +79,198 @@
 	@sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@
 	@echo ";" >> $@
 
-BUILT_SOURCES = \
+BUILT_SOURCES += \
 	gen-messages-service.xml.h \
 	gen-messages-service.xml.c
 
-CLEANFILES = \
+EXTRA_DIST += \
+	messages-service.xml
+
+######################################
+# Status Provider Library
+######################################
+
+STATUS_PROVIDER_API_VERSION = 1
+STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION)
+statusprovidersdir = $(STATUS_PROVIDER_DIR)
+statusproviders_LTLIBRARIES = 
+
+EXTRA_DIST += \
+	indicator-messages-status-provider-0.5.pc.in.in
+CLEANFILES += \
+	indicator-messages-status-provider-0.5.pc
+
+pkgconfig_DATA = indicator-messages-status-provider-0.5.pc
+pkgconfigdir = $(libdir)/pkgconfig
+
+%.pc: %.pc.in
+	sed \
+		-e "s|\@status_provider_dir\@|$(STATUS_PROVIDER_DIR)|" \
+		-e "s|\@status_provider_api_version\@|$(STATUS_PROVIDER_API_VERSION)|" \
+		$< > $@
+
+lib_LTLIBRARIES = \
+	libindicator-messages-status-provider.la
+
+libindicator_messages_status_provider_la_HEADERS = \
+	status-provider.h
+
+libindicator_messages_status_provider_la_SOURCES = \
+	$(libindicator_messages_status_provider_HEADERS) \
+	status-provider.c
+
+libindicator_messages_status_provider_ladir = \
+	$(includedir)/libindicator-messages-status-provider-$(STATUS_PROVIDER_API_VERSION)/
+
+libindicator_messages_status_provider_la_LDFLAGS = \
+	-version-info $(STATUS_PROVIDER_API_VERSION):0:0 \
+	-no-undefined \
+	-export-symbols-regex "^[^_].*"
+
+libindicator_messages_status_provider_la_LIBADD = \
+	$(APPLET_LIBS)
+
+libindicator_messages_status_provider_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	-Wall -Werror
+
+######################################
+# Status provider: Pidgin
+######################################
+
+statusproviders_LTLIBRARIES += libpidgin.la
+libpidgin_la_SOURCES = \
+	status-provider-pidgin.h \
+	status-provider-pidgin.c \
+	status-provider-pidgin-marshal.h \
+	status-provider-pidgin-marshal.c
+libpidgin_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(STATUS_PROVIDER_PIDGIN_CFLAGS) \
+	-Wall -Werror \
+	-DG_LOG_DOMAIN=\"Status-Provider-Pidgin\"
+libpidgin_la_LIBADD = \
+	libindicator-messages-status-provider.la \
+	$(APPLET_LIBS) \
+	$(STATUS_PROVIDER_PIDGIN_LIBS)
+libpidgin_la_LDFLAGS = -module -avoid-version
+
+status-provider-pidgin-marshal.h: $(srcdir)/status-provider-pidgin.list
+	glib-genmarshal --header \
+		--prefix=_status_provider_pidgin_marshal $(srcdir)/status-provider-pidgin.list \
+		> status-provider-pidgin-marshal.h
+
+status-provider-pidgin-marshal.c: $(srcdir)/status-provider-pidgin.list
+	glib-genmarshal --body \
+		--prefix=_status_provider_pidgin_marshal $(srcdir)/status-provider-pidgin.list \
+		> status-provider-pidgin-marshal.c
+
+BUILT_SOURCES += \
+	status-provider-pidgin-marshal.h \
+	status-provider-pidgin-marshal.c 
+
+EXTRA_DIST += \
+	status-provider-pidgin.list
+
+######################################
+# Status provider: Mission Control 4
+######################################
+
+statusproviders_LTLIBRARIES += libtelepathy.la
+libtelepathy_la_SOURCES = \
+	status-provider-telepathy.h \
+	status-provider-telepathy.c \
+	status-provider-telepathy-marshal.h \
+	status-provider-telepathy-marshal.c
+libtelepathy_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(STATUS_PROVIDER_TELEPATHY_CFLAGS) \
+	-Wall -Werror \
+	-DG_LOG_DOMAIN=\"Status-Provider-Telepathy\"
+libtelepathy_la_LIBADD = \
+	libindicator-messages-status-provider.la \
+	$(APPLET_LIBS) \
+	$(STATUS_PROVIDER_TELEPATHY_LIBS)
+libtelepathy_la_LDFLAGS = -module -avoid-version
+
+status-provider-telepathy-marshal.h: $(srcdir)/status-provider-telepathy.list
+	glib-genmarshal --header \
+		--prefix=_status_provider_telepathy_marshal $(srcdir)/status-provider-telepathy.list \
+		> status-provider-telepathy-marshal.h
+
+status-provider-telepathy-marshal.c: $(srcdir)/status-provider-telepathy.list
+	glib-genmarshal --body \
+		--prefix=_status_provider_telepathy_marshal $(srcdir)/status-provider-telepathy.list \
+		> status-provider-telepathy-marshal.c
+
+BUILT_SOURCES += \
+	status-provider-telepathy-marshal.h \
+	status-provider-telepathy-marshal.c
+
+EXTRA_DIST += \
+	status-provider-telepathy.list
+
+######################################
+# Status provider: Mission Control 5
+######################################
+
+statusproviders_LTLIBRARIES += libmc5.la
+libmc5_la_SOURCES = \
+	status-provider-mc5.h \
+	status-provider-mc5.c \
+	status-provider-mc5-marshal.h \
+	status-provider-mc5-marshal.c
+libmc5_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(STATUS_PROVIDER_MC5_CFLAGS) \
+	-Wall -Werror \
+	-DG_LOG_DOMAIN=\"Status-Provider-MC5\"
+libmc5_la_LIBADD = \
+	libindicator-messages-status-provider.la \
+	$(APPLET_LIBS) \
+	$(STATUS_PROVIDER_MC5_LIBS)
+libmc5_la_LDFLAGS = -module -avoid-version
+
+status-provider-mc5-marshal.h: $(srcdir)/status-provider-mc5.list
+	glib-genmarshal --header \
+		--prefix=_status_provider_mc5_marshal $(srcdir)/status-provider-mc5.list \
+		> status-provider-mc5-marshal.h
+
+status-provider-mc5-marshal.c: $(srcdir)/status-provider-mc5.list
+	glib-genmarshal --body \
+		--prefix=_status_provider_mc5_marshal $(srcdir)/status-provider-mc5.list \
+		> status-provider-mc5-marshal.c
+
+BUILT_SOURCES += \
+	status-provider-mc5-marshal.h \
+	status-provider-mc5-marshal.c
+
+EXTRA_DIST += \
+	status-provider-mc5.list
+
+######################################
+# Status provider: Emesene
+######################################
+
+statusproviders_LTLIBRARIES += libemesene.la
+libemesene_la_SOURCES = \
+	status-provider-emesene.h \
+	status-provider-emesene.c
+libemesene_la_CFLAGS = \
+	$(APPLET_CFLAGS) \
+	$(STATUS_PROVIDER_EMESENE_CFLAGS) \
+	-Wall -Werror \
+	-DG_LOG_DOMAIN=\"Status-Provider-Emesene\"
+libemesene_la_LIBADD = \
+	libindicator-messages-status-provider.la \
+	$(APPLET_LIBS) \
+	$(STATUS_PROVIDER_EMESENE_LIBS)
+libemesene_la_LDFLAGS = -module -avoid-version
+
+######################################
+# Extras
+######################################
+
+CLEANFILES += \
 	$(BUILT_SOURCES)
 
-EXTRA_DIST = \
-	messages-service.xml
-

=== added file 'src/indicator-messages-status-provider-0.5.pc.in.in'
--- src/indicator-messages-status-provider-0.5.pc.in.in	1970-01-01 00:00:00 +0000
+++ src/indicator-messages-status-provider-0.5.pc.in.in	2011-07-13 20:27:12 +0000
@@ -0,0 +1,15 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+bindir=@bindir@
+includedir=@includedir@
+
+statusproviderdir=@status_provider_dir@
+
+Cflags: -I${includedir}/indicator-messages-status-provider-0.@status_provider_api_version@
+Requires: gobject-2.0
+Libs: -L${libdir} -lindicator-messages-status-provider
+
+Name: indicator-messages-status-provider
+Description: Status providers for the indicator-messages menu.
+Version: @VERSION@

=== modified file 'src/messages-service.c'
--- src/messages-service.c	2011-01-14 19:13:43 +0000
+++ src/messages-service.c	2011-07-13 20:27:12 +0000
@@ -40,6 +40,7 @@
 #include "dirs.h"
 #include "messages-service-dbus.h"
 #include "seen-db.h"
+#include "status-items.h"
 
 static IndicatorService * service = NULL;
 static IndicateListener * listener = NULL;
@@ -47,6 +48,7 @@
 static GList * launcherList = NULL;
 
 static DbusmenuMenuitem * root_menuitem = NULL;
+static DbusmenuMenuitem * status_separator = NULL;
 static GMainLoop * mainloop = NULL;
 
 static MessageServiceDbus * dbus_interface = NULL;
@@ -836,6 +838,11 @@
 	DbusmenuMenuitem * last_separator = NULL;
 
 	g_debug("Reordering Menu:");
+	
+	if (DBUSMENU_IS_MENUITEM(status_separator)) {
+		position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1;
+		g_debug("\tPriming with location of status separator: %d", position);
+	}
 
 	for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) {
 		serverList_t * si = (serverList_t *)serverentry->data;
@@ -1432,13 +1439,21 @@
 	return;
 }
 
+static void
+status_update_callback (void)
+{
+	return;
+}
+
 /* Oh, if you don't know what main() is for
    we really shouldn't be talking. */
 int
 main (int argc, char ** argv)
 {
+	/* Glib init */
 	g_type_init();
 
+	/* Create the Indicator Service interface */
 	service = indicator_service_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1);
 	g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL);
 
@@ -1448,31 +1463,50 @@
 	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 	textdomain (GETTEXT_PACKAGE);
 
+	/* Create the Seen DB */
 	seen_db_init();
 
+	/* Bring up the service DBus interface */
 	dbus_interface = message_service_dbus_new();
 
-	listener = indicate_listener_ref_default();
-	serverList = NULL;
-
+	/* Build the base menu */
 	root_menuitem = dbusmenu_menuitem_new();
 	DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT);
 	dbusmenu_server_set_root(server, root_menuitem);
 
+	/* Add status items */
+	GList * statusitems = status_items_build(&status_update_callback);
+	while (statusitems != NULL) {
+		dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(statusitems->data));
+		statusitems = g_list_next(statusitems);
+	}
+	status_separator = dbusmenu_menuitem_new();
+	dbusmenu_menuitem_property_set(status_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+	dbusmenu_menuitem_child_append(root_menuitem, status_separator);
+
+	/* Start up the libindicate listener */
+	listener = indicate_listener_ref_default();
+	serverList = NULL;
+
 	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem);
 	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem);
 	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem);
 	g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem);
 
+	/* Find launchers by looking through the config directories
+	   in the idle loop */
 	g_idle_add(blacklist_init, NULL);
 	g_idle_add(build_launchers, SYSTEM_APPS_DIR);
 	g_idle_add(build_launchers, SYSTEM_APPS_DIR_OLD);
 	gchar * userdir = g_build_filename(g_get_user_config_dir(), USER_APPS_DIR, NULL);
 	g_idle_add(build_launchers, userdir);
 
+	/* Let's run a mainloop */
 	mainloop = g_main_loop_new(NULL, FALSE);
 	g_main_loop_run(mainloop);
 
+	/* Clean up */
+	status_items_cleanup();
 	g_free(userdir);
 
 	return 0;

=== added file 'src/status-items.c'
--- src/status-items.c	1970-01-01 00:00:00 +0000
+++ src/status-items.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,314 @@
+/*
+Code to build and maintain the status adjustment menuitems.
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <libdbusmenu-glib/dbusmenu-glib.h>
+
+#include "status-items.h"
+#include "status-provider.h"
+
+static const gchar * status_strings [STATUS_PROVIDER_STATUS_LAST] = {
+  /* STATUS_PROVIDER_STATUS_ONLINE,    */   N_("Available"),
+  /* STATUS_PROVIDER_STATUS_AWAY,      */   N_("Away"),
+  /* STATUS_PROVIDER_STATUS_DND        */   N_("Busy"),
+  /* STATUS_PROVIDER_STATUS_INVISIBLE  */   N_("Invisible"),
+  /* STATUS_PROVIDER_STATUS_OFFLINE,   */   N_("Offline"),
+  /* STATUS_PROVIDER_STATUS_DISCONNECTED*/  N_("Offline")
+};
+
+static const gchar * status_icons[STATUS_PROVIDER_STATUS_LAST] = {
+  /* STATUS_PROVIDER_STATUS_ONLINE, */      "user-available",
+  /* STATUS_PROVIDER_STATUS_AWAY, */        "user-away",
+  /* STATUS_PROVIDER_STATUS_DND, */         "user-busy",
+  /* STATUS_PROVIDER_STATUS_INVISIBLE, */   "user-invisible",
+  /* STATUS_PROVIDER_STATUS_OFFLINE */      "user-offline",
+  /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "user-offline-panel"
+};
+
+static const gchar * panel_icons[STATUS_PROVIDER_STATUS_LAST] = {
+  /* STATUS_PROVIDER_STATUS_ONLINE, */      "indicator-messages-user-available",
+  /* STATUS_PROVIDER_STATUS_AWAY, */        "indicator-messages-user-away",
+  /* STATUS_PROVIDER_STATUS_DND, */         "indicator-messages-user-busy",
+  /* STATUS_PROVIDER_STATUS_INVISIBLE, */   "indicator-messages-user-invisible",
+  /* STATUS_PROVIDER_STATUS_OFFLINE */      "indicator-messages-user-offline",
+  /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "indicator-messages-user-disconnected"
+};
+
+static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = {
+  /* STATUS_PROVIDER_STATUS_ONLINE, */      "indicator-messages-new-user-available",
+  /* STATUS_PROVIDER_STATUS_AWAY, */        "indicator-messages-new-user-away",
+  /* STATUS_PROVIDER_STATUS_DND, */         "indicator-messages-new-user-busy",
+  /* STATUS_PROVIDER_STATUS_INVISIBLE, */   "indicator-messages-new-user-invisible",
+  /* STATUS_PROVIDER_STATUS_OFFLINE */      "indicator-messages-new-user-offline",
+  /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "indicator-messages-new-user-disconnected"
+};
+
+/* Prototypes */
+static gboolean provider_directory_parse (gpointer dir);
+static gboolean load_status_provider (gpointer dir);
+static void user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus);
+
+/* Globals */
+static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED;
+static GList * menuitems = NULL;
+static GList * status_providers = NULL;
+static StatusUpdateFunc update_func = NULL;
+
+/* Build the inital status items and start kicking off the async code
+   for handling all the statuses */
+GList *
+status_items_build (StatusUpdateFunc status_update_func)
+{
+	int i;
+	for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) {
+		DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+
+		dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, _(status_strings[i]));
+		dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_ICON_NAME, status_icons[i]);
+
+		dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+		dbusmenu_menuitem_property_set_bool(item, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+
+		dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, DBUSMENU_MENUITEM_TOGGLE_RADIO);
+		dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+
+		g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(user_status_change), GINT_TO_POINTER(i));
+
+		menuitems = g_list_append(menuitems, item);
+	}
+
+	update_func = status_update_func;
+
+	const gchar * status_providers_env = g_getenv("INDICATOR_MESSAGES_STATUS_PROVIDER_DIR");
+	if (status_providers_env == NULL) {
+		g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR);
+	} else {
+		g_idle_add(provider_directory_parse, (gpointer)status_providers_env);
+	}
+
+	return menuitems;
+}
+
+/* Clean up our globals and stop with all this allocation
+   of memory */
+void
+status_items_cleanup (void)
+{
+	while (status_providers != NULL) {
+		StatusProvider * sprovider = STATUS_PROVIDER(status_providers->data);
+		g_object_unref(sprovider);
+		status_providers = g_list_remove(status_providers, sprovider);
+	}
+
+	return;
+}
+
+/* Get the icon that should be shown on the panel */
+const gchar *
+status_current_panel_icon (gboolean alert)
+{
+	if (alert) {
+		return panel_active_icons[current_status];
+	} else {
+		return panel_icons[current_status];
+	}
+}
+
+/* Update status from all the providers */
+static void
+update_status (void)
+{
+	StatusProviderStatus status = STATUS_PROVIDER_STATUS_DISCONNECTED;
+	GList * provider;
+
+	for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) {
+		StatusProviderStatus localstatus = status_provider_get_status(STATUS_PROVIDER(provider->data));
+
+		if (localstatus < status) {
+			status = localstatus;
+		}
+	}
+
+	if (status == current_status) {
+		return;
+	}
+
+	current_status = status;
+
+	if (update_func != NULL) {
+		update_func();
+	}
+
+	GList * menu;
+	int i;
+	for (menu = menuitems, i = 0; menu != NULL && i < STATUS_PROVIDER_STATUS_DISCONNECTED; menu = g_list_next(menu), i++) {
+		/* If we're the seleced status or if we're disconnected
+		   show the user that we're offline */
+		if (i == current_status || (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED && i == STATUS_PROVIDER_STATUS_OFFLINE)) {
+			dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED);
+		} else {
+			dbusmenu_menuitem_property_set_int(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+		}
+
+		if (current_status == STATUS_PROVIDER_STATUS_DISCONNECTED) {
+			dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+		} else {
+			dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(menu->data), DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+		}
+	}
+
+	return;
+}
+
+/* Handle the user requesting a status change */
+static void
+user_status_change (DbusmenuMenuitem * item, guint timestamp, gpointer pstatus)
+{
+	StatusProviderStatus status = GPOINTER_TO_INT(pstatus);
+	GList * provider;
+
+	/* Set each provider to this status */
+	for (provider = status_providers; provider != NULL; provider = g_list_next(provider)) {
+		status_provider_set_status(STATUS_PROVIDER(provider->data), status);
+	}
+
+	/* See what we really are now */
+	update_status();
+	return;
+}
+
+/* Start parsing a directory and setting up the entires in the idle loop */
+static gboolean
+provider_directory_parse (gpointer directory)
+{
+	const gchar * dirname = (const gchar *)directory;
+	g_debug("Looking for status providers in: %s", dirname);
+
+	if (!g_file_test(dirname, G_FILE_TEST_EXISTS)) {
+		return FALSE;
+	}
+
+	GDir * dir = g_dir_open(dirname, 0, NULL);
+	if (dir == NULL) {
+		return FALSE;
+	}
+
+	const gchar * name;
+	while ((name = g_dir_read_name(dir)) != NULL) {
+		if (!g_str_has_suffix(name, G_MODULE_SUFFIX)) {
+			continue;
+		}
+
+		gchar * fullname = g_build_filename(dirname, name, NULL);
+		g_idle_add(load_status_provider, fullname);
+	}
+
+	g_dir_close(dir);
+
+	return FALSE;
+}
+
+/* Close the module as an idle function so that we know
+   it's all cleaned up */
+static gboolean
+module_destroy_in_idle_helper (gpointer data)
+{
+	GModule * module = (GModule *)data;
+	if (module != NULL) {
+		g_debug("Unloading module: %s", g_module_name(module));
+		g_module_close(module);
+	}
+	return FALSE;
+}
+
+/* Set up an idle function to close the module */
+static void
+module_destroy_in_idle (gpointer data)
+{
+	g_idle_add_full(G_PRIORITY_LOW, module_destroy_in_idle_helper, data, NULL);
+	return;
+}
+
+/* Load a particular status provider */
+static gboolean
+load_status_provider (gpointer dir)
+{
+	gchar * provider = (gchar *)dir;
+
+	if (!g_file_test(provider, G_FILE_TEST_EXISTS)) {
+		goto exit_final;
+	}
+
+	g_debug("Loading status provider: %s", provider);
+
+	GModule * module;
+
+	module = g_module_open(provider, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+	if (module == NULL) {
+		g_warning("Unable to module for: %s", provider);
+		goto exit_module_fail;
+	}
+
+	/* Got it */
+	GType (*type_func) (void);
+	if (!g_module_symbol(module, STATUS_PROVIDER_EXPORT_S, (gpointer *)&type_func)) {
+		g_warning("Unable to find type symbol in: %s", provider);
+		goto exit_module_fail;
+	}
+
+	GType provider_type = type_func();
+	if (provider_type == 0) {
+		g_warning("Unable to create type from: %s", provider);
+		goto exit_module_fail;
+	}
+
+	StatusProvider * sprovider = STATUS_PROVIDER(g_object_new(provider_type, NULL));
+	if (sprovider == NULL) {
+		g_warning("Unable to build provider from: %s", provider);
+		goto exit_module_fail;
+	}
+
+	/* On update let's talk to all of them and create the aggregate
+	   value to export */
+	g_signal_connect(G_OBJECT(sprovider), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED, G_CALLBACK(update_status), NULL);
+
+	/* Attach the module object to the status provider so
+	   that when the status provider is free'd the module
+	   is close automatically. */
+	g_object_set_data_full(G_OBJECT(sprovider), "status-provider-module", module, module_destroy_in_idle);
+
+	status_providers = g_list_prepend(status_providers, sprovider);
+
+	/* Force and update every time just so we know we're
+	   in a consistent state*/
+	update_status();
+
+	goto exit_final;
+
+exit_module_fail:
+	g_module_close(module);
+
+exit_final:
+	g_free(provider);
+	return FALSE;
+}

=== added file 'src/status-items.h'
--- src/status-items.h	1970-01-01 00:00:00 +0000
+++ src/status-items.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,38 @@
+/*
+Code to build and maintain the status adjustment menuitems.
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_ITEMS_H__
+#define __STATUS_ITEMS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef void (*StatusUpdateFunc) (void);
+
+GList * status_items_build (StatusUpdateFunc update_func);
+const gchar * status_current_panel_icon (gboolean alert);
+void status_items_cleanup (void);
+
+G_END_DECLS
+
+#endif /* __STATUS_ITEMS_H__ */
+

=== added file 'src/status-provider-emesene.c'
--- src/status-provider-emesene.c	1970-01-01 00:00:00 +0000
+++ src/status-provider-emesene.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,346 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+    Stefano Candori <stefano.candori@xxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "status-provider.h"
+#include "status-provider-emesene.h"
+
+#include <dbus/dbus-glib.h>
+
+typedef enum {
+        EM_STATUS_ONLINE,
+	EM_STATUS_OFFLINE,
+	EM_STATUS_BUSY,
+	EM_STATUS_AWAY,
+	EM_STATUS_IDLE
+} em_status_t;
+
+static const StatusProviderStatus em_to_sp_map[] = {
+	/* EM_STATUS_ONLINE,         */   STATUS_PROVIDER_STATUS_ONLINE,
+	/* EM_STATUS_OFFLINE,        */   STATUS_PROVIDER_STATUS_OFFLINE,
+	/* EM_STATUS_BUSY,           */   STATUS_PROVIDER_STATUS_DND,
+	/* EM_STATUS_AWAY,           */   STATUS_PROVIDER_STATUS_AWAY,
+	/* EM_STATUS_IDLE,           */   STATUS_PROVIDER_STATUS_AWAY
+};
+
+static const em_status_t sp_to_em_map[STATUS_PROVIDER_STATUS_LAST] = {
+	/* STATUS_PROVIDER_STATUS_ONLINE,  */  EM_STATUS_ONLINE,
+	/* STATUS_PROVIDER_STATUS_AWAY,    */  EM_STATUS_AWAY,
+	/* STATUS_PROVIDER_STATUS_DND      */  EM_STATUS_BUSY,
+	/* STATUS_PROVIDER_STATUS_INVISIBLE*/  EM_STATUS_OFFLINE,
+	/* STATUS_PROVIDER_STATUS_OFFLINE  */  EM_STATUS_OFFLINE,
+	/* STATUS_PROVIDER_STATUS_DISCONNECTED*/ EM_STATUS_OFFLINE
+};
+
+typedef struct _StatusProviderEmesenePrivate StatusProviderEmesenePrivate;
+struct _StatusProviderEmesenePrivate {
+	DBusGProxy * proxy;
+	DBusGProxy * dbus_proxy;
+	em_status_t  em_status;
+};
+
+#define STATUS_PROVIDER_EMESENE_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmesenePrivate))
+
+/* Prototypes */
+/* GObject stuff */
+static void status_provider_emesene_class_init (StatusProviderEmeseneClass *klass);
+static void status_provider_emesene_init       (StatusProviderEmesene *self);
+static void status_provider_emesene_dispose    (GObject *object);
+static void status_provider_emesene_finalize   (GObject *object);
+/* Internal Funcs */
+static void set_status (StatusProvider * sp, StatusProviderStatus status);
+static StatusProviderStatus get_status (StatusProvider * sp);
+static void setup_emesene_proxy (StatusProviderEmesene * self);
+static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderEmesene * self);
+
+G_DEFINE_TYPE (StatusProviderEmesene, status_provider_emesene, STATUS_PROVIDER_TYPE);
+
+STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_EMESENE_TYPE)
+
+static void
+status_provider_emesene_class_init (StatusProviderEmeseneClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (StatusProviderEmesenePrivate));
+
+	object_class->dispose = status_provider_emesene_dispose;
+	object_class->finalize = status_provider_emesene_finalize;
+
+	StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass);
+
+	spclass->set_status = set_status;
+	spclass->get_status = get_status;
+
+	return;
+}
+
+static void
+status_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
+{
+        StatusProviderEmesene * spe = STATUS_PROVIDER_EMESENE(userdata);
+        StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe);
+        
+	GError * error = NULL;
+	gint status = 0;
+	if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) {
+		g_warning("Unable to get status from Emesene: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	priv->em_status = status;
+	g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE);
+	return;
+}
+
+static void
+changed_status (DBusGProxy * proxy, gint status, StatusProviderEmesene * spe)
+{
+        StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe);
+        g_debug("Emesene changed status to %d", status);
+        priv->em_status = status;
+	g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE);
+	return;
+}
+
+static void
+proxy_destroy (DBusGProxy * proxy, StatusProviderEmesene * spe)
+{
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(spe);
+
+	priv->proxy = NULL;
+	priv->em_status = EM_STATUS_OFFLINE;
+
+	g_signal_emit(G_OBJECT(spe), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE);
+	return;
+}
+
+static void
+status_provider_emesene_init (StatusProviderEmesene *self)
+{
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(self);
+
+	priv->proxy = NULL;
+	priv->em_status = EM_STATUS_OFFLINE;
+
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this,
+	                                  all non-DBus stuff should be done */
+
+	GError * error = NULL;
+
+	/* Set up the dbus Proxy */
+	priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                                    DBUS_SERVICE_DBUS,
+	                                                    DBUS_PATH_DBUS,
+	                                                    DBUS_INTERFACE_DBUS,
+	                                                    &error);
+	if (error != NULL) {
+		g_warning("Unable to connect to DBus events: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Configure the name owner changing */
+	dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+							G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_CALLBACK(dbus_namechange),
+	                        self, NULL);
+
+	setup_emesene_proxy(self);
+
+	return;
+}
+
+/* Watch to see if the Emesene comes up on Dbus */
+static void
+dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderEmesene * self)
+{
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(new != NULL);
+
+	if (g_strcmp0(name, "org.emesene.Service") == 0) {
+		setup_emesene_proxy(self);
+	}
+	return;
+}
+
+/* Setup the Emesene proxy so that we can talk to it
+   and get signals from it.  */
+static void
+setup_emesene_proxy (StatusProviderEmesene * self)
+{
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(self);
+
+	if (priv->proxy != NULL) {
+		g_debug("Doh!We were asked to set up a Emesene proxy when we already had one.");
+		return;
+	}
+
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this,
+	                                  all non-DBus stuff should be done */
+
+	GError * error = NULL;
+
+	/* Set up the Emesene Proxy */
+	priv->proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                               "org.emesene.Service",
+	                                               "/org/emesene/Service",
+	                                               "org.emesene.Service",
+	                                               &error);
+	/* Report any errors */
+	if (error != NULL) {
+		g_debug("Unable to get Emesene proxy: %s", error->message);
+		g_error_free(error);
+	}
+
+	/* If we have a proxy, let's start using it */
+	if (priv->proxy != NULL) {
+		/* Set the proxy to NULL if it's destroyed */
+		g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy);
+		/* If it's destroyed, let's clean up as well */
+		g_signal_connect(G_OBJECT(priv->proxy), "destroy",
+		                 G_CALLBACK(proxy_destroy), self);
+
+		/* Watching for the status change coming from the
+		   Emesene side of things. */
+		g_debug("Adding Emesene Signals");
+		dbus_g_proxy_add_signal    (priv->proxy,
+		                            "status_changed",
+		                            G_TYPE_INT,
+		                            G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal(priv->proxy,
+		                            "status_changed",
+		                            G_CALLBACK(changed_status),
+		                            (void *)self,
+		                            NULL);
+
+		/* Get the current status to update our cached
+		   value of the status. */
+		dbus_g_proxy_begin_call(priv->proxy,
+		                        "get_status",
+		                        status_cb,
+		                        self,
+		                        NULL,
+		                        G_TYPE_INVALID);
+	}
+
+	return;
+}
+
+static void
+status_provider_emesene_dispose (GObject *object)
+{
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(object);
+
+	if (priv->proxy != NULL) {
+		g_object_unref(priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (status_provider_emesene_parent_class)->dispose (object);
+	return;
+}
+
+static void
+status_provider_emesene_finalize (GObject *object)
+{
+
+	G_OBJECT_CLASS (status_provider_emesene_parent_class)->finalize (object);
+	return;
+}
+
+/**
+	status_provider_emesene_new:
+
+	Creates a new #StatusProviderEmesene object.  No parameters or anything
+	like that.  Just a convience function.
+
+	Return value: A new instance of #StatusProviderEmesene
+*/
+StatusProvider *
+status_provider_emesene_new (void)
+{
+	return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_EMESENE_TYPE, NULL));
+}
+
+/* Takes the status provided generically for Status providers
+   and turns it into a Emesene status and sends it to Emesene. */
+static void
+set_status (StatusProvider * sp, StatusProviderStatus status)
+{
+	g_return_if_fail(IS_STATUS_PROVIDER_EMESENE(sp));
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(sp);
+
+	g_debug("Emesene set status to %d", status);
+	if (priv->proxy == NULL) {
+		return;
+	}
+
+	priv->em_status = sp_to_em_map[status];
+	
+	gboolean ret = FALSE;
+	GError * error = NULL;
+
+	ret = dbus_g_proxy_call(priv->proxy,
+	                        "set_status", &error,
+				G_TYPE_INT, priv->em_status,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INVALID);
+
+	if (!ret) {
+		if (error != NULL) {
+			g_warning("Emesene unable to change to status: %s", error->message);
+			g_error_free(error);
+		} else {
+			g_warning("Emesene unable to change to status");
+		}
+		error = NULL;
+	}
+
+	g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, em_to_sp_map[priv->em_status], TRUE);
+	return;
+}
+
+/* Takes the cached Emesene status and makes it into the generic
+   Status provider status.  If there is no Emesene proxy then it
+   returns the disconnected state. */
+static StatusProviderStatus
+get_status (StatusProvider * sp)
+{
+	g_return_val_if_fail(IS_STATUS_PROVIDER_EMESENE(sp), STATUS_PROVIDER_STATUS_DISCONNECTED);
+	StatusProviderEmesenePrivate * priv = STATUS_PROVIDER_EMESENE_GET_PRIVATE(sp);
+
+	if (priv->proxy == NULL) {
+		return STATUS_PROVIDER_STATUS_DISCONNECTED;
+	}
+
+	return em_to_sp_map[priv->em_status];
+}

=== added file 'src/status-provider-emesene.h'
--- src/status-provider-emesene.h	1970-01-01 00:00:00 +0000
+++ src/status-provider-emesene.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,56 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 20011 Canonical Ltd.
+
+Authors:
+    Stefano Candori <stefano.candori@xxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_PROVIDER_EMESENE_H__
+#define __STATUS_PROVIDER_EMESENE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "status-provider.h"
+
+G_BEGIN_DECLS
+
+#define STATUS_PROVIDER_EMESENE_TYPE            (status_provider_emesene_get_type ())
+#define STATUS_PROVIDER_EMESENE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmesene))
+#define STATUS_PROVIDER_EMESENE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmeseneClass))
+#define IS_STATUS_PROVIDER_EMESENE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_EMESENE_TYPE))
+#define IS_STATUS_PROVIDER_EMESENE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_EMESENE_TYPE))
+#define STATUS_PROVIDER_EMESENE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_EMESENE_TYPE, StatusProviderEmeseneClass))
+
+
+typedef struct _StatusProviderEmeseneClass StatusProviderEmeseneClass;
+struct _StatusProviderEmeseneClass {
+	StatusProviderClass parent_class;
+};
+
+typedef struct _StatusProviderEmesene      StatusProviderEmesene;
+struct _StatusProviderEmesene {
+	StatusProvider parent;
+};
+
+GType status_provider_emesene_get_type (void);
+StatusProvider * status_provider_emesene_new (void);
+
+G_END_DECLS
+
+#endif

=== added file 'src/status-provider-mc5.c'
--- src/status-provider-mc5.c	1970-01-01 00:00:00 +0000
+++ src/status-provider-mc5.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,308 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <telepathy-glib/account-manager.h>
+
+#include "status-provider.h"
+#include "status-provider-mc5.h"
+#include "status-provider-mc5-marshal.h"
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
+
+static gchar * sp_to_mc_map[STATUS_PROVIDER_STATUS_LAST] = {
+	/* STATUS_PROVIDER_STATUS_ONLINE,  */  "available",
+	/* STATUS_PROVIDER_STATUS_AWAY,    */  "away",
+	/* STATUS_PROVIDER_STATUS_DND      */  "busy",
+	/* STATUS_PROVIDER_STATUS_INVISIBLE*/  "hidden",
+	/* STATUS_PROVIDER_STATUS_OFFLINE  */  "offline",
+	/* STATUS_PROVIDER_STATUS_DISCONNECTED*/NULL
+};
+
+static TpConnectionPresenceType sp_to_tp_map[STATUS_PROVIDER_STATUS_LAST] = {
+	/* STATUS_PROVIDER_STATUS_ONLINE,  */    TP_CONNECTION_PRESENCE_TYPE_AVAILABLE,
+	/* STATUS_PROVIDER_STATUS_AWAY,    */    TP_CONNECTION_PRESENCE_TYPE_AWAY,
+	/* STATUS_PROVIDER_STATUS_DND      */    TP_CONNECTION_PRESENCE_TYPE_BUSY,
+	/* STATUS_PROVIDER_STATUS_INVISIBLE*/    TP_CONNECTION_PRESENCE_TYPE_HIDDEN,
+	/* STATUS_PROVIDER_STATUS_OFFLINE  */    TP_CONNECTION_PRESENCE_TYPE_OFFLINE,
+	/* STATUS_PROVIDER_STATUS_DISCONNECTED*/ TP_CONNECTION_PRESENCE_TYPE_UNSET
+};
+
+static StatusProviderStatus tp_to_sp_map[TP_CONNECTION_PRESENCE_TYPE_ERROR + 1] = {
+	/* TP_CONNECTION_PRESENCE_TYPE_UNSET          */  STATUS_PROVIDER_STATUS_DISCONNECTED,
+	/* TP_CONNECTION_PRESENCE_TYPE_OFFLINE        */  STATUS_PROVIDER_STATUS_OFFLINE,
+	/* TP_CONNECTION_PRESENCE_TYPE_AVAILABLE      */  STATUS_PROVIDER_STATUS_ONLINE,
+	/* TP_CONNECTION_PRESENCE_TYPE_AWAY           */  STATUS_PROVIDER_STATUS_AWAY,
+	/* TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY  */  STATUS_PROVIDER_STATUS_AWAY,
+	/* TP_CONNECTION_PRESENCE_TYPE_HIDDEN         */  STATUS_PROVIDER_STATUS_INVISIBLE,
+	/* TP_CONNECTION_PRESENCE_TYPE_BUSY           */  STATUS_PROVIDER_STATUS_DND,
+	/* TP_CONNECTION_PRESENCE_TYPE_UNKNOWN        */  STATUS_PROVIDER_STATUS_DISCONNECTED,
+	/* TP_CONNECTION_PRESENCE_TYPE_ERROR          */  STATUS_PROVIDER_STATUS_DISCONNECTED
+};
+
+typedef struct _StatusProviderMC5Private StatusProviderMC5Private;
+struct _StatusProviderMC5Private {
+	TpAccountManager * manager;
+	StatusProviderStatus status;
+	DBusGProxy * dbus_proxy;
+};
+
+#define STATUS_PROVIDER_MC5_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Private))
+#define MC5_WELL_KNOWN_NAME  "org.freedesktop.Telepathy.AccountManager"
+
+/* Prototypes */
+/* GObject stuff */
+static void status_provider_mc5_class_init (StatusProviderMC5Class *klass);
+static void status_provider_mc5_init       (StatusProviderMC5 *self);
+static void status_provider_mc5_dispose    (GObject *object);
+static void status_provider_mc5_finalize   (GObject *object);
+/* Internal Funcs */
+static void set_status (StatusProvider * sp, StatusProviderStatus status);
+static StatusProviderStatus get_status (StatusProvider * sp);
+static void presence_changed (TpAccountManager * eam, guint type, const gchar * type_str, const gchar * message, StatusProviderMC5 * sp);
+static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderMC5 * self);
+static void mc5_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata);
+
+G_DEFINE_TYPE (StatusProviderMC5, status_provider_mc5, STATUS_PROVIDER_TYPE);
+
+STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_MC5_TYPE)
+
+/* Create the class.  We over ride a few functions but nothing
+   really shocking.  Most interesting is the set and get status. */
+static void
+status_provider_mc5_class_init (StatusProviderMC5Class *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (StatusProviderMC5Private));
+
+	object_class->dispose = status_provider_mc5_dispose;
+	object_class->finalize = status_provider_mc5_finalize;
+
+	StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass);
+
+	spclass->set_status = set_status;
+	spclass->get_status = get_status;
+
+	return;
+}
+
+/* Build our telepathy account manager instance if we don't
+   have one. */
+static void
+build_eam (StatusProviderMC5 * self)
+{
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self);
+
+	if (priv->manager != NULL) {
+		return;
+	}
+
+	priv->manager = tp_account_manager_dup();
+	g_signal_connect(G_OBJECT(priv->manager), "most-available-presence-changed", G_CALLBACK(presence_changed), self);
+
+	return;
+}
+
+/* Creating an instance of the status provider.  We set the variables
+   and create an TpAccountManager object.  It does all the hard
+   work in this module of tracking MissionControl and enumerating the
+   accounts and all that jazz. */
+static void
+status_provider_mc5_init (StatusProviderMC5 *self)
+{
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self);
+
+	priv->status = STATUS_PROVIDER_STATUS_DISCONNECTED;
+	priv->manager = NULL;
+
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this,
+	                                  all non-DBus stuff should be done */
+
+	GError * error = NULL;
+
+	/* Set up the dbus Proxy */
+	priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                                    DBUS_SERVICE_DBUS,
+	                                                    DBUS_PATH_DBUS,
+	                                                    DBUS_INTERFACE_DBUS,
+	                                                    &error);
+	if (error != NULL) {
+		g_warning("Unable to connect to DBus events: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Configure the name owner changing */
+	dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+							G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_CALLBACK(dbus_namechange),
+	                        self, NULL);
+
+	org_freedesktop_DBus_name_has_owner_async(priv->dbus_proxy, MC5_WELL_KNOWN_NAME, mc5_exists_cb, self);
+
+	return;
+}
+
+/* Unref the account manager and move on.  Sadly, we're
+   leaving the show. */
+static void
+status_provider_mc5_dispose (GObject *object)
+{
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(object);
+
+	if (priv->manager != NULL) {
+		g_object_unref(priv->manager);
+		priv->manager = NULL;
+	}
+
+	if (priv->dbus_proxy != NULL) {
+		g_object_unref(priv->dbus_proxy);
+		priv->dbus_proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (status_provider_mc5_parent_class)->dispose (object);
+	return;
+}
+
+/* Pass to superclass */
+static void
+status_provider_mc5_finalize (GObject *object)
+{
+
+	G_OBJECT_CLASS (status_provider_mc5_parent_class)->finalize (object);
+	return;
+}
+
+/* Watch for MC5 Coming on and off the bus. */
+static void
+dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderMC5 * self)
+{
+	/* g_debug("DBUS NAMECHANGE: %s %s %s", name, prev, new); */
+
+	if (prev[0] == '\0' && g_strcmp0(name, MC5_WELL_KNOWN_NAME) == 0) {
+		g_debug("MC5 Coming online");
+		build_eam(self);
+	}
+	if (new[0] == '\0' && g_strcmp0(name, MC5_WELL_KNOWN_NAME) == 0) {
+		g_debug("MC5 going offline");
+		StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(self);
+		if (priv->manager != NULL) {
+			g_object_unref(priv->manager);
+			priv->manager = NULL;
+		}
+
+		priv->status = STATUS_PROVIDER_STATUS_DISCONNECTED;
+		g_signal_emit(G_OBJECT(self), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, priv->status, TRUE);
+	}
+
+	return;
+}
+
+/* Callback for the Dbus command to do HasOwner on
+   the MC5 service.  If it exists, we want to have an
+   account manager. */
+static void
+mc5_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata)
+{
+	if (error) {
+		g_warning("Unable to check if MC5 is running: %s", error->message);
+		return;
+	}
+
+	if (exists) {
+		build_eam(STATUS_PROVIDER_MC5(userdata));
+	}
+
+	return;
+}
+
+/**
+	status_provider_mc5_new:
+
+	Creates a new #StatusProviderMC5 object.  No parameters or anything
+	like that.  Just a convience function.
+
+	Return value: A new instance of #StatusProviderMC5
+*/
+StatusProvider *
+status_provider_mc5_new (void)
+{
+	return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_MC5_TYPE, NULL));
+}
+
+/* Setting the status in the empathy account manager.  We're
+   basically requesting a global status.  This may or may not
+   get applied to all accounts.  It's really the best we can
+   hope to do. */
+static void
+set_status (StatusProvider * sp, StatusProviderStatus status)
+{
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp);
+
+	build_eam(STATUS_PROVIDER_MC5(sp));
+	tp_account_manager_set_all_requested_presences(priv->manager, sp_to_tp_map[status], sp_to_mc_map[status], "");
+
+	return;
+}
+
+/* Gets the status, uses the cached value that we have.  Asking
+   would just be painful. */
+static StatusProviderStatus
+get_status (StatusProvider * sp)
+{
+	g_return_val_if_fail(IS_STATUS_PROVIDER_MC5(sp), STATUS_PROVIDER_STATUS_DISCONNECTED);
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp);
+
+	if (priv->manager == NULL) {
+		return STATUS_PROVIDER_STATUS_DISCONNECTED;
+	}
+
+	return priv->status;
+}
+
+/* A signal handler for when the TpAccountManager believes
+   that the global status has changed.  It roughly calculates this
+   by finding the most available of all accounts that are active. */
+static void
+presence_changed (TpAccountManager * eam, guint type, const gchar * type_str, const gchar * message, StatusProviderMC5 * sp)
+{
+	StatusProviderMC5Private * priv = STATUS_PROVIDER_MC5_GET_PRIVATE(sp);
+
+	g_debug("MC5 Status changed: %d %s %s", type, type_str, message);
+
+	if (priv->status != tp_to_sp_map[type]) {
+		priv->status = tp_to_sp_map[type];
+		g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, priv->status, TRUE);
+	}
+
+	return;
+}
+

=== added file 'src/status-provider-mc5.h'
--- src/status-provider-mc5.h	1970-01-01 00:00:00 +0000
+++ src/status-provider-mc5.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,56 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_PROVIDER_MC5_H__
+#define __STATUS_PROVIDER_MC5_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "status-provider.h"
+
+G_BEGIN_DECLS
+
+#define STATUS_PROVIDER_MC5_TYPE            (status_provider_mc5_get_type ())
+#define STATUS_PROVIDER_MC5(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5))
+#define STATUS_PROVIDER_MC5_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Class))
+#define IS_STATUS_PROVIDER_MC5(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_MC5_TYPE))
+#define IS_STATUS_PROVIDER_MC5_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_MC5_TYPE))
+#define STATUS_PROVIDER_MC5_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_MC5_TYPE, StatusProviderMC5Class))
+
+
+typedef struct _StatusProviderMC5Class StatusProviderMC5Class;
+struct _StatusProviderMC5Class {
+	StatusProviderClass parent_class;
+};
+
+typedef struct _StatusProviderMC5      StatusProviderMC5;
+struct _StatusProviderMC5 {
+	StatusProvider parent;
+};
+
+GType status_provider_mc5_get_type (void);
+StatusProvider * status_provider_mc5_new (void);
+
+G_END_DECLS
+
+#endif

=== added file 'src/status-provider-mc5.list'
--- src/status-provider-mc5.list	1970-01-01 00:00:00 +0000
+++ src/status-provider-mc5.list	2011-07-13 20:27:12 +0000
@@ -0,0 +1,1 @@
+VOID:UINT,STRING

=== added file 'src/status-provider-pidgin.c'
--- src/status-provider-pidgin.c	1970-01-01 00:00:00 +0000
+++ src/status-provider-pidgin.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,433 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "status-provider.h"
+#include "status-provider-pidgin.h"
+#include "status-provider-pidgin-marshal.h"
+
+#include <dbus/dbus-glib.h>
+
+typedef enum {
+	PG_STATUS_UNKNOWN,
+	PG_STATUS_OFFLINE,
+	PG_STATUS_AVAILABLE,
+	PG_STATUS_UNAVAILABLE,
+	PG_STATUS_INVISIBLE,
+	PG_STATUS_AWAY,
+	PG_STATUS_EXTENDEND_AWAY,
+	PG_STATUS_MOBILE,
+	PG_STATUS_TUNE
+} pg_status_t;
+
+static const StatusProviderStatus pg_to_sp_map[] = {
+	/* PG_STATUS_UNKNOWN,        */   STATUS_PROVIDER_STATUS_OFFLINE,
+	/* PG_STATUS_OFFLINE,        */   STATUS_PROVIDER_STATUS_OFFLINE,
+	/* PG_STATUS_AVAILABLE,      */   STATUS_PROVIDER_STATUS_ONLINE,
+	/* PG_STATUS_UNAVAILABLE,    */   STATUS_PROVIDER_STATUS_DND,
+	/* PG_STATUS_INVISIBLE,      */   STATUS_PROVIDER_STATUS_INVISIBLE,
+	/* PG_STATUS_AWAY,           */   STATUS_PROVIDER_STATUS_AWAY,
+	/* PG_STATUS_EXTENDEND_AWAY, */   STATUS_PROVIDER_STATUS_AWAY,
+	/* PG_STATUS_MOBILE,         */   STATUS_PROVIDER_STATUS_OFFLINE,
+	/* PG_STATUS_TUNE            */   STATUS_PROVIDER_STATUS_OFFLINE
+};
+
+static const pg_status_t sp_to_pg_map[STATUS_PROVIDER_STATUS_LAST] = {
+	/* STATUS_PROVIDER_STATUS_ONLINE,  */  PG_STATUS_AVAILABLE,
+	/* STATUS_PROVIDER_STATUS_AWAY,    */  PG_STATUS_AWAY,
+	/* STATUS_PROVIDER_STATUS_DND      */  PG_STATUS_UNAVAILABLE,
+	/* STATUS_PROVIDER_STATUS_INVISIBLE*/  PG_STATUS_INVISIBLE,
+	/* STATUS_PROVIDER_STATUS_OFFLINE  */  PG_STATUS_OFFLINE,
+	/* STATUS_PROVIDER_STATUS_DISCONNECTED*/ PG_STATUS_OFFLINE
+};
+
+typedef struct _StatusProviderPidginPrivate StatusProviderPidginPrivate;
+struct _StatusProviderPidginPrivate {
+	DBusGProxy * proxy;
+	DBusGProxy * dbus_proxy;
+	pg_status_t  pg_status;
+};
+
+#define STATUS_PROVIDER_PIDGIN_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginPrivate))
+
+/* Prototypes */
+/* GObject stuff */
+static void status_provider_pidgin_class_init (StatusProviderPidginClass *klass);
+static void status_provider_pidgin_init       (StatusProviderPidgin *self);
+static void status_provider_pidgin_dispose    (GObject *object);
+static void status_provider_pidgin_finalize   (GObject *object);
+/* Internal Funcs */
+static void set_status (StatusProvider * sp, StatusProviderStatus status);
+static StatusProviderStatus get_status (StatusProvider * sp);
+static void setup_pidgin_proxy (StatusProviderPidgin * self);
+static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderPidgin * self);
+
+G_DEFINE_TYPE (StatusProviderPidgin, status_provider_pidgin, STATUS_PROVIDER_TYPE);
+
+STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_PIDGIN_TYPE)
+
+static void
+status_provider_pidgin_class_init (StatusProviderPidginClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (StatusProviderPidginPrivate));
+
+	object_class->dispose = status_provider_pidgin_dispose;
+	object_class->finalize = status_provider_pidgin_finalize;
+
+	StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass);
+
+	spclass->set_status = set_status;
+	spclass->get_status = get_status;
+
+	return;
+}
+
+static void
+type_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
+{
+	GError * error = NULL;
+	gint status = 0;
+	if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) {
+		g_warning("Unable to get type from Pidgin: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(userdata);
+	if (status != priv->pg_status) {
+		priv->pg_status = status;
+
+		g_signal_emit(G_OBJECT(userdata), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE);
+	}
+
+	return;
+}
+
+static void
+saved_status_to_type (StatusProviderPidgin * spp, gint savedstatus)
+{
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(spp);
+
+	g_debug("Pidgin figuring out type for %d", savedstatus);
+	dbus_g_proxy_begin_call(priv->proxy,
+	                        "PurpleSavedstatusGetType", type_cb, spp, NULL,
+	                        G_TYPE_INT, savedstatus, G_TYPE_INVALID);
+
+	return;
+}
+
+static void
+savedstatus_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
+{
+	GError * error = NULL;
+	gint status = 0;
+	if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INT, &status, G_TYPE_INVALID)) {
+		g_warning("Unable to get saved status from Pidgin: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	saved_status_to_type(STATUS_PROVIDER_PIDGIN(userdata), status);
+	return;
+}
+
+
+static void
+changed_status (DBusGProxy * proxy, gint savedstatus, GError ** error, StatusProviderPidgin * spp)
+{
+	saved_status_to_type(spp, savedstatus);
+	return;
+}
+
+static void
+proxy_destroy (DBusGProxy * proxy, StatusProviderPidgin * spp)
+{
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(spp);
+
+	priv->proxy = NULL;
+	priv->pg_status = PG_STATUS_OFFLINE;
+
+	g_signal_emit(G_OBJECT(spp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE);
+	return;
+}
+
+static void
+status_provider_pidgin_init (StatusProviderPidgin *self)
+{
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(self);
+
+	priv->proxy = NULL;
+	priv->pg_status = PG_STATUS_OFFLINE;
+
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this,
+	                                  all non-DBus stuff should be done */
+
+	GError * error = NULL;
+
+	/* Set up the dbus Proxy */
+	priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                                    DBUS_SERVICE_DBUS,
+	                                                    DBUS_PATH_DBUS,
+	                                                    DBUS_INTERFACE_DBUS,
+	                                                    &error);
+	if (error != NULL) {
+		g_warning("Unable to connect to DBus events: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Configure the name owner changing */
+	dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+							G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_CALLBACK(dbus_namechange),
+	                        self, NULL);
+
+	setup_pidgin_proxy(self);
+
+	return;
+}
+
+/* Watch to see if the Pidgin comes up on Dbus */
+static void
+dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderPidgin * self)
+{
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(new != NULL);
+
+	if (g_strcmp0(name, "im.pidgin.purple.PurpleService") == 0) {
+		setup_pidgin_proxy(self);
+	}
+	return;
+}
+
+/* Setup the Pidgin proxy so that we can talk to it
+   and get signals from it.  */
+static void
+setup_pidgin_proxy (StatusProviderPidgin * self)
+{
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(self);
+
+	if (priv->proxy != NULL) {
+		g_debug("Odd, we were asked to set up a Pidgin proxy when we already had one.");
+		return;
+	}
+
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_return_if_fail(bus != NULL); /* Can't do anymore DBus stuff without this,
+	                                  all non-DBus stuff should be done */
+
+	GError * error = NULL;
+
+	/* Set up the Pidgin Proxy */
+	priv->proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                               "im.pidgin.purple.PurpleService",
+	                                               "/im/pidgin/purple/PurpleObject",
+	                                               "im.pidgin.purple.PurpleInterface",
+	                                               &error);
+	/* Report any errors */
+	if (error != NULL) {
+		g_debug("Unable to get Pidgin proxy: %s", error->message);
+		g_error_free(error);
+	}
+
+	/* If we have a proxy, let's start using it */
+	if (priv->proxy != NULL) {
+		/* Set the proxy to NULL if it's destroyed */
+		g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy);
+		/* If it's destroyed, let's clean up as well */
+		g_signal_connect(G_OBJECT(priv->proxy), "destroy",
+		                 G_CALLBACK(proxy_destroy), self);
+
+		/* Watching for the status change coming from the
+		   Pidgin side of things. */
+		g_debug("Adding Pidgin Signals");
+		dbus_g_object_register_marshaller(_status_provider_pidgin_marshal_VOID__INT_INT,
+		                            G_TYPE_NONE,
+		                            G_TYPE_INT,
+		                            G_TYPE_INT,
+		                            G_TYPE_INVALID);
+		dbus_g_proxy_add_signal    (priv->proxy,
+		                            "SavedstatusChanged",
+		                            G_TYPE_INT,
+		                            G_TYPE_INT,
+		                            G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal(priv->proxy,
+		                            "SavedstatusChanged",
+		                            G_CALLBACK(changed_status),
+		                            (void *)self,
+		                            NULL);
+
+		/* Get the current status to update our cached
+		   value of the status. */
+		dbus_g_proxy_begin_call(priv->proxy,
+		                        "PurpleSavedstatusGetCurrent",
+		                        savedstatus_cb,
+		                        self,
+		                        NULL,
+		                        G_TYPE_INVALID);
+	}
+
+	return;
+}
+
+static void
+status_provider_pidgin_dispose (GObject *object)
+{
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(object);
+
+	if (priv->proxy != NULL) {
+		g_object_unref(priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (status_provider_pidgin_parent_class)->dispose (object);
+	return;
+}
+
+static void
+status_provider_pidgin_finalize (GObject *object)
+{
+
+	G_OBJECT_CLASS (status_provider_pidgin_parent_class)->finalize (object);
+	return;
+}
+
+/**
+	status_provider_pidgin_new:
+
+	Creates a new #StatusProviderPidgin object.  No parameters or anything
+	like that.  Just a convience function.
+
+	Return value: A new instance of #StatusProviderPidgin
+*/
+StatusProvider *
+status_provider_pidgin_new (void)
+{
+	return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_PIDGIN_TYPE, NULL));
+}
+
+/* Takes the status provided generically for Status providers
+   and turns it into a Pidgin status and sends it to Pidgin. */
+static void
+set_status (StatusProvider * sp, StatusProviderStatus status)
+{
+	gchar * message = "";
+
+	g_return_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp));
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp);
+
+	g_debug("\tPidgin set status to %d", status);
+	if (priv->proxy == NULL) {
+		return;
+	}
+
+	priv->pg_status = sp_to_pg_map[status];
+	gint status_val = 0;
+	gboolean ret = FALSE;
+	GError * error = NULL;
+
+	ret = dbus_g_proxy_call(priv->proxy,
+	                        "PurpleSavedstatusFindTransientByTypeAndMessage", &error,
+							G_TYPE_INT, priv->pg_status,
+							G_TYPE_STRING, message,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INT, &status_val,
+	                        G_TYPE_INVALID);
+
+	if (!ret) {
+		if (error != NULL) {
+			g_error_free(error);
+		}
+		error = NULL;
+		status_val = 0;
+		g_debug("No Pidgin saved status to apply");
+	}
+
+	if (status_val == 0) {
+		ret = dbus_g_proxy_call(priv->proxy,
+								"PurpleSavedstatusNew", &error,
+								G_TYPE_STRING, message,
+								G_TYPE_INT, priv->pg_status,
+								G_TYPE_INVALID,
+								G_TYPE_INT, &status_val,
+								G_TYPE_INVALID);
+
+		if (!ret) {
+			status_val = 0;
+			if (error != NULL) {
+				g_warning("Unable to create Pidgin status for %d: %s", status, error->message);
+				g_error_free(error);
+			} else {
+				g_warning("Unable to create Pidgin status for %d", status);
+			}
+			error = NULL;
+		}
+	}
+
+	if (status_val == 0) {
+		return;
+	}
+
+	ret = dbus_g_proxy_call(priv->proxy,
+	                        "PurpleSavedstatusActivate", &error,
+	                        G_TYPE_INT, status_val,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INVALID);
+
+	if (!ret) {
+		if (error != NULL) {
+			g_warning("Pidgin unable to change to status: %s", error->message);
+			g_error_free(error);
+		} else {
+			g_warning("Pidgin unable to change to status");
+		}
+		error = NULL;
+	}
+
+	g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, pg_to_sp_map[priv->pg_status], TRUE);
+	return;
+}
+
+/* Takes the cached Pidgin status and makes it into the generic
+   Status provider status.  If there is no Pidgin proxy then it
+   returns the disconnected state. */
+static StatusProviderStatus
+get_status (StatusProvider * sp)
+{
+	g_return_val_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp), STATUS_PROVIDER_STATUS_DISCONNECTED);
+	StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp);
+
+	if (priv->proxy == NULL) {
+		return STATUS_PROVIDER_STATUS_DISCONNECTED;
+	}
+
+	return pg_to_sp_map[priv->pg_status];
+}

=== added file 'src/status-provider-pidgin.h'
--- src/status-provider-pidgin.h	1970-01-01 00:00:00 +0000
+++ src/status-provider-pidgin.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,56 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_PROVIDER_PIDGIN_H__
+#define __STATUS_PROVIDER_PIDGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "status-provider.h"
+
+G_BEGIN_DECLS
+
+#define STATUS_PROVIDER_PIDGIN_TYPE            (status_provider_pidgin_get_type ())
+#define STATUS_PROVIDER_PIDGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidgin))
+#define STATUS_PROVIDER_PIDGIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass))
+#define IS_STATUS_PROVIDER_PIDGIN(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_PIDGIN_TYPE))
+#define IS_STATUS_PROVIDER_PIDGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_PIDGIN_TYPE))
+#define STATUS_PROVIDER_PIDGIN_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass))
+
+
+typedef struct _StatusProviderPidginClass StatusProviderPidginClass;
+struct _StatusProviderPidginClass {
+	StatusProviderClass parent_class;
+};
+
+typedef struct _StatusProviderPidgin      StatusProviderPidgin;
+struct _StatusProviderPidgin {
+	StatusProvider parent;
+};
+
+GType status_provider_pidgin_get_type (void);
+StatusProvider * status_provider_pidgin_new (void);
+
+G_END_DECLS
+
+#endif

=== added file 'src/status-provider-pidgin.list'
--- src/status-provider-pidgin.list	1970-01-01 00:00:00 +0000
+++ src/status-provider-pidgin.list	2011-07-13 20:27:12 +0000
@@ -0,0 +1,1 @@
+VOID:INT,INT

=== added file 'src/status-provider-telepathy.c'
--- src/status-provider-telepathy.c	1970-01-01 00:00:00 +0000
+++ src/status-provider-telepathy.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,385 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "status-provider.h"
+#include "status-provider-telepathy.h"
+#include "status-provider-telepathy-marshal.h"
+
+#include <dbus/dbus-glib.h>
+
+typedef enum {
+	MC_STATUS_UNSET,
+	MC_STATUS_OFFLINE,
+	MC_STATUS_AVAILABLE,
+	MC_STATUS_AWAY,
+	MC_STATUS_EXTENDED_AWAY,
+	MC_STATUS_HIDDEN,
+	MC_STATUS_DND
+} mc_status_t;
+
+static StatusProviderStatus mc_to_sp_map[] = {
+	/* MC_STATUS_UNSET,         */  STATUS_PROVIDER_STATUS_OFFLINE,
+	/* MC_STATUS_OFFLINE,       */  STATUS_PROVIDER_STATUS_OFFLINE,
+	/* MC_STATUS_AVAILABLE,     */  STATUS_PROVIDER_STATUS_ONLINE,
+	/* MC_STATUS_AWAY,          */  STATUS_PROVIDER_STATUS_AWAY,
+	/* MC_STATUS_EXTENDED_AWAY, */  STATUS_PROVIDER_STATUS_AWAY,
+	/* MC_STATUS_HIDDEN,        */  STATUS_PROVIDER_STATUS_INVISIBLE,
+	/* MC_STATUS_DND            */  STATUS_PROVIDER_STATUS_DND
+};
+
+static mc_status_t sp_to_mc_map[] = {
+	/* STATUS_PROVIDER_STATUS_ONLINE,  */  MC_STATUS_AVAILABLE,
+	/* STATUS_PROVIDER_STATUS_AWAY,    */  MC_STATUS_AWAY,
+	/* STATUS_PROVIDER_STATUS_DND      */  MC_STATUS_DND,
+	/* STATUS_PROVIDER_STATUS_INVISIBLE*/  MC_STATUS_HIDDEN,
+	/* STATUS_PROVIDER_STATUS_OFFLINE  */  MC_STATUS_OFFLINE,
+	/* STATUS_PROVIDER_STATUS_DISCONNECTED*/MC_STATUS_OFFLINE
+};
+
+typedef struct _StatusProviderTelepathyPrivate StatusProviderTelepathyPrivate;
+struct _StatusProviderTelepathyPrivate {
+	DBusGProxy * proxy;
+	DBusGProxy * dbus_proxy;
+	mc_status_t  mc_status;
+};
+
+#define STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyPrivate))
+
+/* Prototypes */
+/* GObject stuff */
+static void status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass);
+static void status_provider_telepathy_init       (StatusProviderTelepathy *self);
+static void status_provider_telepathy_dispose    (GObject *object);
+static void status_provider_telepathy_finalize   (GObject *object);
+/* Internal Funcs */
+static void build_telepathy_proxy (StatusProviderTelepathy * self);
+static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderTelepathy * self);
+static void set_status (StatusProvider * sp, StatusProviderStatus status);
+static StatusProviderStatus get_status (StatusProvider * sp);
+static void changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp);
+static void proxy_destroy (DBusGProxy * proxy, StatusProvider * sp);
+static void get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata);
+
+G_DEFINE_TYPE (StatusProviderTelepathy, status_provider_telepathy, STATUS_PROVIDER_TYPE);
+
+STATUS_PROVIDER_EXPORT_TYPE(STATUS_PROVIDER_TELEPATHY_TYPE)
+
+static void
+status_provider_telepathy_class_init (StatusProviderTelepathyClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (StatusProviderTelepathyPrivate));
+
+	object_class->dispose = status_provider_telepathy_dispose;
+	object_class->finalize = status_provider_telepathy_finalize;
+
+	StatusProviderClass * spclass = STATUS_PROVIDER_CLASS(klass);
+
+	spclass->set_status = set_status;
+	spclass->get_status = get_status;
+
+	return;
+}
+
+
+static void
+status_provider_telepathy_init (StatusProviderTelepathy *self)
+{
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(self);
+
+	priv->proxy = NULL;
+	priv->dbus_proxy = NULL;
+	priv->mc_status = MC_STATUS_OFFLINE;
+
+	GError * error = NULL;
+
+	/* Grabbing the session bus */
+	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+	if (bus == NULL) {
+		g_warning("Unable to connect to Session Bus: %s", error == NULL ? "No message" : error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Set up the dbus Proxy */
+	priv->dbus_proxy = dbus_g_proxy_new_for_name_owner (bus,
+	                                                    DBUS_SERVICE_DBUS,
+	                                                    DBUS_PATH_DBUS,
+	                                                    DBUS_INTERFACE_DBUS,
+	                                                    &error);
+	if (error != NULL) {
+		g_warning("Unable to connect to DBus events: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Configure the name owner changing */
+	dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+							G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
+	                        G_CALLBACK(dbus_namechange),
+	                        self, NULL);
+
+	build_telepathy_proxy(self);
+
+	return;
+}
+
+/* Builds up the proxy to Mission Control and configures all of the
+   signals for getting info from the proxy.  Also does a call to get
+   the inital value of the status. */
+static void
+build_telepathy_proxy (StatusProviderTelepathy * self)
+{
+	g_debug("Building Telepathy Proxy");
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(self);
+
+	if (priv->proxy != NULL) {
+		g_debug("Hmm, being asked to build a proxy we alredy have.");
+		return;
+	}
+
+	GError * error = NULL;
+
+	/* Grabbing the session bus */
+	DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+	if (session_bus == NULL) {
+		g_warning("Unable to connect to Session Bus: %s", error == NULL ? "No message" : error->message);
+		g_error_free(error);
+		return;
+	}
+
+	/* Get the proxy to Mission Control */
+	priv->proxy = dbus_g_proxy_new_for_name_owner(session_bus,
+	                         "org.freedesktop.Telepathy.MissionControl",
+	                        "/org/freedesktop/Telepathy/MissionControl",
+	                         "org.freedesktop.Telepathy.MissionControl",
+	                         &error);
+
+	if (priv->proxy != NULL) {
+		/* If it goes, we set the proxy to NULL */
+		g_object_add_weak_pointer (G_OBJECT(priv->proxy), (gpointer *)&priv->proxy);
+		/* And we clean up other variables associated */
+		g_signal_connect(G_OBJECT(priv->proxy), "destroy",
+		                 G_CALLBACK(proxy_destroy), self);
+
+		/* Set up the signal handler for watching when status changes. */
+		dbus_g_object_register_marshaller(_status_provider_telepathy_marshal_VOID__UINT_STRING,
+		                            G_TYPE_NONE,
+		                            G_TYPE_UINT,
+		                            G_TYPE_STRING,
+		                            G_TYPE_INVALID);
+		dbus_g_proxy_add_signal    (priv->proxy,
+		                            "PresenceChanged",
+		                            G_TYPE_UINT,
+		                            G_TYPE_STRING,
+		                            G_TYPE_INVALID);
+		dbus_g_proxy_connect_signal(priv->proxy,
+		                            "PresenceChanged",
+		                            G_CALLBACK(changed_status),
+		                            (void *)self,
+		                            NULL);
+
+		/* Do a get here, to init the status */
+		dbus_g_proxy_begin_call(priv->proxy,
+		                        "GetStatus",
+		                        get_status_async,
+		                        self,
+		                        NULL,
+		                        G_TYPE_INVALID);
+	} else {
+		g_warning("Unable to connect to Mission Control");
+		if (error != NULL) {
+			g_error_free(error);
+		}
+	}
+
+	return;
+}
+
+/* Watch to see if the Mission Control comes up on Dbus */
+static void
+dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, StatusProviderTelepathy * self)
+{
+	g_return_if_fail(name != NULL);
+	g_return_if_fail(new != NULL);
+
+	if (g_strcmp0(name, "org.freedesktop.Telepathy.MissionControl") == 0) {
+		build_telepathy_proxy(self);
+	}
+	return;
+}
+
+static void
+status_provider_telepathy_dispose (GObject *object)
+{
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(object);
+
+	if (priv->proxy != NULL) {
+		g_object_unref(priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (status_provider_telepathy_parent_class)->dispose (object);
+	return;
+}
+
+static void
+status_provider_telepathy_finalize (GObject *object)
+{
+
+	G_OBJECT_CLASS (status_provider_telepathy_parent_class)->finalize (object);
+	return;
+}
+
+/**
+	status_provider_telepathy_new:
+
+	Creates a new #StatusProviderTelepathy object.  No parameters or anything
+	like that.  Just a convience function.
+
+	Return value: A new instance of #StatusProviderTelepathy
+*/
+StatusProvider *
+status_provider_telepathy_new (void)
+{
+	return STATUS_PROVIDER(g_object_new(STATUS_PROVIDER_TELEPATHY_TYPE, NULL));
+}
+
+static void
+set_status (StatusProvider * sp, StatusProviderStatus status)
+{
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
+	if (priv->proxy == NULL) {
+		priv->mc_status = MC_STATUS_OFFLINE;
+		return;
+	}
+
+	priv->mc_status = sp_to_mc_map[status];	
+
+	guint mcstatus = MC_STATUS_UNSET;
+	gboolean ret = FALSE;
+	GError * error = NULL;
+
+	ret = dbus_g_proxy_call(priv->proxy,
+	                        "GetPresence", &error,
+	                        G_TYPE_INVALID,
+	                        G_TYPE_UINT, &priv->mc_status,
+	                        G_TYPE_INVALID);
+
+	/* If we can't get the  get call to work, let's not set */
+	if (!ret) {
+		if (error != NULL) {
+			g_error_free(error);
+		}
+		return;
+	}
+	
+	/* If the get call doesn't return a status, that means that there
+	   are no clients connected.  We don't want to connect them by telling
+	   MC that we're going online -- we'd like to be more passive than that. */
+	if (mcstatus == MC_STATUS_UNSET) {
+		return;
+	}
+
+	ret = dbus_g_proxy_call(priv->proxy,
+	                        "SetPresence", &error,
+	                        G_TYPE_UINT, priv->mc_status,
+	                        G_TYPE_STRING, "",
+	                        G_TYPE_INVALID,
+	                        G_TYPE_INVALID);
+
+	if (!ret) {
+		if (error != NULL) {
+			g_warning("Unable to set Mission Control Presence: %s", error->message);
+			g_error_free(error);
+		} else {
+			g_warning("Unable to set Mission Control Presence");
+		}
+		return;
+	}
+
+	return;
+}
+
+static StatusProviderStatus
+get_status (StatusProvider * sp)
+{
+	g_return_val_if_fail(IS_STATUS_PROVIDER_TELEPATHY(sp), STATUS_PROVIDER_STATUS_DISCONNECTED);
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
+
+	if (priv->proxy == NULL) {
+		return STATUS_PROVIDER_STATUS_DISCONNECTED;
+	}
+
+	return mc_to_sp_map[priv->mc_status];
+}
+
+static void
+changed_status (DBusGProxy * proxy, guint status, gchar * message, StatusProvider * sp)
+{
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(sp);
+	priv->mc_status = status;
+	g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE);
+}
+
+static void
+proxy_destroy (DBusGProxy * proxy, StatusProvider * sp)
+{
+	g_debug("Signal: Mission Control proxy destroyed");
+	g_signal_emit(G_OBJECT(sp), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, STATUS_PROVIDER_STATUS_OFFLINE, TRUE);
+	return;
+}
+
+static void
+get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
+{
+	GError * error = NULL;
+	guint status = 0;
+	if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_UINT, &status, G_TYPE_INVALID)) {
+		g_warning("Unable to get type from Mission Control: %s", error->message);
+		g_error_free(error);
+		return;
+	}
+
+	StatusProviderTelepathyPrivate * priv = STATUS_PROVIDER_TELEPATHY_GET_PRIVATE(userdata);
+
+	gboolean changed = FALSE;
+	if (status != priv->mc_status) {
+		changed = TRUE;
+	}
+
+	priv->mc_status = status;
+
+	if (changed) {
+		g_signal_emit(G_OBJECT(userdata), STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID, 0, mc_to_sp_map[priv->mc_status], TRUE);
+	}
+
+	return;
+}

=== added file 'src/status-provider-telepathy.h'
--- src/status-provider-telepathy.h	1970-01-01 00:00:00 +0000
+++ src/status-provider-telepathy.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,56 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_PROVIDER_TELEPATHY_H__
+#define __STATUS_PROVIDER_TELEPATHY_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "status-provider.h"
+
+G_BEGIN_DECLS
+
+#define STATUS_PROVIDER_TELEPATHY_TYPE            (status_provider_telepathy_get_type ())
+#define STATUS_PROVIDER_TELEPATHY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathy))
+#define STATUS_PROVIDER_TELEPATHY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyClass))
+#define IS_STATUS_PROVIDER_TELEPATHY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_TELEPATHY_TYPE))
+#define IS_STATUS_PROVIDER_TELEPATHY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_TELEPATHY_TYPE))
+#define STATUS_PROVIDER_TELEPATHY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_TELEPATHY_TYPE, StatusProviderTelepathyClass))
+
+
+typedef struct _StatusProviderTelepathyClass StatusProviderTelepathyClass;
+struct _StatusProviderTelepathyClass {
+	StatusProviderClass parent_class;
+};
+
+typedef struct _StatusProviderTelepathy      StatusProviderTelepathy;
+struct _StatusProviderTelepathy {
+	StatusProvider parent;
+};
+
+GType status_provider_telepathy_get_type (void);
+StatusProvider * status_provider_telepathy_new (void);
+
+G_END_DECLS
+
+#endif

=== added file 'src/status-provider-telepathy.list'
--- src/status-provider-telepathy.list	1970-01-01 00:00:00 +0000
+++ src/status-provider-telepathy.list	2011-07-13 20:27:12 +0000
@@ -0,0 +1,1 @@
+VOID:UINT,STRING

=== added file 'src/status-provider.c'
--- src/status-provider.c	1970-01-01 00:00:00 +0000
+++ src/status-provider.c	2011-07-13 20:27:12 +0000
@@ -0,0 +1,101 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "status-provider.h"
+
+/* Signals */
+enum {
+	STATUS_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* GObject Boilerplate */
+static void status_provider_class_init (StatusProviderClass *klass);
+static void status_provider_init       (StatusProvider *self);
+
+G_DEFINE_TYPE (StatusProvider, status_provider, G_TYPE_OBJECT);
+
+static void
+status_provider_class_init (StatusProviderClass *klass)
+{
+	// GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	klass->status_changed = NULL;
+
+	klass->set_status = NULL;
+	klass->get_status = NULL;
+
+	/**
+		StatusProvider::status-changed:
+		@arg0: The #StatusProvider object.
+		@arg1: The new status #StatusProviderStatus
+
+		Should be emitted by subclasses everytime that the status
+		changes externally to us.
+	*/
+	signals[STATUS_CHANGED]    = g_signal_new(STATUS_PROVIDER_SIGNAL_STATUS_CHANGED,
+	                                          G_TYPE_FROM_CLASS(klass),
+	                                          G_SIGNAL_RUN_LAST,
+	                                          G_STRUCT_OFFSET(StatusProviderClass, status_changed),
+	                                          NULL, NULL,
+	                                          g_cclosure_marshal_VOID__UINT,
+	                                          G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	return;
+}
+
+static void
+status_provider_init (StatusProvider *self)
+{
+
+	return;
+}
+
+void
+status_provider_set_status (StatusProvider * sp, StatusProviderStatus status)
+{
+	g_return_if_fail(IS_STATUS_PROVIDER(sp));
+
+	StatusProviderClass * class = STATUS_PROVIDER_GET_CLASS(sp);
+	g_return_if_fail(class != NULL);
+	g_return_if_fail(class->set_status != NULL);
+
+	return class->set_status(sp, status);
+}
+
+StatusProviderStatus
+status_provider_get_status (StatusProvider * sp)
+{
+	g_return_val_if_fail(IS_STATUS_PROVIDER(sp), STATUS_PROVIDER_STATUS_OFFLINE);
+
+	StatusProviderClass * class = STATUS_PROVIDER_GET_CLASS(sp);
+	g_return_val_if_fail(class->get_status != NULL, STATUS_PROVIDER_STATUS_OFFLINE);
+
+	return class->get_status(sp);
+}
+

=== added file 'src/status-provider.h'
--- src/status-provider.h	1970-01-01 00:00:00 +0000
+++ src/status-provider.h	2011-07-13 20:27:12 +0000
@@ -0,0 +1,81 @@
+/*
+A small wrapper utility to load indicators and put them as menu items
+into the gnome-panel using it's applet interface.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+This program is free software: you can redistribute it and/or modify it 
+under the terms of the GNU General Public License version 3, as published 
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but 
+WITHOUT ANY WARRANTY; without even the implied warranties of 
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
+PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along 
+with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __STATUS_PROVIDER_H__
+#define __STATUS_PROVIDER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define STATUS_PROVIDER_EXPORT_TYPE(x)  GType status_provider_export_type (void) { return (x); }
+#define STATUS_PROVIDER_EXPORT_S             "status_provider_export_type"
+
+#define STATUS_PROVIDER_TYPE            (status_provider_get_type ())
+#define STATUS_PROVIDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_TYPE, StatusProvider))
+#define STATUS_PROVIDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_TYPE, StatusProviderClass))
+#define IS_STATUS_PROVIDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_TYPE))
+#define IS_STATUS_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_TYPE))
+#define STATUS_PROVIDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_TYPE, StatusProviderClass))
+
+typedef enum
+{
+  STATUS_PROVIDER_STATUS_ONLINE,
+  STATUS_PROVIDER_STATUS_AWAY,
+  STATUS_PROVIDER_STATUS_DND,
+  STATUS_PROVIDER_STATUS_INVISIBLE,
+  STATUS_PROVIDER_STATUS_OFFLINE,
+  STATUS_PROVIDER_STATUS_DISCONNECTED,
+  /* Leave as last */
+  STATUS_PROVIDER_STATUS_LAST
+}
+StatusProviderStatus;
+
+#define STATUS_PROVIDER_SIGNAL_STATUS_CHANGED     "status-changed"
+#define STATUS_PROVIDER_SIGNAL_STATUS_CHANGED_ID  (g_signal_lookup(STATUS_PROVIDER_SIGNAL_STATUS_CHANGED, STATUS_PROVIDER_TYPE))
+
+typedef struct _StatusProvider      StatusProvider;
+struct _StatusProvider {
+	GObject parent;
+};
+
+typedef struct _StatusProviderClass StatusProviderClass;
+struct _StatusProviderClass {
+	GObjectClass parent_class;
+
+	/* Signals */
+	void (*status_changed) (StatusProviderStatus newstatus);
+
+	/* Virtual Functions */
+	void  (*set_status) (StatusProvider * sp, StatusProviderStatus newstatus);
+	StatusProviderStatus (*get_status) (StatusProvider * sp);
+};
+
+GType status_provider_get_type (void);
+
+void status_provider_set_status (StatusProvider * sp, StatusProviderStatus status);
+StatusProviderStatus status_provider_get_status (StatusProvider * sp);
+
+G_END_DECLS
+
+#endif


Follow ups