Merge lp:~indicator-applet-developers/libindicator/ubuntu into lp:~ubuntu-desktop/libindicator/ubuntu

Proposed by Ted Gould
Status: Merged
Merge reported by: Ken VanDine
Merged at revision: not available
Proposed branch: lp:~indicator-applet-developers/libindicator/ubuntu
Merge into: lp:~ubuntu-desktop/libindicator/ubuntu
Diff against target: 3570 lines (+3246/-29)
41 files modified
.bzrignore (+40/-0)
Makefile.am (+3/-1)
autogen.sh (+1/-1)
configure.ac (+17/-2)
debian/changelog (+21/-0)
debian/control (+26/-2)
debian/libindicator-dev.install (+4/-0)
debian/libindicator-tools.install (+1/-0)
debian/libindicator0.install (+1/-0)
libindicator/Makefile.am (+53/-2)
libindicator/dbus-shared.h (+28/-0)
libindicator/indicator-object.c (+344/-0)
libindicator/indicator-object.h (+123/-0)
libindicator/indicator-service-manager.c (+493/-0)
libindicator/indicator-service-manager.h (+88/-0)
libindicator/indicator-service.c (+479/-0)
libindicator/indicator-service.h (+85/-0)
libindicator/indicator-service.xml (+21/-0)
libindicator/indicator.h (+4/-18)
libindicator/indicator.pc.in (+3/-3)
tests/Makefile.am (+308/-0)
tests/dummy-indicator-blank.c (+5/-0)
tests/dummy-indicator-null.c (+95/-0)
tests/dummy-indicator-signaler.c (+109/-0)
tests/dummy-indicator-simple.c (+98/-0)
tests/service-manager-connect-service.c (+48/-0)
tests/service-manager-connect.c (+63/-0)
tests/service-manager-connect.service.in (+3/-0)
tests/service-manager-no-connect.c (+47/-0)
tests/service-manager-nostart-connect.c (+65/-0)
tests/service-shutdown-timeout.c (+46/-0)
tests/service-version-bad-service.c (+47/-0)
tests/service-version-bad.service.in (+3/-0)
tests/service-version-good-service.c (+47/-0)
tests/service-version-good.service.in (+3/-0)
tests/service-version-manager.c (+64/-0)
tests/service-version-values.h (+4/-0)
tests/session.conf.in (+40/-0)
tests/test-loader.c (+146/-0)
tools/Makefile.am (+21/-0)
tools/indicator-loader.c (+149/-0)
To merge this branch: bzr merge lp:~indicator-applet-developers/libindicator/ubuntu
Reviewer Review Type Date Requested Status
Ken VanDine Pending
Review via email: mp+15966@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2009-08-07 15:06:32 +0000
3+++ .bzrignore 2009-12-10 17:02:12 +0000
4@@ -103,3 +103,43 @@
5 data/GNOME_IndicatorAppletSUS.server
6 data/GNOME_IndicatorAppletSUS.server.in
7 src-sus/indicator-applet-no-sus
8+libindicator/libindicator.la
9+libindicator/libindicator_la-indicator-object.
10+libindicator/libindicator_la-indicator-object.lo
11+tests/loader-check-results.xml
12+tests/loader-check-results.html
13+tests/test-loader
14+tests/libdummy-indicator-null.la
15+tests/libdummy_indicator_null_la-dummy-indicator-null.lo
16+tests/libdummy-indicator-simple.la
17+tests/libdummy_indicator_simple_la-dummy-indicator-simple.lo
18+tests/libdummy-indicator-blank.la
19+tests/libdummy_indicator_blank_la-dummy-indicator-blank.lo
20+libindicator-[0-9].[0-9].[0-9].tar.gz
21+libindicator-[0-9].[0-9].[0-9].tar.gz.asc
22+libindicator/libindicator_la-indicator-instance.lo
23+tests/libdummy-indicator-signaler.la
24+tests/libdummy_indicator_signaler_la-dummy-indicator-signaler.lo
25+libindicator/indicator-service-client.h
26+libindicator/indicator-service-server.h
27+libindicator/libindicator_la-indicator-service.lo
28+libindicator/libindicator_la-indicator-service-manager.lo
29+tests/service-shutdown-timeout
30+tests/loader-tester
31+tests/service-shutdown-timeout-tester
32+tests/service-manager-no-connect
33+tests/service-manager-no-connect-tester
34+tests/service-manager-connect
35+tests/service-manager-connect-service
36+tests/service-manager-connect-tester
37+tests/session.conf
38+tests/service-manager-connect.service
39+tools/indicator-loader
40+tests/service-version-bad-service
41+tests/service-version-bad.service
42+tests/service-version-good-service
43+tests/service-version-good.service
44+tests/service-version-manager
45+tests/service-version-tester
46+tests/service-manager-connect-nostart-tester
47+tests/service-manager-nostart-connect
48
49=== modified file 'Makefile.am'
50--- Makefile.am 2009-08-18 16:52:09 +0000
51+++ Makefile.am 2009-12-10 17:02:12 +0000
52@@ -1,6 +1,8 @@
53
54 SUBDIRS = \
55- libindicator
56+ libindicator \
57+ tests \
58+ tools
59
60 DISTCLEANFILES = \
61 libindicator-*.tar.gz
62
63=== modified file 'autogen.sh'
64--- autogen.sh 2009-08-18 16:52:09 +0000
65+++ autogen.sh 2009-12-10 17:02:12 +0000
66@@ -8,4 +8,4 @@
67 }
68
69 USE_GNOME2_MACROS=1 \
70-gnome-autogen.sh
71+. gnome-autogen.sh
72
73=== modified file 'configure.ac'
74--- configure.ac 2009-10-08 14:16:40 +0000
75+++ configure.ac 2009-12-10 17:02:12 +0000
76@@ -1,10 +1,10 @@
77
78-AC_INIT(libindicator, 0.2.1, ted@canonical.com)
79+AC_INIT(libindicator, 0.3.0, ted@canonical.com)
80
81 AC_PREREQ(2.53)
82
83 AM_CONFIG_HEADER(config.h)
84-AM_INIT_AUTOMAKE(libindicator, 0.2.1)
85+AM_INIT_AUTOMAKE(libindicator, 0.3.0)
86
87 AM_MAINTAINER_MODE
88 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES])
89@@ -21,6 +21,19 @@
90 m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
91
92 ##############################
93+# Dependencies
94+##############################
95+
96+GTK_REQUIRED_VERSION=2.18
97+DBUS_REQUIRED_VERSION=0.76
98+
99+PKG_CHECK_MODULES(LIBINDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
100+ dbus-glib-1 >= $DBUS_REQUIRED_VERSION)
101+
102+AC_SUBST(LIBINDICATOR_CFLAGS)
103+AC_SUBST(LIBINDICATOR_LIBS)
104+
105+##############################
106 # Custom Junk
107 ##############################
108
109@@ -73,6 +86,8 @@
110 Makefile
111 libindicator/Makefile
112 libindicator/indicator.pc
113+tests/Makefile
114+tools/Makefile
115 ])
116
117 ###########################
118
119=== modified file 'debian/changelog'
120--- debian/changelog 2009-10-09 06:12:31 +0000
121+++ debian/changelog 2009-12-10 17:02:12 +0000
122@@ -1,3 +1,24 @@
123+libindicator (0.3.0-0ubuntu1~ppa1) karmic; urgency=low
124+
125+ * Upstream 0.3.0 Release
126+ * Adds a new tool to load indicators from the command line.
127+ * Adds an object for loading indicators.
128+ * Changes the indicator interface to be object based.
129+ * debian/control, debian/libindicator0: Adding in a new packages
130+ for the binary library.
131+ * debian/control, debian/libindicator-tools: Adding in a new
132+ package for the tools of libindicator.
133+
134+ -- Ted Gould <ted@ubuntu.com> Thu, 10 Dec 2009 10:59:37 -0600
135+
136+libindicator (0.2.1-0ubuntu2~ppa1) karmic; urgency=low
137+
138+ * Adding in service management code.
139+ * debian/control: Adding a target for libindicator0
140+ * Adding libindicator0.install and libindicator-dev.install
141+
142+ -- Ted Gould <ted@ubuntu.com> Wed, 04 Nov 2009 08:19:01 -0600
143+
144 libindicator (0.2.1-0ubuntu1) karmic; urgency=low
145
146 * Upstream release 0.2.1 (LP: #446619)
147
148=== modified file 'debian/control'
149--- debian/control 2009-08-25 06:33:06 +0000
150+++ debian/control 2009-12-10 17:02:12 +0000
151@@ -4,21 +4,45 @@
152 Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
153 Build-Depends: debhelper (>= 5.0),
154 cdbs (>= 0.4.41),
155- libtool
156+ libgtk2.0-dev (>= 2.12.0),
157+ libdbus-glib-1-dev,
158+ libtool,
159+ intltool,
160+ gtk-doc-tools
161 Standards-Version: 3.8.0
162 Homepage: https://launchpad.net/libindicator
163 Vcs-Bzr: https://code.launchpad.net/~ubuntu-desktop/libindicator/ubuntu
164 Vcs-Browser: http://bazaar.launchpad.net/~ubuntu-desktop/libindicator/ubuntu
165
166+Package: libindicator0
167+Section: libs
168+Architecture: any
169+Depends: ${shlibs:Depends},
170+ ${misc:Depends}
171+Description: GNOME panel indicator applet - shared library
172+ This library contains information to build indicators to go into
173+ the indicator applet.
174+ .
175+ This package contains files that are needed to build applications.
176+
177 Package: libindicator-dev
178 Section: libdevel
179 Architecture: any
180 Depends: ${shlibs:Depends},
181 ${misc:Depends},
182- libgtk2.0-dev (>= 2.12.0)
183+ libgtk2.0-dev (>= 2.12.0),
184+ libindicator0 (= ${binary:Version})
185 Description: GNOME panel indicator applet - shared library
186 This library contains information to build indicators to go into
187 the indicator applet.
188 .
189 This package contains files that are needed to build applications.
190
191+Package: libindicator-tools
192+Section: devel
193+Architecture: any
194+Depends: ${shlibs:Depends},
195+ ${misc:Depends},
196+ libindicator0 (= ${binary:Version})
197+Description: Need a better description
198+
199
200=== added file 'debian/libindicator-dev.install'
201--- debian/libindicator-dev.install 1970-01-01 00:00:00 +0000
202+++ debian/libindicator-dev.install 2009-12-10 17:02:12 +0000
203@@ -0,0 +1,4 @@
204+debian/tmp/usr/include/libindicator-0.3/libindicator/*
205+debian/tmp/usr/lib/pkgconfig/indicator.pc
206+debian/tmp/usr/lib/libindicator.a
207+debian/tmp/usr/lib/libindicator.so
208
209=== added file 'debian/libindicator-tools.install'
210--- debian/libindicator-tools.install 1970-01-01 00:00:00 +0000
211+++ debian/libindicator-tools.install 2009-12-10 17:02:12 +0000
212@@ -0,0 +1,1 @@
213+debian/tmp/usr/lib/libindicator/*
214
215=== added file 'debian/libindicator0.install'
216--- debian/libindicator0.install 1970-01-01 00:00:00 +0000
217+++ debian/libindicator0.install 2009-12-10 17:02:12 +0000
218@@ -0,0 +1,1 @@
219+debian/tmp/usr/lib/libindicator.so.*
220
221=== modified file 'libindicator/Makefile.am'
222--- libindicator/Makefile.am 2009-04-21 19:15:22 +0000
223+++ libindicator/Makefile.am 2009-12-10 17:02:12 +0000
224@@ -1,14 +1,65 @@
225+BUILT_SOURCES =
226+CLEANFILES =
227 EXTRA_DIST = \
228 indicator.pc.in
229
230-libindicatorincludedir=$(includedir)/libindicator-0.1/libindicator
231+libindicatorincludedir=$(includedir)/libindicator-0.3/libindicator
232
233 indicator_headers = \
234- indicator.h
235+ indicator.h \
236+ indicator-object.h \
237+ indicator-service.h \
238+ indicator-service-manager.h
239
240 libindicatorinclude_HEADERS = \
241 $(indicator_headers)
242
243+lib_LTLIBRARIES = \
244+ libindicator.la
245+
246+libindicator_la_SOURCES = \
247+ $(indicator_headers) \
248+ dbus-shared.h \
249+ indicator-object.c \
250+ indicator-service.c \
251+ indicator-service-manager.c
252+
253+libindicator_la_CFLAGS = \
254+ $(LIBINDICATOR_CFLAGS) \
255+ -DG_LOG_DOMAIN=\"libindicator\" \
256+ -Wall -Werror
257+
258+libindicator_la_LIBADD = \
259+ $(LIBINDICATOR_LIBS)
260+
261 pkgconfig_DATA = indicator.pc
262 pkgconfigdir = $(libdir)/pkgconfig
263
264+##################################
265+# DBus Specs
266+##################################
267+
268+DBUS_SPECS = \
269+ indicator-service.xml
270+
271+%-client.h: %.xml
272+ dbus-binding-tool \
273+ --prefix=_$(subst -,_,$(basename $(notdir $<)))_client \
274+ --mode=glib-client \
275+ --output=$@ \
276+ $<
277+
278+%-server.h: %.xml
279+ dbus-binding-tool \
280+ --prefix=_$(subst -,_,$(basename $(notdir $<)))_server \
281+ --mode=glib-server \
282+ --output=$@ \
283+ $<
284+
285+BUILT_SOURCES += \
286+ $(DBUS_SPECS:.xml=-client.h) \
287+ $(DBUS_SPECS:.xml=-server.h)
288+
289+CLEANFILES += $(BUILT_SOURCES)
290+
291+EXTRA_DIST += $(DBUS_SPECS)
292
293=== added file 'libindicator/dbus-shared.h'
294--- libindicator/dbus-shared.h 1970-01-01 00:00:00 +0000
295+++ libindicator/dbus-shared.h 2009-12-10 17:02:12 +0000
296@@ -0,0 +1,28 @@
297+/*
298+Shared defines for DBus interfaces and API versions to
299+make sure the server and client agree.
300+
301+Copyright 2009 Canonical Ltd.
302+
303+Authors:
304+ Ted Gould <ted@canonical.com>
305+
306+This library is free software; you can redistribute it and/or
307+modify it under the terms of the GNU General Public License
308+version 3.0 as published by the Free Software Foundation.
309+
310+This library is distributed in the hope that it will be useful,
311+but WITHOUT ANY WARRANTY; without even the implied warranty of
312+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
313+GNU General Public License version 3.0 for more details.
314+
315+You should have received a copy of the GNU General Public
316+License along with this library. If not, see
317+<http://www.gnu.org/licenses/>.
318+*/
319+
320+#define INDICATOR_SERVICE_INTERFACE "org.ayatana.indicator.service"
321+#define INDICATOR_SERVICE_OBJECT "/org/ayatana/indicator/service"
322+
323+#define INDICATOR_SERVICE_VERSION 1
324+
325
326=== added file 'libindicator/indicator-object.c'
327--- libindicator/indicator-object.c 1970-01-01 00:00:00 +0000
328+++ libindicator/indicator-object.c 2009-12-10 17:02:12 +0000
329@@ -0,0 +1,344 @@
330+/*
331+An object to represent loadable indicator modules to make loading
332+them easy and objectified.
333+
334+Copyright 2009 Canonical Ltd.
335+
336+Authors:
337+ Ted Gould <ted@canonical.com>
338+
339+This library is free software; you can redistribute it and/or
340+modify it under the terms of the GNU General Public License
341+version 3.0 as published by the Free Software Foundation.
342+
343+This library is distributed in the hope that it will be useful,
344+but WITHOUT ANY WARRANTY; without even the implied warranty of
345+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
346+GNU General Public License version 3.0 for more details.
347+
348+You should have received a copy of the GNU General Public
349+License along with this library. If not, see
350+<http://www.gnu.org/licenses/>.
351+*/
352+
353+#ifdef HAVE_CONFIG_H
354+#include "config.h"
355+#endif
356+
357+#include "indicator.h"
358+#include "indicator-object.h"
359+
360+/**
361+ IndicatorObjectPrivate:
362+ @module: The loaded module representing the object. Note to
363+ subclasses: This will not be set when you're initalized.
364+ @entry: A default entry for objects that don't need all the
365+ fancy stuff. This works with #get_entries_default.
366+ @gotten_entries: A check to see if the @entry has been
367+ populated intelligently yet.
368+
369+ Structure to define the memory for the private area
370+ of the object instance.
371+*/
372+struct _IndicatorObjectPrivate {
373+ GModule * module;
374+
375+ /* For get_entries_default */
376+ IndicatorObjectEntry entry;
377+ gboolean gotten_entries;
378+};
379+
380+#define INDICATOR_OBJECT_GET_PRIVATE(o) (INDICATOR_OBJECT(o)->priv)
381+
382+/* Signals Stuff */
383+enum {
384+ ENTRY_ADDED,
385+ ENTRY_REMOVED,
386+ LAST_SIGNAL
387+};
388+
389+static guint signals[LAST_SIGNAL] = { 0 };
390+
391+/* GObject stuff */
392+static void indicator_object_class_init (IndicatorObjectClass *klass);
393+static void indicator_object_init (IndicatorObject *self);
394+static void indicator_object_dispose (GObject *object);
395+static void indicator_object_finalize (GObject *object);
396+
397+static GList * get_entries_default (IndicatorObject * io);
398+
399+G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT);
400+
401+/* Setup the class and put the functions into the
402+ class structure */
403+static void
404+indicator_object_class_init (IndicatorObjectClass *klass)
405+{
406+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
407+
408+ g_type_class_add_private (klass, sizeof (IndicatorObjectPrivate));
409+
410+ object_class->dispose = indicator_object_dispose;
411+ object_class->finalize = indicator_object_finalize;
412+
413+ klass->get_label = NULL;
414+ klass->get_menu = NULL;
415+ klass->get_image = NULL;
416+
417+ klass->get_entries = get_entries_default;
418+
419+ /**
420+ IndicatorObject::entry-added:
421+ @arg0: The #IndicatorObject object
422+
423+ Signaled when a new entry is added and should
424+ be shown by the person using this object.
425+ */
426+ signals[ENTRY_ADDED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED,
427+ G_TYPE_FROM_CLASS(klass),
428+ G_SIGNAL_RUN_LAST,
429+ G_STRUCT_OFFSET (IndicatorObjectClass, entry_added),
430+ NULL, NULL,
431+ g_cclosure_marshal_VOID__POINTER,
432+ G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE);
433+
434+ /**
435+ IndicatorObject::entry-removed:
436+ @arg0: The #IndicatorObject object
437+
438+ Signaled when an entry is removed and should
439+ be removed by the person using this object.
440+ */
441+ signals[ENTRY_REMOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED,
442+ G_TYPE_FROM_CLASS(klass),
443+ G_SIGNAL_RUN_LAST,
444+ G_STRUCT_OFFSET (IndicatorObjectClass, entry_removed),
445+ NULL, NULL,
446+ g_cclosure_marshal_VOID__POINTER,
447+ G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE);
448+
449+ return;
450+}
451+
452+/* Initialize an instance */
453+static void
454+indicator_object_init (IndicatorObject *self)
455+{
456+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_OBJECT_TYPE, IndicatorObjectPrivate);
457+
458+ self->priv->module = NULL;
459+
460+ self->priv->entry.menu = NULL;
461+ self->priv->entry.label = NULL;
462+ self->priv->entry.image = NULL;
463+
464+ self->priv->gotten_entries = FALSE;
465+
466+ return;
467+}
468+
469+/* Unref the objects that we're holding on to. */
470+static void
471+indicator_object_dispose (GObject *object)
472+{
473+
474+ G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object);
475+ return;
476+}
477+
478+/* A small helper function that closes a module but
479+ in the function prototype of a GSourceFunc. */
480+static gboolean
481+module_unref (gpointer data)
482+{
483+ if (!g_module_close((GModule *)data)) {
484+ /* All we can do is warn. */
485+ g_warning("Unable to close module!");
486+ }
487+ return FALSE;
488+}
489+
490+/* Free memory */
491+static void
492+indicator_object_finalize (GObject *object)
493+{
494+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
495+
496+ if (priv->module != NULL) {
497+ /* Wow, this is convoluted. So basically we want to unref
498+ the module which will cause the code it included to be
499+ removed. But, since it's finalize function is the function
500+ that called this one, we can't really remove it before
501+ it finishes being executed. So we're putting the job into
502+ the main loop to remove it the next time it gets a chance.
503+ Slightly non-deterministic, but should work. */
504+ g_idle_add(module_unref, priv->module);
505+ priv->module = NULL;
506+ }
507+
508+ G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object);
509+ return;
510+}
511+
512+/**
513+ indicator_object_new_from_file:
514+ @file: Filename containing a loadable module
515+
516+ This function builds an #IndicatorObject using the symbols
517+ that are found in @file. The module is loaded and the
518+ references are all kept by the object. To unload the
519+ module the object must be destroyed.
520+
521+ Return value: A valid #IndicatorObject or #NULL if error.
522+*/
523+IndicatorObject *
524+indicator_object_new_from_file (const gchar * file)
525+{
526+ GObject * object = NULL;
527+ GModule * module = NULL;
528+
529+ /* Check to make sure the name exists and that the
530+ file itself exists */
531+ if (file == NULL) {
532+ g_warning("Invalid filename.");
533+ return NULL;
534+ }
535+
536+ if (!g_file_test(file, G_FILE_TEST_EXISTS)) {
537+ g_warning("File '%s' does not exist.", file);
538+ return NULL;
539+ }
540+
541+ /* Grab the g_module reference, pull it in but let's
542+ keep the symbols local to avoid conflicts. */
543+ module = g_module_open(file,
544+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
545+ if (module == NULL) {
546+ g_warning("Unable to load module: %s", file);
547+ return NULL;
548+ }
549+
550+ /* Look for the version function, error if not found. */
551+ get_version_t lget_version = NULL;
552+ if (!g_module_symbol(module, INDICATOR_GET_VERSION_S, (gpointer *)(&lget_version))) {
553+ g_warning("Unable to get the symbol for getting the version.");
554+ return NULL;
555+ }
556+
557+ /* Check the version with the macro and make sure we're
558+ all talking the same language. */
559+ if (!INDICATOR_VERSION_CHECK(lget_version())) {
560+ g_warning("Indicator using API version '%s' we're expecting '%s'", lget_version(), INDICATOR_VERSION);
561+ return NULL;
562+ }
563+
564+ /* The function for grabbing a label from the module
565+ execute it, and make sure everything is a-okay */
566+ get_type_t lget_type = NULL;
567+ if (!g_module_symbol(module, INDICATOR_GET_TYPE_S, (gpointer *)(&lget_type))) {
568+ g_warning("Unable to get '" INDICATOR_GET_TYPE_S "' symbol from module: %s", file);
569+ goto unrefandout;
570+ }
571+ if (lget_type == NULL) {
572+ g_warning("Symbol '" INDICATOR_GET_TYPE_S "' is (null) in module: %s", file);
573+ goto unrefandout;
574+ }
575+
576+ /* A this point we allocate the object, any code beyond
577+ here needs to deallocate it if we're returning in an
578+ error'd state. */
579+ object = g_object_new(lget_type(), NULL);
580+ if (object == NULL) {
581+ g_warning("Unable to build an object if type '%d' in module: %s", (gint)lget_type(), file);
582+ goto unrefandout;
583+ }
584+ if (!INDICATOR_IS_OBJECT(object)) {
585+ g_warning("Type '%d' in file %s is not a subclass of IndicatorObject.", (gint)lget_type(), file);
586+ goto unrefandout;
587+ }
588+
589+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object);
590+ /* Now we can track the module */
591+ priv->module = module;
592+
593+ return INDICATOR_OBJECT(object);
594+
595+ /* Error, let's drop the object and return NULL. Sad when
596+ this happens. */
597+unrefandout:
598+ if (object != NULL) {
599+ g_object_unref(object);
600+ }
601+ if (module != NULL) {
602+ g_object_unref(module);
603+ }
604+ g_warning("Error building IndicatorObject from file: %s", file);
605+ return NULL;
606+}
607+
608+/* The default get entries function uses the other single
609+ entries in the class to create an entry structure and
610+ put it into a list. This makes it simple for simple objects
611+ to create the list. Small changes from the way they
612+ previously were. */
613+static GList *
614+get_entries_default (IndicatorObject * io)
615+{
616+ IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io);
617+
618+ if (!priv->gotten_entries) {
619+ IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io);
620+
621+ if (class->get_label) {
622+ priv->entry.label = class->get_label(io);
623+ }
624+
625+ if (class->get_image) {
626+ priv->entry.image = class->get_image(io);
627+ }
628+
629+ if (priv->entry.image == NULL && priv->entry.label == NULL) {
630+ g_warning("IndicatorObject class does not create an image or a label. We need one of those.");
631+ return NULL;
632+ }
633+
634+ if (class->get_menu) {
635+ priv->entry.menu = class->get_menu(io);
636+ }
637+
638+ if (priv->entry.menu == NULL) {
639+ g_warning("IndicatorObject class does not create a menu. We need one of those.");
640+ return NULL;
641+ }
642+
643+ priv->gotten_entries = TRUE;
644+ }
645+
646+ return g_list_append(NULL, &(priv->entry));
647+}
648+
649+/**
650+ indicator_object_get_entires:
651+ @io: #IndicatorObject to query
652+
653+ This function looks on the class for the object and calls
654+ it's #IndicatorObjectClass::get_entries function. The
655+ list should be owned by the caller, but the individual
656+ enteries should not be.
657+
658+ Return value: A list if #IndicatorObjectEntry structures or
659+ NULL if there is an error.
660+*/
661+GList *
662+indicator_object_get_entries (IndicatorObject * io)
663+{
664+ g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL);
665+ IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io);
666+
667+ if (class->get_entries) {
668+ return class->get_entries(io);
669+ }
670+
671+ g_error("No get_entries function on object. It must have been deleted?!?!");
672+ return NULL;
673+}
674
675=== added file 'libindicator/indicator-object.h'
676--- libindicator/indicator-object.h 1970-01-01 00:00:00 +0000
677+++ libindicator/indicator-object.h 2009-12-10 17:02:12 +0000
678@@ -0,0 +1,123 @@
679+/*
680+An object to represent loadable indicator modules to make loading
681+them easy and objectified.
682+
683+Copyright 2009 Canonical Ltd.
684+
685+Authors:
686+ Ted Gould <ted@canonical.com>
687+
688+This library is free software; you can redistribute it and/or
689+modify it under the terms of the GNU General Public License
690+version 3.0 as published by the Free Software Foundation.
691+
692+This library is distributed in the hope that it will be useful,
693+but WITHOUT ANY WARRANTY; without even the implied warranty of
694+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
695+GNU General Public License version 3.0 for more details.
696+
697+You should have received a copy of the GNU General Public
698+License along with this library. If not, see
699+<http://www.gnu.org/licenses/>.
700+*/
701+
702+#ifndef __INDICATOR_OBJECT_H__
703+#define __INDICATOR_OBJECT_H__
704+
705+#include <glib.h>
706+#include <glib-object.h>
707+
708+G_BEGIN_DECLS
709+
710+#define INDICATOR_OBJECT_TYPE (indicator_object_get_type ())
711+#define INDICATOR_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_OBJECT_TYPE, IndicatorObject))
712+#define INDICATOR_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_OBJECT_TYPE, IndicatorObjectClass))
713+#define INDICATOR_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_OBJECT_TYPE))
714+#define INDICATOR_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_OBJECT_TYPE))
715+#define INDICATOR_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_OBJECT_TYPE, IndicatorObjectClass))
716+
717+#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED "entry-added"
718+#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, INDICATOR_OBJECT_TYPE))
719+#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED "entry-removed"
720+#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, INDICATOR_OBJECT_TYPE))
721+
722+typedef struct _IndicatorObject IndicatorObject;
723+typedef struct _IndicatorObjectClass IndicatorObjectClass;
724+typedef struct _IndicatorObjectPrivate IndicatorObjectPrivate;
725+typedef struct _IndicatorObjectEntry IndicatorObjectEntry;
726+
727+/**
728+ IndicatorObjectClass:
729+ @parent_class: #GObjectClass
730+ @get_label: Gets the label for this object. Should be set
731+ to #NULL if @get_entries is set. Should NOT ref the
732+ object.
733+ @get_image: Gets the image for this object. Should be set
734+ to #NULL if @get_entries is set. Should NOT ref the
735+ object.
736+ @get_menu: Gets the image for this object. Should be set
737+ to #NULL if @get_entries is set. Should NOT ref the
738+ object.
739+ @get_entries: Gets all of the entires for this object returning
740+ a #GList of #IndicatorObjectEntries. The list should be
741+ under the ownership of the caller but the entires will
742+ not be.
743+ @entry_added: Slot for #IndicatorObject::entry-added
744+ @entry_removed: Slot for #IndicatorObject::entry-removed
745+ @indicator_object_reserved_1: Reserved for future use
746+ @indicator_object_reserved_2: Reserved for future use
747+ @indicator_object_reserved_3: Reserved for future use
748+ @indicator_object_reserved_4: Reserved for future use
749+*/
750+struct _IndicatorObjectClass {
751+ GObjectClass parent_class;
752+
753+ /* Virtual Functions */
754+ GtkLabel * (*get_label) (IndicatorObject * io);
755+ GtkImage * (*get_image) (IndicatorObject * io);
756+ GtkMenu * (*get_menu) (IndicatorObject * io);
757+
758+ GList * (*get_entries) (IndicatorObject * io);
759+
760+ /* Signals */
761+ void (*entry_added) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data);
762+ void (*entry_removed) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data);
763+
764+ /* Reserved */
765+ void (* indicator_object_reserved_1) (void);
766+ void (* indicator_object_reserved_2) (void);
767+ void (* indicator_object_reserved_3) (void);
768+ void (* indicator_object_reserved_4) (void);
769+};
770+
771+/**
772+ IndicatorObject:
773+ @parent: #GObject
774+ @priv: A cached reference to the private data for the
775+ instance.
776+*/
777+struct _IndicatorObject {
778+ GObject parent;
779+ IndicatorObjectPrivate * priv;
780+};
781+
782+/**
783+ IndicatorObjectEntry:
784+ @label: The label to be shown on the panel
785+ @image: The image to be shown on the panel
786+ @menu: The menu to be added to the menubar
787+*/
788+struct _IndicatorObjectEntry {
789+ GtkLabel * label;
790+ GtkImage * image;
791+ GtkMenu * menu;
792+};
793+
794+GType indicator_object_get_type (void);
795+IndicatorObject * indicator_object_new_from_file (const gchar * file);
796+
797+GList * indicator_object_get_entries (IndicatorObject * io);
798+
799+G_END_DECLS
800+
801+#endif
802
803=== added file 'libindicator/indicator-service-manager.c'
804--- libindicator/indicator-service-manager.c 1970-01-01 00:00:00 +0000
805+++ libindicator/indicator-service-manager.c 2009-12-10 17:02:12 +0000
806@@ -0,0 +1,493 @@
807+/*
808+An object used to manage services. Either start them or
809+just connect to them.
810+
811+Copyright 2009 Canonical Ltd.
812+
813+Authors:
814+ Ted Gould <ted@canonical.com>
815+
816+This library is free software; you can redistribute it and/or
817+modify it under the terms of the GNU General Public License
818+version 3.0 as published by the Free Software Foundation.
819+
820+This library is distributed in the hope that it will be useful,
821+but WITHOUT ANY WARRANTY; without even the implied warranty of
822+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
823+GNU General Public License version 3.0 for more details.
824+
825+You should have received a copy of the GNU General Public
826+License along with this library. If not, see
827+<http://www.gnu.org/licenses/>.
828+*/
829+
830+#ifdef HAVE_CONFIG_H
831+#include "config.h"
832+#endif
833+
834+#include <dbus/dbus-glib-bindings.h>
835+#include <dbus/dbus-glib-lowlevel.h>
836+
837+#include "indicator-service-manager.h"
838+#include "indicator-service-client.h"
839+#include "dbus-shared.h"
840+
841+/* Private Stuff */
842+/**
843+ IndicatorServiceManagerPrivate:
844+ @name: The well known dbus name the service should be on.
845+ @dbus_proxy: A proxy to talk to the dbus daemon.
846+ @service_proxy: The proxy to the service itself.
847+ @connected: Whether we're connected to the service or not.
848+ @this_service_version: The version of the service that we're looking for.
849+ @bus: A reference to the bus so we don't have to keep getting it.
850+*/
851+typedef struct _IndicatorServiceManagerPrivate IndicatorServiceManagerPrivate;
852+struct _IndicatorServiceManagerPrivate {
853+ gchar * name;
854+ DBusGProxy * dbus_proxy;
855+ DBusGProxy * service_proxy;
856+ gboolean connected;
857+ guint this_service_version;
858+ DBusGConnection * bus;
859+};
860+
861+/* Signals Stuff */
862+enum {
863+ CONNECTION_CHANGE,
864+ LAST_SIGNAL
865+};
866+
867+static guint signals[LAST_SIGNAL] = { 0 };
868+
869+
870+/* Properties */
871+/* Enum for the properties so that they can be quickly
872+ found and looked up. */
873+enum {
874+ PROP_0,
875+ PROP_NAME,
876+ PROP_VERSION
877+};
878+
879+/* The strings so that they can be slowly looked up. */
880+#define PROP_NAME_S "name"
881+#define PROP_VERSION_S "version"
882+
883+/* GObject Stuff */
884+#define INDICATOR_SERVICE_MANAGER_GET_PRIVATE(o) \
885+(G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerPrivate))
886+
887+static void indicator_service_manager_class_init (IndicatorServiceManagerClass *klass);
888+static void indicator_service_manager_init (IndicatorServiceManager *self);
889+static void indicator_service_manager_dispose (GObject *object);
890+static void indicator_service_manager_finalize (GObject *object);
891+
892+/* Prototypes */
893+static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
894+static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
895+static void start_service (IndicatorServiceManager * service);
896+
897+G_DEFINE_TYPE (IndicatorServiceManager, indicator_service_manager, G_TYPE_OBJECT);
898+
899+/* Build all of our signals and proxies and tie everything
900+ all together. Lovely. */
901+static void
902+indicator_service_manager_class_init (IndicatorServiceManagerClass *klass)
903+{
904+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
905+
906+ g_type_class_add_private (klass, sizeof (IndicatorServiceManagerPrivate));
907+
908+ object_class->dispose = indicator_service_manager_dispose;
909+ object_class->finalize = indicator_service_manager_finalize;
910+
911+ /* Property funcs */
912+ object_class->set_property = set_property;
913+ object_class->get_property = get_property;
914+
915+ /**
916+ IndicatorServiceManager::connecton-change:
917+ @arg0: The #IndicatorServiceManager object
918+ @arg1: The state of the connection, TRUE is connected.
919+
920+ Signaled when the service is connected or disconnected
921+ depending on it's previous state.
922+ */
923+ signals[CONNECTION_CHANGE] = g_signal_new (INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
924+ G_TYPE_FROM_CLASS(klass),
925+ G_SIGNAL_RUN_LAST,
926+ G_STRUCT_OFFSET (IndicatorServiceManagerClass, connection_change),
927+ NULL, NULL,
928+ g_cclosure_marshal_VOID__BOOLEAN,
929+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE);
930+
931+ /* Properties */
932+ g_object_class_install_property(object_class, PROP_NAME,
933+ g_param_spec_string(PROP_NAME_S,
934+ "The DBus name for the service to monitor",
935+ "This is the name that should be used to start a service.",
936+ NULL,
937+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
938+ g_object_class_install_property(object_class, PROP_VERSION,
939+ g_param_spec_uint(PROP_VERSION_S,
940+ "The version of the service that we're expecting.",
941+ "A number to check and reject a service if it gives us the wrong number. This should match across the manager and the service",
942+ 0, G_MAXUINT, 0,
943+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
944+
945+ return;
946+}
947+
948+/* This inits all the variable and sets up the proxy
949+ to dbus. It doesn't look for the service as at this
950+ point we don't know it's name. */
951+static void
952+indicator_service_manager_init (IndicatorServiceManager *self)
953+{
954+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
955+
956+ /* Get the private variables in a decent state */
957+ priv->name = NULL;
958+ priv->dbus_proxy = NULL;
959+ priv->service_proxy = NULL;
960+ priv->connected = FALSE;
961+ priv->this_service_version = 0;
962+ priv->bus = NULL;
963+
964+ /* Start talkin' dbus */
965+ GError * error = NULL;
966+ priv->bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
967+ if (error != NULL) {
968+ g_error("Unable to get session bus for manager: %s", error->message);
969+ g_error_free(error);
970+ return;
971+ }
972+
973+ priv->dbus_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
974+ DBUS_SERVICE_DBUS,
975+ DBUS_PATH_DBUS,
976+ DBUS_INTERFACE_DBUS,
977+ &error);
978+ if (error != NULL) {
979+ g_error("Unable to get the proxy to DBus: %s", error->message);
980+ g_error_free(error);
981+ return;
982+ }
983+
984+ return;
985+}
986+
987+/* If we're connected this provides all the signals to say
988+ that we're about to not be. Then it takes down the proxies
989+ and tells the service that we're not interested in being
990+ its friend anymore either. */
991+static void
992+indicator_service_manager_dispose (GObject *object)
993+{
994+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(object);
995+
996+ /* If we were connected we need to make sure to
997+ tell people that it's no longer the case. */
998+ if (priv->connected) {
999+ priv->connected = FALSE;
1000+ g_signal_emit(object, signals[CONNECTION_CHANGE], 0, FALSE, TRUE);
1001+ }
1002+
1003+ /* Destory our DBus proxy, we won't need it. */
1004+ if (priv->dbus_proxy != NULL) {
1005+ g_object_unref(G_OBJECT(priv->dbus_proxy));
1006+ priv->dbus_proxy = NULL;
1007+ }
1008+
1009+ /* If we have a proxy, tell it we're shutting down. Just
1010+ to be polite about it. */
1011+ if (priv->service_proxy != NULL) {
1012+ dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID);
1013+ }
1014+
1015+ /* Destory our service proxy, we won't need it. */
1016+ if (priv->service_proxy != NULL) {
1017+ g_object_unref(G_OBJECT(priv->service_proxy));
1018+ priv->service_proxy = NULL;
1019+ }
1020+
1021+ /* Let's see if our parents want to do anything. */
1022+ G_OBJECT_CLASS (indicator_service_manager_parent_class)->dispose (object);
1023+ return;
1024+}
1025+
1026+/* Ironically, we don't allocate a lot of memory ourselves. */
1027+static void
1028+indicator_service_manager_finalize (GObject *object)
1029+{
1030+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(object);
1031+
1032+ if (priv->name != NULL) {
1033+ g_free(priv->name);
1034+ priv->name = NULL;
1035+ }
1036+
1037+ G_OBJECT_CLASS (indicator_service_manager_parent_class)->finalize (object);
1038+ return;
1039+}
1040+
1041+/* Either copies the name into the private variable or
1042+ sets the version. Do it wrong and it'll get upset. */
1043+static void
1044+set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
1045+{
1046+ IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object);
1047+ g_return_if_fail(self != NULL);
1048+
1049+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
1050+ g_return_if_fail(priv != NULL);
1051+
1052+ switch (prop_id) {
1053+ /* *********************** */
1054+ case PROP_NAME:
1055+ if (priv->name != NULL) {
1056+ g_error("Name can not be set twice!");
1057+ return;
1058+ }
1059+ priv->name = g_value_dup_string(value);
1060+ start_service(self);
1061+ break;
1062+ /* *********************** */
1063+ case PROP_VERSION:
1064+ priv->this_service_version = g_value_get_uint(value);
1065+ break;
1066+ /* *********************** */
1067+ default:
1068+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1069+ break;
1070+ }
1071+
1072+ return;
1073+}
1074+
1075+/* Grabs the values from the private variables and
1076+ puts them into the value. */
1077+static void
1078+get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
1079+{
1080+ IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object);
1081+ g_return_if_fail(self != NULL);
1082+
1083+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(self);
1084+ g_return_if_fail(priv != NULL);
1085+
1086+ switch (prop_id) {
1087+ /* *********************** */
1088+ case PROP_NAME:
1089+ g_value_set_string(value, priv->name);
1090+ break;
1091+ /* *********************** */
1092+ case PROP_VERSION:
1093+ g_value_set_uint(value, priv->this_service_version);
1094+ break;
1095+ /* *********************** */
1096+ default:
1097+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1098+ break;
1099+ }
1100+
1101+ return;
1102+}
1103+
1104+/* A callback from telling a service that we want to watch
1105+ it. It gives us the service API version and the version
1106+ of the other APIs it supports. We check both of those.
1107+ If they don't match then we unwatch it. Otherwise, we
1108+ signal a connection change to tell the rest of the world
1109+ that we have a service now. */
1110+static void
1111+watch_cb (DBusGProxy * proxy, guint service_api_version, guint this_service_version, GError * error, gpointer user_data)
1112+{
1113+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data);
1114+
1115+ if (error != NULL) {
1116+ g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message);
1117+ g_error_free(error);
1118+ return;
1119+ }
1120+
1121+ if (service_api_version != INDICATOR_SERVICE_VERSION) {
1122+ g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version);
1123+ dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID);
1124+ return;
1125+ }
1126+
1127+ if (this_service_version != priv->this_service_version) {
1128+ g_warning("Service is using a different API version than the manager. Expecting %d and got %d.", priv->this_service_version, this_service_version);
1129+ dbus_g_proxy_call_no_reply(priv->service_proxy, "UnWatch", G_TYPE_INVALID);
1130+ return;
1131+ }
1132+
1133+ if (!priv->connected) {
1134+ priv->connected = TRUE;
1135+ g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE);
1136+ }
1137+
1138+ return;
1139+}
1140+
1141+/* The callback after asking the dbus-daemon to start a
1142+ service for us. It can return success or failure, on
1143+ failure we can't do much. But, with sucess, we start
1144+ to build a proxy and tell the service that we're watching. */
1145+static void
1146+start_service_cb (DBusGProxy * proxy, guint status, GError * error, gpointer user_data)
1147+{
1148+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(user_data);
1149+
1150+ if (error != NULL) {
1151+ g_warning("Unable to start service '%s': %s", priv->name, error->message);
1152+ return;
1153+ }
1154+
1155+ if (status != DBUS_START_REPLY_SUCCESS && status != DBUS_START_REPLY_ALREADY_RUNNING) {
1156+ g_warning("Status of starting the process '%s' was an error: %d", priv->name, status);
1157+ return;
1158+ }
1159+
1160+ /* Woot! it's running. Let's do it some more. */
1161+ priv->service_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1162+ priv->name,
1163+ INDICATOR_SERVICE_OBJECT,
1164+ INDICATOR_SERVICE_INTERFACE,
1165+ &error);
1166+ g_object_add_weak_pointer(G_OBJECT(priv->service_proxy), (gpointer *)&(priv->service_proxy));
1167+
1168+ org_ayatana_indicator_service_watch_async(priv->service_proxy,
1169+ watch_cb,
1170+ user_data);
1171+
1172+ return;
1173+}
1174+
1175+/* The function that handles getting us connected to the service.
1176+ In many cases it will start the service, but if the service
1177+ is already there it just allocates the service proxy and acts
1178+ like it was no big deal. */
1179+static void
1180+start_service (IndicatorServiceManager * service)
1181+{
1182+ GError * error = NULL;
1183+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(service);
1184+
1185+ g_return_if_fail(priv->dbus_proxy != NULL);
1186+ g_return_if_fail(priv->name != NULL);
1187+
1188+ /* Check to see if we can get a proxy to it first. */
1189+ priv->service_proxy = dbus_g_proxy_new_for_name_owner(priv->bus,
1190+ priv->name,
1191+ INDICATOR_SERVICE_OBJECT,
1192+ INDICATOR_SERVICE_INTERFACE,
1193+ &error);
1194+
1195+ if (error != NULL) {
1196+ /* We don't care about the error, just start the service anyway. */
1197+ g_error_free(error);
1198+ org_freedesktop_DBus_start_service_by_name_async (priv->dbus_proxy,
1199+ priv->name,
1200+ 0,
1201+ start_service_cb,
1202+ service);
1203+ } else {
1204+ g_object_add_weak_pointer(G_OBJECT(priv->service_proxy), (gpointer *)&(priv->service_proxy));
1205+
1206+ /* If we got a proxy just because we're good people then
1207+ we need to call watch on it just like 'start_service_cb'
1208+ does. */
1209+ org_ayatana_indicator_service_watch_async(priv->service_proxy,
1210+ watch_cb,
1211+ service);
1212+ }
1213+
1214+ return;
1215+}
1216+
1217+/* API */
1218+
1219+/**
1220+ indicator_service_manager_new:
1221+ @dbus_name: The well known name of the service on DBus
1222+
1223+ This creates a new service manager object. If the service
1224+ is not running it will start it. No matter what, it will
1225+ give a IndicatorServiceManager::connection-changed event
1226+ signal when it gets connected.
1227+
1228+ Return value: A brand new lovely #IndicatorServiceManager
1229+ object.
1230+*/
1231+IndicatorServiceManager *
1232+indicator_service_manager_new (gchar * dbus_name)
1233+{
1234+ GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE,
1235+ PROP_NAME_S, dbus_name,
1236+ NULL);
1237+
1238+ return INDICATOR_SERVICE_MANAGER(obj);
1239+}
1240+
1241+/**
1242+ inicator_service_manager_new_version:
1243+ @dbus_name: The well known name of the service on DBus
1244+ @version: Version of the service we expect
1245+
1246+ This creates a new service manager object. It also sets
1247+ the version of the service that we're expecting to see.
1248+ In general, it behaves similarly to #indicator_service_manager_new()
1249+ except that it checks @version against the version returned
1250+ by the service.
1251+
1252+ Return value: A brand new lovely #IndicatorServiceManager
1253+ object.
1254+*/
1255+IndicatorServiceManager *
1256+indicator_service_manager_new_version (gchar * dbus_name, guint version)
1257+{
1258+ GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE,
1259+ PROP_NAME_S, dbus_name,
1260+ PROP_VERSION_S, version,
1261+ NULL);
1262+
1263+ return INDICATOR_SERVICE_MANAGER(obj);
1264+}
1265+
1266+/**
1267+ indicator_service_manager_connected:
1268+ @sm: #IndicatorServiceManager object to check
1269+
1270+ Checks to see if the service manager is connected to a
1271+ service.
1272+
1273+ Return value: #TRUE if there is a service connceted.
1274+*/
1275+gboolean
1276+indicator_service_manager_connected (IndicatorServiceManager * sm)
1277+{
1278+ g_return_val_if_fail(INDICATOR_IS_SERVICE_MANAGER(sm), FALSE);
1279+ IndicatorServiceManagerPrivate * priv = INDICATOR_SERVICE_MANAGER_GET_PRIVATE(sm);
1280+ return priv->connected;
1281+}
1282+
1283+/**
1284+ indicator_service_manager_set_refresh:
1285+ @sm: #IndicatorServiceManager object to configure
1286+ @time_in_ms: The refresh time in milliseconds
1287+
1288+ Use this function to set the amount of time between restarting
1289+ services that may crash or shutdown. This is mostly useful
1290+ for testing and development.
1291+
1292+ NOTE: Not yet implemented.
1293+*/
1294+void
1295+indicator_service_manager_set_refresh (IndicatorServiceManager * sm, guint time_in_ms)
1296+{
1297+
1298+ return;
1299+}
1300
1301=== added file 'libindicator/indicator-service-manager.h'
1302--- libindicator/indicator-service-manager.h 1970-01-01 00:00:00 +0000
1303+++ libindicator/indicator-service-manager.h 2009-12-10 17:02:12 +0000
1304@@ -0,0 +1,88 @@
1305+/*
1306+An object used to manage services. Either start them or
1307+just connect to them.
1308+
1309+Copyright 2009 Canonical Ltd.
1310+
1311+Authors:
1312+ Ted Gould <ted@canonical.com>
1313+
1314+This library is free software; you can redistribute it and/or
1315+modify it under the terms of the GNU General Public License
1316+version 3.0 as published by the Free Software Foundation.
1317+
1318+This library is distributed in the hope that it will be useful,
1319+but WITHOUT ANY WARRANTY; without even the implied warranty of
1320+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1321+GNU General Public License version 3.0 for more details.
1322+
1323+You should have received a copy of the GNU General Public
1324+License along with this library. If not, see
1325+<http://www.gnu.org/licenses/>.
1326+*/
1327+
1328+#ifndef __INDICATOR_SERVICE_MANAGER_H__
1329+#define __INDICATOR_SERVICE_MANAGER_H__
1330+
1331+#include <glib.h>
1332+#include <glib-object.h>
1333+
1334+G_BEGIN_DECLS
1335+
1336+#define INDICATOR_SERVICE_MANAGER_TYPE (indicator_service_manager_get_type ())
1337+#define INDICATOR_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManager))
1338+#define INDICATOR_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass))
1339+#define INDICATOR_IS_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_MANAGER_TYPE))
1340+#define INDICATOR_IS_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_MANAGER_TYPE))
1341+#define INDICATOR_SERVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass))
1342+
1343+#define INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE "connection-change"
1344+
1345+typedef struct _IndicatorServiceManager IndicatorServiceManager;
1346+typedef struct _IndicatorServiceManagerClass IndicatorServiceManagerClass;
1347+
1348+/**
1349+ IndicatorServiceManagerClass:
1350+ @parent: #GObjectClass
1351+ @connection_changed: Slot for #IndicatorServiceManager::connection-changed.
1352+ @indicator_service_manager_reserved1: Reserved for future use.
1353+ @indicator_service_manager_reserved2: Reserved for future use.
1354+ @indicator_service_manager_reserved3: Reserved for future use.
1355+ @indicator_service_manager_reserved4: Reserved for future use.
1356+
1357+*/
1358+struct _IndicatorServiceManagerClass {
1359+ GObjectClass parent_class;
1360+
1361+ /* Signals */
1362+ void (*connection_change) (IndicatorServiceManager * sm, gboolean connected, gpointer user_data);
1363+
1364+ /* Buffer */
1365+ void (*indicator_service_manager_reserved1) (void);
1366+ void (*indicator_service_manager_reserved2) (void);
1367+ void (*indicator_service_manager_reserved3) (void);
1368+ void (*indicator_service_manager_reserved4) (void);
1369+};
1370+
1371+/**
1372+ IndicatorServiceManager:
1373+ @parent: #GObject
1374+
1375+*/
1376+struct _IndicatorServiceManager {
1377+ GObject parent;
1378+
1379+};
1380+
1381+GType indicator_service_manager_get_type (void);
1382+
1383+IndicatorServiceManager * indicator_service_manager_new (gchar * dbus_name);
1384+IndicatorServiceManager * indicator_service_manager_new_version (gchar * dbus_name,
1385+ guint version);
1386+gboolean indicator_service_manager_connected (IndicatorServiceManager * sm);
1387+void indicator_service_manager_set_refresh (IndicatorServiceManager * sm,
1388+ guint time_in_ms);
1389+
1390+G_END_DECLS
1391+
1392+#endif
1393
1394=== added file 'libindicator/indicator-service.c'
1395--- libindicator/indicator-service.c 1970-01-01 00:00:00 +0000
1396+++ libindicator/indicator-service.c 2009-12-10 17:02:12 +0000
1397@@ -0,0 +1,479 @@
1398+/*
1399+An object used to provide a simple interface for a service
1400+to query version and manage whether it's running.
1401+
1402+Copyright 2009 Canonical Ltd.
1403+
1404+Authors:
1405+ Ted Gould <ted@canonical.com>
1406+
1407+This library is free software; you can redistribute it and/or
1408+modify it under the terms of the GNU General Public License
1409+version 3.0 as published by the Free Software Foundation.
1410+
1411+This library is distributed in the hope that it will be useful,
1412+but WITHOUT ANY WARRANTY; without even the implied warranty of
1413+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License version 3.0 for more details.
1415+
1416+You should have received a copy of the GNU General Public
1417+License along with this library. If not, see
1418+<http://www.gnu.org/licenses/>.
1419+*/
1420+
1421+#ifdef HAVE_CONFIG_H
1422+#include "config.h"
1423+#endif
1424+#include <dbus/dbus-glib-bindings.h>
1425+#include <dbus/dbus-glib-lowlevel.h>
1426+
1427+#include "indicator-service.h"
1428+
1429+/* DBus Prototypes */
1430+static gboolean _indicator_service_server_watch (IndicatorService * service, DBusGMethodInvocation * method);
1431+static gboolean _indicator_service_server_un_watch (IndicatorService * service, DBusGMethodInvocation * method);
1432+
1433+#include "indicator-service-server.h"
1434+#include "dbus-shared.h"
1435+
1436+/* Private Stuff */
1437+/**
1438+ IndicatorSevicePrivate:
1439+ @name: The DBus well known name for the service.
1440+ @dbus_proxy: A proxy for talking to the dbus bus manager.
1441+ @timeout: The source ID for the timeout event.
1442+ @watcher: A list of processes on dbus that are watching us.
1443+ @this_service_version: The version to hand out that we're
1444+ implementing. May not be set, so we'll send zero (default).
1445+*/
1446+typedef struct _IndicatorServicePrivate IndicatorServicePrivate;
1447+struct _IndicatorServicePrivate {
1448+ gchar * name;
1449+ DBusGProxy * dbus_proxy;
1450+ guint timeout;
1451+ GList * watchers;
1452+ guint this_service_version;
1453+};
1454+
1455+/* Signals Stuff */
1456+enum {
1457+ SHUTDOWN,
1458+ LAST_SIGNAL
1459+};
1460+
1461+static guint signals[LAST_SIGNAL] = { 0 };
1462+
1463+/* Properties */
1464+/* Enum for the properties so that they can be quickly
1465+ found and looked up. */
1466+enum {
1467+ PROP_0,
1468+ PROP_NAME,
1469+ PROP_VERSION
1470+};
1471+
1472+/* The strings so that they can be slowly looked up. */
1473+#define PROP_NAME_S "name"
1474+#define PROP_VERSION_S "version"
1475+
1476+/* GObject Stuff */
1477+#define INDICATOR_SERVICE_GET_PRIVATE(o) \
1478+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_TYPE, IndicatorServicePrivate))
1479+
1480+static void indicator_service_class_init (IndicatorServiceClass *klass);
1481+static void indicator_service_init (IndicatorService *self);
1482+static void indicator_service_dispose (GObject *object);
1483+static void indicator_service_finalize (GObject *object);
1484+
1485+/* Other prototypes */
1486+static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
1487+static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
1488+static void try_and_get_name (IndicatorService * service);
1489+
1490+G_DEFINE_TYPE (IndicatorService, indicator_service, G_TYPE_OBJECT);
1491+
1492+static void
1493+indicator_service_class_init (IndicatorServiceClass *klass)
1494+{
1495+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
1496+
1497+ g_type_class_add_private (klass, sizeof (IndicatorServicePrivate));
1498+
1499+ object_class->dispose = indicator_service_dispose;
1500+ object_class->finalize = indicator_service_finalize;
1501+
1502+ /* Property funcs */
1503+ object_class->set_property = set_property;
1504+ object_class->get_property = get_property;
1505+
1506+ /* Properties */
1507+ g_object_class_install_property(object_class, PROP_NAME,
1508+ g_param_spec_string(PROP_NAME_S,
1509+ "The DBus name for this service",
1510+ "This is the name that should be used on DBus for this service.",
1511+ NULL,
1512+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1513+ g_object_class_install_property(object_class, PROP_VERSION,
1514+ g_param_spec_uint(PROP_VERSION_S,
1515+ "The version of the service that we're implementing.",
1516+ "A number to represent the version of the other APIs the service provides. This should match across the manager and the service",
1517+ 0, G_MAXUINT, 0,
1518+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1519+
1520+ /* Signals */
1521+
1522+ /**
1523+ IndicatorService::shutdown:
1524+ @arg0: The #IndicatorService object
1525+
1526+ Signaled when the service should shutdown as no one
1527+ is listening anymore.
1528+ */
1529+ signals[SHUTDOWN] = g_signal_new (INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
1530+ G_TYPE_FROM_CLASS(klass),
1531+ G_SIGNAL_RUN_LAST,
1532+ G_STRUCT_OFFSET (IndicatorServiceClass, shutdown),
1533+ NULL, NULL,
1534+ g_cclosure_marshal_VOID__VOID,
1535+ G_TYPE_NONE, 0, G_TYPE_NONE);
1536+
1537+ /* Initialize the object as a DBus type */
1538+ dbus_g_object_type_install_info(INDICATOR_SERVICE_TYPE,
1539+ &dbus_glib__indicator_service_server_object_info);
1540+
1541+ return;
1542+}
1543+
1544+/* This function builds the variables, sets up the dbus
1545+ proxy and registers the object on dbus. Importantly,
1546+ it does not request a name as we don't know what name
1547+ we have yet. */
1548+static void
1549+indicator_service_init (IndicatorService *self)
1550+{
1551+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(self);
1552+
1553+ /* Get the private variables in a decent state */
1554+ priv->name = NULL;
1555+ priv->dbus_proxy = NULL;
1556+ priv->timeout = 0;
1557+ priv->watchers = NULL;
1558+ priv->this_service_version = 0;
1559+
1560+ /* Start talkin' dbus */
1561+ GError * error = NULL;
1562+ DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_STARTER, &error);
1563+ if (error != NULL) {
1564+ g_error("Unable to get starter bus: %s", error->message);
1565+ g_error_free(error);
1566+
1567+ /* Okay, fine let's try the session bus then. */
1568+ /* I think this should automatically, but I can't find confirmation
1569+ of that, so we're putting the extra little code in here. */
1570+ error = NULL;
1571+ bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
1572+ if (error != NULL) {
1573+ g_error("Unable to get session bus: %s", error->message);
1574+ g_error_free(error);
1575+ return;
1576+ }
1577+ }
1578+
1579+ priv->dbus_proxy = dbus_g_proxy_new_for_name_owner(bus,
1580+ DBUS_SERVICE_DBUS,
1581+ DBUS_PATH_DBUS,
1582+ DBUS_INTERFACE_DBUS,
1583+ &error);
1584+ if (error != NULL) {
1585+ g_error("Unable to get the proxy to DBus: %s", error->message);
1586+ g_error_free(error);
1587+ return;
1588+ }
1589+
1590+ dbus_g_connection_register_g_object(bus,
1591+ INDICATOR_SERVICE_OBJECT,
1592+ G_OBJECT(self));
1593+
1594+ return;
1595+}
1596+
1597+/* Unrefcounting the proxies and making sure that our
1598+ timeout doesn't come to haunt us. */
1599+static void
1600+indicator_service_dispose (GObject *object)
1601+{
1602+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(object);
1603+
1604+ if (priv->dbus_proxy != NULL) {
1605+ g_object_unref(G_OBJECT(priv->dbus_proxy));
1606+ priv->dbus_proxy = NULL;
1607+ }
1608+
1609+ if (priv->timeout != 0) {
1610+ g_source_remove(priv->timeout);
1611+ priv->timeout = 0;
1612+ }
1613+
1614+ G_OBJECT_CLASS (indicator_service_parent_class)->dispose (object);
1615+ return;
1616+}
1617+
1618+/* Freeing the name we're looking for and all of the
1619+ information on the watchers we're tracking. */
1620+static void
1621+indicator_service_finalize (GObject *object)
1622+{
1623+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(object);
1624+
1625+ if (priv->name != NULL) {
1626+ g_free(priv->name);
1627+ }
1628+
1629+ if (priv->watchers != NULL) {
1630+ g_list_foreach(priv->watchers, (GFunc)g_free, NULL);
1631+ g_list_free(priv->watchers);
1632+ priv->watchers = NULL;
1633+ }
1634+
1635+ G_OBJECT_CLASS (indicator_service_parent_class)->finalize (object);
1636+ return;
1637+}
1638+
1639+/* Either copies a string for the name or it just grabs
1640+ the value of the version. */
1641+static void
1642+set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
1643+{
1644+ IndicatorService * self = INDICATOR_SERVICE(object);
1645+ g_return_if_fail(self != NULL);
1646+
1647+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(self);
1648+ g_return_if_fail(priv != NULL);
1649+
1650+ switch (prop_id) {
1651+ /* *********************** */
1652+ case PROP_NAME:
1653+ if (G_VALUE_HOLDS_STRING(value)) {
1654+ if (priv->name != NULL) {
1655+ g_error("Name can not be set twice!");
1656+ return;
1657+ }
1658+ priv->name = g_value_dup_string(value);
1659+ try_and_get_name(self);
1660+ } else {
1661+ g_warning("Name property requires a string value.");
1662+ }
1663+ break;
1664+ /* *********************** */
1665+ case PROP_VERSION:
1666+ priv->this_service_version = g_value_get_uint(value);
1667+ break;
1668+ /* *********************** */
1669+ default:
1670+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1671+ break;
1672+ }
1673+
1674+ return;
1675+}
1676+
1677+/* Copies out the name into a value or the version number.
1678+ Probably this is the least useful code in this file. */
1679+static void
1680+get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
1681+{
1682+ IndicatorService * self = INDICATOR_SERVICE(object);
1683+ g_return_if_fail(self != NULL);
1684+
1685+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(self);
1686+ g_return_if_fail(priv != NULL);
1687+
1688+ switch (prop_id) {
1689+ /* *********************** */
1690+ case PROP_NAME:
1691+ if (G_VALUE_HOLDS_STRING(value)) {
1692+ g_value_set_string(value, priv->name);
1693+ } else {
1694+ g_warning("Name property requires a string value.");
1695+ }
1696+ break;
1697+ /* *********************** */
1698+ case PROP_VERSION:
1699+ g_value_set_uint(value, priv->this_service_version);
1700+ break;
1701+ /* *********************** */
1702+ default:
1703+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1704+ break;
1705+ }
1706+
1707+ return;
1708+}
1709+
1710+/* This is the function that gets executed if we timeout
1711+ because there are no watchers. We sent the shutdown
1712+ signal and hope someone does something sane with it. */
1713+static gboolean
1714+timeout_no_watchers (gpointer data)
1715+{
1716+ g_signal_emit(G_OBJECT(data), signals[SHUTDOWN], 0, TRUE);
1717+ return FALSE;
1718+}
1719+
1720+/* The callback from our request to get a well known name
1721+ on dbus. If we can't get it we send the shutdown signal.
1722+ Else we start the timer to see if anyone cares about us. */
1723+static void
1724+try_and_get_name_cb (DBusGProxy * proxy, guint status, GError * error, gpointer data)
1725+{
1726+ IndicatorService * service = INDICATOR_SERVICE(data);
1727+ g_return_if_fail(service != NULL);
1728+
1729+ if (status != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && status != DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER) {
1730+ /* The already owner seems like it shouldn't ever
1731+ happen, but I have a hard time throwing an error
1732+ on it as we did achieve our goals. */
1733+ g_signal_emit(G_OBJECT(data), signals[SHUTDOWN], 0, TRUE);
1734+ return;
1735+ }
1736+
1737+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(service);
1738+ priv->timeout = g_timeout_add(500, timeout_no_watchers, service);
1739+
1740+ return;
1741+}
1742+
1743+/* This function sets up the request for the name on dbus. */
1744+static void
1745+try_and_get_name (IndicatorService * service)
1746+{
1747+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(service);
1748+ g_return_if_fail(priv->dbus_proxy != NULL);
1749+ g_return_if_fail(priv->name != NULL);
1750+
1751+ org_freedesktop_DBus_request_name_async(priv->dbus_proxy,
1752+ priv->name,
1753+ DBUS_NAME_FLAG_DO_NOT_QUEUE,
1754+ try_and_get_name_cb,
1755+ service);
1756+
1757+ return;
1758+}
1759+
1760+/* Here is the function that gets called by the dbus
1761+ interface "Watch" function. It is an async function so
1762+ that we can get the sender and store that information. We
1763+ put them in a list and reset the timeout. */
1764+static gboolean
1765+_indicator_service_server_watch (IndicatorService * service, DBusGMethodInvocation * method)
1766+{
1767+ g_return_val_if_fail(INDICATOR_IS_SERVICE(service), FALSE);
1768+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(service);
1769+
1770+ priv->watchers = g_list_append(priv->watchers,
1771+ g_strdup(dbus_g_method_get_sender(method)));
1772+
1773+ if (priv->timeout != 0) {
1774+ g_source_remove(priv->timeout);
1775+ priv->timeout = 0;
1776+ }
1777+
1778+ dbus_g_method_return(method, INDICATOR_SERVICE_VERSION, priv->this_service_version);
1779+ return TRUE;
1780+}
1781+
1782+/* Mung g_strcmp0 into GCompareFunc */
1783+static gint
1784+find_watcher (gconstpointer a, gconstpointer b)
1785+{
1786+ return g_strcmp0((const gchar *)a, (const gchar *)b);
1787+}
1788+
1789+/* A function connecting into the dbus interface for the
1790+ "UnWatch" function. It is also an async function to get
1791+ the sender. It then looks the sender up and removes them
1792+ from the list of watchers. If there are none left, it then
1793+ starts the timer for the shutdown signal. */
1794+static gboolean
1795+_indicator_service_server_un_watch (IndicatorService * service, DBusGMethodInvocation * method)
1796+{
1797+ g_return_val_if_fail(INDICATOR_IS_SERVICE(service), FALSE);
1798+ IndicatorServicePrivate * priv = INDICATOR_SERVICE_GET_PRIVATE(service);
1799+
1800+ /* Remove us from the watcher list here */
1801+ GList * watcher_item = g_list_find_custom(priv->watchers, dbus_g_method_get_sender(method), find_watcher);
1802+ if (watcher_item != NULL) {
1803+ /* Free the watcher */
1804+ gchar * name = watcher_item->data;
1805+ priv->watchers = g_list_remove(priv->watchers, name);
1806+ g_free(name);
1807+ } else {
1808+ /* Odd that we couldn't find the person, but, eh */
1809+ g_warning("Unable to find watcher who is unwatching: %s", dbus_g_method_get_sender(method));
1810+ }
1811+
1812+ /* If we're out of watchers set the timeout for shutdown */
1813+ if (priv->watchers == NULL) {
1814+ if (priv->timeout != 0) {
1815+ /* This should never really happen, but let's ensure that
1816+ bad things don't happen if it does. */
1817+ g_warning("No watchers timeout set twice. Resolving, but odd.");
1818+ g_source_remove(priv->timeout);
1819+ priv->timeout = 0;
1820+ }
1821+ /* If we don't get a new watcher quickly, we'll shutdown. */
1822+ priv->timeout = g_timeout_add(500, timeout_no_watchers, service);
1823+ }
1824+
1825+ dbus_g_method_return(method);
1826+ return TRUE;
1827+}
1828+
1829+/* API */
1830+
1831+/**
1832+ indicator_service_new:
1833+ @name: The name for the service on dbus
1834+
1835+ This function creates the service on DBus and tries to
1836+ get a well-known name specified in @name. If the name
1837+ can't be estabilished then the #IndicatorService::shutdown
1838+ signal will be sent.
1839+
1840+ Return value: A brand new #IndicatorService object or #NULL
1841+ if there is an error.
1842+*/
1843+IndicatorService *
1844+indicator_service_new (gchar * name)
1845+{
1846+ GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE,
1847+ PROP_NAME_S, name,
1848+ NULL);
1849+
1850+ return INDICATOR_SERVICE(obj);
1851+}
1852+
1853+/**
1854+ indicator_service_new_version:
1855+ @name: The name for the service on dbus
1856+ @version: The version of the other interfaces provide
1857+ by the service.
1858+
1859+ This function creates the service on DBus and tries to
1860+ get a well-known name specified in @name. If the name
1861+ can't be estabilished then the #IndicatorService::shutdown
1862+ signal will be sent.
1863+
1864+ Return value: A brand new #IndicatorService object or #NULL
1865+ if there is an error.
1866+*/
1867+IndicatorService *
1868+indicator_service_new_version (gchar * name, guint version)
1869+{
1870+ GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE,
1871+ PROP_NAME_S, name,
1872+ PROP_VERSION_S, version,
1873+ NULL);
1874+
1875+ return INDICATOR_SERVICE(obj);
1876+}
1877
1878=== added file 'libindicator/indicator-service.h'
1879--- libindicator/indicator-service.h 1970-01-01 00:00:00 +0000
1880+++ libindicator/indicator-service.h 2009-12-10 17:02:12 +0000
1881@@ -0,0 +1,85 @@
1882+/*
1883+An object used to provide a simple interface for a service
1884+to query version and manage whether it's running.
1885+
1886+Copyright 2009 Canonical Ltd.
1887+
1888+Authors:
1889+ Ted Gould <ted@canonical.com>
1890+
1891+This library is free software; you can redistribute it and/or
1892+modify it under the terms of the GNU General Public License
1893+version 3.0 as published by the Free Software Foundation.
1894+
1895+This library is distributed in the hope that it will be useful,
1896+but WITHOUT ANY WARRANTY; without even the implied warranty of
1897+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1898+GNU General Public License version 3.0 for more details.
1899+
1900+You should have received a copy of the GNU General Public
1901+License along with this library. If not, see
1902+<http://www.gnu.org/licenses/>.
1903+*/
1904+
1905+#ifndef __INDICATOR_SERVICE_H__
1906+#define __INDICATOR_SERVICE_H__
1907+
1908+#include <glib.h>
1909+#include <glib-object.h>
1910+
1911+G_BEGIN_DECLS
1912+
1913+#define INDICATOR_SERVICE_TYPE (indicator_service_get_type ())
1914+#define INDICATOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_TYPE, IndicatorService))
1915+#define INDICATOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_TYPE, IndicatorServiceClass))
1916+#define INDICATOR_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_TYPE))
1917+#define INDICATOR_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_TYPE))
1918+#define INDICATOR_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_TYPE, IndicatorServiceClass))
1919+
1920+#define INDICATOR_SERVICE_SIGNAL_SHUTDOWN "shutdown"
1921+
1922+typedef struct _IndicatorService IndicatorService;
1923+typedef struct _IndicatorServiceClass IndicatorServiceClass;
1924+
1925+/**
1926+ IndicatorServiceClass:
1927+ @parent_class: #GObjectClass
1928+ @shutdown: Slot for IndicatorServiceClass::shutdown
1929+ @indicator_service_reserved1: Reserved for future use
1930+ @indicator_service_reserved2: Reserved for future use
1931+ @indicator_service_reserved3: Reserved for future use
1932+ @indicator_service_reserved4: Reserved for future use
1933+
1934+*/
1935+struct _IndicatorServiceClass {
1936+ GObjectClass parent_class;
1937+
1938+ /* Signals */
1939+ void (*shutdown) (IndicatorService * service, gpointer user_data);
1940+
1941+ /* Reserved */
1942+ void (*indicator_service_reserved1) (void);
1943+ void (*indicator_service_reserved2) (void);
1944+ void (*indicator_service_reserved3) (void);
1945+ void (*indicator_service_reserved4) (void);
1946+};
1947+
1948+/**
1949+ IndicatorService:
1950+ @parent: #GObject
1951+
1952+*/
1953+struct _IndicatorService {
1954+ GObject parent;
1955+
1956+};
1957+
1958+GType indicator_service_get_type (void);
1959+
1960+IndicatorService * indicator_service_new (gchar * name);
1961+IndicatorService * indicator_service_new_version (gchar * name,
1962+ guint version);
1963+
1964+G_END_DECLS
1965+
1966+#endif
1967
1968=== added file 'libindicator/indicator-service.xml'
1969--- libindicator/indicator-service.xml 1970-01-01 00:00:00 +0000
1970+++ libindicator/indicator-service.xml 2009-12-10 17:02:12 +0000
1971@@ -0,0 +1,21 @@
1972+<?xml version="1.0" encoding="UTF-8"?>
1973+<node name="/">
1974+ <interface name="org.ayatana.indicator.service">
1975+<!-- Properties -->
1976+ <!-- None currently -->
1977+
1978+<!-- Methods -->
1979+ <method name="Watch">
1980+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
1981+ <arg type="u" name="version" direction="out" />
1982+ <arg type="u" name="service_version" direction="out" />
1983+ </method>
1984+ <method name="UnWatch">
1985+ <annotation name="org.freedesktop.DBus.GLib.Async" value="true" />
1986+ </method>
1987+
1988+<!-- Signals -->
1989+ <!-- None currently -->
1990+
1991+ </interface>
1992+</node>
1993
1994=== modified file 'libindicator/indicator.h'
1995--- libindicator/indicator.h 2009-10-06 15:00:34 +0000
1996+++ libindicator/indicator.h 2009-12-10 17:02:12 +0000
1997@@ -25,31 +25,17 @@
1998
1999 #include <gtk/gtk.h>
2000
2001-#define INDICATOR_GET_LABEL_S "get_label"
2002-typedef GtkLabel * (*get_label_t)(void);
2003-GtkLabel * get_label (void);
2004-
2005-#define INDICATOR_GET_ICON_S "get_icon"
2006-typedef GtkImage * (*get_icon_t) (void);
2007-GtkImage * get_icon (void);
2008-
2009-#define INDICATOR_GET_MENU_S "get_menu"
2010-typedef GtkMenu * (*get_menu_t) (void);
2011-GtkMenu * get_menu (void);
2012-
2013 #define INDICATOR_GET_VERSION_S "get_version"
2014 typedef gchar * (*get_version_t) (void);
2015 gchar * get_version (void);
2016
2017-#define INDICATOR_VERSION "0.2.0"
2018+#define INDICATOR_VERSION "0.3.0"
2019 #define INDICATOR_SET_VERSION gchar * get_version(void) { return INDICATOR_VERSION; }
2020 #define INDICATOR_VERSION_CHECK(x) (!g_strcmp0(x, INDICATOR_VERSION))
2021
2022-#define INDICATOR_GET_NAME_S "get_name"
2023-typedef gchar * (*get_name_t) (void);
2024-gchar * get_name (void);
2025-#define INDICATOR_SET_NAME(x) gchar * get_name(void) {return (x); }
2026-
2027+#define INDICATOR_GET_TYPE_S "get_type"
2028+typedef GType (*get_type_t) (void);
2029+#define INDICATOR_SET_TYPE(x) GType get_type (void) { return x; }
2030
2031 #endif /* __LIBINDICATOR_INDICATOR_H_SEEN__ */
2032
2033
2034=== modified file 'libindicator/indicator.pc.in'
2035--- libindicator/indicator.pc.in 2009-08-08 15:55:54 +0000
2036+++ libindicator/indicator.pc.in 2009-12-10 17:02:12 +0000
2037@@ -4,12 +4,12 @@
2038 bindir=@bindir@
2039 includedir=@includedir@
2040
2041-indicatordir=${libdir}/indicators/2/
2042+indicatordir=${libdir}/indicators/3/
2043 iconsdir=@datarootdir@/@PACKAGE@/icons/
2044
2045-Cflags: -I${includedir}/libindicator-0.1
2046+Cflags: -I${includedir}/libindicator-0.3
2047 Requires: gtk+-2.0
2048-Libs:
2049+Libs: -lindicator
2050
2051 Name: libindicator
2052 Description: libindicator.
2053
2054=== added directory 'tests'
2055=== added file 'tests/Makefile.am'
2056--- tests/Makefile.am 1970-01-01 00:00:00 +0000
2057+++ tests/Makefile.am 2009-12-10 17:02:12 +0000
2058@@ -0,0 +1,308 @@
2059+TESTS =
2060+DISTCLEANFILES =
2061+
2062+check_PROGRAMS =
2063+
2064+lib_LTLIBRARIES = \
2065+ libdummy-indicator-blank.la \
2066+ libdummy-indicator-null.la \
2067+ libdummy-indicator-signaler.la \
2068+ libdummy-indicator-simple.la
2069+
2070+DBUS_RUNNER=dbus-test-runner --dbus-config /usr/share/dbus-test-runner/session.conf
2071+
2072+#############################
2073+# Test Loader
2074+#############################
2075+
2076+check_PROGRAMS += test-loader
2077+
2078+test_loader_SOURCES = \
2079+ test-loader.c
2080+
2081+test_loader_CFLAGS = \
2082+ -Wall -Werror \
2083+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir) \
2084+ -DBUILD_DIR="\"$(builddir)\""
2085+
2086+test_loader_LDADD = \
2087+ $(LIBINDICATOR_LIBS) \
2088+ -L$(top_builddir)/libindicator/.libs \
2089+ -lindicator
2090+
2091+#############################
2092+# Dummy Indicator Blank
2093+#############################
2094+
2095+libdummy_indicator_blank_la_SOURCES = \
2096+ dummy-indicator-blank.c
2097+
2098+libdummy_indicator_blank_la_CFLAGS = \
2099+ -Wall -Werror \
2100+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2101+
2102+libdummy_indicator_blank_la_LIBADD = \
2103+ $(LIBINDICATOR_LIBS) \
2104+ -L$(top_builddir)/libindicator/.libs \
2105+ -lindicator
2106+
2107+libdummy_indicator_blank_la_LDFLAGS = \
2108+ -module \
2109+ -avoid-version
2110+
2111+#############################
2112+# Dummy Indicator NULL
2113+#############################
2114+
2115+libdummy_indicator_null_la_SOURCES = \
2116+ dummy-indicator-null.c
2117+
2118+libdummy_indicator_null_la_CFLAGS = \
2119+ -Wall -Werror \
2120+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2121+
2122+libdummy_indicator_null_la_LIBADD = \
2123+ $(LIBINDICATOR_LIBS) \
2124+ -L$(top_builddir)/libindicator/.libs \
2125+ -lindicator
2126+
2127+libdummy_indicator_null_la_LDFLAGS = \
2128+ -module \
2129+ -avoid-version
2130+
2131+#############################
2132+# Dummy Indicator Signaler
2133+#############################
2134+
2135+libdummy_indicator_signaler_la_SOURCES = \
2136+ dummy-indicator-signaler.c
2137+
2138+libdummy_indicator_signaler_la_CFLAGS = \
2139+ -Wall -Werror \
2140+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2141+
2142+libdummy_indicator_signaler_la_LIBADD = \
2143+ $(LIBINDICATOR_LIBS) \
2144+ -L$(top_builddir)/libindicator/.libs \
2145+ -lindicator
2146+
2147+libdummy_indicator_signaler_la_LDFLAGS = \
2148+ -module \
2149+ -avoid-version
2150+
2151+#############################
2152+# Dummy Indicator Simple
2153+#############################
2154+
2155+libdummy_indicator_simple_la_SOURCES = \
2156+ dummy-indicator-simple.c
2157+
2158+libdummy_indicator_simple_la_CFLAGS = \
2159+ -Wall -Werror \
2160+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2161+
2162+libdummy_indicator_simple_la_LIBADD = \
2163+ $(LIBINDICATOR_LIBS) \
2164+ -L$(top_builddir)/libindicator/.libs \
2165+ -lindicator
2166+
2167+libdummy_indicator_simple_la_LDFLAGS = \
2168+ -module \
2169+ -avoid-version
2170+
2171+#############################
2172+# Service Shutdown Timeout
2173+#############################
2174+
2175+check_PROGRAMS += service-shutdown-timeout
2176+
2177+service_shutdown_timeout_SOURCES = \
2178+ service-shutdown-timeout.c
2179+
2180+service_shutdown_timeout_CFLAGS = \
2181+ -Wall -Werror \
2182+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2183+
2184+service_shutdown_timeout_LDADD = \
2185+ $(LIBINDICATOR_LIBS) \
2186+ $(top_builddir)/libindicator/.libs/libindicator.a
2187+
2188+service-shutdown-timeout-tester: service-shutdown-timeout Makefile
2189+ @echo "#!/bin/sh" > service-shutdown-timeout-tester
2190+ @echo $(DBUS_RUNNER) --task ./service-shutdown-timeout >> service-shutdown-timeout-tester
2191+ @chmod +x service-shutdown-timeout-tester
2192+
2193+TESTS += service-shutdown-timeout-tester
2194+DISTCLEANFILES += service-shutdown-timeout-tester
2195+
2196+#############################
2197+# Service Manager No Connect
2198+#############################
2199+
2200+check_PROGRAMS += service-manager-no-connect
2201+
2202+service_manager_no_connect_SOURCES = \
2203+ service-manager-no-connect.c
2204+
2205+service_manager_no_connect_CFLAGS = \
2206+ -Wall -Werror \
2207+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2208+
2209+service_manager_no_connect_LDADD = \
2210+ $(LIBINDICATOR_LIBS) \
2211+ $(top_builddir)/libindicator/.libs/libindicator.a
2212+
2213+service-manager-no-connect-tester: service-manager-no-connect Makefile.am
2214+ @echo "#!/bin/sh" > service-manager-no-connect-tester
2215+ @echo $(DBUS_RUNNER) --task ./service-manager-no-connect >> service-manager-no-connect-tester
2216+ @chmod +x service-manager-no-connect-tester
2217+
2218+TESTS += service-manager-no-connect-tester
2219+DISTCLEANFILES += service-manager-no-connect-tester
2220+
2221+#############################
2222+# Service Manager Connect
2223+#############################
2224+
2225+session.conf: $(srcdir)/session.conf.in Makefile.am
2226+ sed -e "s|\@servicedir\@|$(abspath $(builddir))|" $< > $@
2227+
2228+service-manager-connect.service: $(srcdir)/service-manager-connect.service.in Makefile.am
2229+ sed -e "s|\@builddir\@|$(abspath $(builddir))|" $< > $@
2230+
2231+check_PROGRAMS += service-manager-connect
2232+
2233+service_manager_connect_SOURCES = \
2234+ service-manager-connect.c
2235+
2236+service_manager_connect_CFLAGS = \
2237+ -Wall -Werror \
2238+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2239+
2240+service_manager_connect_LDADD = \
2241+ $(LIBINDICATOR_LIBS) \
2242+ $(top_builddir)/libindicator/.libs/libindicator.a
2243+
2244+check_PROGRAMS += service-manager-connect-service
2245+
2246+service_manager_connect_service_SOURCES = \
2247+ service-manager-connect-service.c
2248+
2249+service_manager_connect_service_CFLAGS = \
2250+ -Wall -Werror \
2251+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2252+
2253+service_manager_connect_service_LDADD = \
2254+ $(LIBINDICATOR_LIBS) \
2255+ $(top_builddir)/libindicator/.libs/libindicator.a
2256+
2257+service-manager-connect-tester: service-manager-connect service-manager-connect-service session.conf service-manager-connect.service Makefile.am
2258+ @echo "#!/bin/sh" > service-manager-connect-tester
2259+ @echo dbus-test-runner --dbus-config $(builddir)/session.conf --task ./service-manager-connect >> service-manager-connect-tester
2260+ @chmod +x service-manager-connect-tester
2261+
2262+TESTS += service-manager-connect-tester
2263+DISTCLEANFILES += service-manager-connect-tester session.conf service-manager-connect.service
2264+
2265+#############################
2266+# Service Versions
2267+#############################
2268+
2269+service-version-good.service: $(srcdir)/service-version-good.service.in Makefile.am
2270+ sed -e "s|\@builddir\@|$(abspath $(builddir))|" $< > $@
2271+
2272+service-version-bad.service: $(srcdir)/service-version-bad.service.in Makefile.am
2273+ sed -e "s|\@builddir\@|$(abspath $(builddir))|" $< > $@
2274+
2275+check_PROGRAMS += service-version-manager
2276+
2277+service_version_manager_SOURCES = \
2278+ service-version-values.h \
2279+ service-version-manager.c
2280+
2281+service_version_manager_CFLAGS = \
2282+ -Wall -Werror \
2283+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2284+
2285+service_version_manager_LDADD = \
2286+ $(LIBINDICATOR_LIBS) \
2287+ $(top_builddir)/libindicator/.libs/libindicator.a
2288+
2289+check_PROGRAMS += service-version-bad-service
2290+
2291+service_version_bad_service_SOURCES = \
2292+ service-version-values.h \
2293+ service-version-bad-service.c
2294+
2295+service_version_bad_service_CFLAGS = \
2296+ -Wall -Werror \
2297+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2298+
2299+service_version_bad_service_LDADD = \
2300+ $(LIBINDICATOR_LIBS) \
2301+ $(top_builddir)/libindicator/.libs/libindicator.a
2302+
2303+check_PROGRAMS += service-version-good-service
2304+
2305+service_version_good_service_SOURCES = \
2306+ service-version-values.h \
2307+ service-version-good-service.c
2308+
2309+service_version_good_service_CFLAGS = \
2310+ -Wall -Werror \
2311+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2312+
2313+service_version_good_service_LDADD = \
2314+ $(LIBINDICATOR_LIBS) \
2315+ $(top_builddir)/libindicator/.libs/libindicator.a
2316+
2317+service-version-tester: service-version-manager service-version-bad-service service-version-good-service session.conf service-version-bad.service service-version-good.service Makefile.am
2318+ @echo "#!/bin/sh" > $@
2319+ @echo dbus-test-runner --dbus-config $(builddir)/session.conf --task ./service-version-manager >> $@
2320+ @chmod +x $@
2321+
2322+TESTS += service-version-tester
2323+DISTCLEANFILES += service-version-tester service-version-bad.service service-version-good.service
2324+
2325+#############################
2326+# Service Manager Shutdown
2327+#############################
2328+
2329+check_PROGRAMS += service-manager-nostart-connect
2330+
2331+service_manager_nostart_connect_SOURCES = \
2332+ service-manager-nostart-connect.c
2333+
2334+service_manager_nostart_connect_CFLAGS = \
2335+ -Wall -Werror \
2336+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir)
2337+
2338+service_manager_nostart_connect_LDADD = \
2339+ $(LIBINDICATOR_LIBS) \
2340+ $(top_builddir)/libindicator/.libs/libindicator.a
2341+
2342+service-manager-connect-nostart-tester: service-manager-nostart-connect service-manager-connect-service Makefile.am
2343+ @echo "#!/bin/sh" > $@
2344+ @echo dbus-test-runner --task ./service-manager-nostart-connect --task ./service-manager-connect-service >> $@
2345+ @chmod +x $@
2346+
2347+TESTS += service-manager-connect-nostart-tester
2348+DISTCLEANFILES += service-manager-connect-nostart-tester
2349+
2350+#############################
2351+# Test stuff
2352+#############################
2353+
2354+XML_REPORT = loader-check-results.xml
2355+HTML_REPORT = loader-check-results.html
2356+
2357+loader-tester: test-loader libdummy-indicator-null.la libdummy-indicator-simple.la Makefile
2358+ @echo "#!/bin/sh" > loader-tester
2359+ @echo gtester -k --verbose -o=$(XML_REPORT) ./test-loader >> loader-tester
2360+ @chmod +x loader-tester
2361+
2362+TESTS += loader-tester
2363+DISTCLEANFILES += loader-tester
2364+
2365+DISTCLEANFILES += $(XML_REPORT) $(HTML_REPORT)
2366+
2367
2368=== added file 'tests/dummy-indicator-blank.c'
2369--- tests/dummy-indicator-blank.c 1970-01-01 00:00:00 +0000
2370+++ tests/dummy-indicator-blank.c 2009-12-10 17:02:12 +0000
2371@@ -0,0 +1,5 @@
2372+
2373+#include "libindicator/indicator.h"
2374+
2375+INDICATOR_SET_VERSION
2376+
2377
2378=== added file 'tests/dummy-indicator-null.c'
2379--- tests/dummy-indicator-null.c 1970-01-01 00:00:00 +0000
2380+++ tests/dummy-indicator-null.c 2009-12-10 17:02:12 +0000
2381@@ -0,0 +1,95 @@
2382+
2383+#include <glib.h>
2384+#include <glib-object.h>
2385+
2386+#include "libindicator/indicator.h"
2387+#include "libindicator/indicator-object.h"
2388+
2389+#define DUMMY_INDICATOR_NULL_TYPE (dummy_indicator_null_get_type ())
2390+#define DUMMY_INDICATOR_NULL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_NULL_TYPE, DummyIndicatorNull))
2391+#define DUMMY_INDICATOR_NULL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_NULL_TYPE, DummyIndicatorNullClass))
2392+#define IS_DUMMY_INDICATOR_NULL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_NULL_TYPE))
2393+#define IS_DUMMY_INDICATOR_NULL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_NULL_TYPE))
2394+#define DUMMY_INDICATOR_NULL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_NULL_TYPE, DummyIndicatorNullClass))
2395+
2396+typedef struct _DummyIndicatorNull DummyIndicatorNull;
2397+typedef struct _DummyIndicatorNullClass DummyIndicatorNullClass;
2398+
2399+struct _DummyIndicatorNullClass {
2400+ IndicatorObjectClass parent_class;
2401+};
2402+
2403+struct _DummyIndicatorNull {
2404+ IndicatorObject parent;
2405+};
2406+
2407+GType dummy_indicator_null_get_type (void);
2408+
2409+INDICATOR_SET_VERSION
2410+INDICATOR_SET_TYPE(DUMMY_INDICATOR_NULL_TYPE)
2411+
2412+
2413+GtkLabel *
2414+get_label (IndicatorObject * io)
2415+{
2416+ return NULL;
2417+}
2418+
2419+GtkImage *
2420+get_icon (IndicatorObject * io)
2421+{
2422+ return NULL;
2423+}
2424+
2425+GtkMenu *
2426+get_menu (IndicatorObject * io)
2427+{
2428+ return NULL;
2429+}
2430+
2431+static void dummy_indicator_null_class_init (DummyIndicatorNullClass *klass);
2432+static void dummy_indicator_null_init (DummyIndicatorNull *self);
2433+static void dummy_indicator_null_dispose (GObject *object);
2434+static void dummy_indicator_null_finalize (GObject *object);
2435+
2436+G_DEFINE_TYPE (DummyIndicatorNull, dummy_indicator_null, INDICATOR_OBJECT_TYPE);
2437+
2438+static void
2439+dummy_indicator_null_class_init (DummyIndicatorNullClass *klass)
2440+{
2441+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2442+
2443+ object_class->dispose = dummy_indicator_null_dispose;
2444+ object_class->finalize = dummy_indicator_null_finalize;
2445+
2446+ IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
2447+
2448+ io_class->get_label = get_label;
2449+ io_class->get_image = get_icon;
2450+ io_class->get_menu = get_menu;
2451+
2452+ return;
2453+}
2454+
2455+static void
2456+dummy_indicator_null_init (DummyIndicatorNull *self)
2457+{
2458+
2459+ return;
2460+}
2461+
2462+static void
2463+dummy_indicator_null_dispose (GObject *object)
2464+{
2465+
2466+ G_OBJECT_CLASS (dummy_indicator_null_parent_class)->dispose (object);
2467+ return;
2468+}
2469+
2470+static void
2471+dummy_indicator_null_finalize (GObject *object)
2472+{
2473+
2474+ G_OBJECT_CLASS (dummy_indicator_null_parent_class)->finalize (object);
2475+ return;
2476+}
2477
2478=== added file 'tests/dummy-indicator-signaler.c'
2479--- tests/dummy-indicator-signaler.c 1970-01-01 00:00:00 +0000
2480+++ tests/dummy-indicator-signaler.c 2009-12-10 17:02:12 +0000
2481@@ -0,0 +1,109 @@
2482+#include <glib.h>
2483+#include <glib-object.h>
2484+
2485+#include "libindicator/indicator.h"
2486+#include "libindicator/indicator-object.h"
2487+
2488+#define DUMMY_INDICATOR_SIGNALER_TYPE (dummy_indicator_signaler_get_type ())
2489+#define DUMMY_INDICATOR_SIGNALER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIGNALER_TYPE, DummyIndicatorSignaler))
2490+#define DUMMY_INDICATOR_SIGNALER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_SIGNALER_TYPE, DummyIndicatorSignalerClass))
2491+#define IS_DUMMY_INDICATOR_SIGNALER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_SIGNALER_TYPE))
2492+#define IS_DUMMY_INDICATOR_SIGNALER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_SIGNALER_TYPE))
2493+#define DUMMY_INDICATOR_SIGNALER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_SIGNALER_TYPE, DummyIndicatorSignalerClass))
2494+
2495+typedef struct _DummyIndicatorSignaler DummyIndicatorSignaler;
2496+typedef struct _DummyIndicatorSignalerClass DummyIndicatorSignalerClass;
2497+
2498+struct _DummyIndicatorSignalerClass {
2499+ IndicatorObjectClass parent_class;
2500+};
2501+
2502+struct _DummyIndicatorSignaler {
2503+ IndicatorObject parent;
2504+};
2505+
2506+GType dummy_indicator_signaler_get_type (void);
2507+
2508+INDICATOR_SET_VERSION
2509+INDICATOR_SET_TYPE(DUMMY_INDICATOR_SIGNALER_TYPE)
2510+
2511+GtkLabel *
2512+get_label (IndicatorObject * io)
2513+{
2514+ return GTK_LABEL(gtk_label_new("Signaler Item"));
2515+}
2516+
2517+GtkImage *
2518+get_icon (IndicatorObject * io)
2519+{
2520+ return GTK_IMAGE(gtk_image_new());
2521+}
2522+
2523+GtkMenu *
2524+get_menu (IndicatorObject * io)
2525+{
2526+ GtkMenu * main_menu = GTK_MENU(gtk_menu_new());
2527+ GtkWidget * loading_item = gtk_menu_item_new_with_label("Loading...");
2528+ gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), loading_item);
2529+ gtk_widget_show(GTK_WIDGET(loading_item));
2530+
2531+ return main_menu;
2532+}
2533+
2534+static void dummy_indicator_signaler_class_init (DummyIndicatorSignalerClass *klass);
2535+static void dummy_indicator_signaler_init (DummyIndicatorSignaler *self);
2536+static void dummy_indicator_signaler_dispose (GObject *object);
2537+static void dummy_indicator_signaler_finalize (GObject *object);
2538+
2539+G_DEFINE_TYPE (DummyIndicatorSignaler, dummy_indicator_signaler, INDICATOR_OBJECT_TYPE);
2540+
2541+static void
2542+dummy_indicator_signaler_class_init (DummyIndicatorSignalerClass *klass)
2543+{
2544+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2545+
2546+ object_class->dispose = dummy_indicator_signaler_dispose;
2547+ object_class->finalize = dummy_indicator_signaler_finalize;
2548+
2549+ IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
2550+
2551+ io_class->get_label = get_label;
2552+ io_class->get_image = get_icon;
2553+ io_class->get_menu = get_menu;
2554+
2555+ return;
2556+}
2557+
2558+static gboolean
2559+idle_signal (gpointer data)
2560+{
2561+ DummyIndicatorSignaler * self = DUMMY_INDICATOR_SIGNALER(data);
2562+
2563+ g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, GUINT_TO_POINTER(5), TRUE);
2564+ g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, GUINT_TO_POINTER(5), TRUE);
2565+
2566+ return FALSE; /* Don't queue again */
2567+}
2568+
2569+static void
2570+dummy_indicator_signaler_init (DummyIndicatorSignaler *self)
2571+{
2572+ g_idle_add(idle_signal, self);
2573+ return;
2574+}
2575+
2576+static void
2577+dummy_indicator_signaler_dispose (GObject *object)
2578+{
2579+
2580+ G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->dispose (object);
2581+ return;
2582+}
2583+
2584+static void
2585+dummy_indicator_signaler_finalize (GObject *object)
2586+{
2587+
2588+ G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->finalize (object);
2589+ return;
2590+}
2591
2592=== added file 'tests/dummy-indicator-simple.c'
2593--- tests/dummy-indicator-simple.c 1970-01-01 00:00:00 +0000
2594+++ tests/dummy-indicator-simple.c 2009-12-10 17:02:12 +0000
2595@@ -0,0 +1,98 @@
2596+#include <glib.h>
2597+#include <glib-object.h>
2598+
2599+#include "libindicator/indicator.h"
2600+#include "libindicator/indicator-object.h"
2601+
2602+#define DUMMY_INDICATOR_SIMPLE_TYPE (dummy_indicator_simple_get_type ())
2603+#define DUMMY_INDICATOR_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIMPLE_TYPE, DummyIndicatorSimple))
2604+#define DUMMY_INDICATOR_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_SIMPLE_TYPE, DummyIndicatorSimpleClass))
2605+#define IS_DUMMY_INDICATOR_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_SIMPLE_TYPE))
2606+#define IS_DUMMY_INDICATOR_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_SIMPLE_TYPE))
2607+#define DUMMY_INDICATOR_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_SIMPLE_TYPE, DummyIndicatorSimpleClass))
2608+
2609+typedef struct _DummyIndicatorSimple DummyIndicatorSimple;
2610+typedef struct _DummyIndicatorSimpleClass DummyIndicatorSimpleClass;
2611+
2612+struct _DummyIndicatorSimpleClass {
2613+ IndicatorObjectClass parent_class;
2614+};
2615+
2616+struct _DummyIndicatorSimple {
2617+ IndicatorObject parent;
2618+};
2619+
2620+GType dummy_indicator_simple_get_type (void);
2621+
2622+INDICATOR_SET_VERSION
2623+INDICATOR_SET_TYPE(DUMMY_INDICATOR_SIMPLE_TYPE)
2624+
2625+GtkLabel *
2626+get_label (IndicatorObject * io)
2627+{
2628+ return GTK_LABEL(gtk_label_new("Simple Item"));
2629+}
2630+
2631+GtkImage *
2632+get_icon (IndicatorObject * io)
2633+{
2634+ return GTK_IMAGE(gtk_image_new());
2635+}
2636+
2637+GtkMenu *
2638+get_menu (IndicatorObject * io)
2639+{
2640+ GtkMenu * main_menu = GTK_MENU(gtk_menu_new());
2641+ GtkWidget * loading_item = gtk_menu_item_new_with_label("Loading...");
2642+ gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), loading_item);
2643+ gtk_widget_show(GTK_WIDGET(loading_item));
2644+
2645+ return main_menu;
2646+}
2647+
2648+static void dummy_indicator_simple_class_init (DummyIndicatorSimpleClass *klass);
2649+static void dummy_indicator_simple_init (DummyIndicatorSimple *self);
2650+static void dummy_indicator_simple_dispose (GObject *object);
2651+static void dummy_indicator_simple_finalize (GObject *object);
2652+
2653+G_DEFINE_TYPE (DummyIndicatorSimple, dummy_indicator_simple, INDICATOR_OBJECT_TYPE);
2654+
2655+static void
2656+dummy_indicator_simple_class_init (DummyIndicatorSimpleClass *klass)
2657+{
2658+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2659+
2660+ object_class->dispose = dummy_indicator_simple_dispose;
2661+ object_class->finalize = dummy_indicator_simple_finalize;
2662+
2663+ IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
2664+
2665+ io_class->get_label = get_label;
2666+ io_class->get_image = get_icon;
2667+ io_class->get_menu = get_menu;
2668+
2669+ return;
2670+}
2671+
2672+static void
2673+dummy_indicator_simple_init (DummyIndicatorSimple *self)
2674+{
2675+
2676+ return;
2677+}
2678+
2679+static void
2680+dummy_indicator_simple_dispose (GObject *object)
2681+{
2682+
2683+ G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->dispose (object);
2684+ return;
2685+}
2686+
2687+static void
2688+dummy_indicator_simple_finalize (GObject *object)
2689+{
2690+
2691+ G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->finalize (object);
2692+ return;
2693+}
2694
2695=== added file 'tests/service-manager-connect-service.c'
2696--- tests/service-manager-connect-service.c 1970-01-01 00:00:00 +0000
2697+++ tests/service-manager-connect-service.c 2009-12-10 17:02:12 +0000
2698@@ -0,0 +1,48 @@
2699+
2700+#include <glib.h>
2701+#include "libindicator/indicator-service.h"
2702+
2703+static GMainLoop * mainloop = NULL;
2704+static gboolean passed = FALSE;
2705+
2706+gboolean
2707+timeout (gpointer data)
2708+{
2709+ passed = FALSE;
2710+ g_debug("Timeout with no shutdown.");
2711+ g_main_loop_quit(mainloop);
2712+ return FALSE;
2713+}
2714+
2715+void
2716+shutdown (void)
2717+{
2718+ g_debug("Shutdown");
2719+ passed = TRUE;
2720+ g_main_loop_quit(mainloop);
2721+ return;
2722+}
2723+
2724+int
2725+main (int argc, char ** argv)
2726+{
2727+ g_type_init();
2728+
2729+ g_debug("Starting service");
2730+
2731+ IndicatorService * is = indicator_service_new("org.ayatana.test");
2732+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL);
2733+
2734+ g_timeout_add_seconds(1, timeout, NULL);
2735+
2736+ mainloop = g_main_loop_new(NULL, FALSE);
2737+ g_main_loop_run(mainloop);
2738+
2739+ g_debug("Quiting");
2740+ if (passed) {
2741+ g_debug("Passed");
2742+ return 0;
2743+ }
2744+ g_debug("Failed");
2745+ return 1;
2746+}
2747
2748=== added file 'tests/service-manager-connect.c'
2749--- tests/service-manager-connect.c 1970-01-01 00:00:00 +0000
2750+++ tests/service-manager-connect.c 2009-12-10 17:02:12 +0000
2751@@ -0,0 +1,63 @@
2752+
2753+#include <glib.h>
2754+#include "libindicator/indicator-service-manager.h"
2755+
2756+static GMainLoop * mainloop = NULL;
2757+static gboolean passed = FALSE;
2758+
2759+gboolean
2760+timeout (gpointer data)
2761+{
2762+ passed = FALSE;
2763+ g_error("Timeout with no connection.");
2764+ g_main_loop_quit(mainloop);
2765+ return FALSE;
2766+}
2767+
2768+void
2769+connection (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
2770+{
2771+ static gboolean has_connected = FALSE;
2772+
2773+ if (has_connected && connected) {
2774+ g_warning("We got two connected signals. FAIL.");
2775+ passed = FALSE;
2776+ return;
2777+ }
2778+
2779+ if (!connected) {
2780+ g_debug("Not connected");
2781+ return;
2782+ }
2783+
2784+ has_connected = TRUE;
2785+ g_debug("Connection");
2786+ passed = TRUE;
2787+ g_main_loop_quit(mainloop);
2788+ return;
2789+}
2790+
2791+int
2792+main (int argc, char ** argv)
2793+{
2794+ g_type_init();
2795+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
2796+
2797+ IndicatorServiceManager * is = indicator_service_manager_new("org.ayatana.test");
2798+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection), NULL);
2799+
2800+ g_timeout_add_seconds(1, timeout, NULL);
2801+
2802+ mainloop = g_main_loop_new(NULL, FALSE);
2803+ g_main_loop_run(mainloop);
2804+
2805+ g_object_unref(is);
2806+
2807+ g_debug("Quiting");
2808+ if (passed) {
2809+ g_debug("Passed");
2810+ return 0;
2811+ }
2812+ g_debug("Failed");
2813+ return 1;
2814+}
2815
2816=== added file 'tests/service-manager-connect.service.in'
2817--- tests/service-manager-connect.service.in 1970-01-01 00:00:00 +0000
2818+++ tests/service-manager-connect.service.in 2009-12-10 17:02:12 +0000
2819@@ -0,0 +1,3 @@
2820+[D-BUS Service]
2821+Name=org.ayatana.test
2822+Exec=@builddir@/service-manager-connect-service
2823
2824=== added file 'tests/service-manager-no-connect.c'
2825--- tests/service-manager-no-connect.c 1970-01-01 00:00:00 +0000
2826+++ tests/service-manager-no-connect.c 2009-12-10 17:02:12 +0000
2827@@ -0,0 +1,47 @@
2828+
2829+#include <glib.h>
2830+#include "libindicator/indicator-service-manager.h"
2831+
2832+static GMainLoop * mainloop = NULL;
2833+static gboolean passed = FALSE;
2834+
2835+gboolean
2836+timeout (gpointer data)
2837+{
2838+ passed = TRUE;
2839+ g_debug("Timeout with no connection.");
2840+ g_main_loop_quit(mainloop);
2841+ return FALSE;
2842+}
2843+
2844+void
2845+connection (void)
2846+{
2847+ g_debug("Connection");
2848+ passed = FALSE;
2849+ g_main_loop_quit(mainloop);
2850+ return;
2851+}
2852+
2853+int
2854+main (int argc, char ** argv)
2855+{
2856+ g_type_init();
2857+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
2858+
2859+ IndicatorServiceManager * is = indicator_service_manager_new("my.test.name");
2860+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, connection, NULL);
2861+
2862+ g_timeout_add_seconds(1, timeout, NULL);
2863+
2864+ mainloop = g_main_loop_new(NULL, FALSE);
2865+ g_main_loop_run(mainloop);
2866+
2867+ g_debug("Quiting");
2868+ if (passed) {
2869+ g_debug("Passed");
2870+ return 0;
2871+ }
2872+ g_debug("Failed");
2873+ return 1;
2874+}
2875
2876=== added file 'tests/service-manager-nostart-connect.c'
2877--- tests/service-manager-nostart-connect.c 1970-01-01 00:00:00 +0000
2878+++ tests/service-manager-nostart-connect.c 2009-12-10 17:02:12 +0000
2879@@ -0,0 +1,65 @@
2880+
2881+#include <glib.h>
2882+#include "libindicator/indicator-service-manager.h"
2883+
2884+static GMainLoop * mainloop = NULL;
2885+static gboolean passed = FALSE;
2886+
2887+gboolean
2888+timeout (gpointer data)
2889+{
2890+ passed = FALSE;
2891+ g_error("Timeout with no connection.");
2892+ g_main_loop_quit(mainloop);
2893+ return FALSE;
2894+}
2895+
2896+void
2897+connection (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
2898+{
2899+ static gboolean has_connected = FALSE;
2900+
2901+ if (has_connected && connected) {
2902+ g_warning("We got two connected signals. FAIL.");
2903+ passed = FALSE;
2904+ return;
2905+ }
2906+
2907+ if (!connected) {
2908+ g_debug("Not connected");
2909+ return;
2910+ }
2911+
2912+ has_connected = TRUE;
2913+ g_debug("Connection");
2914+ passed = TRUE;
2915+ g_main_loop_quit(mainloop);
2916+ return;
2917+}
2918+
2919+int
2920+main (int argc, char ** argv)
2921+{
2922+ g_type_init();
2923+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
2924+
2925+ g_usleep(150000);
2926+
2927+ IndicatorServiceManager * is = indicator_service_manager_new("org.ayatana.test");
2928+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection), NULL);
2929+
2930+ g_timeout_add_seconds(1, timeout, NULL);
2931+
2932+ mainloop = g_main_loop_new(NULL, FALSE);
2933+ g_main_loop_run(mainloop);
2934+
2935+ g_object_unref(is);
2936+
2937+ g_debug("Quiting");
2938+ if (passed) {
2939+ g_debug("Passed");
2940+ return 0;
2941+ }
2942+ g_debug("Failed");
2943+ return 1;
2944+}
2945
2946=== added file 'tests/service-shutdown-timeout.c'
2947--- tests/service-shutdown-timeout.c 1970-01-01 00:00:00 +0000
2948+++ tests/service-shutdown-timeout.c 2009-12-10 17:02:12 +0000
2949@@ -0,0 +1,46 @@
2950+
2951+#include <glib.h>
2952+#include "libindicator/indicator-service.h"
2953+
2954+static GMainLoop * mainloop = NULL;
2955+static gboolean passed = FALSE;
2956+
2957+gboolean
2958+timeout (gpointer data)
2959+{
2960+ passed = FALSE;
2961+ g_error("Timeout with no shutdown.");
2962+ g_main_loop_quit(mainloop);
2963+ return FALSE;
2964+}
2965+
2966+void
2967+shutdown (void)
2968+{
2969+ g_debug("Shutdown");
2970+ passed = TRUE;
2971+ g_main_loop_quit(mainloop);
2972+ return;
2973+}
2974+
2975+int
2976+main (int argc, char ** argv)
2977+{
2978+ g_type_init();
2979+
2980+ IndicatorService * is = indicator_service_new("my.test.name");
2981+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL);
2982+
2983+ g_timeout_add_seconds(1, timeout, NULL);
2984+
2985+ mainloop = g_main_loop_new(NULL, FALSE);
2986+ g_main_loop_run(mainloop);
2987+
2988+ g_debug("Quiting");
2989+ if (passed) {
2990+ g_debug("Passed");
2991+ return 0;
2992+ }
2993+ g_debug("Failed");
2994+ return 1;
2995+}
2996
2997=== added file 'tests/service-version-bad-service.c'
2998--- tests/service-version-bad-service.c 1970-01-01 00:00:00 +0000
2999+++ tests/service-version-bad-service.c 2009-12-10 17:02:12 +0000
3000@@ -0,0 +1,47 @@
3001+
3002+#include <glib.h>
3003+#include "libindicator/indicator-service.h"
3004+#include "service-version-values.h"
3005+
3006+static GMainLoop * mainloop = NULL;
3007+static gboolean passed = FALSE;
3008+
3009+gboolean
3010+timeout (gpointer data)
3011+{
3012+ passed = FALSE;
3013+ g_debug("Timeout with no shutdown.");
3014+ g_main_loop_quit(mainloop);
3015+ return FALSE;
3016+}
3017+
3018+void
3019+shutdown (void)
3020+{
3021+ g_debug("Shutdown");
3022+ passed = TRUE;
3023+ g_main_loop_quit(mainloop);
3024+ return;
3025+}
3026+
3027+int
3028+main (int argc, char ** argv)
3029+{
3030+ g_type_init();
3031+
3032+ IndicatorService * is = indicator_service_new_version("org.ayatana.version.bad", SERVICE_VERSION_BAD);
3033+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL);
3034+
3035+ g_timeout_add_seconds(1, timeout, NULL);
3036+
3037+ mainloop = g_main_loop_new(NULL, FALSE);
3038+ g_main_loop_run(mainloop);
3039+
3040+ g_debug("Quiting");
3041+ if (passed) {
3042+ g_debug("Passed");
3043+ return 0;
3044+ }
3045+ g_debug("Failed");
3046+ return 1;
3047+}
3048
3049=== added file 'tests/service-version-bad.service.in'
3050--- tests/service-version-bad.service.in 1970-01-01 00:00:00 +0000
3051+++ tests/service-version-bad.service.in 2009-12-10 17:02:12 +0000
3052@@ -0,0 +1,3 @@
3053+[D-BUS Service]
3054+Name=org.ayatana.version.bad
3055+Exec=@builddir@/service-version-bad-service
3056
3057=== added file 'tests/service-version-good-service.c'
3058--- tests/service-version-good-service.c 1970-01-01 00:00:00 +0000
3059+++ tests/service-version-good-service.c 2009-12-10 17:02:12 +0000
3060@@ -0,0 +1,47 @@
3061+
3062+#include <glib.h>
3063+#include "libindicator/indicator-service.h"
3064+#include "service-version-values.h"
3065+
3066+static GMainLoop * mainloop = NULL;
3067+static gboolean passed = FALSE;
3068+
3069+gboolean
3070+timeout (gpointer data)
3071+{
3072+ passed = FALSE;
3073+ g_debug("Timeout with no shutdown.");
3074+ g_main_loop_quit(mainloop);
3075+ return FALSE;
3076+}
3077+
3078+void
3079+shutdown (void)
3080+{
3081+ g_debug("Shutdown");
3082+ passed = TRUE;
3083+ g_main_loop_quit(mainloop);
3084+ return;
3085+}
3086+
3087+int
3088+main (int argc, char ** argv)
3089+{
3090+ g_type_init();
3091+
3092+ IndicatorService * is = indicator_service_new_version("org.ayatana.version.good", SERVICE_VERSION_GOOD);
3093+ g_signal_connect(G_OBJECT(is), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, shutdown, NULL);
3094+
3095+ g_timeout_add_seconds(1, timeout, NULL);
3096+
3097+ mainloop = g_main_loop_new(NULL, FALSE);
3098+ g_main_loop_run(mainloop);
3099+
3100+ g_debug("Quiting");
3101+ if (passed) {
3102+ g_debug("Passed");
3103+ return 0;
3104+ }
3105+ g_debug("Failed");
3106+ return 1;
3107+}
3108
3109=== added file 'tests/service-version-good.service.in'
3110--- tests/service-version-good.service.in 1970-01-01 00:00:00 +0000
3111+++ tests/service-version-good.service.in 2009-12-10 17:02:12 +0000
3112@@ -0,0 +1,3 @@
3113+[D-BUS Service]
3114+Name=org.ayatana.version.good
3115+Exec=@builddir@/service-version-good-service
3116
3117=== added file 'tests/service-version-manager.c'
3118--- tests/service-version-manager.c 1970-01-01 00:00:00 +0000
3119+++ tests/service-version-manager.c 2009-12-10 17:02:12 +0000
3120@@ -0,0 +1,64 @@
3121+
3122+#include <glib.h>
3123+#include "libindicator/indicator-service-manager.h"
3124+#include "service-version-values.h"
3125+
3126+static GMainLoop * mainloop = NULL;
3127+static gboolean con_good = FALSE;
3128+static gboolean con_bad = FALSE;
3129+
3130+gboolean
3131+timeout (gpointer data)
3132+{
3133+ g_debug("Timeout.");
3134+ g_main_loop_quit(mainloop);
3135+ return FALSE;
3136+}
3137+
3138+void
3139+connection_bad (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
3140+{
3141+ if (!connected) return;
3142+ g_debug("Connection From Bad!");
3143+ con_bad = TRUE;
3144+ return;
3145+}
3146+
3147+void
3148+connection_good (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
3149+{
3150+ if (!connected) return;
3151+ g_debug("Connection From Good.");
3152+ con_good = TRUE;
3153+ return;
3154+}
3155+
3156+int
3157+main (int argc, char ** argv)
3158+{
3159+ g_type_init();
3160+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
3161+ g_print("Manager: DBUS_SESSION_BUS_ADDRESS = %s\n", g_getenv("DBUS_SESSION_BUS_ADDRESS"));
3162+
3163+ IndicatorServiceManager * goodis = indicator_service_manager_new_version("org.ayatana.version.good", SERVICE_VERSION_GOOD);
3164+ g_signal_connect(G_OBJECT(goodis), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_good), NULL);
3165+
3166+ IndicatorServiceManager * badis = indicator_service_manager_new_version("org.ayatana.version.bad", SERVICE_VERSION_GOOD);
3167+ g_signal_connect(G_OBJECT(badis), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(connection_bad), NULL);
3168+
3169+ g_timeout_add_seconds(1, timeout, NULL);
3170+
3171+ mainloop = g_main_loop_new(NULL, FALSE);
3172+ g_main_loop_run(mainloop);
3173+
3174+ g_object_unref(goodis);
3175+ g_object_unref(badis);
3176+
3177+ g_debug("Quiting");
3178+ if (con_good && !con_bad) {
3179+ g_debug("Passed");
3180+ return 0;
3181+ }
3182+ g_debug("Failed");
3183+ return 1;
3184+}
3185
3186=== added file 'tests/service-version-values.h'
3187--- tests/service-version-values.h 1970-01-01 00:00:00 +0000
3188+++ tests/service-version-values.h 2009-12-10 17:02:12 +0000
3189@@ -0,0 +1,4 @@
3190+
3191+#define SERVICE_VERSION_GOOD 1342
3192+#define SERVICE_VERSION_BAD 543
3193+
3194
3195=== added file 'tests/session.conf.in'
3196--- tests/session.conf.in 1970-01-01 00:00:00 +0000
3197+++ tests/session.conf.in 2009-12-10 17:02:12 +0000
3198@@ -0,0 +1,40 @@
3199+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
3200+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
3201+<busconfig>
3202+ <!-- If we fork, keep the user's original umask to avoid affecting
3203+ the behavior of child processes. -->
3204+ <keep_umask/>
3205+
3206+ <listen>unix:tmpdir=/tmp</listen>
3207+
3208+ <servicedir>@servicedir@</servicedir>
3209+
3210+ <policy context="default">
3211+ <!-- Allow everything to be sent -->
3212+ <allow send_destination="*" eavesdrop="true"/>
3213+ <!-- Allow everything to be received -->
3214+ <allow eavesdrop="true"/>
3215+ <!-- Allow anyone to own anything -->
3216+ <allow own="*"/>
3217+ </policy>
3218+
3219+ <!-- raise the service start timeout to 40 seconds as it can timeout
3220+ on the live cd on slow machines -->
3221+ <limit name="service_start_timeout">60000</limit>
3222+
3223+ <!-- the memory limits are 1G instead of say 4G because they can't exceed 32-bit signed int max -->
3224+ <limit name="max_incoming_bytes">1000000000</limit>
3225+ <limit name="max_outgoing_bytes">1000000000</limit>
3226+ <limit name="max_message_size">1000000000</limit>
3227+ <limit name="service_start_timeout">120000</limit>
3228+ <limit name="auth_timeout">240000</limit>
3229+ <limit name="max_completed_connections">100000</limit>
3230+ <limit name="max_incomplete_connections">10000</limit>
3231+ <limit name="max_connections_per_user">100000</limit>
3232+ <limit name="max_pending_service_starts">10000</limit>
3233+ <limit name="max_names_per_connection">50000</limit>
3234+ <limit name="max_match_rules_per_connection">50000</limit>
3235+ <limit name="max_replies_per_connection">50000</limit>
3236+ <limit name="reply_timeout">300000</limit>
3237+
3238+</busconfig>
3239
3240=== added file 'tests/test-loader.c'
3241--- tests/test-loader.c 1970-01-01 00:00:00 +0000
3242+++ tests/test-loader.c 2009-12-10 17:02:12 +0000
3243@@ -0,0 +1,146 @@
3244+#include <gtk/gtk.h>
3245+#include "libindicator/indicator-object.h"
3246+
3247+void destroy_cb (gpointer data, GObject * object);
3248+
3249+void
3250+entry_change_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer data)
3251+{
3252+ gpointer * valuestore = (gpointer *)data;
3253+ *valuestore = entry;
3254+ return;
3255+}
3256+
3257+void
3258+test_loader_filename_dummy_signaler (void)
3259+{
3260+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-signaler.so");
3261+ g_assert(object != NULL);
3262+
3263+ gpointer added_value = NULL, removed_value = NULL;
3264+
3265+ g_signal_connect(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_change_cb), &added_value);
3266+ g_signal_connect(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_change_cb), &removed_value);
3267+
3268+ GList * list = indicator_object_get_entries(object);
3269+ g_assert(list != NULL);
3270+ g_list_free(list);
3271+
3272+ while (g_main_context_pending(NULL)) {
3273+ g_main_context_iteration(NULL, TRUE);
3274+ }
3275+
3276+ g_assert(GPOINTER_TO_UINT(added_value) == 5);
3277+ g_assert(GPOINTER_TO_UINT(removed_value) == 5);
3278+
3279+ g_object_unref(object);
3280+
3281+ return;
3282+}
3283+
3284+
3285+void
3286+test_loader_filename_dummy_simple_accessors (void)
3287+{
3288+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so");
3289+ g_assert(object != NULL);
3290+
3291+ g_assert(indicator_object_get_entries(object) != NULL);
3292+
3293+ g_object_unref(object);
3294+
3295+ return;
3296+}
3297+
3298+void
3299+test_loader_filename_dummy_simple (void)
3300+{
3301+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so");
3302+ g_assert(object != NULL);
3303+
3304+ gboolean unreffed = FALSE;
3305+ g_object_weak_ref(G_OBJECT(object), destroy_cb, &unreffed);
3306+
3307+ g_object_unref(object);
3308+ g_assert(unreffed == TRUE);
3309+
3310+ return;
3311+}
3312+
3313+void
3314+test_loader_filename_dummy_blank (void)
3315+{
3316+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-blank.so");
3317+ g_assert(object == NULL);
3318+ return;
3319+}
3320+
3321+void
3322+test_loader_filename_dummy_null (void)
3323+{
3324+ IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-null.so");
3325+ g_assert(object != NULL);
3326+ g_assert(indicator_object_get_entries(object) == NULL);
3327+ g_object_unref(G_OBJECT(object));
3328+ return;
3329+}
3330+
3331+void
3332+test_loader_filename_bad (void)
3333+{
3334+ IndicatorObject * object = indicator_object_new_from_file("/this/file/should/not/exist.so");
3335+ g_assert(object == NULL);
3336+ return;
3337+}
3338+
3339+void
3340+destroy_cb (gpointer data, GObject * object)
3341+{
3342+ gboolean * bob = (gboolean *)data;
3343+ *bob = TRUE;
3344+ return;
3345+}
3346+
3347+void
3348+test_loader_refunref (void)
3349+{
3350+ GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL);
3351+
3352+ gboolean unreffed = FALSE;
3353+ g_object_weak_ref(object, destroy_cb, &unreffed);
3354+
3355+ g_object_unref(object);
3356+
3357+ g_assert(unreffed == TRUE);
3358+
3359+ return;
3360+}
3361+
3362+void
3363+test_loader_creation_deletion_suite (void)
3364+{
3365+ g_test_add_func ("/libindicator/loader/ref_and_unref", test_loader_refunref);
3366+ g_test_add_func ("/libindicator/loader/filename_bad", test_loader_filename_bad);
3367+ g_test_add_func ("/libindicator/loader/dummy/null_load", test_loader_filename_dummy_null);
3368+ g_test_add_func ("/libindicator/loader/dummy/blank_load", test_loader_filename_dummy_null);
3369+ g_test_add_func ("/libindicator/loader/dummy/simple_load", test_loader_filename_dummy_simple);
3370+ g_test_add_func ("/libindicator/loader/dummy/simple_accessors", test_loader_filename_dummy_simple_accessors);
3371+ g_test_add_func ("/libindicator/loader/dummy/signaler", test_loader_filename_dummy_signaler);
3372+
3373+ return;
3374+}
3375+
3376+
3377+int
3378+main (int argc, char ** argv)
3379+{
3380+ g_type_init ();
3381+ g_test_init (&argc, &argv, NULL);
3382+ gtk_init(&argc, &argv);
3383+
3384+ test_loader_creation_deletion_suite();
3385+
3386+ g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL);
3387+
3388+ return g_test_run();
3389+}
3390
3391=== added directory 'tools'
3392=== added file 'tools/Makefile.am'
3393--- tools/Makefile.am 1970-01-01 00:00:00 +0000
3394+++ tools/Makefile.am 2009-12-10 17:02:12 +0000
3395@@ -0,0 +1,21 @@
3396+
3397+libexec_PROGRAMS = \
3398+ indicator-loader
3399+
3400+#############################
3401+# Indicator Loader
3402+#############################
3403+
3404+indicator_loader_SOURCES = \
3405+ indicator-loader.c
3406+
3407+indicator_loader_CFLAGS = \
3408+ -Wall -Werror \
3409+ $(LIBINDICATOR_CFLAGS) -I$(top_srcdir) \
3410+ -DBUILD_DIR="\"$(builddir)\""
3411+
3412+indicator_loader_LDADD = \
3413+ $(LIBINDICATOR_LIBS) \
3414+ -L$(top_builddir)/libindicator/.libs \
3415+ -lindicator
3416+
3417
3418=== added file 'tools/indicator-loader.c'
3419--- tools/indicator-loader.c 1970-01-01 00:00:00 +0000
3420+++ tools/indicator-loader.c 2009-12-10 17:02:12 +0000
3421@@ -0,0 +1,149 @@
3422+/*
3423+A small test loader for loading indicators in test suites
3424+and during development of them.
3425+
3426+Copyright 2009 Canonical Ltd.
3427+
3428+Authors:
3429+ Ted Gould <ted@canonical.com>
3430+
3431+This library is free software; you can redistribute it and/or
3432+modify it under the terms of the GNU General Public License
3433+version 3.0 as published by the Free Software Foundation.
3434+
3435+This library is distributed in the hope that it will be useful,
3436+but WITHOUT ANY WARRANTY; without even the implied warranty of
3437+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3438+GNU General Public License version 3.0 for more details.
3439+
3440+You should have received a copy of the GNU General Public
3441+License along with this library. If not, see
3442+<http://www.gnu.org/licenses/>.
3443+*/
3444+
3445+
3446+#include <gtk/gtk.h>
3447+#include <libindicator/indicator-object.h>
3448+
3449+#define ENTRY_DATA_NAME "indicator-custom-entry-data"
3450+
3451+static void
3452+entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
3453+{
3454+ g_debug("Signal: Entry Added");
3455+
3456+ GtkWidget * menuitem = gtk_menu_item_new();
3457+ GtkWidget * hbox = gtk_hbox_new(FALSE, 3);
3458+
3459+ if (entry->image != NULL) {
3460+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry->image), FALSE, FALSE, 0);
3461+ }
3462+ if (entry->label != NULL) {
3463+ gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry->label), FALSE, FALSE, 0);
3464+ }
3465+ gtk_container_add(GTK_CONTAINER(menuitem), hbox);
3466+ gtk_widget_show(hbox);
3467+
3468+ if (entry->menu != NULL) {
3469+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(entry->menu));
3470+ }
3471+
3472+ gtk_menu_shell_append(GTK_MENU_SHELL(user_data), menuitem);
3473+ gtk_widget_show(menuitem);
3474+
3475+ g_object_set_data(G_OBJECT(menuitem), ENTRY_DATA_NAME, entry);
3476+
3477+ return;
3478+}
3479+
3480+static void
3481+entry_removed_cb (GtkWidget * widget, gpointer userdata)
3482+{
3483+ gpointer data = g_object_get_data(G_OBJECT(widget), ENTRY_DATA_NAME);
3484+
3485+ if (data != userdata) {
3486+ return;
3487+ }
3488+
3489+ gtk_widget_destroy(widget);
3490+ return;
3491+}
3492+
3493+static void
3494+entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
3495+{
3496+ g_debug("Signal: Entry Removed");
3497+
3498+ gtk_container_foreach(GTK_CONTAINER(user_data), entry_removed_cb, entry);
3499+
3500+ return;
3501+}
3502+
3503+static gboolean
3504+load_module (const gchar * name, GtkWidget * menu)
3505+{
3506+ g_debug("Looking at Module: %s", name);
3507+ g_return_val_if_fail(name != NULL, FALSE);
3508+
3509+ if (!g_str_has_suffix(name, G_MODULE_SUFFIX)) {
3510+ return FALSE;
3511+ }
3512+
3513+ g_debug("Loading Module: %s", name);
3514+
3515+ /* Build the object for the module */
3516+ IndicatorObject * io = indicator_object_new_from_file(name);
3517+
3518+ /* Connect to it's signals */
3519+ g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_added), menu);
3520+ g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_removed), menu);
3521+
3522+ /* Work on the entries */
3523+ GList * entries = indicator_object_get_entries(io);
3524+ GList * entry = NULL;
3525+
3526+ for (entry = entries; entry != NULL; entry = g_list_next(entry)) {
3527+ IndicatorObjectEntry * entrydata = (IndicatorObjectEntry *)entry->data;
3528+ entry_added(io, entrydata, menu);
3529+ }
3530+
3531+ g_list_free(entries);
3532+
3533+ return TRUE;
3534+}
3535+
3536+static void
3537+destroy (gpointer data)
3538+{
3539+ gtk_main_quit();
3540+ return;
3541+}
3542+
3543+int
3544+main (int argc, char ** argv)
3545+{
3546+ gtk_init(&argc, &argv);
3547+
3548+ if (argc != 2) {
3549+ g_error("Need filename");
3550+ return 1;
3551+ }
3552+
3553+ GtkWidget * menubar = gtk_menu_bar_new();
3554+ if (!load_module(argv[1], menubar)) {
3555+ g_error("Unable to load module");
3556+ return 1;
3557+ }
3558+
3559+ GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
3560+ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
3561+
3562+ gtk_container_add(GTK_CONTAINER(window), menubar);
3563+
3564+ gtk_widget_show(menubar);
3565+ gtk_widget_show(window);
3566+
3567+ gtk_main();
3568+
3569+ return 0;
3570+}

Subscribers

People subscribed via source and target branches

to all changes: