diff options
-rw-r--r-- | .bzrignore | 9 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rwxr-xr-x | autogen.sh | 2 | ||||
-rw-r--r-- | configure.ac | 60 | ||||
-rw-r--r-- | data/Makefile.am | 13 | ||||
-rw-r--r-- | data/indicator-session.service.in | 3 | ||||
-rw-r--r-- | data/indicator-status.service.in | 3 | ||||
-rw-r--r-- | data/indicator-users.service.in | 3 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | src/Makefile.am | 76 | ||||
-rw-r--r-- | src/dbus-shared-names.h | 14 | ||||
-rw-r--r-- | src/indicator-fusa.c | 26 | ||||
-rw-r--r-- | src/indicator-sus.c | 86 | ||||
-rw-r--r-- | src/session-service.c | 42 | ||||
-rw-r--r-- | src/status-provider-pidgin.c | 142 | ||||
-rw-r--r-- | src/status-provider-pidgin.h | 34 | ||||
-rw-r--r-- | src/status-provider.c | 85 | ||||
-rw-r--r-- | src/status-provider.h | 56 | ||||
-rw-r--r-- | src/status-service-dbus.c | 72 | ||||
-rw-r--r-- | src/status-service-dbus.h | 31 | ||||
-rw-r--r-- | src/status-service.c | 122 | ||||
-rw-r--r-- | src/status-service.xml | 25 | ||||
-rw-r--r-- | src/users-service.c | 42 |
23 files changed, 919 insertions, 38 deletions
@@ -14,3 +14,12 @@ debian/indicator-messages.postrm.debhelper debian/indicator-messages.substvars debian/stamp-autotools-files debian/stamp-makefile-build +libstatus-users-session.la +libstatus_users_session_la-indicator-fusa.lo +libstatus_users_session_la-indicator-sus.lo +indicator-session-service +indicator-status-service +indicator-users-service +indicator-session.service +indicator-status.service +indicator-users.service diff --git a/Makefile.am b/Makefile.am index f0f2247..7d58c6b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ SUBDIRS = \ - src + src \ + data + +DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall @@ -1,6 +1,6 @@ #!/bin/sh -PKG_NAME="indicator-fusa" +PKG_NAME="indicator-sus" which gnome-autogen.sh || { echo "You need gnome-common from GNOME SVN" diff --git a/configure.ac b/configure.ac index ec22ca2..d299a0d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,10 +1,10 @@ -AC_INIT(src/indicator-fusa.c) +AC_INIT(src/indicator-sus.c) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(indicator-fusa, 0.1) +AM_INIT_AUTOMAKE(indicator-sus, 0.1dev) AM_MAINTAINER_MODE @@ -22,12 +22,61 @@ AC_CONFIG_MACRO_DIR([m4]) ########################### GTK_REQUIRED_VERSION=2.12 -PANEL_REQUIRED_VERSION=2.0.0 +INDICATOR_REQUIRED_VERSION=0.2.0 +DBUSMENUGTK_REQUIRED_VERSION=0.0.0 -PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION) +PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION + indicator >= $INDICATOR_REQUIRED_VERSION + dbusmenu-gtk >= $DBUSMENUGTK_REQUIRED_VERSION) AC_SUBST(APPLET_CFLAGS) AC_SUBST(APPLET_LIBS) +DBUSMENUGLIB_REQUIRED_VERSION=0.0.0 + +PKG_CHECK_MODULES(STATUSSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION) + +AC_SUBST(STATUSERVICE_CFLAGS) +AC_SUBST(STATUSERVICE_LIBS) + +PKG_CHECK_MODULES(USERSSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION) + +AC_SUBST(USERSERVICE_CFLAGS) +AC_SUBST(USERSERVICE_LIBS) + +PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSION) + +AC_SUBST(SESSIONERVICE_CFLAGS) +AC_SUBST(SESSIONERVICE_LIBS) + +########################### +# Check to see if we're local +########################### + +with_localinstall="no" +AC_ARG_ENABLE(localinstall, AS_HELP_STRING([--enable-localinstall], [install all of the files localy instead of system directories (for distcheck)]), with_localinstall=$enableval, with_localinstall=no) + +########################### +# Indicator Info +########################### + +if test "x$with_localinstall" = "xyes"; then + INDICATORDIR="${libdir}/indicators/2/" +else + INDICATORDIR=`$PKG_CONFIG --variable=indicatordir indicator` +fi +AC_SUBST(INDICATORDIR) + +########################### +# DBus Service Info +########################### + +if test "x$with_localinstall" = "xyes"; then + DBUSSERVICEDIR="${datadir}/dbus-1/services/" +else + DBUSSERVICEDIR=`$PKG_CONFIG --variable=session_bus_services_dir dbus-1` +fi +AC_SUBST(DBUSSERVICEDIR) + ########################### # Files ########################### @@ -35,6 +84,7 @@ AC_SUBST(APPLET_LIBS) AC_OUTPUT([ Makefile src/Makefile +data/Makefile ]) ########################### @@ -43,7 +93,7 @@ src/Makefile AC_MSG_NOTICE([ -FUSA Indicator Configuration: +SUS Indicator Configuration: Prefix: $prefix ]) diff --git a/data/Makefile.am b/data/Makefile.am new file mode 100644 index 0000000..da1bcd2 --- /dev/null +++ b/data/Makefile.am @@ -0,0 +1,13 @@ + +dbus_servicesdir = $(DBUSSERVICEDIR) +service_in_files = indicator-status.service.in \ + indicator-users.service.in \ + indicator-session.service.in +dbus_services_DATA = $(service_in_files:.service.in=.service) + +$(dbus_services_DATA): $(service_in_files) Makefile + @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = $(service_in_files) + +CLEANFILES = $(dbus_services_DATA) diff --git a/data/indicator-session.service.in b/data/indicator-session.service.in new file mode 100644 index 0000000..790600a --- /dev/null +++ b/data/indicator-session.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=com.ubuntu.indicator.session +Exec=@libexecdir@/indicator-session-service diff --git a/data/indicator-status.service.in b/data/indicator-status.service.in new file mode 100644 index 0000000..9fe92ad --- /dev/null +++ b/data/indicator-status.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=com.ubuntu.indicator.status +Exec=@libexecdir@/indicator-status-service diff --git a/data/indicator-users.service.in b/data/indicator-users.service.in new file mode 100644 index 0000000..2843743 --- /dev/null +++ b/data/indicator-users.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=com.ubuntu.indicator.users +Exec=@libexecdir@/indicator-users-service diff --git a/debian/changelog b/debian/changelog index ed0dab5..48cb071 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +indicator-fusa (0.1~ppa2~indicator1) UNRELEASED; urgency=low + + * Upstream from the indicator branch. + + -- Ted Gould <ted@ubuntu.com> Mon, 15 Jun 2009 16:19:59 -0500 + indicator-fusa (0.1~ppa1) intrepid; urgency=low * Initial release diff --git a/src/Makefile.am b/src/Makefile.am index c29d179..1965fe9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,72 @@ -fusalibdir = $(libdir)/indicators/1 -fusalib_LTLIBRARIES = libfusa.la -libfusa_la_SOURCES = indicator-fusa.c -libfusa_la_CFLAGS = $(APPLET_CFLAGS) -libfusa_la_LIBADD = $(APPLET_LIBS) +libexec_PROGRAMS = indicator-status-service indicator-users-service indicator-session-service + +################### +# Indicator Stuff +################### + +status_users_sessionlibdir = $(INDICATORDIR) +status_users_sessionlib_LTLIBRARIES = libstatus-users-session.la +libstatus_users_session_la_SOURCES = \ + indicator-sus.c \ + dbus-shared-names.h \ + status-service-client.h +libstatus_users_session_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror +libstatus_users_session_la_LIBADD = $(APPLET_LIBS) + +################ +# Status Stuff +################ + +indicator_status_service_SOURCES = \ + status-service.c \ + status-service-dbus.h \ + status-service-dbus.c \ + status-service-server.h \ + status-provider.h \ + status-provider.c \ + status-provider-pidgin.h \ + status-provider-pidgin.c +indicator_status_service_CFLAGS = $(STATUSSERVICE_CFLAGS) +indicator_status_service_LDADD = $(STATUSSERVICE_LIBS) + +status-service-client.h: status-service.xml + dbus-binding-tool \ + --prefix=_status_service_client \ + --mode=glib-client \ + --output=status-service-client.h \ + $(srcdir)/status-service.xml + +status-service-server.h: status-service.xml + dbus-binding-tool \ + --prefix=_status_service_server \ + --mode=glib-server \ + --output=status-service-server.h \ + $(srcdir)/status-service.xml + +############### +# Users Stuff +############### + +indicator_users_service_SOURCES = users-service.c +indicator_users_service_CFLAGS = $(USERSSERVICE_CFLAGS) +indicator_users_service_LDADD = $(USERSSERVICE_LIBS) + +################# +# Session Stuff +################# + +indicator_session_service_SOURCES = session-service.c +indicator_session_service_CFLAGS = $(SESSIONSERVICE_CFLAGS) +indicator_session_service_LDADD = $(SESSIONSERVICE_LIBS) + +############### +# Other Stuff +############### + +BUILT_SOURCES = \ + status-service-client.h \ + status-service-server.h + +EXTRA_DIST = \ + status-service.xml diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h new file mode 100644 index 0000000..f56e9cb --- /dev/null +++ b/src/dbus-shared-names.h @@ -0,0 +1,14 @@ + +#ifndef __DBUS_SHARED_NAMES_H__ +#define __DBUS_SHARED_NAMES_H__ 1 + +#define INDICATOR_STATUS_DBUS_NAME "com.ubuntu.indicator.status" +#define INDICATOR_STATUS_DBUS_OBJECT "/com/ubuntu/indicator/status" + +#define INDICATOR_USERS_DBUS_NAME "com.ubuntu.indicator.users" +#define INDICATOR_USERS_DBUS_OBJECT "/com/ubuntu/indicator/users" + +#define INDICATOR_SESSION_DBUS_NAME "com.ubuntu.indicator.session" +#define INDICATOR_SESSION_DBUS_OBJECT "/com/ubuntu/indicator/session" + +#endif /* __DBUS_SHARED_NAMES_H__ */ diff --git a/src/indicator-fusa.c b/src/indicator-fusa.c deleted file mode 100644 index 21c0817..0000000 --- a/src/indicator-fusa.c +++ /dev/null @@ -1,26 +0,0 @@ - -#include <gtk/gtk.h> - -GtkWidget * -get_menu_item (void) -{ - GtkWidget * mainmenu = gtk_menu_item_new(); - - GtkWidget * hbox = gtk_hbox_new(FALSE, 3); - - GtkWidget * label = gtk_label_new("Ted Gould"); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 3); - gtk_widget_show(label); - - GtkWidget * icon = gtk_image_new_from_icon_name("gnome-logout", - GTK_ICON_SIZE_MENU); - gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0); - gtk_widget_show(icon); - - gtk_container_add(GTK_CONTAINER(mainmenu), hbox); - gtk_widget_show(hbox); - - gtk_widget_show(mainmenu); - return mainmenu; -} - diff --git a/src/indicator-sus.c b/src/indicator-sus.c new file mode 100644 index 0000000..5d6c219 --- /dev/null +++ b/src/indicator-sus.c @@ -0,0 +1,86 @@ + +#include <gtk/gtk.h> +#include <libdbusmenu-gtk/menu.h> + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libindicator/indicator.h> +INDICATOR_SET_VERSION +INDICATOR_SET_NAME("users-status-session") + +#include "dbus-shared-names.h" +#include "status-service-client.h" + +static GtkMenu * status_menu = NULL; +static GtkMenu * users_menu = NULL; +static GtkMenu * session_menu = NULL; +static GtkMenu * main_menu = NULL; + +GtkLabel * +get_label (void) +{ + GtkLabel * returnval = GTK_LABEL(gtk_label_new("Ted Gould")); + return returnval; +} + +GtkImage * +get_icon (void) +{ + return NULL; +} + +GtkMenu * +get_menu (void) +{ + guint returnval = 0; + GError * error = NULL; + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + DBusGProxy * proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + if (!org_freedesktop_DBus_start_service_by_name (proxy, INDICATOR_STATUS_DBUS_NAME, 0, &returnval, &error)) { + g_error("Unable to send message to DBus to start service: %s", error != NULL ? error->message : "(NULL error)" ); + g_error_free(error); + return NULL; + } + + if (returnval != DBUS_START_REPLY_SUCCESS && returnval != DBUS_START_REPLY_ALREADY_RUNNING) { + g_error("Return value isn't indicative of success: %d", returnval); + return NULL; + } + + status_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_STATUS_DBUS_NAME, INDICATOR_STATUS_DBUS_OBJECT)); + + if (!org_freedesktop_DBus_start_service_by_name (proxy, INDICATOR_USERS_DBUS_NAME, 0, &returnval, &error)) { + g_error("Unable to send message to DBus to start service: %s", error != NULL ? error->message : "(NULL error)" ); + g_error_free(error); + return NULL; + } + + if (returnval != DBUS_START_REPLY_SUCCESS && returnval != DBUS_START_REPLY_ALREADY_RUNNING) { + g_error("Return value isn't indicative of success: %d", returnval); + return NULL; + } + + users_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_USERS_DBUS_NAME, INDICATOR_USERS_DBUS_OBJECT)); + + if (!org_freedesktop_DBus_start_service_by_name (proxy, INDICATOR_SESSION_DBUS_NAME, 0, &returnval, &error)) { + g_error("Unable to send message to DBus to start service: %s", error != NULL ? error->message : "(NULL error)" ); + g_error_free(error); + return NULL; + } + + if (returnval != DBUS_START_REPLY_SUCCESS && returnval != DBUS_START_REPLY_ALREADY_RUNNING) { + g_error("Return value isn't indicative of success: %d", returnval); + return NULL; + } + + session_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_OBJECT)); + + main_menu = GTK_MENU(gtk_menu_new()); + + return main_menu; +} + + diff --git a/src/session-service.c b/src/session-service.c new file mode 100644 index 0000000..7a2ad27 --- /dev/null +++ b/src/session-service.c @@ -0,0 +1,42 @@ + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "dbus-shared-names.h" + +static DbusmenuMenuitem * root_menuitem = NULL; +static GMainLoop * mainloop = NULL; + +int +main (int argc, char ** argv) +{ + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + GError * error = NULL; + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_SESSION_DBUS_NAME, 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + root_menuitem = dbusmenu_menuitem_new(); + DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT); + dbusmenu_server_set_root(server, root_menuitem); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + return 0; +} + diff --git a/src/status-provider-pidgin.c b/src/status-provider-pidgin.c new file mode 100644 index 0000000..600ee79 --- /dev/null +++ b/src/status-provider-pidgin.c @@ -0,0 +1,142 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "status-provider.h" +#include "status-provider-pidgin.h" + +#include <dbus/dbus-glib.h> + +typedef enum { + PG_STATUS_UNKNOWN, + PG_STATUS_OFFLINE, + PG_STATUS_AVAILABLE, + PG_STATUS_UNAVAILABLE, + PG_STATUS_INVISIBLE, + PG_STATUS_AWAY, + PG_STATUS_EXTENDEND_AWAY, + PG_STATUS_MOBILE, + PG_STATUS_TUNE +} pg_status_t; + +static const StatusProviderStatus pg_to_sp_map[] = { + /* PG_STATUS_UNKNOWN, */ STATUS_PROVIDER_STATUS_OFFLINE, + /* PG_STATUS_OFFLINE, */ STATUS_PROVIDER_STATUS_OFFLINE, + /* PG_STATUS_AVAILABLE, */ STATUS_PROVIDER_STATUS_ONLINE, + /* PG_STATUS_UNAVAILABLE, */ STATUS_PROVIDER_STATUS_DND, + /* PG_STATUS_INVISIBLE, */ STATUS_PROVIDER_STATUS_INVISIBLE, + /* PG_STATUS_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, + /* PG_STATUS_EXTENDEND_AWAY, */ STATUS_PROVIDER_STATUS_AWAY, + /* PG_STATUS_MOBILE, */ STATUS_PROVIDER_STATUS_OFFLINE, + /* PG_STATUS_TUNE */ STATUS_PROVIDER_STATUS_OFFLINE +}; + +static const pg_status_t sp_to_pg_map[STATUS_PROVIDER_STATUS_LAST] = { + /* STATUS_PROVIDER_STATUS_ONLINE, */ PG_STATUS_AVAILABLE, + /* STATUS_PROVIDER_STATUS_AWAY, */ PG_STATUS_AWAY, + /* STATUS_PROVIDER_STATUS_DND */ PG_STATUS_UNAVAILABLE, + /* STATUS_PROVIDER_STATUS_INVISIBLE*/ PG_STATUS_INVISIBLE, + /* STATUS_PROVIDER_STATUS_OFFLINE */ PG_STATUS_OFFLINE +}; + +typedef struct _StatusProviderPidginPrivate StatusProviderPidginPrivate; +struct _StatusProviderPidginPrivate { + DBusGProxy * 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); + +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 +status_provider_pidgin_init (StatusProviderPidgin *self) +{ + StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(self); + + priv->proxy = NULL; + priv->pg_status = PG_STATUS_OFFLINE; + + return; +} + +static void +status_provider_pidgin_dispose (GObject *object) +{ + + 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) +{ + g_return_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp)); + StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp); + pg_status_t pg_status = sp_to_pg_map[status]; + priv->pg_status = pg_status; + return; +} + +/* Takes the cached Pidgin status and makes it into the generic + Status provider status */ +static StatusProviderStatus +get_status (StatusProvider * sp) +{ + g_return_val_if_fail(IS_STATUS_PROVIDER_PIDGIN(sp), STATUS_PROVIDER_STATUS_OFFLINE); + StatusProviderPidginPrivate * priv = STATUS_PROVIDER_PIDGIN_GET_PRIVATE(sp); + 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..85077e8 --- /dev/null +++ b/src/status-provider-pidgin.h @@ -0,0 +1,34 @@ +#ifndef __STATUS_PROVIDER_PIDGIN_H__ +#define __STATUS_PROVIDER_PIDGIN_H__ + +#include <glib.h> +#include <glib-object.h> + +#include "status-provider.h" + +G_BEGIN_DECLS + +#define STATUS_PROVIDER_PIDGIN_TYPE (status_provider_pidgin_get_type ()) +#define STATUS_PROVIDER_PIDGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidgin)) +#define STATUS_PROVIDER_PIDGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass)) +#define IS_STATUS_PROVIDER_PIDGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_PROVIDER_PIDGIN_TYPE)) +#define IS_STATUS_PROVIDER_PIDGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_PROVIDER_PIDGIN_TYPE)) +#define STATUS_PROVIDER_PIDGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_PROVIDER_PIDGIN_TYPE, StatusProviderPidginClass)) + + +typedef struct _StatusProviderPidginClass StatusProviderPidginClass; +struct _StatusProviderPidginClass { + StatusProviderClass parent_class; +}; + +typedef struct _StatusProviderPidgin StatusProviderPidgin; +struct _StatusProviderPidgin { + StatusProvider parent; +}; + +GType status_provider_pidgin_get_type (void); +StatusProvider * status_provider_pidgin_new (void); + +G_END_DECLS + +#endif diff --git a/src/status-provider.c b/src/status-provider.c new file mode 100644 index 0000000..cc9eb32 --- /dev/null +++ b/src/status-provider.c @@ -0,0 +1,85 @@ +#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_CLASS(sp); + 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_CLASS(sp); + g_return_val_if_fail(class->get_status != NULL, STATUS_PROVIDER_STATUS_OFFLINE); + + return class->get_status(sp); +} + +void +status_provider_emit_status_changed (StatusProvider * sp, StatusProviderStatus newstatus) +{ + g_return_if_fail(IS_STATUS_PROVIDER(sp)); + g_signal_emit(sp, signals[STATUS_CHANGED], 0, newstatus, TRUE); + return; +} diff --git a/src/status-provider.h b/src/status-provider.h new file mode 100644 index 0000000..87a2ea3 --- /dev/null +++ b/src/status-provider.h @@ -0,0 +1,56 @@ +#ifndef __STATUS_PROVIDER_H__ +#define __STATUS_PROVIDER_H__ + +#include <glib.h> +#include <glib-object.h> + +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, + /* Leave as last */ + STATUS_PROVIDER_STATUS_LAST +} +StatusProviderStatus; + +#define STATUS_PROVIDER_SIGNAL_STATUS_CHANGED "status-changed" + +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); + +void status_provider_emit_status_changed (StatusProvider * sp, StatusProviderStatus newstatus); + +G_END_DECLS + +#endif diff --git a/src/status-service-dbus.c b/src/status-service-dbus.c new file mode 100644 index 0000000..9ffc6aa --- /dev/null +++ b/src/status-service-dbus.c @@ -0,0 +1,72 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "status-service-dbus.h" + +static void status_service_dbus_class_init (StatusServiceDbusClass *klass); +static void status_service_dbus_init (StatusServiceDbus *self); +static void status_service_dbus_dispose (GObject *object); +static void status_service_dbus_finalize (GObject *object); +static void _status_service_server_watch (void); +static void _status_service_server_status_icons (void); +static void _status_service_server_pretty_user_name (void); + +#include "status-service-server.h" + +G_DEFINE_TYPE (StatusServiceDbus, status_service_dbus, G_TYPE_OBJECT); + +static void +status_service_dbus_class_init (StatusServiceDbusClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = status_service_dbus_dispose; + object_class->finalize = status_service_dbus_finalize; + + return; +} + +static void +status_service_dbus_init (StatusServiceDbus *self) +{ + + return; +} + +static void +status_service_dbus_dispose (GObject *object) +{ + + G_OBJECT_CLASS (status_service_dbus_parent_class)->dispose (object); + return; +} + +static void +status_service_dbus_finalize (GObject *object) +{ + + G_OBJECT_CLASS (status_service_dbus_parent_class)->finalize (object); + return; +} + +static void +_status_service_server_watch (void) +{ + + return; +} + +static void +_status_service_server_status_icons (void) +{ + + return; +} + +static void +_status_service_server_pretty_user_name (void) +{ + + return; +} diff --git a/src/status-service-dbus.h b/src/status-service-dbus.h new file mode 100644 index 0000000..1805dc5 --- /dev/null +++ b/src/status-service-dbus.h @@ -0,0 +1,31 @@ +#ifndef __STATUS_SERVICE_DBUS_H__ +#define __STATUS_SERVICE_DBUS_H__ + +#include <glib.h> +#include <glib-object.h> + +G_BEGIN_DECLS + +#define STATUS_SERVICE_DBUS_TYPE (status_service_dbus_get_type ()) +#define STATUS_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), STATUS_SERVICE_DBUS_TYPE, StatusServiceDbus)) +#define STATUS_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), STATUS_SERVICE_DBUS_TYPE, StatusServiceDbusClass)) +#define IS_STATUS_SERVICE_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), STATUS_SERVICE_DBUS_TYPE)) +#define IS_STATUS_SERVICE_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), STATUS_SERVICE_DBUS_TYPE)) +#define STATUS_SERVICE_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), STATUS_SERVICE_DBUS_TYPE, StatusServiceDbusClass)) + +typedef struct _StatusServiceDbus StatusServiceDbus; +typedef struct _StatusServiceDbusClass StatusServiceDbusClass; + +struct _StatusServiceDbusClass { + GObjectClass parent_class; +}; + +struct _StatusServiceDbus { + GObject parent; +}; + +GType status_service_dbus_get_type (void); + +G_END_DECLS + +#endif diff --git a/src/status-service.c b/src/status-service.c new file mode 100644 index 0000000..e31a0db --- /dev/null +++ b/src/status-service.c @@ -0,0 +1,122 @@ + +#include <glib/gi18n.h> + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "dbus-shared-names.h" + +#include "status-service-dbus.h" + +#include "status-provider.h" +#include "status-provider-pidgin.h" + +typedef StatusProvider * (*newfunc) (void); +#define STATUS_PROVIDER_CNT 1 +static newfunc status_provider_newfuncs[STATUS_PROVIDER_CNT] = { + status_provider_pidgin_new +}; +static StatusProvider * status_providers[STATUS_PROVIDER_CNT] = { 0 }; + +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") +}; + +static const gchar * status_icons[STATUS_PROVIDER_STATUS_LAST] = { + /* STATUS_PROVIDER_STATUS_ONLINE, */ "user-online", + /* STATUS_PROVIDER_STATUS_AWAY, */ "user-away", + /* STATUS_PROVIDER_STATUS_DND, */ "user-busy", + /* STATUS_PROVIDER_STATUS_INVISIBLE, */ "user-invisible", + /* STATUS_PROVIDER_STATUS_OFFLINE */ "user-offline" +}; + + +static DbusmenuMenuitem * root_menuitem = NULL; +static GMainLoop * mainloop = NULL; + +static void +status_menu_click (DbusmenuMenuitem * mi, gpointer data) +{ + StatusProviderStatus status = (StatusProviderStatus)GPOINTER_TO_INT(data); + int i; + for (i = 0; i < STATUS_PROVIDER_CNT; i++) { + status_provider_set_status(status_providers[i], status); + } + + return; +} + +static gboolean +build_providers (gpointer data) +{ + int i; + for (i = 0; i < STATUS_PROVIDER_CNT; i++) { + status_providers[i] = status_provider_newfuncs[i](); + } + + return FALSE; +} + +static gboolean +build_menu (gpointer data) +{ + DbusmenuMenuitem * root = DBUSMENU_MENUITEM(data); + g_return_val_if_fail(root != NULL, FALSE); + + StatusProviderStatus i; + for (i = STATUS_PROVIDER_STATUS_ONLINE; i < STATUS_PROVIDER_STATUS_LAST; i++) { + DbusmenuMenuitem * mi = dbusmenu_menuitem_new(); + + dbusmenu_menuitem_property_set(mi, "label", _(status_strings[i])); + dbusmenu_menuitem_property_set(mi, "icon", status_icons[i]); + g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(status_menu_click), GINT_TO_POINTER(i)); + + dbusmenu_menuitem_child_append(root, mi); + + g_debug("Built %s", status_strings[i]); + } + + return FALSE; +} + +int +main (int argc, char ** argv) +{ + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + GError * error = NULL; + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_STATUS_DBUS_NAME, 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + g_idle_add(build_providers, NULL); + + root_menuitem = dbusmenu_menuitem_new(); + DbusmenuServer * server = dbusmenu_server_new(INDICATOR_STATUS_DBUS_OBJECT); + dbusmenu_server_set_root(server, root_menuitem); + + g_idle_add(build_menu, root_menuitem); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + return 0; +} + diff --git a/src/status-service.xml b/src/status-service.xml new file mode 100644 index 0000000..df10859 --- /dev/null +++ b/src/status-service.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<node name="/"> + <interface name="com.ubuntu.indicator.status"> + +<!-- Methods --> + <method name="Watch"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true" /> + </method> + <method name="StatusIcons"> + <arg type="a(s)" name="icons" direction="out" /> + </method> + <method name="PrettyUserName"> + <arg type="s" name="name" direction="out" /> + </method> + +<!-- Signals --> + <signal name="UserChanged"> + <arg type="s" name="name" direction="out" /> + </signal> + <signal name="StatusIconsChanged"> + <arg type="a(s)" name="icons" direction="out" /> + </signal> + + </interface> +</node> diff --git a/src/users-service.c b/src/users-service.c new file mode 100644 index 0000000..39afe39 --- /dev/null +++ b/src/users-service.c @@ -0,0 +1,42 @@ + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "dbus-shared-names.h" + +static DbusmenuMenuitem * root_menuitem = NULL; +static GMainLoop * mainloop = NULL; + +int +main (int argc, char ** argv) +{ + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + GError * error = NULL; + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_USERS_DBUS_NAME, 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + root_menuitem = dbusmenu_menuitem_new(); + DbusmenuServer * server = dbusmenu_server_new(INDICATOR_USERS_DBUS_OBJECT); + dbusmenu_server_set_root(server, root_menuitem); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + return 0; +} + |