← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~dbarth/indicator-me/gwibber-service into lp:indicator-me

 

David Barth has proposed merging lp:~dbarth/indicator-me/gwibber-service into lp:indicator-me with lp:~dbarth/indicator-me/character-limit as a prerequisite.

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


Big patch to be able to monitor the gwibber service and update the UI. See commit below.
-- 
https://code.launchpad.net/~dbarth/indicator-me/gwibber-service/+merge/21490
Your team ayatana-commits is subscribed to branch lp:indicator-me.
=== modified file 'src/me-service-gwibber.c'
--- src/me-service-gwibber.c	2010-03-10 14:39:43 +0000
+++ src/me-service-gwibber.c	2010-03-16 20:51:26 +0000
@@ -1,6 +1,6 @@
 /*
 
-Logic to send messages via gwibber
+GObject wrapper for the gwibber service
 
 Copyright 2010 Canonical Ltd.
 
@@ -20,48 +20,278 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include "me-service-gwibber.h"
+
 #include <glib.h>
+
 #include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-bindings.h>
 
 #define GWIBBER_ADDRESS    "com.Gwibber.Service"
 #define GWIBBER_OBJECT     "/com/gwibber/Service"
 #define GWIBBER_INTERFACE  "com.Gwibber.Service"
 
-static DBusGProxy * gwibber_proxy = NULL;
-
-/*
-  static */ void
-gwibber_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data)
-{
-	g_debug ("gwibber_send_response");
-
-	return;
-}
-
-static void
-setup_gwibber_proxy (void) {
-	DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
-	g_return_if_fail(bus != NULL);
-
-	if (gwibber_proxy == NULL) {
-		gwibber_proxy = dbus_g_proxy_new_for_name(bus,
-												  GWIBBER_ADDRESS,
-												  GWIBBER_OBJECT,
-												  GWIBBER_INTERFACE);
-	}
-	g_return_if_fail (gwibber_proxy != NULL);
+/* gobject infrastructure */
+
+typedef struct _GwibberServicePrivate GwibberServicePrivate;
+struct _GwibberServicePrivate {
+	DBusGProxy * dbus_proxy;
+	DBusGProxy * service_proxy;
+	int status;
+	gboolean has_configured_accounts;
+};
+
+/* Signals */
+enum {
+	STATUS_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Prototypes */
+static void gwibber_service_class_init (GwibberServiceClass *klass);
+static void gwibber_service_init       (GwibberService *self);
+static void gwibber_service_dispose    (GObject *object);
+static void gwibber_service_finalize   (GObject *object);
+
+static void dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, GwibberService * self);
+static void gwibber_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata);
+static void setup_service_proxy (GwibberService *self);
+static void query_account_manager (GwibberService *self);
+
+G_DEFINE_TYPE (GwibberService, gwibber_service, G_TYPE_OBJECT);
+
+#define GWIBBER_SERVICE_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), GWIBBER_SERVICE_TYPE, GwibberServicePrivate))
+
+static void
+gwibber_service_class_init (GwibberServiceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GwibberServicePrivate));
+
+	object_class->dispose = gwibber_service_dispose;
+	object_class->finalize = gwibber_service_finalize;
+
+	signals[STATUS_CHANGED]  = g_signal_new(GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED,
+											G_TYPE_FROM_CLASS(klass),
+											G_SIGNAL_RUN_LAST,
+											G_STRUCT_OFFSET(GwibberServiceClass, status_changed),
+											NULL, NULL,
+											g_cclosure_marshal_VOID__UINT,
+											G_TYPE_NONE, 1, G_TYPE_UINT);
+	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
+gwibber_service_init (GwibberService *self)
+{
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
+
+	priv->dbus_proxy = NULL;
+	priv->service_proxy = NULL;
+	priv->status = GWIBBER_SERVICE_STATUS_NOT_RUNNING;
+	priv->has_configured_accounts = FALSE;
+
+	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, GWIBBER_ADDRESS, gwibber_exists_cb, self);
+
+	return;
+}
+
+/* Unref the account manager and move on.  Sadly, we're
+   leaving the show. */
+static void
+gwibber_service_dispose (GObject *object)
+{
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(object);
+
+	if (priv->dbus_proxy != NULL) {
+		g_object_unref(priv->dbus_proxy);
+		priv->dbus_proxy = NULL;
+	}
+
+	if (priv->service_proxy != NULL) {
+		g_object_unref(priv->service_proxy);
+		priv->service_proxy = NULL;
+	}
+
+	G_OBJECT_CLASS (gwibber_service_parent_class)->dispose (object);
+	return;
+}
+
+/* Pass to superclass */
+static void
+gwibber_service_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gwibber_service_parent_class)->finalize (object);
+	return;
+}
+
+
+/* Watch for Gwibber coming on and off the bus. */
+static void
+dbus_namechange (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, GwibberService * self)
+{
+	g_return_if_fail (IS_GWIBBER_SERVICE (self));
+
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
+
+	if (prev[0] == '\0' && g_strcmp0(name, GWIBBER_ADDRESS) == 0) {
+		g_debug("Gwibber Service coming online");
+		priv->status = GWIBBER_SERVICE_STATUS_RUNNING;
+		if (priv->service_proxy == NULL)
+			setup_service_proxy (self);
+		query_account_manager (self);
+	}
+
+	if (new[0] == '\0' && g_strcmp0(name, GWIBBER_ADDRESS) == 0) {
+		g_debug("Gwibber Service going offline");
+		priv->status = GWIBBER_SERVICE_STATUS_NOT_RUNNING;
+		g_signal_emit (G_OBJECT (self), GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED_ID, 0, priv->status, TRUE);
+	}
+
+	return;
+}
+
+static void
+get_accounts_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data)
+{
+	GError *error = NULL;
+	gchar  *accounts_string = NULL;
+
+	dbus_g_proxy_end_call (proxy, call, &error,
+						   G_TYPE_STRING, &accounts_string,
+						   G_TYPE_INVALID);
+
+	if (error != NULL) {
+		g_error_free (error);
+		g_warning ("GetAccounts: %s", error->message);
+		return;
+	}
+
+	/* don't print the accounts string, it contains passwords */
+	/* g_debug ("GetAccounts: %s", accounts_string); */
+
+	g_return_if_fail (IS_GWIBBER_SERVICE (data));
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(data);
+	g_return_if_fail (priv != NULL);
+
+	priv->status = GWIBBER_SERVICE_STATUS_RUNNING;
+	priv->has_configured_accounts = g_strrstr (accounts_string, " \"send_enabled\": true,") ? TRUE : FALSE;
+
+	/* trigger a status update */
+	g_signal_emit (G_OBJECT (data),
+				   GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED_ID,
+				   0, priv->status, TRUE);
+
+	return;
+}
+
+static void
+query_account_manager (GwibberService *self)
+{
+	g_return_if_fail (IS_GWIBBER_SERVICE (self));
+
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
+
+	if (priv->service_proxy == NULL) {
+		g_warning ("no service_proxy, can't query for accounts");
+		return;
+	}
+
+	dbus_g_proxy_begin_call(priv->service_proxy,
+	                        "GetAccounts",
+	                        get_accounts_response,
+	                        self,
+	                        NULL,
+							G_TYPE_INVALID);
+}
+
+static void
+setup_service_proxy (GwibberService *self)
+{
+	g_return_if_fail (IS_GWIBBER_SERVICE (self));
+
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
+
+	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 */
+
+	if (priv->service_proxy == NULL) {
+		priv->service_proxy = dbus_g_proxy_new_for_name(bus,
+														GWIBBER_ADDRESS,
+														GWIBBER_OBJECT,
+														GWIBBER_INTERFACE);
+	}
+}
+
+static void
+gwibber_exists_cb (DBusGProxy * proxy, gboolean exists, GError * error, gpointer userdata)
+{
+	if (error) {
+		g_warning ("Unable to check if Gwibber is running: %s", error->message);
+		return;
+	}
+
+	if (exists) {
+		setup_service_proxy (GWIBBER_SERVICE (userdata));
+		query_account_manager (GWIBBER_SERVICE (userdata));
+	}
+
+	return;
+}
+
+GwibberService * gwibber_service_new (void){
+	return GWIBBER_SERVICE (g_object_new (GWIBBER_SERVICE_TYPE, NULL));
+}
+
+static void
+send_message_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data)
+{
+	g_debug ("send_message_response");
 
 	return;
 }
 
 void
