aboutsummaryrefslogtreecommitdiff
path: root/libindicate
diff options
context:
space:
mode:
Diffstat (limited to 'libindicate')
-rw-r--r--libindicate/Makefile.am60
-rw-r--r--libindicate/indicate.pc.in2
-rw-r--r--libindicate/indicator-message.c7
-rw-r--r--libindicate/indicator-message.h39
-rw-r--r--libindicate/indicator.c205
-rw-r--r--libindicate/indicator.h72
-rw-r--r--libindicate/interests.h5
-rw-r--r--libindicate/listener-private.h63
-rw-r--r--libindicate/listener.c239
-rw-r--r--libindicate/listener.h14
-rw-r--r--libindicate/server-marshal.list29
-rw-r--r--libindicate/server.c232
-rw-r--r--libindicate/server.h87
13 files changed, 897 insertions, 157 deletions
diff --git a/libindicate/Makefile.am b/libindicate/Makefile.am
index c1900a6..d4746fb 100644
--- a/libindicate/Makefile.am
+++ b/libindicate/Makefile.am
@@ -1,3 +1,6 @@
+MARSHAL_PREFIX = indicate_marshal
+MARSHAL_FILE = indicate-marshal
+ENUM_FILE = indicate-enum-types
INCLUDES= \
-DG_LOG_DOMAIN=\"libindicate\"
@@ -6,6 +9,7 @@ EXTRA_DIST = \
indicate-interface.xml \
indicate-listener.xml \
listener-marshal.list \
+ server-marshal.list \
indicate.pc.in
BUILT_SOURCES = \
@@ -14,7 +18,11 @@ BUILT_SOURCES = \
dbus-listener-server.h \
dbus-listener-client.h \
listener-marshal.c \
- listener-marshal.h
+ listener-marshal.h \
+ server-marshal.c \
+ server-marshal.h \
+ $(ENUM_FILE).h \
+ $(ENUM_FILE).c
lib_LTLIBRARIES = \
libindicate.la
@@ -26,7 +34,8 @@ indicate_headers = \
indicator-message.h \
listener.h \
server.h \
- interests.h
+ interests.h \
+ $(ENUM_FILE).h
libindicateinclude_HEADERS = \
$(indicate_headers)
@@ -37,10 +46,14 @@ libindicate_la_SOURCES = \
dbus-indicate-client.h \
dbus-listener-server.h \
dbus-listener-client.h \
+ indicate-enum-types.c \
server.c \
+ server-marshal.c \
+ server-marshal.h \
listener.c \
listener-marshal.c \
listener-marshal.h \
+ listener-private.h \
indicator.c \
indicator-message.c \
interests-priv.h
@@ -94,9 +107,52 @@ listener-marshal.c: $(srcdir)/listener-marshal.list
--prefix=_indicate_listener_marshal $(srcdir)/listener-marshal.list \
> listener-marshal.c
+server-marshal.h: $(srcdir)/server-marshal.list
+ glib-genmarshal --header \
+ --prefix=_indicate_server_marshal $(srcdir)/server-marshal.list \
+ > server-marshal.h
+
+server-marshal.c: $(srcdir)/server-marshal.list
+ glib-genmarshal --body \
+ --prefix=_indicate_server_marshal $(srcdir)/server-marshal.list \
+ > server-marshal.c
+
pkgconfig_DATA = indicate.pc
pkgconfigdir = $(libdir)/pkgconfig
+$(ENUM_FILE).h: s-enum-types-h
+ @true
+s-enum-types-h: $(indicate_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#ifndef _INDICATE_ENUM_TYPES_H_\n#define _INDICATE_ENUM_TYPES_H_\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type(void);\n#define INDICATE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* _INDICATE_ENUM_TYPES_H_ */" \
+ interests.h ) > tmp-$(ENUM_FILE).h \
+ && (cmp -s tmp-$(ENUM_FILE).h $(ENUM_FILE).h || cp tmp-$(ENUM_FILE).h $(ENUM_FILE).h ) \
+ && rm -f tmp-$(ENUM_FILE).h \
+ && echo timestamp > $(@F)
+
+$(ENUM_FILE).c: s-enum-types-c
+ @true
+s-enum-types-c: $(indicate_headers) Makefile
+ ( cd $(srcdir) && glib-mkenums \
+ --fhead "#include \"interests.h\"\n#include <glib-object.h>" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
+ interests.h ) > tmp-$(ENUM_FILE).c \
+ && (cmp -s tmp-$(ENUM_FILE).c $(ENUM_FILE).c || cp tmp-$(ENUM_FILE).c $(ENUM_FILE).c ) \
+ && rm -f tmp-$(ENUM_FILE).c \
+ && echo timestamp > $(@F)
+
+CLEANFILES = \
+ $(ENUM_FILE).c \
+ $(ENUM_FILE).h \
+ s-enum-types-c \
+ s-enum-types-h
+
if USE_GIR
gobjectintrospection_gir_DATA = \
diff --git a/libindicate/indicate.pc.in b/libindicate/indicate.pc.in
index cdc79b6..ff17ecb 100644
--- a/libindicate/indicate.pc.in
+++ b/libindicate/indicate.pc.in
@@ -5,7 +5,7 @@ bindir=@bindir@
includedir=@includedir@
Cflags: -I${includedir}/libindicate-0.1
-Requires: gtk+-2.0 dbus-glib-1
+Requires: gobject-2.0 glib-2.0 dbus-glib-1
Libs: -L${libdir} -lindicate
Name: libindicate
diff --git a/libindicate/indicator-message.c b/libindicate/indicator-message.c
index 4e8ef30..9cd735a 100644
--- a/libindicate/indicator-message.c
+++ b/libindicate/indicator-message.c
@@ -85,6 +85,13 @@ indicate_indicator_message_finalize (GObject *object)
G_OBJECT_CLASS (indicate_indicator_message_parent_class)->finalize (object);
}
+/**
+ indicate_indicator_message_new:
+
+ Builds a new indicator message object using #g_object_new.
+
+ Return value: A pointer to a new #IndicateIndicatorMessage object.
+*/
static const gchar *
get_indicator_type (IndicateIndicator * indicator)
{
diff --git a/libindicate/indicator-message.h b/libindicate/indicator-message.h
index 0910477..76273c6 100644
--- a/libindicate/indicator-message.h
+++ b/libindicate/indicator-message.h
@@ -47,19 +47,46 @@ G_BEGIN_DECLS
typedef struct _IndicateIndicatorMessage IndicateIndicatorMessage;
typedef struct _IndicateIndicatorMessageClass IndicateIndicatorMessageClass;
-struct _IndicateIndicatorMessageClass
-{
-IndicateIndicatorClass parent_class;
+/**
+ IndicateIndicatorMessageClass:
+ @parent_class: Parent Class
+
+ Subclass of #IndicateIndicator with no new functions or signals.
+*/
+struct _IndicateIndicatorMessageClass {
+ IndicateIndicatorClass parent_class;
};
-struct _IndicateIndicatorMessage
-{
-IndicateIndicator parent;
+/**
+ IndicateIndicatorMessage:
+
+ A class to represent indicators who's 'type' is "message". These
+ are basically indicators that represent messages from humans to
+ humans via computers. Things like instance messages, micro blogging
+ entries or e-mails. All of these qualify as messages.
+
+ TODO: This should include a list of properties that are supported.
+*/
+struct _IndicateIndicatorMessage {
+ IndicateIndicator parent;
};
GType indicate_indicator_message_get_type (void);
IndicateIndicatorMessage * indicate_indicator_message_new (void);
+/**
+ SECTION:indicator-message
+ @short_description: A representation of human generated messages
+ @stability: Unstable
+ @include: libindicate/indicator-message.h
+
+ The message indicators represent messages that come from humans
+ to humans using computers. They come in all different forms with
+ various different interaction protocols, but they all want the human
+ at the computer to interact back with the human that sent the
+ message.
+*/
+
G_END_DECLS
#endif
diff --git a/libindicate/indicator.c b/libindicate/indicator.c
index dfcba67..cb257eb 100644
--- a/libindicate/indicator.c
+++ b/libindicate/indicator.c
@@ -76,6 +76,14 @@ indicate_indicator_class_init (IndicateIndicatorClass * class)
gobj->finalize = indicate_indicator_finalize;
+ /**
+ IndicateIndicator::display:
+ @arg0: The #IndicateIndicator object
+
+ Emitted when the user has clicked on this indicator. In the
+ messaging indicator this would be when someone clicks on the
+ menu item for the indicator.
+ */
signals[USER_DISPLAY] = g_signal_new(INDICATE_INDICATOR_SIGNAL_DISPLAY,
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_LAST,
@@ -83,6 +91,15 @@ indicate_indicator_class_init (IndicateIndicatorClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /**
+ IndicateIndicator::hide:
+ @arg0: The #IndicateIndicator object
+
+ Emitted every time this indicator is hidden. This
+ is mostly used by #IndicateServer.
+
+ Typically this results in an emition of #IndicateServer::indicator-removed.
+ */
signals[HIDE] = g_signal_new(INDICATE_INDICATOR_SIGNAL_HIDE,
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_LAST,
@@ -90,6 +107,15 @@ indicate_indicator_class_init (IndicateIndicatorClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /**
+ IndicateIndicator::show:
+ @arg0: The #IndicateIndicator object
+
+ Emitted every time this indicator is shown. This
+ is mostly used by #IndicateServer.
+
+ Typically this results in an emition of #IndicateServer::indicator-added.
+ */
signals[SHOW] = g_signal_new(INDICATE_INDICATOR_SIGNAL_SHOW,
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_LAST,
@@ -97,6 +123,16 @@ indicate_indicator_class_init (IndicateIndicatorClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /**
+ IndicateIndicator::modified:
+ @arg0: The #IndicateIndicator object
+ @arg1: The name of the property that changed.
+
+ Emitted every time an indicator property is changed.
+ This is mostly used by #IndicateServer.
+
+ Typically this results in an emition of #IndicateServer::indicator-modified.
+ */
signals[MODIFIED] = g_signal_new(INDICATE_INDICATOR_SIGNAL_MODIFIED,
G_TYPE_FROM_CLASS(class),
G_SIGNAL_RUN_LAST,
@@ -145,6 +181,21 @@ indicate_indicator_finalize (GObject * obj)
return;
}
+/**
+ indicate_indicator_get_type:
+
+ Gets a unique #GType for the #IndicateIndicator objects.
+
+ Return value: A unique #GType value.
+*/
+
+/**
+ indicate_indicator_new:
+
+ Builds a new indicator object using g_object_new().
+
+ Return value: A pointer to a new #IndicateIndicator object.
+*/
IndicateIndicator *
indicate_indicator_new (void)
{
@@ -152,6 +203,44 @@ indicate_indicator_new (void)
return indicator;
}
+/**
+ indicate_indicator_new_with_server:
+ @server: The server that should be associated with this indicator.
+
+ Builds a new indicator object using g_object_new() and sets
+ the server to the specified server. Also, adds a reference
+ to the server.
+
+ Return value: A pointer to a new #IndicateIndicator object.
+*/
+IndicateIndicator *
+indicate_indicator_new_with_server (IndicateServer * server)
+{
+ g_return_val_if_fail(server != NULL, NULL);
+
+ IndicateIndicator * indicator = g_object_new(INDICATE_TYPE_INDICATOR, NULL);
+
+ IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
+ if (priv->server != NULL) {
+ g_object_unref(priv->server);
+ priv->server = NULL;
+ }
+
+ priv->server = server;
+ g_object_ref(priv->server);
+
+ return indicator;
+}
+
+
+/**
+ indicate_indicator_show:
+ @indicator: a #IndicateIndicator to act on
+
+ Shows this indicator on the bus. If the #IndicateServer that it's
+ connected to is not shown itself this function will show the server
+ as well using #indicate_server_show.
+*/
void
indicate_indicator_show (IndicateIndicator * indicator)
{
@@ -171,6 +260,13 @@ indicate_indicator_show (IndicateIndicator * indicator)
return;
}
+/**
+ indicate_indicator_hide:
+ @indicator: a #IndicateIndicator to act on
+
+ Hides the indicator from the bus. Does not effect the
+ indicator's #IndicateServer in any way.
+*/
void
indicate_indicator_hide (IndicateIndicator * indicator)
{
@@ -186,6 +282,14 @@ indicate_indicator_hide (IndicateIndicator * indicator)
return;
}
+/**
+ indicate_indicator_is_visible:
+ @indicator: a #IndicateIndicator to act on
+
+ Checkes the visibility status of @indicator.
+
+ Return value: %TRUE if the indicator is visible else %FALSE.
+*/
gboolean
indicate_indicator_is_visible (IndicateIndicator * indicator)
{
@@ -194,6 +298,15 @@ indicate_indicator_is_visible (IndicateIndicator * indicator)
return priv->is_visible;
}
+/**
+ indicate_indicator_get_id:
+ @indicator: a #IndicateIndicator to act on
+
+ Gets the ID value of the @indicator.
+
+ Return value: The ID of the indicator. Can not be zero.
+ Zero represents an error.
+*/
guint
indicate_indicator_get_id (IndicateIndicator * indicator)
{
@@ -202,6 +315,15 @@ indicate_indicator_get_id (IndicateIndicator * indicator)
return priv->id;
}
+/**
+ indicate_indicator_get_indicator_type:
+ @indicator: a #IndicateIndicator to act on
+
+ Returns the type of @indicator. This is largely set by the subclass
+ that the indicator was built with and should not be free'd.
+
+ Return value: A string defining the type or NULL for no type.
+*/
const gchar *
indicate_indicator_get_indicator_type (IndicateIndicator * indicator)
{
@@ -215,6 +337,14 @@ indicate_indicator_get_indicator_type (IndicateIndicator * indicator)
return NULL;
}
+/**
+ indicate_indicator_user_display:
+ @indicator: a #IndicateIndicator to act on
+
+ Emits the #IndicateIndicator::user-display signal simliar to a user
+ clicking on @indicator over the bus. Signal will not be sent if the
+ @indicator is not visible.
+*/
void
indicate_indicator_user_display (IndicateIndicator * indicator)
{
@@ -227,6 +357,18 @@ indicate_indicator_user_display (IndicateIndicator * indicator)
return;
}
+/**
+ indicate_indicator_set_property:
+ @indicator: a #IndicateIndicator to act on
+ @key: name of the property
+ @data: value of the property
+
+ Sets a simple string property on @indicator. If the property
+ had previously been set it will replace it with the new value,
+ otherwise it will create the property. This will include an
+ emition of #IndicateIndicator::modified if the property value
+ was changed.
+*/
void
indicate_indicator_set_property (IndicateIndicator * indicator, const gchar * key, const gchar * data)
{
@@ -238,39 +380,17 @@ indicate_indicator_set_property (IndicateIndicator * indicator, const gchar * ke
return class->set_property(indicator, key, data);
}
-void
-indicate_indicator_set_property_icon (IndicateIndicator * indicator, const gchar * key, const GdkPixbuf * data)
-{
- if (!GDK_IS_PIXBUF(data)) {
- g_warning("Invalide GdkPixbuf");
- return;
- }
-
- GError * error = NULL;
- gchar * png_data;
- gsize png_data_len;
-
- if (!gdk_pixbuf_save_to_buffer((GdkPixbuf *)data, &png_data, &png_data_len, "png", &error, NULL)) {
- if (error == NULL) {
- g_warning("Unable to create pixbuf data stream: %d", png_data_len);
- } else {
- g_warning("Unable to create pixbuf data stream: %s", error->message);
- g_error_free(error);
- error = NULL;
- }
-
- return;
- }
-
- gchar * prop_str = g_base64_encode((guchar *)png_data, png_data_len);
- indicate_indicator_set_property(indicator, key, prop_str);
-
- g_free(prop_str);
- g_free(png_data);
-
- return;
-}
+/**
+ indicate_indicator_set_property_time:
+ @indicator: a #IndicateIndicator to act on
+ @key: name of the property
+ @time: time to set property with
+ This is a helper function that wraps around #indicate_indicator_set_property
+ but takes an #GTimeVal parameter. It then takes the @data
+ parameter converts it to an ISO 8601 time string and
+ uses that data to call #indicate_indicator_set_property.
+*/
void
indicate_indicator_set_property_time (IndicateIndicator * indicator, const gchar * key, GTimeVal * time)
{
@@ -282,6 +402,16 @@ indicate_indicator_set_property_time (IndicateIndicator * indicator, const gchar
return;
}
+/**
+ indicate_indicator_get_property:
+ @indicator: a #IndicateIndicator to act on
+ @key: name of the property
+
+ Returns the value that is set for a property or %NULL if that
+ property is not set.
+
+ Return value: A constant string or NULL.
+*/
const gchar *
indicate_indicator_get_property (IndicateIndicator * indicator, const gchar * key)
{
@@ -293,6 +423,17 @@ indicate_indicator_get_property (IndicateIndicator * indicator, const gchar * ke
return class->get_property(indicator, key);
}
+/**
+ indicate_indicator_list_properties:
+ @indicator: a #IndicateIndicator to act on
+
+ This function gets a list of all the properties that exist
+ on a @indicator. The array may have zero entries but almost
+ always at least has 'type' in it.
+
+ Return value: An array of strings that is the keys of all
+ the properties on this indicator.
+*/
GPtrArray *
indicate_indicator_list_properties (IndicateIndicator * indicator)
{
diff --git a/libindicate/indicator.h b/libindicate/indicator.h
index 8af5568..20b998d 100644
--- a/libindicate/indicator.h
+++ b/libindicate/indicator.h
@@ -33,8 +33,6 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib.h>
#include <glib-object.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
G_BEGIN_DECLS
/* Boilerplate */
@@ -56,10 +54,45 @@ G_BEGIN_DECLS
typedef struct _IndicateIndicator IndicateIndicator;
typedef struct _IndicateIndicatorClass IndicateIndicatorClass;
+/**
+ IndicateIndicator:
+
+ The indicator object represents a single item that is shared over the
+ indicator bus. This could be something like one IM, one e-mail or
+ a single system update. It should be accessed only through its
+ accessors.
+*/
struct _IndicateIndicator {
GObject parent;
};
+#include "server.h"
+
+/**
+ IndicateIndicatorClass:
+ @parent_class: Parent class #GObjectClass.
+ @hide: Slot for #IndicateIndicator::hide.
+ @show: Slot for #IndicateIndicator::show.
+ @user_display: Slot for #IndicateIndicator::user-display.
+ @modified: Slot for #IndicateIndicator::modified.
+ @get_type: Returns a constant string for the type of this indicator.
+ Typically gets overridden by subclasses and defines the type of
+ the indicator. Is called by indicate_indicator_get_indicator_type().
+ @set_property: Called when indicate_indicator_set_property() is called
+ and should set the value. While typically it is overridden by
+ subclasses they usually handle special properties themselves and
+ then call the superclass for storage.
+ @get_property: Called when indicate_indicator_get_property() is called
+ and should return the value requested. Many times this is left alone.
+ @list_properties: Called when indicate_indicator_list_properties() is called
+ and returns a list of the properties available. Again this can be
+ overridden by subclasses to handle special properties.
+
+ All of the functions that are used to modify or change data that is
+ in the indicator. Typically gets subclassed by other types of
+ indicators, for example #IndicateIndicatorMessages.
+
+*/
struct _IndicateIndicatorClass {
GObjectClass parent_class;
@@ -76,7 +109,9 @@ struct _IndicateIndicatorClass {
GType indicate_indicator_get_type(void) G_GNUC_CONST;
+/* New Indicator Functions */
IndicateIndicator * indicate_indicator_new (void);
+IndicateIndicator * indicate_indicator_new_with_server (IndicateServer * server);
/* Show and hide this indicator */
void indicate_indicator_show (IndicateIndicator * indicator);
@@ -95,12 +130,41 @@ void indicate_indicator_user_display (IndicateIndicator * indicator);
/* Properties handling */
void indicate_indicator_set_property (IndicateIndicator * indicator, const gchar * key, const gchar * data);
-void indicate_indicator_set_property_icon (IndicateIndicator * indicator, const gchar * key, const GdkPixbuf * data);
void indicate_indicator_set_property_time (IndicateIndicator * indicator, const gchar * key, GTimeVal * time);
const gchar * indicate_indicator_get_property (IndicateIndicator * indicator, const gchar * key);
GPtrArray * indicate_indicator_list_properties (IndicateIndicator * indicator);
+/**
+ SECTION:indicator
+ @short_description: A representation of state for applications
+ @stability: Unstable
+ @include: libindicate/indicator.h
+
+ An indicator is designed to represent a single instance of something
+ in your application. So this might be an IM or Email using #IndicateIndicatorMessage
+ or any other thing that is a small unit of information to pass on
+ to the user.
+
+ Indicators make no promises about how they are preceived by the
+ user, it's up to the listener to represent them in an intutive and
+ visually appealling way. But, what we can do is provide information
+ on the indicator to provide enough information for the listener
+ to do that.
+
+ Mostly this is done through properties. The only property that is
+ defined for the base indicator is the 'type' property. And this
+ is only available to set by creating a subclass of the
+ #IndicateIndicator object. It is assumed that you can look at the
+ definitions of the various subtypes to determine which properties
+ they support.
+
+ It may be that some users don't want to create objects for every
+ indicator as it could be a lot of overhead if there are large numbers
+ and there is already a data structure representing them all. In that
+ case it is recommended that you ignore the #IndicateIndicator object
+ tree in general and move to subclassing #IndicateServer directly.
+*/
+
G_END_DECLS
#endif /* INDICATE_INDICATOR_H_INCLUDED__ */
-
diff --git a/libindicate/interests.h b/libindicate/interests.h
index 70c52d9..1c6215a 100644
--- a/libindicate/interests.h
+++ b/libindicate/interests.h
@@ -34,8 +34,7 @@ License version 3 and version 2.1 along with this program. If not, see
G_BEGIN_DECLS
-typedef enum _IndicateInterests IndicateInterests;
-enum _IndicateInterests {
+typedef enum {
INDICATE_INTEREST_NONE, /**< We're of no interest */
INDICATE_INTEREST_SERVER_DISPLAY, /**< Displays the server's existance to the user */
INDICATE_INTEREST_SERVER_SIGNAL, /**< Will send signals to the server to be displayed */
@@ -43,7 +42,7 @@ enum _IndicateInterests {
INDICATE_INTEREST_INDICATOR_SIGNAL, /**< Will return signals based on individual indicators being responded to */
INDICATE_INTEREST_INDICATOR_COUNT, /**< Only displays a count of the indicators */
INDICATE_INTEREST_LAST /**< Makes merges and counting easier */
-};
+} IndicateInterests;
G_END_DECLS
diff --git a/libindicate/listener-private.h b/libindicate/listener-private.h
new file mode 100644
index 0000000..ea1b108
--- /dev/null
+++ b/libindicate/listener-private.h
@@ -0,0 +1,63 @@
+/*
+A library to allow applictions to provide simple indications of
+information to be displayed to users of the application through the
+interface shell.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef INDICATE_LISTENER_PRIVATE_H__
+#define INDICATE_LISTENER_PRIVATE_H__ 1
+
+struct _IndicateListenerServer {
+ gchar * name;
+ DBusGProxy * proxy;
+ DBusGConnection * connection;
+ gboolean interests[INDICATE_INTEREST_LAST];
+};
+
+struct _IndicateListenerIndicator {
+ guint id;
+};
+
+typedef struct _IndicateListenerPrivate IndicateListenerPrivate;
+struct _IndicateListenerPrivate
+{
+ DBusGConnection * session_bus;
+ DBusGConnection * system_bus;
+
+ DBusGProxy * dbus_proxy_session;
+ DBusGProxy * dbus_proxy_system;
+
+ GList * proxies_working;
+ GList * proxies_possible;
+
+ GArray * proxy_todo;
+ guint todo_idle;
+};
+
+#define INDICATE_LISTENER_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATE_TYPE_LISTENER, IndicateListenerPrivate))
+
+#endif /* INDICATE_LISTENER_PRIVATE_H__ */
diff --git a/libindicate/listener.c b/libindicate/listener.c
index 3cc84b6..48ad616 100644
--- a/libindicate/listener.c
+++ b/libindicate/listener.c
@@ -27,6 +27,9 @@ License version 3 and version 2.1 along with this program. If not, see
<http://www.gnu.org/licenses/>
*/
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
#include "listener.h"
#include "listener-marshal.h"
#include <dbus/dbus-glib-bindings.h>
@@ -51,35 +54,7 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-struct _IndicateListenerServer {
- gchar * name;
- DBusGProxy * proxy;
- DBusGConnection * connection;
- gboolean interests[INDICATE_INTEREST_LAST];
-};
-
-struct _IndicateListenerIndicator {
- guint id;
-};
-
-typedef struct _IndicateListenerPrivate IndicateListenerPrivate;
-struct _IndicateListenerPrivate
-{
- DBusGConnection * session_bus;
- DBusGConnection * system_bus;
-
- DBusGProxy * dbus_proxy_session;
- DBusGProxy * dbus_proxy_system;
-
- GList * proxies_working;
- GList * proxies_possible;
-
- GArray * proxy_todo;
- guint todo_idle;
-};
-
-#define INDICATE_LISTENER_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATE_TYPE_LISTENER, IndicateListenerPrivate))
+#include "listener-private.h"
typedef struct {
DBusGProxy * proxy;
@@ -89,6 +64,7 @@ typedef struct {
gchar * type;
IndicateListener * listener;
GHashTable * indicators;
+ guint introspect_level;
IndicateListenerServer server;
} proxy_t;
@@ -129,6 +105,7 @@ static void proxy_indicator_modified (DBusGProxy * proxy, guint id, const gchar
static void proxy_get_indicator_list (DBusGProxy * proxy, GArray * indicators, GError * error, gpointer data);
static void proxy_get_indicator_type (DBusGProxy * proxy, gchar * type, GError * error, gpointer data);
static void proxy_indicators_free (gpointer data);
+static void introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data);
/* DBus interface */
gboolean _indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers);
@@ -154,35 +131,35 @@ indicate_listener_class_init (IndicateListenerClass * class)
G_STRUCT_OFFSET (IndicateListenerClass, indicator_added),
NULL, NULL,
_indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
- G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING);
+ G_TYPE_NONE, 3, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING);
signals[INDICATOR_REMOVED] = g_signal_new(INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateListenerClass, indicator_removed),
NULL, NULL,
_indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
- G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING);
+ G_TYPE_NONE, 3, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING);
signals[INDICATOR_MODIFIED] = g_signal_new(INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateListenerClass, indicator_modified),
NULL, NULL,
_indicate_listener_marshal_VOID__POINTER_POINTER_STRING_STRING,
- G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+ G_TYPE_NONE, 4, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING, G_TYPE_STRING);
signals[SERVER_ADDED] = g_signal_new(INDICATE_LISTENER_SIGNAL_SERVER_ADDED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateListenerClass, server_added),
NULL, NULL,
_indicate_listener_marshal_VOID__POINTER_STRING,
- G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
+ G_TYPE_NONE, 2, INDICATE_TYPE_LISTENER_SERVER, G_TYPE_STRING);
signals[SERVER_REMOVED] = g_signal_new(INDICATE_LISTENER_SIGNAL_SERVER_REMOVED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateListenerClass, server_removed),
NULL, NULL,
_indicate_listener_marshal_VOID__POINTER_STRING,
- G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
+ G_TYPE_NONE, 2, INDICATE_TYPE_LISTENER_SERVER, G_TYPE_STRING);
dbus_g_object_register_marshaller(_indicate_listener_marshal_VOID__UINT_STRING,
G_TYPE_NONE,
@@ -272,8 +249,19 @@ indicate_listener_init (IndicateListener * listener)
static void
indicate_listener_finalize (GObject * obj)
{
- /* IndicateListener * listener = INDICATE_LISTENER(obj); */
-
+ IndicateListener * listener = INDICATE_LISTENER(obj);
+ IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
+
+ if (priv->todo_idle != 0) {
+ g_idle_remove_by_data(obj);
+ }
+ /* Hack: proxy_struct_destroy() lacks a user_data parameter, but since the
+ * caller is responsible for handling params on the stack, it works
+ */
+ g_list_foreach(priv->proxies_possible, (GFunc)proxy_struct_destroy, NULL);
+ g_list_free(priv->proxies_possible);
+ g_list_foreach(priv->proxies_working, (GFunc)proxy_struct_destroy, NULL);
+ g_list_free(priv->proxies_working);
G_OBJECT_CLASS (indicate_listener_parent_class)->finalize (obj);
return;
}
@@ -281,8 +269,6 @@ indicate_listener_finalize (GObject * obj)
IndicateListener *
indicate_listener_new (void)
{
- g_warning("Creating a new listener is generally discouraged, please use indicate_listener_ref_default");
-
IndicateListener * listener;
listener = g_object_new(INDICATE_TYPE_LISTENER, NULL);
return listener;
@@ -499,13 +485,9 @@ todo_idle (gpointer data)
priv->proxies_possible = g_list_prepend(priv->proxies_possible, proxyt);
- /* I think that we need to have this as there is a race
- * condition here. If someone comes on the bus and we get
- * that message, but before we set up the handler for the ServerShow
- * signal it gets sent, we wouldn't get it. So then we would
- * miss an indicator server coming on the bus. I'd like to not
- * generate a warning in every app with DBus though. */
- indicate_listener_server_get_type(listener, &proxyt->server, get_type_cb, proxyt);
+ /* Look through the introspection data to see if this
+ is already a server */
+ introspect_this (NULL, NULL, NULL, proxyt);
return TRUE;
}
@@ -708,8 +690,7 @@ proxy_indicators_free (gpointer data)
typedef enum _get_property_type get_property_type;
enum _get_property_type {
PROPERTY_TYPE_STRING,
- PROPERTY_TYPE_TIME,
- PROPERTY_TYPE_ICON
+ PROPERTY_TYPE_TIME
};
typedef struct _get_property_t get_property_t;
@@ -740,44 +721,6 @@ get_property_cb (DBusGProxy *proxy, char * OUT_value, GError *error, gpointer us
cb(get_property_data->listener, get_property_data->server, get_property_data->indicator, get_property_data->property, OUT_value, get_property_data->data);
break;
}
- case PROPERTY_TYPE_ICON: {
- indicate_listener_get_property_icon_cb cb = (indicate_listener_get_property_icon_cb)get_property_data->cb;
-
- /* There is no icon */
- if (OUT_value == NULL || OUT_value[0] == '\0') {
- break;
- }
-
- gsize length = 0;
- guchar * icondata = g_base64_decode(OUT_value, &length);
-
- GInputStream * input = g_memory_input_stream_new_from_data(icondata, length, NULL);
- if (input == NULL) {
- g_warning("Cound not create input stream from icon property data");
- g_free(icondata);
- break;
- }
-
- GError * error = NULL;
- GdkPixbuf * icon = gdk_pixbuf_new_from_stream(input, NULL, &error);
- if (icon != NULL) {
- cb(get_property_data->listener, get_property_data->server, get_property_data->indicator, get_property_data->property, icon, get_property_data->data);
- }
-
- if (error != NULL) {
- g_warning("Unable to build Pixbuf from icon data: %s", error->message);
- g_error_free(error);
- }
-
- error = NULL;
- g_input_stream_close(input, NULL, &error);
- if (error != NULL) {
- g_warning("Unable to close input stream: %s", error->message);
- g_error_free(error);
- }
- g_free(icondata);
- break;
- }
case PROPERTY_TYPE_TIME: {
indicate_listener_get_property_time_cb cb = (indicate_listener_get_property_time_cb)get_property_data->cb;
GTimeVal time;
@@ -824,12 +767,6 @@ indicate_listener_get_property_time (IndicateListener * listener, IndicateListen
return get_property_helper(listener, server, indicator, property, G_CALLBACK(callback), data, PROPERTY_TYPE_TIME);
}
-void
-indicate_listener_get_property_icon (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, indicate_listener_get_property_icon_cb callback, gpointer data)
-{
- return get_property_helper(listener, server, indicator, property, G_CALLBACK(callback), data, PROPERTY_TYPE_ICON);
-}
-
gboolean
_indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers)
{
@@ -1002,6 +939,10 @@ interest_cb (DBusGProxy *proxy, GError *error, gpointer userdata)
void
indicate_listener_server_show_interest (IndicateListener * listener, IndicateListenerServer * server, IndicateInterests interest)
{
+ if (!(interest > INDICATE_INTEREST_NONE && interest < INDICATE_INTEREST_LAST)) {
+ return;
+ }
+
if (!server->interests[interest]) {
org_freedesktop_indicator_show_interest_async (server->proxy, interest_to_string(interest), interest_cb, server);
server->interests[interest] = TRUE;
@@ -1025,3 +966,119 @@ indicate_listener_server_check_interest (IndicateListener * listener, IndicateLi
return server->interests[interest];
}
+GType
+indicate_listener_server_get_gtype (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_pointer_type_register_static ("IndicateListenerServer");
+
+ return our_type;
+}
+
+GType
+indicate_listener_indicator_get_gtype (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ our_type = g_pointer_type_register_static ("IndicateListenerIndicator");
+
+ return our_type;
+}
+
+static const gchar * _introspector_path[] = {"", "org", "freedesktop", "indicate", NULL};
+static const gchar * _introspector_fullpath[] = {"/", "/org", "/org/freedesktop", "/org/freedesktop/indicate", NULL};
+static const gchar * _introspector_interface = "org.freedesktop.indicator";
+
+static void
+introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data)
+{
+ /* g_debug("Introspect this:\n%s", OUT_data); */
+ proxy_t * server = (proxy_t *)data;
+ if (proxy != NULL) {
+ g_object_unref(proxy);
+ }
+ if (error != NULL) {
+ /* We probably couldn't introspect that far up. That's
+ life, it happens. Or there's a timeout, that happens
+ too, I guess some apps are too busy for us. */
+ /* g_debug("Introspection error on %s object %s: %s", server->name, _introspector_fullpath[server->introspect_level], error->message); */
+ return;
+ }
+
+ if (OUT_data != NULL) {
+ xmlDocPtr xmldoc;
+ /* Parse the XML */
+ xmldoc = xmlReadMemory(OUT_data, g_utf8_strlen(OUT_data, 16*1024), "introspection.xml", NULL, 0);
+
+ /* Check for root being "node" */
+ xmlNodePtr root = xmlDocGetRootElement(xmldoc);
+ if (g_strcmp0(root->name, "node") != 0) {
+ xmlFreeDoc(xmldoc);
+ g_warning("Introspection data from %s is not valid: %s", server->name, OUT_data);
+ return;
+ }
+
+ server->introspect_level += 1;
+ const gchar * nodename = NULL;
+ const gchar * nameval = NULL;
+ if (_introspector_path[server->introspect_level] == NULL) {
+ /* We're looking for our interface */
+ nodename = "interface";
+ nameval = _introspector_interface;
+ } else {
+ /* We're looking for our next node */
+ nodename = "node";
+ nameval = _introspector_path[server->introspect_level];
+ }
+
+ gboolean found = FALSE;
+ xmlNodePtr children;
+ for (children = root->children; children != NULL; children = children->next) {
+ gchar * xmlnameval = NULL;
+ if (g_strcmp0(children->name, nodename) == 0) {
+ xmlAttrPtr attrib;
+ for (attrib = children->properties; attrib != NULL; attrib = attrib->next) {
+ if (g_strcmp0(attrib->name, "name") == 0) {
+ if (attrib->children != NULL) {
+ xmlnameval = attrib->children->content;
+ }
+ break;
+ }
+ }
+
+ if (!g_strcmp0(nameval, xmlnameval)) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ xmlFreeDoc(xmldoc);
+
+ if (!found) {
+ /* Ah, nothing we're interested in */
+ return;
+ }
+
+ if (_introspector_path[server->introspect_level] == NULL) {
+ /* If we've found the interface at the end of the tree, whoo! hoo! */
+ /* Now we know it's safe to get the type on it */
+ indicate_listener_server_get_type(server->listener, &server->server, get_type_cb, server);
+ return;
+ }
+ } else {
+ server->introspect_level = 0;
+ }
+
+ DBusGProxy * newproxy = dbus_g_proxy_new_for_name(server->connection,
+ server->name,
+ _introspector_fullpath[server->introspect_level],
+ DBUS_INTERFACE_INTROSPECTABLE);
+
+ org_freedesktop_DBus_Introspectable_introspect_async(newproxy, introspect_this, server);
+
+ return;
+}
diff --git a/libindicate/listener.h b/libindicate/listener.h
index 0fdaa9b..37cda03 100644
--- a/libindicate/listener.h
+++ b/libindicate/listener.h
@@ -33,8 +33,6 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib.h>
#include <glib-object.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
#include "indicator.h"
#include "server.h"
#include "interests.h"
@@ -59,7 +57,12 @@ G_BEGIN_DECLS
#define INDICATE_LISTENER_INDICATOR_ID(indicator) (indicate_listener_indicator_get_id(indicator))
typedef struct _IndicateListenerServer IndicateListenerServer;
+#define INDICATE_TYPE_LISTENER_SERVER (indicate_listener_server_get_gtype ())
+GType indicate_listener_server_get_gtype (void) G_GNUC_CONST;
+
typedef struct _IndicateListenerIndicator IndicateListenerIndicator;
+#define INDICATE_TYPE_LISTENER_INDICATOR (indicate_listener_indicator_get_gtype ())
+GType indicate_listener_indicator_get_gtype (void) G_GNUC_CONST;
typedef struct _IndicateListener IndicateListener;
struct _IndicateListener {
@@ -83,7 +86,6 @@ GType indicate_listener_get_type (void) G_GNUC_CONST;
typedef void (*indicate_listener_get_property_cb) (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, gchar * propertydata, gpointer data);
typedef void (*indicate_listener_get_property_time_cb) (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GTimeVal * propertydata, gpointer data);
-typedef void (*indicate_listener_get_property_icon_cb) (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GdkPixbuf * propertydata, gpointer data);
typedef void (*indicate_listener_get_server_property_cb) (IndicateListener * listener, IndicateListenerServer * server, gchar * value, gpointer data);
/* Create a new listener */
@@ -101,12 +103,6 @@ void indicate_listener_get_property_time (IndicateListener * l
gchar * property,
indicate_listener_get_property_time_cb callback,
gpointer data);
-void indicate_listener_get_property_icon (IndicateListener * listener,
- IndicateListenerServer * server,
- IndicateListenerIndicator * indicator,
- gchar * property,
- indicate_listener_get_property_icon_cb callback,
- gpointer data);
void indicate_listener_display (IndicateListener * listener,
IndicateListenerServer * server,
IndicateListenerIndicator * indicator);
diff --git a/libindicate/server-marshal.list b/libindicate/server-marshal.list
new file mode 100644
index 0000000..540f0fe
--- /dev/null
+++ b/libindicate/server-marshal.list
@@ -0,0 +1,29 @@
+# A library to allow applictions to provide simple indications of
+# information to be displayed to users of the application through the
+# interface shell.
+#
+# Copyright 2009 Canonical Ltd.
+#
+# Authors:
+# Ted Gould <ted@canonical.com>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of either or both of the following licenses:
+#
+# 1) the GNU Lesser General Public License version 3, as published by the
+# Free Software Foundation; and/or
+# 2) the GNU Lesser General Public License version 2.1, 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 applicable version of the GNU Lesser General Public
+# License for more details.
+#
+# You should have received a copy of both the GNU Lesser General Public
+# License version 3 and version 2.1 along with this program. If not, see
+# <http://www.gnu.org/licenses/>
+#
+# IndicatorAdded
+VOID:UINT,STRING
diff --git a/libindicate/server.c b/libindicate/server.c
index e3d071c..a3d3be8 100644
--- a/libindicate/server.c
+++ b/libindicate/server.c
@@ -29,6 +29,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "server.h"
#include "interests-priv.h"
+#include "server-marshal.h"
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
@@ -163,41 +164,101 @@ indicate_server_class_init (IndicateServerClass * class)
gobj->set_property = set_property;
gobj->get_property = get_property;
+ /**
+ IndicateServer::indicator-added:
+ @arg0: The #IndicateServer object
+ @arg1: The #IndicateIndicator ID number
+ @arg2: The type of the indicator
+
+ Emitted every time that a new indicator is made visible to
+ the world. This results in a signal on DBus.
+
+ Can be emitted by subclasses using indicate_server_emit_indicator_added()
+ */
signals[INDICATOR_ADDED] = g_signal_new(INDICATE_SERVER_SIGNAL_INDICATOR_ADDED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateServerClass, indicator_added),
NULL, NULL,
- g_cclosure_marshal_VOID__UINT_POINTER,
+ _indicate_server_marshal_VOID__UINT_STRING,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+ /**
+ IndicateServer::indicator-removed:
+ @arg0: The #IndicateServer object
+ @arg1: The #IndicateIndicator ID number
+ @arg2: The type of the indicator
+
+ Emitted every time that a new indicator is made invisible to
+ the world. This results in a signal on DBus.
+
+ Can be emitted by subclasses using indicate_server_emit_indicator_removed()
+ */
signals[INDICATOR_REMOVED] = g_signal_new(INDICATE_SERVER_SIGNAL_INDICATOR_REMOVED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateServerClass, indicator_removed),
NULL, NULL,
- g_cclosure_marshal_VOID__UINT_POINTER,
+ _indicate_server_marshal_VOID__UINT_STRING,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+ /**
+ IndicateServer::indicator-modified:
+ @arg0: The #IndicateServer object
+ @arg1: The #IndicateIndicator ID number
+ @arg2: The name of the property modified
+
+ Emitted every time that a property on an indicator changes
+ and it is visible to the world. This results in a signal on DBus.
+
+ Can be emitted by subclasses using indicate_server_emit_indicator_modified()
+ */
signals[INDICATOR_MODIFIED] = g_signal_new(INDICATE_SERVER_SIGNAL_INDICATOR_MODIFIED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateServerClass, indicator_modified),
NULL, NULL,
- g_cclosure_marshal_VOID__UINT_POINTER,
+ _indicate_server_marshal_VOID__UINT_STRING,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+ /**
+ IndicateServer::server-show:
+ @arg0: The #IndicateServer object
+ @arg1: The type of the server
+
+ Emitted when a server comes onto DBus by being shown. This
+ is typically when listeners start reacting to the application's
+ indicators. This results in a signal on DBus.
+ */
signals[SERVER_SHOW] = g_signal_new(INDICATE_SERVER_SIGNAL_SERVER_SHOW,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateServerClass, server_show),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
+ g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
+ /**
+ IndicateServer::server-hide:
+ @arg0: The #IndicateServer object
+ @arg1: The type of the server
+
+ Emitted when a server removes itself from DBus. This results
+ in a signal on DBus.
+ */
signals[SERVER_HIDE] = g_signal_new(INDICATE_SERVER_SIGNAL_SERVER_HIDE,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateServerClass, server_hide),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
+ g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
+ /**
+ IndicateServer::server-display:
+ @arg0: The #IndicateServer object
+
+ Emitted when a listener signals that the server itself should be
+ displayed. This signal is caused by a user clicking on the application
+ item in the Messaging Menu. This signal is emitted by DBus.
+
+ Can be emitted by subclasses using indicate_server_emit_server_display()
+ */
signals[SERVER_DISPLAY] = g_signal_new(INDICATE_SERVER_SIGNAL_SERVER_DISPLAY,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
@@ -205,6 +266,14 @@ indicate_server_class_init (IndicateServerClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
+ /**
+ IndicateServer::interest-added:
+ @arg0: The #IndicateServer object
+ @arg1: The interest that was added from #IndicateInterests
+
+ Emitted when a listener signals that they are interested in
+ this server for a particular reason. This signal is emitted by DBus.
+ */
signals[INTEREST_ADDED] = g_signal_new(INDICATE_SERVER_SIGNAL_INTEREST_ADDED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
@@ -212,6 +281,14 @@ indicate_server_class_init (IndicateServerClass * class)
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
+ /**
+ IndicateServer::interest-removed:
+ @arg0: The #IndicateServer object
+ @arg1: The interest that was removed from #IndicateInterests
+
+ Emitted when a listener signals that they are no longer interested in
+ this server for a particular reason. This signal is emitted by DBus.
+ */
signals[INTEREST_REMOVED] = g_signal_new(INDICATE_SERVER_SIGNAL_INTEREST_REMOVED,
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
@@ -366,7 +443,17 @@ indicate_server_error_quark (void)
return quark;
}
+/**
+ indicate_server_show:
+ @server: The #IndicateServer to be shown
+ This function exports the object onto DBus and shows it
+ to the world. This will be the start of it receiving external
+ signals from DBus. It is likely that, if there are listeners
+ running, there will several #IndicateServer::interest-added
+ signals coming shortly after this function. This function
+ emits the #IndicateServer::server-added signal across the bus.
+*/
void
indicate_server_show (IndicateServer * server)
{
@@ -403,6 +490,16 @@ indicate_server_show (IndicateServer * server)
return;
}
+/**
+ indicate_server_hide:
+ @server: The #IndicateServer to hide.
+
+ This function hides the server from DBus so that it does
+ not get signals anymore. This causes the signal #IndicateServer::server-hide
+ to be sent across the bus for all listeners. Also internally
+ it will signal #IndicateServer::interest-removed for all the
+ interests that were currently set for this server.
+*/
void
indicate_server_hide (IndicateServer * server)
{
@@ -610,6 +707,16 @@ indicator_modified_cb (IndicateIndicator * indicator, gchar * property, Indicate
g_signal_emit(server, signals[INDICATOR_MODIFIED], 0, indicate_indicator_get_id(indicator), property, TRUE);
}
+/**
+ indicate_server_add_indicator:
+ @server: The #IndicateServer to add the #IndicateIndictor to.
+ @indicator: The #IndicateIndicator to add.
+
+ This function adds an indicator @indicator to the list that are
+ watched by the server @server. This means that signals that are
+ emitted by the indicator will be picked up and passed via DBus onto
+ listeners of the application.
+*/
void
indicate_server_add_indicator (IndicateServer * server, IndicateIndicator * indicator)
{
@@ -633,6 +740,14 @@ indicate_server_add_indicator (IndicateServer * server, IndicateIndicator * indi
return;
}
+/**
+ indicate_server_remove_indicator:
+ @server: The #IndicateServer to remove the #IndicateIndictor from.
+ @indicator: The #IndicateIndicator to remove.
+
+ Removes an indicator @indicator from being watched by the server @server
+ so it's signals are no longer watched and set over DBus.
+*/
void
indicate_server_remove_indicator (IndicateServer * server, IndicateIndicator * indicator)
{
@@ -663,6 +778,15 @@ indicate_server_set_dbus_object (const gchar * obj)
return;
}
+/**
+ indicate_server_set_desktop_file:
+ @server: The #IndicateServer to set the type of
+ @path: The new desktop file representing the server
+
+ This is a convience function to set the #IndicateServer:desktop
+ property of the @server object. The property can also be set
+ via traditional means, but this one is easier to read.
+*/
void
indicate_server_set_desktop_file (IndicateServer * server, const gchar * path)
{
@@ -673,6 +797,15 @@ indicate_server_set_desktop_file (IndicateServer * server, const gchar * path)
return;
}
+/**
+ indicate_server_set_type:
+ @server: The #IndicateServer to set the type of
+ @type: The new type of the server
+
+ This is a convience function to set the #IndicateServer:type
+ property of the @server object. The property can also be set
+ via traditional means, but this one is easier to read.
+*/
void
indicate_server_set_type (IndicateServer * server, const gchar * type)
{
@@ -685,6 +818,17 @@ indicate_server_set_type (IndicateServer * server, const gchar * type)
static IndicateServer * default_indicate_server = NULL;
+/**
+ indicate_server_ref_default:
+
+ This function will return a reference to the default #IndicateServer
+ reference if there is one, or it will create one if one had not
+ previously been created. It is recommended that all applications
+ use this function to create a #IndicateServer as it ensure that there
+ is only one per application.
+
+ Return value: A reference to the default #IndicateServer instance.
+*/
IndicateServer *
indicate_server_ref_default (void)
{
@@ -699,6 +843,16 @@ indicate_server_ref_default (void)
return default_indicate_server;
}
+/**
+ indicate_server_set_default:
+ @server: The #IndicateServer that should be used
+
+ This function is used to set the default #IndicateServer that will
+ be used when creating #IndicateIndicators or for anyone else that
+ calls indicate_server_ref_default(). Typically this is just an
+ instance of #IndicateServer but applications that create a subclass
+ of #IndicateServer should set this as well.
+*/
void
indicate_server_set_default (IndicateServer * server)
{
@@ -1103,6 +1257,15 @@ _indicate_server_show_indicator_to_user (IndicateServer * server, guint id, GErr
return TRUE;
}
+/**
+ indicate_server_get_next_id:
+ @server: The #IndicateServer the ID will be on
+
+ Returns the next available unused ID that an indicator
+ can have.
+
+ Return value: A valid indicator ID.
+*/
guint
indicate_server_get_next_id (IndicateServer * server)
{
@@ -1207,7 +1370,41 @@ _indicate_server_remove_interest (IndicateServer * server, gchar * interest, DBu
return FALSE;
}
+/**
+ indicate_server_check_interest:
+ @server: The #IndicateServer being checked
+ @interest: Which interest type we're checking for
+
+ This function looks at all the interest that various listeners
+ have specified that they have for this server and returns whether
+ there is a listener that has the interest specified in @interest.
+
+ Return value: %TRUE if a listener as the interest otherwise %FALSE
+*/
+gboolean
+indicate_server_check_interest (IndicateServer * server, IndicateInterests interest)
+{
+ IndicateServerClass * class = INDICATE_SERVER_GET_CLASS(server);
+
+ if (class != NULL && class->check_interest != NULL) {
+ return class->check_interest (server, interest);
+ }
+
+ g_warning("check_interest function not implemented in this server class: %s", G_OBJECT_TYPE_NAME(server));
+ return FALSE;
+}
+
/* Signal emission functions for sub-classes of the server */
+
+/**
+ indicate_server_emit_indicator_added:
+ @server: The #IndicateServer being represented
+ @id: The ID of the indicator being added
+ @type: The type of the indicator
+
+ This function emits the #IndicateServer::indicator-added signal and is
+ used by subclasses.
+*/
void
indicate_server_emit_indicator_added (IndicateServer *server, guint id, const gchar *type)
{
@@ -1217,6 +1414,15 @@ indicate_server_emit_indicator_added (IndicateServer *server, guint id, const gc
g_signal_emit(server, signals[INDICATOR_ADDED], 0, id, type);
}
+/**
+ indicate_server_emit_indicator_removed:
+ @server: The #IndicateServer being represented
+ @id: The ID of the indicator being removed
+ @type: The type of the indicator
+
+ This function emits the #IndicateServer::indicator-removed signal and is
+ used by subclasses.
+*/
void
indicate_server_emit_indicator_removed (IndicateServer *server, guint id, const gchar *type)
{
@@ -1226,6 +1432,15 @@ indicate_server_emit_indicator_removed (IndicateServer *server, guint id, const
g_signal_emit(server, signals[INDICATOR_REMOVED], 0, id, type);
}
+/**
+ indicate_server_emit_indicator_modified:
+ @server: The #IndicateServer being represented
+ @id: The ID of the indicator with the modified property
+ @property: The name of the property being modified
+
+ This function emits the #IndicateServer::indicator-modified signal and is
+ used by subclasses.
+*/
void
indicate_server_emit_indicator_modified (IndicateServer *server, guint id, const gchar *property)
{
@@ -1235,6 +1450,13 @@ indicate_server_emit_indicator_modified (IndicateServer *server, guint id, const
g_signal_emit(server, signals[INDICATOR_MODIFIED], 0, id, property);
}
+/**
+ indicate_server_emit_server_display:
+ @server: The #IndicateServer being displayed
+
+ This function emits the #IndicateServer::server-display signal and is
+ used by subclasses.
+*/
void
indicate_server_emit_server_display (IndicateServer *server)
{
diff --git a/libindicate/server.h b/libindicate/server.h
index cfb4334..cff76c4 100644
--- a/libindicate/server.h
+++ b/libindicate/server.h
@@ -33,7 +33,6 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib.h>
#include <glib-object.h>
-#include "indicator.h"
#include "interests.h"
G_BEGIN_DECLS
@@ -57,11 +56,65 @@ G_BEGIN_DECLS
#define INDICATE_SERVER_SIGNAL_INTEREST_ADDED "interest-added"
#define INDICATE_SERVER_SIGNAL_INTEREST_REMOVED "interest-removed"
+/**
+ IndicateServer:
+
+ This is the object that represents the overall connection
+ between this application and DBus. It acts as the proxy for
+ incomming DBus calls and also sends the appropriate signals
+ on DBus for events happening on other objects locally. It
+ provides some settings that effection how the application as
+ a whole is perceived by listeners of the indicator protocol.
+*/
typedef struct _IndicateServer IndicateServer;
struct _IndicateServer {
GObject parent;
};
+#include "indicator.h"
+
+/**
+ IndicateServerClass:
+ @parent: Parent Class
+ @indicator_added: Slot for #IndicateServer::indicator-added.
+ @indicator_removed: Slot for #IndicateServer::indicator-removed.
+ @indicator_modified: Slot for #IndicateServer::indicator-modified.
+ @server_show: Slot for #IndicateServer::server-show.
+ @server_hide: Slot for #IndicateServer::server-hide.
+ @server_display: Slot for #IndicateServer::server-display.
+ @interest_added: Slot for #IndicateServer::interest-added.
+ @interest_removed: Slot for #IndicateServer::interest-removed.
+ @get_indicator_count: Returns the number of indicators that are visible
+ on the bus. Hidden indicators should not be counted.
+ @get_indicator_count_by_type: Returns the number of indicators that are
+ of a given type and visible on the bus.
+ @get_indicator_list: List all of the indicators that are visible.
+ @get_indicator_list_by_type: List all of the indicators of a given
+ type that are visible.
+ @get_indicator_property: Get a property from a particular indicator.
+ @get_indicator_property_group: Get the values for a set of properties
+ as an array of entries, returning an array as well.
+ @get_indicator_properties: Get a list of all the properties that are
+ on a particular indicator.
+ @show_indicator_to_user: Respond to someone on the bus asking to show
+ a particular indicator to the user.
+ @get_next_id: Get the next unused indicator ID.
+ @show_interest: React to someone signifying that they are interested
+ in this server.
+ @remove_interest: Someone on the bus is no longer interest in this
+ server, remove it's interest.
+ @check_interest: Check to see if anyone on the bus is interested in this
+ server for a particular feature.
+ @indicate_server_reserved1: Reserved for future use
+ @indicate_server_reserved2: Reserved for future use
+ @indicate_server_reserved3: Reserved for future use
+ @indicate_server_reserved4: Reserved for future use
+
+ All of the functions and signals that make up the server class
+ including those that are public API to the application and those
+ that are public API to all of DBus. Subclasses may need to
+ implement a large portion of these.
+*/
typedef struct _IndicateServerClass IndicateServerClass;
struct _IndicateServerClass {
GObjectClass parent;
@@ -99,9 +152,6 @@ struct _IndicateServerClass {
GType indicate_server_get_type (void) G_GNUC_CONST;
-/* Create a new server */
-IndicateServer * indicate_server_new (void);
-
/* Sets the object. By default this is /org/freedesktop/indicators */
void indicate_server_set_dbus_object (const gchar * obj);
@@ -134,6 +184,35 @@ void indicate_server_emit_indicator_removed (IndicateServer *server, guint id, c
void indicate_server_emit_indicator_modified (IndicateServer *server, guint id, const gchar *property);
void indicate_server_emit_server_display (IndicateServer *server);
+/**
+ SECTION:server
+ @short_description: The representation of the application on DBus.
+ @stability: Unstable
+ @include: libindicate/server.h
+
+ The server object is the object that provides the functions on
+ to DBus for other applications to call. It does this by implementing
+ the DBus indicator spec, but it also allows for subclassing so that
+ subclasses don't have to worry about the DBus-isms as much as
+ the functionality that they're trying to express.
+
+ For simple applications there is limited need to set anything
+ more than the desktop file and the type of the server using
+ indicate_server_set_desktop_file() and indicate_server_set_type().
+ Each of these function sets the respective value and expresses
+ it in a way that other applications on the bus can read it.
+
+ More advanced applications might find the need to subclass the
+ #IndicateServer object and make their own. This is likely the
+ case where applications have complex data stores that they don't
+ want to turn into a large set of #GObjects that can take up a
+ significant amount of memory in the program.
+
+ In general, it is recommended that application authors go with
+ the high memory path first, and then optimize by implementing
+ their server on a second pass.
+*/
+
G_END_DECLS
#endif /* INDICATE_SERVER_H_INCLUDED__ */