From c6055d45604745ac063db2d1daf8207df5c7fad5 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 22 Jun 2011 15:42:44 -0500 Subject: Stealing all of the status providers from indicator-me so that we can use them here. --- .bzrignore | 18 ++ configure.ac | 22 ++ src/Makefile.am | 159 +++++++++++++- src/status-provider-emesene.c | 344 +++++++++++++++++++++++++++++ src/status-provider-emesene.h | 56 +++++ src/status-provider-mc5.c | 306 ++++++++++++++++++++++++++ src/status-provider-mc5.h | 56 +++++ src/status-provider-mc5.list | 1 + src/status-provider-pidgin.c | 431 +++++++++++++++++++++++++++++++++++++ src/status-provider-pidgin.h | 56 +++++ src/status-provider-pidgin.list | 1 + src/status-provider-telepathy.c | 383 ++++++++++++++++++++++++++++++++ src/status-provider-telepathy.h | 56 +++++ src/status-provider-telepathy.list | 1 + src/status-provider.c | 101 +++++++++ src/status-provider.h | 78 +++++++ 16 files changed, 2063 insertions(+), 6 deletions(-) create mode 100644 src/status-provider-emesene.c create mode 100644 src/status-provider-emesene.h create mode 100644 src/status-provider-mc5.c create mode 100644 src/status-provider-mc5.h create mode 100644 src/status-provider-mc5.list create mode 100644 src/status-provider-pidgin.c create mode 100644 src/status-provider-pidgin.h create mode 100644 src/status-provider-pidgin.list create mode 100644 src/status-provider-telepathy.c create mode 100644 src/status-provider-telepathy.h create mode 100644 src/status-provider-telepathy.list create mode 100644 src/status-provider.c create mode 100644 src/status-provider.h diff --git a/.bzrignore b/.bzrignore index f48929a..0a7a2b6 100644 --- a/.bzrignore +++ b/.bzrignore @@ -25,3 +25,21 @@ po/indicator-messages.pot 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 diff --git a/configure.ac b/configure.ac index 781d650..9638b7e 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,28 @@ AS_IF([test "x$with_indicator_gtk" = x3], AC_SUBST(APPLET_CFLAGS) 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 ########################### diff --git a/src/Makefile.am b/src/Makefile.am index 8597d77..8e4f170 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,14 @@ +BUILT_SOURCES = +EXTRA_DIST = + libexec_PROGRAMS = indicator-messages-service +STATUS_PROVIDER_API_VERSION = 1 +STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION)/ +statusprovidersdir = $(STATUS_PROVIDER_DIR) +statusproviders_LTLIBRARIES = + ###################################### # Building the messages indicator ###################################### @@ -44,7 +52,11 @@ indicator_messages_service_SOURCES = \ seen-db.c \ seen-db.h \ dirs.h \ - dbus-data.h + dbus-data.h \ + \ + status-provider.c \ + status-provider.h + indicator_messages_service_CFLAGS = \ $(APPLET_CFLAGS) \ -Wall \ @@ -52,7 +64,9 @@ indicator_messages_service_CFLAGS = \ -Wl,-z,defs \ -Wl,--as-needed \ -Werror \ - -DG_LOG_DOMAIN=\"Indicator-Messages\" + -DG_LOG_DOMAIN=\"Indicator-Messages\" \ + -DSTAUTS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" + indicator_messages_service_LDADD = $(APPLET_LIBS) gen-%.xml.h: %.xml @@ -65,13 +79,146 @@ gen-%.xml.c: %.xml @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ @echo ";" >> $@ -BUILT_SOURCES = \ +BUILT_SOURCES += \ gen-messages-service.xml.h \ gen-messages-service.xml.c +EXTRA_DIST += \ + messages-service.xml + +###################################### +# 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 = \ + $(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 = \ + $(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 = \ + $(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 = \ + $(APPLET_LIBS) \ + $(STATUS_PROVIDER_EMESENE_LIBS) +libemesene_la_LDFLAGS = -module -avoid-version + +###################################### +# Extras +###################################### + CLEANFILES = \ $(BUILT_SOURCES) -EXTRA_DIST = \ - messages-service.xml - diff --git a/src/status-provider-emesene.c b/src/status-provider-emesene.c new file mode 100644 index 0000000..ab75f68 --- /dev/null +++ b/src/status-provider-emesene.c @@ -0,0 +1,344 @@ +/* +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 + +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 . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "status-provider.h" +#include "status-provider-emesene.h" + +#include + +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); + +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]; +} diff --git a/src/status-provider-emesene.h b/src/status-provider-emesene.h new file mode 100644 index 0000000..2309684 --- /dev/null +++ b/src/status-provider-emesene.h @@ -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 + +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 . +*/ + +#ifndef __STATUS_PROVIDER_EMESENE_H__ +#define __STATUS_PROVIDER_EMESENE_H__ + +#include +#include + +#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 diff --git a/src/status-provider-mc5.c b/src/status-provider-mc5.c new file mode 100644 index 0000000..468c6e8 --- /dev/null +++ b/src/status-provider-mc5.c @@ -0,0 +1,306 @@ +/* +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 + +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 . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "status-provider.h" +#include "status-provider-mc5.h" +#include "status-provider-mc5-marshal.h" + +#include +#include + +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); + +/* 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; +} + diff --git a/src/status-provider-mc5.h b/src/status-provider-mc5.h new file mode 100644 index 0000000..4d5659d --- /dev/null +++ b/src/status-provider-mc5.h @@ -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 + +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 . +*/ + +#ifndef __STATUS_PROVIDER_MC5_H__ +#define __STATUS_PROVIDER_MC5_H__ + +#include +#include + +#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 diff --git a/src/status-provider-mc5.list b/src/status-provider-mc5.list new file mode 100644 index 0000000..5ab45bf --- /dev/null +++ b/src/status-provider-mc5.list @@ -0,0 +1 @@ +VOID:UINT,STRING diff --git a/src/status-provider-pidgin.c b/src/status-provider-pidgin.c new file mode 100644 index 0000000..3c0ca15 --- /dev/null +++ b/src/status-provider-pidgin.c @@ -0,0 +1,431 @@ +/* +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 + +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 . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "status-provider.h" +#include "status-provider-pidgin.h" +#include "status-provider-pidgin-marshal.h" + +#include + +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); + +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]; +} diff --git a/src/status-provider-pidgin.h b/src/status-provider-pidgin.h new file mode 100644 index 0000000..54b1718 --- /dev/null +++ b/src/status-provider-pidgin.h @@ -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 + +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 . +*/ + +#ifndef __STATUS_PROVIDER_PIDGIN_H__ +#define __STATUS_PROVIDER_PIDGIN_H__ + +#include +#include + +#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 diff --git a/src/status-provider-pidgin.list b/src/status-provider-pidgin.list new file mode 100644 index 0000000..1f953dd --- /dev/null +++ b/src/status-provider-pidgin.list @@ -0,0 +1 @@ +VOID:INT,INT diff --git a/src/status-provider-telepathy.c b/src/status-provider-telepathy.c new file mode 100644 index 0000000..f2815fb --- /dev/null +++ b/src/status-provider-telepathy.c @@ -0,0 +1,383 @@ +/* +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 + +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 . +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "status-provider.h" +#include "status-provider-telepathy.h" +#include "status-provider-telepathy-marshal.h" + +#include + +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); + +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; +} diff --git a/src/status-provider-telepathy.h b/src/status-provider-telepathy.h new file mode 100644 index 0000000..a67ee40 --- /dev/null +++ b/src/status-provider-telepathy.h @@ -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 + +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 . +*/ + +#ifndef __STATUS_PROVIDER_TELEPATHY_H__ +#define __STATUS_PROVIDER_TELEPATHY_H__ + +#include +#include + +#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 diff --git a/src/status-provider-telepathy.list b/src/status-provider-telepathy.list new file mode 100644 index 0000000..5ab45bf --- /dev/null +++ b/src/status-provider-telepathy.list @@ -0,0 +1 @@ +VOID:UINT,STRING diff --git a/src/status-provider.c b/src/status-provider.c new file mode 100644 index 0000000..1139e54 --- /dev/null +++ b/src/status-provider.c @@ -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 + +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 . +*/ + +#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); +} + diff --git a/src/status-provider.h b/src/status-provider.h new file mode 100644 index 0000000..a0e1c55 --- /dev/null +++ b/src/status-provider.h @@ -0,0 +1,78 @@ +/* +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 + +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 . +*/ + +#ifndef __STATUS_PROVIDER_H__ +#define __STATUS_PROVIDER_H__ + +#include +#include + +G_BEGIN_DECLS + +#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 -- cgit v1.2.3 From cc60029939b6e4128cd6f05b6b7d6657b1a319db Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 22 Jun 2011 16:14:50 -0500 Subject: Commenting out the main function to make it more explanitory --- src/messages-service.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/messages-service.c b/src/messages-service.c index e3352e8..25300ff 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -1437,8 +1437,10 @@ service_shutdown (IndicatorService * service, gpointer user_data) 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 +1450,39 @@ main (int argc, char ** argv) 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); + /* 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 */ g_free(userdir); return 0; -- cgit v1.2.3 From f1e975ba53b6bc180a0a55ef7db64c9371c15f44 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 28 Jun 2011 14:26:39 -0500 Subject: Adding in some helpers with building up all the status-items. --- src/Makefile.am | 2 ++ src/status-items.c | 10 ++++++++++ src/status-items.h | 14 ++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/status-items.c create mode 100644 src/status-items.h diff --git a/src/Makefile.am b/src/Makefile.am index 8e4f170..4f654da 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -54,6 +54,8 @@ indicator_messages_service_SOURCES = \ dirs.h \ dbus-data.h \ \ + status-items.c \ + status-items.h status-provider.c \ status-provider.h diff --git a/src/status-items.c b/src/status-items.c new file mode 100644 index 0000000..7cd9c21 --- /dev/null +++ b/src/status-items.c @@ -0,0 +1,10 @@ + +#include "status-items.h" + +GList * +status_items_build (void) +{ + + + return NULL; +} diff --git a/src/status-items.h b/src/status-items.h new file mode 100644 index 0000000..66844f4 --- /dev/null +++ b/src/status-items.h @@ -0,0 +1,14 @@ + +#ifndef __STATUS_ITEMS_H__ +#define __STATUS_ITEMS_H__ + +#include + +G_BEGIN_DECLS + +GList * status_items_build (void); + +G_END_DECLS + +#endif /* __STATUS_ITEMS_H__ */ + -- cgit v1.2.3 From 8ee9f55f2a83f92860a6998eedcd879e4ac737c4 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 28 Jun 2011 15:15:12 -0500 Subject: Getting some static data and using it a bit to boot strap this data --- src/status-items.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/status-items.h | 1 + 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/status-items.c b/src/status-items.c index 7cd9c21..c0f60cd 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -1,10 +1,81 @@ +#include +#include +#include + #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" +}; + +static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; +GList * menuitems = NULL; +/* Build the inital status items and start kicking off the async code + for handling all the statuses */ GList * status_items_build (void) { + 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]); - return NULL; + 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); + + menuitems = g_list_append(menuitems, item); + } + + return menuitems; +} + +/* 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]; + } } diff --git a/src/status-items.h b/src/status-items.h index 66844f4..686d03c 100644 --- a/src/status-items.h +++ b/src/status-items.h @@ -7,6 +7,7 @@ G_BEGIN_DECLS GList * status_items_build (void); +const gchar * status_current_panel_icon (gboolean alert); G_END_DECLS -- cgit v1.2.3 From 1ee7d8ddc51a65bb14f4a294abd7024fda5c11b3 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 28 Jun 2011 15:58:48 -0500 Subject: Adding in an idle function for handling the directory. --- src/Makefile.am | 2 +- src/status-items.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 4f654da..de4fccb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,7 @@ indicator_messages_service_CFLAGS = \ -Wl,--as-needed \ -Werror \ -DG_LOG_DOMAIN=\"Indicator-Messages\" \ - -DSTAUTS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" + -DSTATUS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" indicator_messages_service_LDADD = $(APPLET_LIBS) diff --git a/src/status-items.c b/src/status-items.c index c0f60cd..e5e0d71 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -42,6 +42,10 @@ static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = { /* STATUS_PROVIDER_STATUS_DISCONNECTED */ "indicator-messages-new-user-disconnected" }; +/* Prototypes */ +static gboolean provider_directory_parse (gpointer dir); + +/* Globals */ static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; GList * menuitems = NULL; @@ -66,6 +70,8 @@ status_items_build (void) menuitems = g_list_append(menuitems, item); } + g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR); + return menuitems; } @@ -79,3 +85,17 @@ status_current_panel_icon (gboolean alert) return panel_icons[current_status]; } } + +/* Start parsing a directory and setting up the entires in the idle loop */ +static gboolean +provider_directory_parse (gpointer directory) +{ + const gchar * dir = (const gchar *)directory; + + if (!g_file_test(dir, G_FILE_TEST_EXISTS)) { + return FALSE; + } + + + return FALSE; +} -- cgit v1.2.3 From 15468aef1b10907846c3a104c09ef4fb7addf9fd Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 28 Jun 2011 16:13:43 -0500 Subject: Turning a directory into a bunch of idles loading status providers --- src/status-items.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/status-items.c b/src/status-items.c index e5e0d71..885b2a7 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -1,6 +1,7 @@ #include #include +#include #include #include "status-items.h" @@ -44,6 +45,7 @@ static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = { /* Prototypes */ static gboolean provider_directory_parse (gpointer dir); +static gboolean load_status_provider (gpointer dir); /* Globals */ static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; @@ -90,12 +92,33 @@ status_current_panel_icon (gboolean alert) static gboolean provider_directory_parse (gpointer directory) { - const gchar * dir = (const gchar *)directory; + const gchar * dirname = (const gchar *)directory; - if (!g_file_test(dir, G_FILE_TEST_EXISTS)) { + 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) { + gchar * fullname = g_build_filename(dirname, name, NULL); + g_idle_add(load_status_provider, fullname); + } + + g_dir_close(dir); return FALSE; } + +/* Load a particular status provider */ +static gboolean +load_status_provider (gpointer dir) +{ + gchar * provider = (gchar *)dir; + g_free(provider); + return FALSE; +} -- cgit v1.2.3 From 48737cc43c2bbf9991a3d86889deaa482ab047c8 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 28 Jun 2011 18:29:18 -0500 Subject: Basic loadable modules --- src/status-items.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index 885b2a7..69d229f 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -50,6 +50,7 @@ static gboolean load_status_provider (gpointer dir); /* Globals */ static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; GList * menuitems = NULL; +GList * status_providers = NULL; /* Build the inital status items and start kicking off the async code for handling all the statuses */ @@ -119,6 +120,25 @@ 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_final; + } + + /* Got it */ + g_module_close(module); + +exit_final: g_free(provider); return FALSE; } -- cgit v1.2.3 From 4aad2ce250a7b7033745cbea39f6752d9b2092f7 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 06:16:50 -0500 Subject: Call the status items build function --- src/messages-service.c | 3 +++ src/status-items.c | 1 + 2 files changed, 4 insertions(+) diff --git a/src/messages-service.c b/src/messages-service.c index 25300ff..0db4a7e 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -40,6 +40,7 @@ with this program. If not, see . #include "dirs.h" #include "messages-service-dbus.h" #include "seen-db.h" +#include "status-items.h" static IndicatorService * service = NULL; static IndicateListener * listener = NULL; @@ -1461,6 +1462,8 @@ main (int argc, char ** argv) DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT); dbusmenu_server_set_root(server, root_menuitem); + status_items_build(); + /* Start up the libindicate listener */ listener = indicate_listener_ref_default(); serverList = NULL; diff --git a/src/status-items.c b/src/status-items.c index 69d229f..3e27529 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -94,6 +94,7 @@ 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; -- cgit v1.2.3 From d936a27b56706eb521f525970dedb63fe24c81bd Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 06:29:45 -0500 Subject: Insure we're only loading .so's --- src/status-items.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index 3e27529..5e8a07c 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -107,6 +107,10 @@ provider_directory_parse (gpointer directory) const gchar * name; while ((name = g_dir_read_name(dir)) != NULL) { + if (!g_str_has_suffix(name, ".so")) { + continue; + } + gchar * fullname = g_build_filename(dirname, name, NULL); g_idle_add(load_status_provider, fullname); } -- cgit v1.2.3 From 782c36c2ccf01dd0db6cbac8cc712cc316f23c90 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 07:15:22 -0500 Subject: Loading the modules and getting an object --- src/Makefile.am | 2 +- src/status-items.c | 26 ++++++++++++++++++++++++-- src/status-provider-emesene.c | 2 ++ src/status-provider-mc5.c | 2 ++ src/status-provider-pidgin.c | 2 ++ src/status-provider-telepathy.c | 2 ++ src/status-provider.h | 3 +++ 7 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index de4fccb..87f3c67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,7 +55,7 @@ indicator_messages_service_SOURCES = \ dbus-data.h \ \ status-items.c \ - status-items.h + status-items.h \ status-provider.c \ status-provider.h diff --git a/src/status-items.c b/src/status-items.c index 5e8a07c..eef240f 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -107,7 +107,7 @@ provider_directory_parse (gpointer directory) const gchar * name; while ((name = g_dir_read_name(dir)) != NULL) { - if (!g_str_has_suffix(name, ".so")) { + if (!g_str_has_suffix(name, G_MODULE_SUFFIX)) { continue; } @@ -137,10 +137,32 @@ load_status_provider (gpointer dir) 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_final; + 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; + } + + + goto exit_final; + +exit_module_fail: g_module_close(module); exit_final: diff --git a/src/status-provider-emesene.c b/src/status-provider-emesene.c index ab75f68..29a8a22 100644 --- a/src/status-provider-emesene.c +++ b/src/status-provider-emesene.c @@ -78,6 +78,8 @@ static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar 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) { diff --git a/src/status-provider-mc5.c b/src/status-provider-mc5.c index 468c6e8..e70496c 100644 --- a/src/status-provider-mc5.c +++ b/src/status-provider-mc5.c @@ -89,6 +89,8 @@ static void mc5_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, 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 diff --git a/src/status-provider-pidgin.c b/src/status-provider-pidgin.c index 3c0ca15..6c73d56 100644 --- a/src/status-provider-pidgin.c +++ b/src/status-provider-pidgin.c @@ -87,6 +87,8 @@ static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar 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) { diff --git a/src/status-provider-telepathy.c b/src/status-provider-telepathy.c index f2815fb..c8e89da 100644 --- a/src/status-provider-telepathy.c +++ b/src/status-provider-telepathy.c @@ -86,6 +86,8 @@ static void get_status_async (DBusGProxy * proxy, DBusGProxyCall * call, gpointe 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) { diff --git a/src/status-provider.h b/src/status-provider.h index a0e1c55..45433fc 100644 --- a/src/status-provider.h +++ b/src/status-provider.h @@ -28,6 +28,9 @@ with this program. If not, see . 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)) -- cgit v1.2.3 From 0b32b5d893fbd6685bb1b900d744a5d320796def Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 07:44:18 -0500 Subject: Breaking the status provider base objec out into it's own library --- src/Makefile.am | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 87f3c67..51551ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,10 +4,6 @@ EXTRA_DIST = libexec_PROGRAMS = indicator-messages-service -STATUS_PROVIDER_API_VERSION = 1 -STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION)/ -statusprovidersdir = $(STATUS_PROVIDER_DIR) -statusproviders_LTLIBRARIES = ###################################### # Building the messages indicator @@ -55,9 +51,7 @@ indicator_messages_service_SOURCES = \ dbus-data.h \ \ status-items.c \ - status-items.h \ - status-provider.c \ - status-provider.h + status-items.h indicator_messages_service_CFLAGS = \ $(APPLET_CFLAGS) \ @@ -69,7 +63,9 @@ indicator_messages_service_CFLAGS = \ -DG_LOG_DOMAIN=\"Indicator-Messages\" \ -DSTATUS_PROVIDER_DIR=\"$(STATUS_PROVIDER_DIR)\" -indicator_messages_service_LDADD = $(APPLET_LIBS) +indicator_messages_service_LDADD = \ + $(APPLET_LIBS) \ + libindicator-messages-status-provider.la gen-%.xml.h: %.xml @echo "Building $@ from $<" @@ -88,6 +84,40 @@ BUILT_SOURCES += \ 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 = + +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 ###################################### @@ -104,6 +134,7 @@ libpidgin_la_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 @@ -141,6 +172,7 @@ libtelepathy_la_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 @@ -178,6 +210,7 @@ libmc5_la_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 @@ -213,6 +246,7 @@ libemesene_la_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 -- cgit v1.2.3 From 22abed03db8cb4d3e8b860075cc832bd964ca543 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 08:50:59 -0500 Subject: Attach the module to the object and put them in the list. Now we're real. --- src/status-items.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index eef240f..e210c01 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -120,6 +120,27 @@ provider_directory_parse (gpointer directory) 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) @@ -159,6 +180,12 @@ load_status_provider (gpointer dir) goto exit_module_fail; } + /* 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); goto exit_final; -- cgit v1.2.3 From 8ae2a2a48815b9fe84e779dad8c581b222ee70e7 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 09:11:23 -0500 Subject: Connecting a callback and cleaning up --- src/messages-service.c | 9 ++++++++- src/status-items.c | 16 +++++++++++++++- src/status-items.h | 5 ++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/messages-service.c b/src/messages-service.c index 0db4a7e..4ccd0f1 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -1433,6 +1433,12 @@ service_shutdown (IndicatorService * service, gpointer user_data) 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 @@ -1462,7 +1468,7 @@ main (int argc, char ** argv) DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT); dbusmenu_server_set_root(server, root_menuitem); - status_items_build(); + status_items_build(&status_update_callback); /* Start up the libindicate listener */ listener = indicate_listener_ref_default(); @@ -1486,6 +1492,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ + status_items_cleanup(); g_free(userdir); return 0; diff --git a/src/status-items.c b/src/status-items.c index e210c01..4f83c23 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -55,7 +55,7 @@ GList * status_providers = NULL; /* Build the inital status items and start kicking off the async code for handling all the statuses */ GList * -status_items_build (void) +status_items_build (StatusUpdateFunc status_update_func) { int i; for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_DISCONNECTED; i++) { @@ -78,6 +78,20 @@ status_items_build (void) 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) diff --git a/src/status-items.h b/src/status-items.h index 686d03c..f685a0e 100644 --- a/src/status-items.h +++ b/src/status-items.h @@ -6,8 +6,11 @@ G_BEGIN_DECLS -GList * status_items_build (void); +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 -- cgit v1.2.3 From 424bb6df27fe846c509e0664982a7e122cf29e86 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 09:33:18 -0500 Subject: Ignoring some more --- .bzrignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bzrignore b/.bzrignore index 0a7a2b6..832fd6e 100644 --- a/.bzrignore +++ b/.bzrignore @@ -43,3 +43,5 @@ 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 -- cgit v1.2.3 From 8a00a71feca7cec8b21f506ada5b6ef18eacbc4f Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 09:42:05 -0500 Subject: Translate the strings in status-items --- po/POTFILES.in | 1 + 1 file changed, 1 insertion(+) diff --git a/po/POTFILES.in b/po/POTFILES.in index 1b686c7..051f8f3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -6,3 +6,4 @@ src/default-applications.c src/launcher-menu-item.c src/im-menu-item.c src/app-menu-item.c +src/status-items.c -- cgit v1.2.3 From 357324760c1d7391276a25a83ecd1f83bea9aa7b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 2 Jul 2011 10:05:14 -0500 Subject: The trailing slash makes distcheck fail. No really. --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 51551ba..62159cb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -89,7 +89,7 @@ EXTRA_DIST += \ ###################################### STATUS_PROVIDER_API_VERSION = 1 -STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION)/ +STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSION) statusprovidersdir = $(STATUS_PROVIDER_DIR) statusproviders_LTLIBRARIES = -- cgit v1.2.3 From 3e9685c57d9df7a353431d0b89138309816dee5b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 8 Jul 2011 14:46:06 -0500 Subject: Making a pkgconfig file for the status providers --- configure.ac | 1 + src/Makefile.am | 18 +++++++++++++++++- src/indicator-messages-status-provider-0.5.pc.in.in | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/indicator-messages-status-provider-0.5.pc.in.in diff --git a/configure.ac b/configure.ac index 95868b7..f57d7ab 100644 --- a/configure.ac +++ b/configure.ac @@ -159,6 +159,7 @@ AM_GLIB_GNU_GETTEXT AC_OUTPUT([ Makefile src/Makefile +src/indicator-messages-status-provider-0.5.pc.in data/Makefile data/icons/Makefile data/icons/16x16/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 62159cb..c631436 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ BUILT_SOURCES = EXTRA_DIST = +CLEANFILES = +DISTCLEANFILES = libexec_PROGRAMS = indicator-messages-service @@ -93,6 +95,20 @@ STATUS_PROVIDER_DIR = $(libexecdir)/status-providers/$(STATUS_PROVIDER_API_VERSI 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 @@ -255,6 +271,6 @@ libemesene_la_LDFLAGS = -module -avoid-version # Extras ###################################### -CLEANFILES = \ +CLEANFILES += \ $(BUILT_SOURCES) diff --git a/src/indicator-messages-status-provider-0.5.pc.in.in b/src/indicator-messages-status-provider-0.5.pc.in.in new file mode 100644 index 0000000..3fe4cf2 --- /dev/null +++ b/src/indicator-messages-status-provider-0.5.pc.in.in @@ -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@ -- cgit v1.2.3 From ac5886d4e7c0eb396502ad05a96a8196d065af63 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 10:41:33 -0500 Subject: Ignoring the PC files --- .bzrignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.bzrignore b/.bzrignore index 832fd6e..3ba685c 100644 --- a/.bzrignore +++ b/.bzrignore @@ -45,3 +45,5 @@ 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 -- cgit v1.2.3 From ca536289f57fdddd161c525159cfdcfc0bfe373e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 12:02:21 -0500 Subject: Putting status items into the menu --- src/messages-service.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/messages-service.c b/src/messages-service.c index 4ccd0f1..fd22555 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -48,6 +48,7 @@ static GList * serverList = NULL; static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; +static DbusmenuMenuitem * status_separator = NULL; static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; @@ -1468,7 +1469,15 @@ main (int argc, char ** argv) DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT); dbusmenu_server_set_root(server, root_menuitem); - status_items_build(&status_update_callback); + /* 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(); -- cgit v1.2.3 From 1bcc5cd6dd75328604cc964a4af2529d7adafb1c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 13:12:46 -0500 Subject: Priming with the status separator --- src/messages-service.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/messages-service.c b/src/messages-service.c index fd22555..3e89845 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -838,6 +838,11 @@ resort_menu (DbusmenuMenuitem * menushell) DbusmenuMenuitem * last_separator = NULL; g_debug("Reordering Menu:"); + + if (DBUSMENU_IS_MENUITEM(status_separator)) { + position = dbusmenu_menuitem_get_position(status_separator, root_menuitem); + 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; -- cgit v1.2.3 From 2d5602d093424119539bd7eee8f8bfde845f6115 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 13:42:05 -0500 Subject: Connect in to update the stati --- src/status-items.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index 4f83c23..6667072 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -103,6 +103,50 @@ status_current_panel_icon (gboolean alert) } } +/* 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; + + /* TODO: Signal updated icon */ + + 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; +} + /* Start parsing a directory and setting up the entires in the idle loop */ static gboolean provider_directory_parse (gpointer directory) @@ -194,6 +238,10 @@ load_status_provider (gpointer dir) 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. */ @@ -201,6 +249,10 @@ load_status_provider (gpointer dir) 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: -- cgit v1.2.3 From 2a04996a4d63a3594c0a5e8e9dbbc3432daf4a29 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 14:00:28 -0500 Subject: Signal back that the icon should be updated --- src/status-items.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/status-items.c b/src/status-items.c index 6667072..3442478 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -49,8 +49,9 @@ static gboolean load_status_provider (gpointer dir); /* Globals */ static StatusProviderStatus current_status = STATUS_PROVIDER_STATUS_DISCONNECTED; -GList * menuitems = NULL; -GList * status_providers = NULL; +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 */ @@ -73,6 +74,8 @@ status_items_build (StatusUpdateFunc status_update_func) menuitems = g_list_append(menuitems, item); } + update_func = status_update_func; + g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR); return menuitems; @@ -124,7 +127,9 @@ update_status (void) current_status = status; - /* TODO: Signal updated icon */ + if (update_func != NULL) { + update_func(); + } GList * menu; int i; -- cgit v1.2.3 From cd0c66774c3f61cee7279211cefd72e980a314aa Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 14:08:39 -0500 Subject: Handle users clicking on those silly menu items that we created. --- src/status-items.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index 3442478..ac92aba 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -46,6 +46,7 @@ static const gchar * panel_active_icons[STATUS_PROVIDER_STATUS_LAST] = { /* 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; @@ -71,6 +72,8 @@ status_items_build (StatusUpdateFunc status_update_func) 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); } @@ -152,6 +155,23 @@ update_status (void) 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) -- cgit v1.2.3 From cfe8a44d153baae7b0f7a015dcd3b04cae98b60a Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 14:13:07 -0500 Subject: Allow the status provider directory to be overridden by an environment variable --- src/status-items.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/status-items.c b/src/status-items.c index ac92aba..ce2db9a 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -79,7 +79,12 @@ status_items_build (StatusUpdateFunc status_update_func) update_func = status_update_func; - g_idle_add(provider_directory_parse, STATUS_PROVIDER_DIR); + 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; } -- cgit v1.2.3 From 753c2e40e087e49f7d0fe93edb2461d290d972af Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 14:26:30 -0500 Subject: Off by one error, because, well, this is a computer program and that's what happens. --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/messages-service.c b/src/messages-service.c index 3e89845..63549e3 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -840,7 +840,7 @@ resort_menu (DbusmenuMenuitem * menushell) g_debug("Reordering Menu:"); if (DBUSMENU_IS_MENUITEM(status_separator)) { - position = dbusmenu_menuitem_get_position(status_separator, root_menuitem); + position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1; g_debug("\tPriming with location of status separator: %d", position); } -- cgit v1.2.3 From e8384bb4257d9f016b0cbc18fb997d34a5ea282b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 13 Jul 2011 15:17:58 -0500 Subject: Adding copyright headers --- src/status-items.c | 20 ++++++++++++++++++++ src/status-items.h | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/status-items.c b/src/status-items.c index ce2db9a..25a7aa2 100644 --- a/src/status-items.c +++ b/src/status-items.c @@ -1,3 +1,23 @@ +/* +Code to build and maintain the status adjustment menuitems. + +Copyright 2011 Canonical Ltd. + +Authors: + Ted Gould + +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 . +*/ #include #include diff --git a/src/status-items.h b/src/status-items.h index f685a0e..fe7900c 100644 --- a/src/status-items.h +++ b/src/status-items.h @@ -1,3 +1,23 @@ +/* +Code to build and maintain the status adjustment menuitems. + +Copyright 2011 Canonical Ltd. + +Authors: + Ted Gould + +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 . +*/ #ifndef __STATUS_ITEMS_H__ #define __STATUS_ITEMS_H__ -- cgit v1.2.3 From acbcc6281bd71cc487c22f6a4565827563631661 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 14 Jul 2011 13:01:07 -0500 Subject: 0.4.92 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f57d7ab..92f5c88 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ AC_INIT(src/indicator-messages.c) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(indicator-messages, 0.4.91) +AM_INIT_AUTOMAKE(indicator-messages, 0.4.92) AM_MAINTAINER_MODE -- cgit v1.2.3