-gwibber_send (const gchar *msg)
+gwibber_service_send (GwibberService *self, const gchar *msg)
 {
-	setup_gwibber_proxy ();
+	g_return_if_fail (IS_GWIBBER_SERVICE (self));
 
-	if (gwibber_proxy == NULL) {
-		g_warning ("Can not get a gwibber proxy object");
-	}
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
 
 	GValue value = {0};
 	g_value_init(&value, G_TYPE_STRING);
@@ -69,9 +299,17 @@
 
 	g_debug ("gwibber_send: %s\n", msg);
 
-	dbus_g_proxy_begin_call(gwibber_proxy,
+	if (priv->service_proxy == NULL) {
+		setup_service_proxy (self);
+		if (priv->service_proxy == NULL) {
+			g_warning ("can't setup service_proxy");
+			return;
+		}
+	}
+
+	dbus_g_proxy_begin_call(priv->service_proxy,
 	                        "SendMessage",
-	                        gwibber_response,
+	                        send_message_response,
 	                        NULL,
 	                        NULL,
 	                        G_TYPE_VALUE,
@@ -82,3 +320,24 @@
 
 	return;
 }
+
+void gwibber_send (const char *msg)
+{
+  static GwibberService *singleton = NULL;
+
+  if (! singleton) {
+	  singleton = gwibber_service_new ();
+  }
+
+  gwibber_service_send (singleton, msg);
+}
+
+gboolean
+gwibber_service_has_configured_accounts (GwibberService *self)
+{
+	g_return_val_if_fail (IS_GWIBBER_SERVICE (self), FALSE);
+
+	GwibberServicePrivate * priv = GWIBBER_SERVICE_GET_PRIVATE(self);
+
+	return priv->has_configured_accounts;
+}

=== modified file 'src/me-service-gwibber.h'
--- src/me-service-gwibber.h	2010-02-04 20:52:03 +0000
+++ src/me-service-gwibber.h	2010-03-16 20:51:26 +0000
@@ -20,16 +20,56 @@
 with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef __ME_SERVICE_GWIBBER_H__
-#define __ME_SERVICE_GWIBBER_H__
+#ifndef __GWIBBER_SERVICE_H__
+#define __GWIBBER_SERVICE_H__
 
 #include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
+#define GWIBBER_SERVICE_TYPE            (gwibber_service_get_type ())
+#define GWIBBER_SERVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GWIBBER_SERVICE_TYPE, GwibberService))
+#define GWIBBER_SERVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GWIBBER_SERVICE_TYPE, GwibberServiceClass))
+#define IS_GWIBBER_SERVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GWIBBER_SERVICE_TYPE))
+#define IS_GWIBBER_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GWIBBER_SERVICE_TYPE))
+#define GWIBBER_SERVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GWIBBER_SERVICE_TYPE, GwibberServiceClass))
+
+typedef enum
+{
+	GWIBBER_SERVICE_STATUS_NOT_RUNNING,
+	/* GWIBBER_SERVICE_STATUS_LOADING_STARTED,
+	GWIBBER_SERVICE_STATUS_LOADING_COMPLETE, */
+	GWIBBER_SERVICE_STATUS_RUNNING,
+	GWIBBER_SERVICE_STATUS_LAST
+}
+GwibberServiceStatus;
+
+#define GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED     "status-changed"
+#define GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED_ID  (g_signal_lookup(GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED, GWIBBER_SERVICE_TYPE))
+
+typedef struct _GwibberServiceClass GwibberServiceClass;
+struct _GwibberServiceClass {
+	GObjectClass parent_class;
+
+	/* Signals */
+	void (*status_changed) (GwibberServiceStatus newstatus);
+};
+
+typedef struct _GwibberService      GwibberService;
+struct _GwibberService {
+	GObject parent;
+};
+
+GType gwibber_service_get_type (void) G_GNUC_CONST;
+GwibberService * gwibber_service_new (void);
+void gwibber_service_send (GwibberService *self, const gchar *msg);
+gboolean gwibber_service_has_configured_accounts (GwibberService *self);
+
+/* old API */
 void gwibber_send (const gchar *msg);
 
 G_END_DECLS
 
-#endif /* __ME_SERVICE_GWIBBER_H__ */
+#endif /* __GWIBBER_SERVICE_H__ */
 

=== modified file 'src/me-service.c'
--- src/me-service.c	2010-03-16 20:51:26 +0000
+++ src/me-service.c	2010-03-16 20:51:26 +0000
@@ -51,6 +51,7 @@
 #include "status-provider-pidgin.h"
 #include "status-provider-telepathy.h"
 
+#include "me-service-gwibber.h"
 #include "entry-menu-item.h"
 
 typedef StatusProvider * (*newfunc) (void);
@@ -80,6 +81,7 @@
   /* STATUS_PROVIDER_STATUS_DISCONNECTED */"user-offline"
 };
 
+static GwibberService * gwibber = NULL;
 
 static DbusmenuMenuitem * root_menuitem = NULL;
 static DbusmenuMenuitem * status_menuitems[STATUS_PROVIDER_STATUS_LAST] = {0};
@@ -87,6 +89,7 @@
 static StatusServiceDbus * dbus_interface = NULL;
 static StatusProviderStatus global_status = STATUS_PROVIDER_STATUS_DISCONNECTED;
 static GFileMonitor *avatar_monitor = NULL;
+static DbusmenuMenuitem *broadcast_field = NULL;
 
 static void
 status_update (void) {
@@ -166,6 +169,38 @@
 }
 
 static void
+gwibber_status_update (GwibberService *instance, GwibberServiceStatus status, gpointer data) {
+  g_return_if_fail (instance != NULL);
+
+  g_debug ("gwibber service status changed to: %d", status);
+
+  if (broadcast_field == NULL) {
+    g_warning ("no broadcast field to update");
+    return;
+  }
+
+  if (! gwibber_service_has_configured_accounts (instance)) {
+    g_debug ("no configured accounts detected, so hiding the broadcast field");
+    dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+    return;
+  }
+
+  if (! dbusmenu_menuitem_property_get_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_VISIBLE))
+    dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
+
+  if (status == GWIBBER_SERVICE_STATUS_RUNNING) {
+    g_debug ("enabling the broadcast field");
+    dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+  } else {
+    g_debug ("disabling the broadcast field");
+    dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
+  }
+
+  return;
+}
+
+
+static void
 status_menu_click (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
 {
 	StatusProviderStatus status = (StatusProviderStatus)GPOINTER_TO_INT(data);
@@ -249,7 +284,12 @@
 
 	status_update();
 
-	return FALSE;
+  gwibber = gwibber_service_new ();
+  if (gwibber != NULL) {
+    g_signal_connect (G_OBJECT (gwibber), GWIBBER_SERVICE_SIGNAL_STATUS_CHANGED, G_CALLBACK (gwibber_status_update), NULL);
+  }
+
+  return FALSE;
 }
 
 #define GCONF_ANONYMOUS "/system/indicator/me/anonymous"
@@ -362,8 +402,10 @@
 
   build_user_item(root);
 
-	DbusmenuMenuitem *entry = DBUSMENU_MENUITEM (entry_menu_item_new());
-	dbusmenu_menuitem_child_append(root, entry);
+  broadcast_field = DBUSMENU_MENUITEM (entry_menu_item_new());
+  dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+  dbusmenu_menuitem_property_set_bool (broadcast_field, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
+  dbusmenu_menuitem_child_append(root, broadcast_field);
 
 	StatusProviderStatus i;
 	for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_LAST; i++) {


Follow ups