Bonobo Unique Application v4.1

Gustavo J A M Carneiro <[email protected]>
Newsgroups gmane.comp.gnome.components
Organization INESC
Message-ID <[email protected]>
  Hi Michael, I just fixed the CORBA_any<->GValue conversion problems,
and got argc/argv forwarding working.

  Changes:

o Lots of bugs have been fixed (I probably shouldn't had sent the last
patch);

o There's a hook mechanism that calls user functions when
BonoboApplication instances are created, for plugging library-specific
standard messages;

o Multiple entities can connect to the 'message' signal, and emission
stops when the first returns non-NULL GValue, so that one signal handler
can ignore messages it is not interested without affecting the others.

o There's a new 'new-instance' standard message and signal, which allows
forwarding of argc/argv.

So now I'm going to look into bonobo closures, to see what I can come up
with.


-- 
Gustavo J. A. M. Carneiro
<[email protected]> <[email protected]>
bonobo-uniqapp-v4.1.diff (text/x-patch, 39 KB)
? autom4te.cache
? stamp-h1
? activation-server/test-performance
? bonobo-activation/bonobo-activation-2.0.pc
? tests/test-uniqapp
Index: libbonobo.h
===================================================================
RCS file: /cvs/gnome/libbonobo/libbonobo.h,v
retrieving revision 1.60
diff -u -p -u -p -r1.60 libbonobo.h
--- libbonobo.h	19 Nov 2001 00:13:33 -0000	1.60
+++ libbonobo.h	30 Apr 2003 11:23:34 -0000
@@ -44,6 +44,8 @@ G_BEGIN_DECLS
 
 #include <bonobo/bonobo-storage.h>
 #include <bonobo/bonobo-storage-memory.h>
+#include <bonobo/bonobo-application.h>
+#include <bonobo/bonobo-app-client.h>
 
 G_END_DECLS
 
Index: bonobo/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/Makefile.am,v
retrieving revision 1.72
diff -u -p -u -p -r1.72 Makefile.am
--- bonobo/Makefile.am	16 Apr 2003 19:10:51 -0000	1.72
+++ bonobo/Makefile.am	30 Apr 2003 11:23:34 -0000
@@ -39,6 +39,7 @@ idls =							\
 	$(top_srcdir)/idl/Bonobo_UI.idl			\
 	$(top_srcdir)/idl/Bonobo_Zoomable.idl		\
 	$(top_srcdir)/idl/Bonobo_Exception.idl		\
+	$(top_srcdir)/idl/Bonobo_Application.idl	\
 	$(top_srcdir)/idl/Bonobo_Clipboard.idl
 
 idl_flags = -I$(top_srcdir)/idl -D__Bonobo_COMPILATION
@@ -88,6 +89,8 @@ libbonoboinclude_HEADERS =		\
 	bonobo-storage-memory.h		\
 	bonobo-xobject.h		\
 	bonobo-i18n.h			\
+	bonobo-application.h		\
+	bonobo-app-client.h		\
 	bonobo-types.h
 
 noinst_HEADERS =			\
@@ -125,6 +128,8 @@ libbonobo_src =				\
 	bonobo-stream-memory.c		\
 	bonobo-storage-memory.c		\
 	bonobo-running-context.c	\
+	bonobo-application.c		\
+	bonobo-app-client.c		\
 	bonobo-types.c			\
 	bonobo-debug.c			\
 	bonobo-debug.h
Index: bonobo/bonobo-app-client.c
===================================================================
RCS file: bonobo/bonobo-app-client.c
diff -N bonobo/bonobo-app-client.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.c	30 Apr 2003 11:23:36 -0000
@@ -0,0 +1,316 @@
+  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+#include "bonobo-app-client.h"
+#include "bonobo-arg.h"
+#include "bonobo-exception.h"
+#include "bonobo-types.h"
+
+
+static void bonobo_app_client_class_init    (BonoboAppClientClass *klass);
+static void bonobo_app_client_init          (BonoboAppClient      *app_client);
+static void bonobo_app_client_free_msgdescs (BonoboAppClient      *self);
+
+static gpointer parent_class;
+
+GType
+bonobo_app_client_get_type (void)
+{
+	static GType app_client_type = 0;
+
+	if (!app_client_type)
+	{
+		static const GTypeInfo app_client_info =
+			{
+				sizeof (BonoboAppClientClass),
+				NULL,		/* base_init */
+				NULL,		/* base_finalize */
+				(GClassInitFunc) bonobo_app_client_class_init,
+				NULL,		/* class_finalize */
+				NULL,		/* class_data */
+				sizeof (BonoboAppClient),
+				0,		/* n_preallocs */
+				(GInstanceInitFunc) bonobo_app_client_init,
+			};
+		
+		app_client_type = g_type_register_static
+			(G_TYPE_OBJECT, "BonoboAppClient", &app_client_info, 0);
+	}
+
+	return app_client_type;
+}
+
+
+static void
+bonobo_app_client_finalize (GObject *object)
+{
+	BonoboAppClient *self = BONOBO_APP_CLIENT (object);
+
+	if (self->msgdescs)
+		bonobo_app_client_free_msgdescs (self);
+
+	if (G_OBJECT_CLASS(parent_class)->finalize)
+		G_OBJECT_CLASS(parent_class)->finalize (object);
+}
+
+
+static void
+bonobo_app_client_class_init (BonoboAppClientClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	parent_class = g_type_class_peek_parent (class);
+	object_class->finalize = bonobo_app_client_finalize;
+}
+
+
+static void
+bonobo_app_client_init (BonoboAppClient *app_client)
+{
+
+}
+
+
+/**
+ * bonobo_app_client_new:
+
+ * @app_server: object reference to a Bonobo::Application; this
+ * function takes ownership of this reference (use
+ * bonobo_object_dup_ref if you want to keep your own reference.)
+ * 
+ * Create an application client object connected to the remote (or
+ * local) Bonobo::Application object.
+ *
+ * Warning: Applications should not use this function. See
+ * bonobo_register_unique_application().
+ * 
+ * Return value: a #BonoboAppClient object.
+ **/
+BonoboAppClient *
+bonobo_app_client_new (Bonobo_Application app_server)
+{
+	BonoboAppClient *app_client;
+
+	app_client = g_object_new (BONOBO_TYPE_APP_CLIENT, NULL);
+	app_client->app_server = app_server;
+	return app_client;
+}
+
+
+GValue *
+bonobo_app_client_msg_send_valist (BonoboAppClient *app_client,
+				   const char      *message,
+				   va_list          var_args)
+{
+	CORBA_any                  *ret;
+	Bonobo_Application_ArgList *args;
+	GValue                     *value, *rv;
+	GPtrArray                  *argv;
+	GType                       type;
+	gchar                      *err;
+	CORBA_Environment           ev;
+	int                         i;
+
+	g_return_val_if_fail (app_client, NULL);
+	g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+	argv = g_ptr_array_new ();
+	while ((type = va_arg (var_args, GType)) != G_TYPE_NONE)
+	{
+		value = g_new0 (GValue, 1);
+		g_value_init (value, type);
+		G_VALUE_COLLECT(value, var_args, 0, &err);
+		if (err) g_error("error collecting value: %s", err);
+		g_ptr_array_add (argv, value);
+	}
+	args = Bonobo_Application_ArgList__alloc ();
+	args->_length = argv->len;
+	args->_buffer = Bonobo_Application_ArgList_allocbuf (argv->len);
+	for (i = 0; i < argv->len; ++i) {
+		value = g_ptr_array_index (argv, i);
+		bonobo_arg_from_gvalue (&args->_buffer[i], value);
+		g_value_unset (value);
+		g_free (value);
+	}
+	CORBA_sequence_set_release (args, CORBA_TRUE);
+	g_ptr_array_free (argv, TRUE);
+
+	CORBA_exception_init (&ev);
+	ret = Bonobo_Application_message (app_client->app_server, message, args, &ev);
+	CORBA_free (args);
+	if (ev._major != CORBA_NO_EXCEPTION) {
+		g_warning ("error while sending message to application server: %s",
+			   bonobo_exception_get_text (&ev));
+		CORBA_exception_free (&ev);
+		return NULL;
+	}
+	CORBA_exception_free (&ev);
+	
+	if (ret->_type != TC_void) {
+		rv = g_new0 (GValue, 1);
+		bonobo_arg_to_gvalue (rv, ret);
+	} else
+		rv = NULL;
+	CORBA_free (ret);
+	return rv;
+}
+
+
+/**
+ * bonobo_app_client_msg_send:
+ * @message: message name
+ * 
+ * Send a message to the application server. Takes a variable length
+ * argument list of GType, value pairs, terminated with
+ * G_TYPE_NONE. Values are direct C values, not GValues! Example:
+ * <informalexample><programlisting>
+ * GValue *retval;
+ * retval = bonobo_app_client_msg_send (app_client, "openURL",
+ *                                      G_TYPE_STRING, "http://www.gnome.org",
+ *                                      G_TYPE_BOOLEAN, TRUE,
+ *                                      G_TYPE_NONE);
+ * </programlisting></informalexample>
+ * 
+ * Return value: a GValue containing the value returned from the
+ * aplication server.
+ **/
+GValue *
+bonobo_app_client_msg_send (BonoboAppClient *app_client,
+			    const char      *message,
+			    ...)
+{
+	GValue  *rv;
+	va_list  var_args;
+	
+	va_start (var_args, message);
+	rv = bonobo_app_client_msg_send_valist (app_client, message, var_args);
+	va_end (var_args);
+	return rv;
+}
+
+
+static __inline__ GType
+_typecode_to_gtype (CORBA_TypeCode tc)
+{
+	static GHashTable *hash = NULL;
+
+	if (!hash) {
+		hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(corba_type, gtype)\
+		g_hash_table_insert (hash, tc, GUINT_TO_POINTER(gtype));
+		
+		mapping(G_TYPE_NONE,    TC_void);
+		mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+		mapping(G_TYPE_INT,     TC_CORBA_long);
+		mapping(G_TYPE_UINT,    TC_CORBA_unsigned_long);
+		mapping(G_TYPE_LONG,    TC_CORBA_long);
+		mapping(G_TYPE_ULONG,   TC_CORBA_unsigned_long);
+		mapping(G_TYPE_FLOAT,   TC_CORBA_float);
+		mapping(G_TYPE_DOUBLE,  TC_CORBA_double);
+		mapping(G_TYPE_STRING,  TC_CORBA_string);
+
+		mapping(BONOBO_TYPE_CORBA_ANY,  TC_CORBA_any);
+#undef mapping
+	}
+	return GPOINTER_TO_UINT(g_hash_table_lookup (hash, tc));
+}
+
+static void
+bonobo_app_client_free_msgdescs (BonoboAppClient *self)
+{
+	int i;
+	
+	for (i = 0; self->msgdescs[i].name; ++i) {
+		g_free (self->msgdescs[i].name);
+		g_free (self->msgdescs[i].types);
+	}
+	g_free (self->msgdescs);
+	self->msgdescs = NULL;
+}
+
+static void
+bonobo_app_client_get_msgdescs (BonoboAppClient *self)
+{
+	Bonobo_Application_MessageList  *msglist;
+	CORBA_Environment                ev;
+	int                              i, j;
+
+	g_return_if_fail(!self->msgdescs);
+	CORBA_exception_init (&ev);
+	msglist = Bonobo_Application_listMessages (self->app_server, &ev);
+	if (ev._major != CORBA_NO_EXCEPTION) {
+		g_warning ("Bonobo::Application::listMessages: %s",
+			   bonobo_exception_get_text (&ev));
+		CORBA_exception_free (&ev);
+		return;
+	}
+	CORBA_exception_free (&ev);
+	g_return_if_fail (msglist);
+	self->msgdescs = g_new (BonoboAppClientMsgDesc, msglist->_length + 1);
+	for (i = 0; i < msglist->_length; ++i) {
+		self->msgdescs[i].name = g_strdup (msglist->_buffer[i].name);
+		self->msgdescs[i].return_type =
+			_typecode_to_gtype (msglist->_buffer[i].return_type);
+		self->msgdescs[i].types = g_new (GType, msglist->_buffer[i].types._length + 1);
+		for (j = 0; j < msglist->_length; ++j)
+			self->msgdescs[i].types[j] =
+				_typecode_to_gtype (msglist->_buffer[i].types._buffer[j]);
+		self->msgdescs[i].types[j] = G_TYPE_NONE;
+	}
+	self->msgdescs[i].name = NULL;
+	self->msgdescs[i].return_type = G_TYPE_NONE;
+	self->msgdescs[i].types = NULL;
+	CORBA_free (msglist);
+}
+
+
+/**
+ * bonobo_app_client_msg_list:
+ * 
+ * Obtain a list of messages supported by the application server.
+ * 
+ * Return value: a NULL terminated vector of strings; use g_strfreev()
+ * to free it.
+ **/
+BonoboAppClientMsgDesc const *
+bonobo_app_client_msg_list (BonoboAppClient *app_client)
+{
+
+	g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+	if (!app_client->msgdescs)
+		bonobo_app_client_get_msgdescs (app_client);
+	return app_client->msgdescs;
+}
+
+
+gint
+bonobo_app_client_new_instance (BonoboAppClient *app_client,
+				int              argc,
+				char            *argv[])
+{
+	CORBA_any                    any;
+	CORBA_sequence_CORBA_string *corba_argv;
+	int                          i;
+	GValue                      *rv;
+
+	corba_argv = CORBA_sequence_CORBA_string__alloc();
+	corba_argv->_buffer  = CORBA_sequence_CORBA_string_allocbuf (argc);
+	corba_argv->_length  = argc;
+	corba_argv->_maximum = argc;
+	for (i = 0; i < argc; ++i)
+		corba_argv->_buffer[i] = CORBA_string_dup (argv[i]);
+
+	any._type    = TC_CORBA_sequence_CORBA_string;
+	any._value   = corba_argv;
+	any._release = CORBA_TRUE;
+
+	rv = bonobo_app_client_msg_send (app_client, "new-instance",
+					 BONOBO_TYPE_CORBA_ANY, &any,
+					 G_TYPE_NONE);
+
+	CORBA_free (corba_argv);
+	return g_value_get_int (rv);
+}
+
+
Index: bonobo/bonobo-app-client.h
===================================================================
RCS file: bonobo/bonobo-app-client.h
diff -N bonobo/bonobo-app-client.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.h	30 Apr 2003 11:23:36 -0000
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef __BONOBO_APP_CLIENT_H__
+#define __BONOBO_APP_CLIENT_H__
+
+#include <glib-object.h>
+#include <bonobo/Bonobo.h>
+
+G_BEGIN_DECLS
+
+#define BONOBO_TYPE_APP_CLIENT            (bonobo_app_client_get_type ())
+#define BONOBO_APP_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClient))
+#define BONOBO_APP_CLIENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClientClass))
+#define BONOBO_IS_APP_CLIENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT))
+#define BONOBO_IS_APP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+                                           BONOBO_TYPE_APP_CLIENT))
+#define BONOBO_APP_CLIENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+                                           BONOBO_TYPE_APP_CLIENT, BonoboAppClientClass))
+
+typedef struct _BonoboAppClient	       BonoboAppClient;
+typedef struct _BonoboAppClientClass   BonoboAppClientClass;
+typedef struct _BonoboAppClientMsgDesc BonoboAppClientMsgDesc;
+
+
+struct _BonoboAppClientMsgDesc {
+	gchar *name;
+	GType  return_type;
+	GType *types;		/* G_TYPE_NONE-terminated array */
+};
+
+
+struct _BonoboAppClient
+{
+	GObject                 parent_instance;
+	  /*< private >*/
+	Bonobo_Application      app_server;
+	BonoboAppClientMsgDesc *msgdescs;
+};
+
+struct _BonoboAppClientClass
+{
+	GObjectClass parent_class;
+  
+};
+
+
+GType	         bonobo_app_client_get_type        (void) G_GNUC_CONST;
+BonoboAppClient* bonobo_app_client_new             (Bonobo_Application  app_server);
+GValue*          bonobo_app_client_msg_send_valist (BonoboAppClient    *app_client,
+						    const char         *message,
+						    va_list             var_args);
+GValue*          bonobo_app_client_msg_send        (BonoboAppClient    *app_client,
+						    const char         *message,
+						    ...);
+gint             bonobo_app_client_new_instance    (BonoboAppClient    *app_client,
+						    int                 argc,
+						    char               *argv[]);
+BonoboAppClientMsgDesc const *
+                 bonobo_app_client_msg_list        (BonoboAppClient    *app_client);
+
+G_END_DECLS
+
+#endif /* __BONOBO_APP_CLIENT_H__ */
Index: bonobo/bonobo-application.c
===================================================================
RCS file: bonobo/bonobo-application.c
diff -N bonobo/bonobo-application.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.c	30 Apr 2003 11:23:37 -0000
@@ -0,0 +1,418 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#define ORBIT2_INTERNAL_API
+#include "config.h"
+#include "bonobo-application.h"
+#include "bonobo-app-client.h"
+#include <bonobo-exception.h>
+#include "bonobo-marshal.h"
+#include "bonobo-arg.h"
+#include "bonobo-main.h"
+#include "bonobo-types.h"
+#include <string.h>
+
+
+enum SIGNALS {
+	MESSAGE,
+	NEW_INSTANCE,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+typedef struct {
+	BonoboAppHookFunc func;
+	gpointer          data;
+} BonoboAppHook;
+
+static GArray *bonobo_application_hooks = NULL;
+
+/*
+ * A pointer to our parent object class
+ */
+static GObjectClass *bonobo_application_parent_class;
+
+
+
+static void bonobo_application_invoke_hooks (BonoboApplication *app);
+
+
+static gboolean
+_bonobo_application_message_accumulator(GSignalInvocationHint *ihint, 
+					GValue                *return_accu, 
+					const GValue          *handler_return, 
+					gpointer               dummy)
+{
+	gboolean null_gvalue;
+
+	  /* There is no good way to find out if a GValue contains a
+	   * NULL GValue as value, if you understand what I'm saying :) */
+	null_gvalue = (G_VALUE_HOLDS (handler_return, G_TYPE_VALUE) &&
+		       (g_value_peek_pointer (handler_return) == NULL));
+
+	if (!null_gvalue) {
+		g_value_copy (handler_return, return_accu);
+		return FALSE;	/* stop emission */
+	}
+	return TRUE;		/* continue emission */
+}
+
+
+
+static void
+bonobo_application_object_finalize (GObject *object)
+{
+	BonoboApplication *self = BONOBO_APPLICATION (object);
+
+	if (self->message_list) {
+		g_slist_foreach (self->message_list, (GFunc) CORBA_free, NULL);
+		g_slist_free (self->message_list);
+		self->message_list = NULL;
+	}
+
+	if (self->name) {
+		g_free (self->name);
+		self->name = NULL;
+	}
+
+	bonobo_application_parent_class->finalize (object);
+}
+
+
+static CORBA_any *
+impl_Bonobo_Application_message (PortableServer_Servant            servant,
+				 const CORBA_char                 *msg,
+				 const Bonobo_Application_ArgList *args,
+				 CORBA_Environment                *ev)
+{
+	BonoboApplication  *app = BONOBO_APPLICATION (bonobo_object (servant));
+	GValue             *signal_return = NULL;
+	GValueArray        *signal_args;
+	int                 i;
+	CORBA_any          *rv;
+	GValue              value;
+
+	signal_args = g_value_array_new (args->_length);
+	memset (&value, 0, sizeof (value));
+	for (i = 0; i < args->_length; ++i) {
+		bonobo_arg_to_gvalue (&value, &args->_buffer [i]);
+		g_value_array_append (signal_args, &value);
+		g_value_unset (&value);
+	}
+
+	g_signal_emit (app, signals [MESSAGE], 0,
+		       msg, signal_args, &signal_return);
+
+	g_value_array_free (signal_args);
+	rv = CORBA_any__alloc ();
+	if (signal_return) {
+		bonobo_arg_from_gvalue (rv, signal_return);
+		g_value_unset (signal_return);
+		g_free (signal_return);
+	} else
+		rv->_type = TC_void;
+
+	return rv;
+}
+
+gint bonobo_application_new_instance (BonoboApplication *app,
+				      gint               argc,
+				      gchar             *argv[])
+{
+	gint rv;
+	g_signal_emit (app, signals [NEW_INSTANCE], 0,
+		       argc, argv, &rv);
+	return rv;
+}
+
+    /* Handle the "new-instance" standard message */
+static GValue *
+bonobo_application_real_message (BonoboApplication *app,
+				 const char        *name,
+				 GValueArray       *args)
+{
+	CORBA_any                    *any;
+	GValue                       *retval;
+	int                           rv;
+	CORBA_sequence_CORBA_string  *argv;
+
+	if (strcmp (name, "new-instance") != 0)
+		return NULL;
+	g_return_val_if_fail (args->n_values == 1, NULL);
+	g_return_val_if_fail (BONOBO_VALUE_HOLDS_CORBA_ANY 
+			      (g_value_array_get_nth (args, 0)), NULL);
+	any = bonobo_value_get_corba_any (g_value_array_get_nth (args, 0));
+	if (!CORBA_TypeCode_equal (any->_type,
+				   TC_CORBA_sequence_CORBA_string, NULL)) {
+		CORBA_free (any);
+		g_return_val_if_reached (NULL);
+	}
+	argv = (CORBA_sequence_CORBA_string *) any->_value;
+	rv = bonobo_application_new_instance (app, argv->_length,
+					      argv->_buffer);
+	CORBA_free (any);
+	retval =  g_new0 (GValue, 1);
+	g_value_init (retval, G_TYPE_INT);
+	g_value_set_int (retval, rv);
+	return retval;
+}
+
+
+static __inline__ void
+message_desc_copy(Bonobo_Application_MessageDesc *dest,
+		  Bonobo_Application_MessageDesc *src)
+{
+	dest->name           = CORBA_string_dup (src->name);
+	dest->return_type    = src->return_type;
+	dest->types._buffer  = src->types._buffer;
+	dest->types._length  = src->types._length;
+	dest->types._maximum = src->types._maximum;
+	dest->types._release = CORBA_FALSE;
+}
+
+
+static Bonobo_Application_MessageList *
+impl_Bonobo_Application_listMessages (PortableServer_Servant  servant,
+				      CORBA_Environment      *ev)
+{
+	BonoboApplication *app = BONOBO_APPLICATION (bonobo_object (servant));
+	int                nmessages;
+	GSList            *l;
+	int                i;
+	Bonobo_Application_MessageList *msglist;
+
+	nmessages = g_slist_length (app->message_list);
+	msglist = Bonobo_Application_MessageList__alloc ();
+	msglist->_length = msglist->_maximum = nmessages;
+	msglist->_buffer = Bonobo_Application_MessageList_allocbuf (nmessages);
+	for (l = app->message_list, i = 0; l; l = l->next, ++i)
+		message_desc_copy(&msglist->_buffer[i],
+				  (Bonobo_Application_MessageDesc *) l->data);
+	CORBA_sequence_set_release (msglist, CORBA_TRUE);
+	return msglist;
+}
+
+
+static void
+bonobo_application_class_init (BonoboApplicationClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass *) klass;
+	POA_Bonobo_Application__epv *epv = &klass->epv;
+
+	bonobo_application_parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = bonobo_application_object_finalize;
+
+
+	signals [MESSAGE] = g_signal_new (
+		"message", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BonoboApplicationClass, message),
+		_bonobo_application_message_accumulator, NULL,	/* accumulator and accumulator data */
+		bonobo_marshal_BOXED__STRING_BOXED,
+		G_TYPE_VALUE, 2, /* return_type, nparams */
+		G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+		G_TYPE_VALUE_ARRAY);
+
+	signals [NEW_INSTANCE] = g_signal_new (
+		"new-instance", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (BonoboApplicationClass, new_instance),
+		NULL, NULL,	/* accumulator and accumulator data */
+		bonobo_marshal_INT__INT_POINTER,
+		G_TYPE_INT, 2, /* return_type, nparams */
+		G_TYPE_INT, G_TYPE_POINTER);
+
+	klass->message = bonobo_application_real_message;
+
+	epv->message      = impl_Bonobo_Application_message;
+	epv->listMessages = impl_Bonobo_Application_listMessages;
+}
+
+static void
+bonobo_application_init (BonoboApplication *bonobo_application)
+{
+	  /* ... */
+}
+
+BONOBO_TYPE_FUNC_FULL (BonoboApplication,
+		       Bonobo_Application,
+		       BONOBO_TYPE_OBJECT,
+		       bonobo_application);
+
+
+BonoboApplication *
+bonobo_application_new (const char *name)
+{
+	GObject           *obj;
+	BonoboApplication *app;
+
+	obj = g_object_new (BONOBO_TYPE_APPLICATION,
+			    "poa", bonobo_poa_get_threaded (BONOBO_POA_ALL_AT_IDLE),
+			    NULL);
+	app = (BonoboApplication *) obj;
+	app->name = g_strdup (name);
+	bonobo_application_invoke_hooks (app);
+	return app;
+}
+
+static __inline__ CORBA_TypeCode
+_gtype_to_typecode (GType gtype)
+{
+	static GHashTable *hash = NULL;
+
+	if (!hash) {
+		hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(gtype, corba_type)\
+		g_hash_table_insert (hash, GUINT_TO_POINTER(gtype), corba_type);
+		
+		mapping(G_TYPE_NONE,    TC_void);
+		mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+		mapping(G_TYPE_INT,     TC_CORBA_long);
+		mapping(G_TYPE_UINT,    TC_CORBA_unsigned_long);
+		mapping(G_TYPE_LONG,    TC_CORBA_long);
+		mapping(G_TYPE_ULONG,   TC_CORBA_unsigned_long);
+		mapping(G_TYPE_FLOAT,   TC_CORBA_float);
+		mapping(G_TYPE_DOUBLE,  TC_CORBA_double);
+		mapping(G_TYPE_STRING,  TC_CORBA_string);
+		
+		mapping(BONOBO_TYPE_CORBA_ANY,  TC_CORBA_any);
+#undef mapping
+	}
+	return (CORBA_TypeCode) g_hash_table_lookup (hash, GUINT_TO_POINTER(G_TYPE_INT));
+}
+
+void
+bonobo_application_register_message_va (BonoboApplication *app,
+					const gchar       *name,
+					GType              return_type,
+					GType              first_arg_type,
+					va_list            var_args)
+{
+	Bonobo_Application_MessageDesc *msgdesc;
+	GType                           gtype;
+	GPtrArray                      *tmparray;
+
+	msgdesc = Bonobo_Application_MessageDesc__alloc();
+	msgdesc->return_type = _gtype_to_typecode(return_type);
+	msgdesc->name        = CORBA_string_dup (name);
+
+	tmparray = g_ptr_array_new ();
+	if (first_arg_type != G_TYPE_NONE) {
+		g_ptr_array_add (tmparray, _gtype_to_typecode (first_arg_type));
+		while ((gtype = va_arg (var_args, GType)) != G_TYPE_NONE)
+			g_ptr_array_add (tmparray, _gtype_to_typecode (gtype));
+	}
+	msgdesc->types._length = msgdesc->types._maximum = tmparray->len;
+	msgdesc->types._buffer = CORBA_sequence_CORBA_TypeCode_allocbuf (tmparray->len);
+	memcpy(msgdesc->types._buffer, tmparray->pdata, sizeof(gpointer)*tmparray->len);
+	g_ptr_array_free (tmparray, TRUE);
+
+	app->message_list = g_slist_append (app->message_list, msgdesc);
+}
+
+
+void
+bonobo_application_register_message (BonoboApplication *app,
+				     const gchar       *name,
+				     GType              return_type,
+				     GType              first_arg_type,
+				     ...)
+{
+	va_list var_args;
+
+	va_start (var_args, first_arg_type);
+	bonobo_application_register_message_va (app, name, return_type,
+						first_arg_type, var_args);
+	va_end (var_args);
+}
+
+
+/**
+ * bonobo_register_unique_application:
+ * @name: Unique name of the application, eg. "GNOME_Terminal".
+ * @first_message_name: first of a NULL terminated list of message
+ * names that the application supports.  This is just an optional hint
+ * to the client.
+ * 
+ * Try to register the running application, or check for an existing
+ * application already registered and get a reference to it.
+ * Applications already running but on different environments (that
+ * usually means different displays, or whatever is set with
+ * bonobo_activation_registration_env_set) than this one are ignored
+ * and do not interfere.
+ * 
+ * Return value: either a BonoboApplication object representing the
+ * current process, if this process was the first to register, or a
+ * BonoboAppClient which acts as client to another process that has
+ * registered earlier with the same name.
+ **/
+BonoboAppClient *
+bonobo_application_register_unique (BonoboApplication *app)
+{
+	Bonobo_RegistrationResult  reg_res;
+	gchar                     *iid;
+	CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
+
+	iid     = g_strdup_printf ("OAFIID:%s", app->name);
+	reg_res = bonobo_activation_register_active_server_ext
+		(iid, bonobo_object_corba_objref (BONOBO_OBJECT (app)), NULL,
+		 Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, &remote_obj);
+	g_free (iid);
+	if (reg_res == Bonobo_ACTIVATION_REG_SUCCESS)
+		return NULL;
+	else if (reg_res == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE) {
+		return bonobo_app_client_new ((Bonobo_Application) remote_obj);
+	} else {
+		g_warning ("bonobo_register_unique_application failed"
+			   " with error code %i", reg_res);
+		return NULL;
+	}
+}
+
+
+void bonobo_application_add_hook (BonoboAppHookFunc func, gpointer data)
+{
+	BonoboAppHook hook;
+
+	if (bonobo_application_hooks == NULL)
+		bonobo_application_hooks = g_array_new (FALSE, FALSE, sizeof (BonoboAppHook));
+	
+	hook.func = func;
+	hook.data = data;
+	g_array_append_val(bonobo_application_hooks, hook);
+}
+
+
+void bonobo_application_remove_hook (BonoboAppHookFunc func, gpointer data)
+{
+	BonoboAppHook *hook;
+	int            i;
+
+	g_return_if_fail (bonobo_application_hooks);
+
+	for (i = 0; i < bonobo_application_hooks->len; ++i) {
+		hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+		if (hook->func == func && hook->data == data) {
+			g_array_remove_index (bonobo_application_hooks, i);
+			return;
+		}
+	}
+
+	g_warning ("bonobo_application_remove_hook: "
+		   "(func, data) == (%p, %p) not found.", func, data);
+}
+
+
+static void
+bonobo_application_invoke_hooks (BonoboApplication *app)
+{
+	BonoboAppHook *hook;
+	int            i;
+
+	if (!bonobo_application_hooks)
+		return;
+
+	for (i = 0; i < bonobo_application_hooks->len; ++i) {
+		hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+		hook->func (app, hook->data);
+	}
+}
+
Index: bonobo/bonobo-application.h
===================================================================
RCS file: bonobo/bonobo-application.h
diff -N bonobo/bonobo-application.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.h	30 Apr 2003 11:23:37 -0000
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _BONOBO_APPLICATION_H_
+#define _BONOBO_APPLICATION_H_
+
+#include <bonobo/bonobo-object.h>
+
+G_BEGIN_DECLS
+
+#define BONOBO_TYPE_APPLICATION        (bonobo_application_get_type ())
+#define BONOBO_APPLICATION(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o),\
+				        BONOBO_TYPE_APPLICATION, BonoboApplication))
+#define BONOBO_APPLICATION_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k),\
+                                        BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+#define BONOBO_IS_APPLICATION(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o),\
+				        BONOBO_TYPE_APPLICATION))
+#define BONOBO_IS_APPLICATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k),\
+					BONOBO_TYPE_APPLICATION))
+#define BONOBO_APPLICATION_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o),\
+				        BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+
+typedef struct _BonoboApplication      BonoboApplication;
+typedef struct _BonoboApplicationClass BonoboApplicationClass;
+
+typedef void (*BonoboAppHookFunc) (BonoboApplication *app, gpointer data);
+
+
+#include <bonobo/bonobo-app-client.h>
+
+
+struct _BonoboApplication {
+	BonoboObject  parent;
+	GSList       *message_list;
+	gchar        *name;
+};
+
+struct _BonoboApplicationClass {
+	BonoboObjectClass parent_class;
+
+	GValue* (*message)      (BonoboApplication *app, const char *name, GValueArray *args);
+	gint    (*new_instance) (BonoboApplication *app, gint argc, gchar *argv[]);
+
+	gpointer unimplemented[8];
+
+	POA_Bonobo_Application__epv epv;
+};
+
+
+GType              bonobo_application_get_type            (void) G_GNUC_CONST;
+BonoboApplication* bonobo_application_new                 (const char        *name);
+void               bonobo_application_register_message    (BonoboApplication *app,
+							   const gchar       *name,
+							   GType              return_type,
+							   GType              first_arg_type,
+							   ...);
+void               bonobo_application_register_message_va (BonoboApplication *app,
+							   const gchar       *name,
+							   GType              return_type,
+							   GType              first_arg_type,
+							   va_list            var_args);
+BonoboAppClient*   bonobo_application_register_unique     (BonoboApplication *app);
+void               bonobo_application_add_hook            (BonoboAppHookFunc  func,
+							   gpointer           data);
+void               bonobo_application_remove_hook         (BonoboAppHookFunc  func,
+							   gpointer           data);
+gint               bonobo_application_new_instance        (BonoboApplication *app,
+							   gint               argc,
+							   gchar             *argv[]);
+
+G_END_DECLS
+
+#endif /* _BONOBO_APPLICATION_H_ */
+
Index: bonobo/bonobo-arg.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-arg.c,v
retrieving revision 1.29
diff -u -p -u -p -r1.29 bonobo-arg.c
--- bonobo/bonobo-arg.c	23 Apr 2003 14:19:48 -0000	1.29
+++ bonobo/bonobo-arg.c	30 Apr 2003 11:23:37 -0000
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * bonobo-arg.c Bonobo argument support:
  *
@@ -13,6 +14,7 @@
 #include <bonobo/bonobo-main.h>
 #include <bonobo/bonobo-exception.h>
 #include <bonobo/bonobo-arg.h>
+#include "bonobo-types.h"
 
 /**
  * bonobo_arg_new:
@@ -219,6 +221,16 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 
 	id = G_VALUE_TYPE (value);
 
+	if (id == BONOBO_TYPE_CORBA_ANY) {
+		CORBA_any *any;
+
+		any = bonobo_value_get_corba_any (value);
+		*a = *any;
+		any->_release = CORBA_FALSE;
+		CORBA_free (any);
+		return;
+	}
+
 	switch (id) {
 
 	case G_TYPE_INVALID:
@@ -237,6 +249,8 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 		MAKE_FROM_GVALUE (DOUBLE,  double,  TC_CORBA_double, double_data, CORBA_double,         CORBA_tk_double);
 
 	case G_TYPE_STRING:
+		a->_type    = TC_CORBA_string;
+		a->_release = CORBA_TRUE;
 		if (G_VALUE_HOLDS_STRING (value))
 			*((CORBA_char **)a->_value) = CORBA_string_dup (g_value_get_string (value));
 		else
@@ -249,14 +263,14 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 
 	case G_TYPE_OBJECT:
 		g_warning ("All objects can be mapped to base gtk types"
-			   "in due course");
+			   " in due course");
 		break;
 
 	case G_TYPE_ENUM:
 	case G_TYPE_FLAGS:
 	case G_TYPE_BOXED:
 	default:
-		g_warning ("Unmapped GValue type %d", id);
+		g_warning ("Unmapped GValue type %d (%s)", id, g_type_name (id));
 		break;
 	}
 }
@@ -303,12 +317,13 @@ bonobo_arg_to_gvalue (GValue *value, con
 		MAKE_TO_GVALUE (DOUBLE,  double,  TC_CORBA_double, double_data, CORBA_double,         CORBA_tk_double);
 
 	case CORBA_tk_string:
+		g_value_init (value, G_TYPE_STRING);
 		g_value_set_string (value, BONOBO_ARG_GET_STRING (arg));
 		break;
 
 	case CORBA_tk_objref:
 		g_warning ("All objects can be mapped to base gtk types"
-			   "in due course");
+			   " in due course");
 		break;
 
 	case CORBA_tk_sequence:
@@ -316,7 +331,8 @@ bonobo_arg_to_gvalue (GValue *value, con
 	case CORBA_tk_enum:
 	case CORBA_tk_array:
 	case CORBA_tk_union:
-		g_warning ("Clever things can be done for these");
+		g_value_init (value, BONOBO_TYPE_CORBA_ANY);
+		bonobo_value_set_corba_any (value, arg);
 		break;
 
 	default:
Index: bonobo/bonobo-marshal.list
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-marshal.list,v
retrieving revision 1.10
diff -u -p -u -p -r1.10 bonobo-marshal.list
--- bonobo/bonobo-marshal.list	30 Oct 2001 02:32:09 -0000	1.10
+++ bonobo/bonobo-marshal.list	30 Apr 2003 11:23:38 -0000
@@ -2,3 +2,5 @@ BOXED:STRING,BOOLEAN,BOXED
 VOID:STRING,BOXED,BOXED
 VOID:BOXED,UINT,BOXED
 OBJECT:STRING
+BOXED:STRING,BOXED
+INT:INT,POINTER
Index: bonobo-activation/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo-activation/Makefile.am,v
retrieving revision 1.47
diff -u -p -u -p -r1.47 Makefile.am
--- bonobo-activation/Makefile.am	16 Apr 2003 19:10:51 -0000	1.47
+++ bonobo-activation/Makefile.am	30 Apr 2003 11:23:38 -0000
@@ -12,7 +12,7 @@ INCLUDES=					\
 	-DG_DISABLE_DEPRECATED			\
 	$(NULL)
 
-LDFLAGS=					\
+AM_LDFLAGS=					\
 	$(LIBBONOBO_LIBS)			\
 	$(BONOBO_ACTIVATION_LT_VERSION_INFO)	\
 	-no-undefined				\
Index: idl/Bonobo.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo.idl,v
retrieving revision 1.55
diff -u -p -u -p -r1.55 Bonobo.idl
--- idl/Bonobo.idl	7 Mar 2003 12:09:42 -0000	1.55
+++ idl/Bonobo.idl	30 Apr 2003 11:23:38 -0000
@@ -49,6 +49,8 @@
 /* Clipboard */
 #include <Bonobo_Clipboard.idl>
 
+#include <Bonobo_Application.idl>
+
 #ifndef __Bonobo_COMPILATION
 #ifdef __ORBIT_IDL__
 #pragma inhibit pop
Index: idl/Bonobo_Application.idl
===================================================================
RCS file: idl/Bonobo_Application.idl
diff -N idl/Bonobo_Application.idl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ idl/Bonobo_Application.idl	30 Apr 2003 11:23:38 -0000
@@ -0,0 +1,46 @@
+/* -*- Mode: idl; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Bonobo_Application.idl: Unique application support (some would call
+ * it--or can be used for--Automation).
+ *
+ */
+
+#ifndef BONOBO_APPLICATION_IDL
+#define BONOBO_APPLICATION_IDL
+
+#include "Bonobo_Unknown.idl"
+
+module Bonobo {
+  
+	interface Application : Bonobo::Unknown {
+
+                typedef sequence<any> ArgList;
+
+                struct MessageDesc {
+                        string             name;
+                        sequence<TypeCode> types;
+                        TypeCode           return_type;
+                };
+
+                typedef sequence<MessageDesc> MessageList;
+
+                  // Send a message (message) to the application
+	        any         message      (in string  msg,
+                                          in ArgList args);
+                MessageList listMessages ();
+
+
+                void unimplemented1 ();
+                void unimplemented2 ();
+                void unimplemented3 ();
+                void unimplemented4 ();
+                void unimplemented5 ();
+                void unimplemented6 ();
+                void unimplemented7 ();
+                void unimplemented8 ();
+  	};
+
+};
+
+#endif /* BONOBO_APPLICATION_IDL */
+
Index: idl/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Makefile.am,v
retrieving revision 1.52
diff -u -p -u -p -r1.52 Makefile.am
--- idl/Makefile.am	16 Apr 2003 19:10:52 -0000	1.52
+++ idl/Makefile.am	30 Apr 2003 11:23:39 -0000
@@ -20,6 +20,7 @@ idl_DATA =				\
 	Bonobo_Zoomable.idl		\
 	Bonobo_Exception.idl		\
 	Bonobo_Clipboard.idl		\
+	Bonobo_Application.idl		\
 	$(NULL)
 
 activation_idldir=$(datadir)/idl/bonobo-activation-2.0
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/Makefile.am,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 Makefile.am
--- tests/Makefile.am	7 Apr 2003 10:31:12 -0000	1.18
+++ tests/Makefile.am	30 Apr 2003 11:23:39 -0000
@@ -7,7 +7,8 @@ noinst_PROGRAMS =		\
 	test-event-source	\
 	test-object		\
 	test-stream-mem		\
-	test-storage-mem
+	test-storage-mem	\
+	test-uniqapp
 
 INCLUDES =	\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
@@ -32,6 +33,8 @@ test_event_source_SOURCES = test-event-s
 test_stream_mem_SOURCES = test-stream-mem.c
 
 test_storage_mem_SOURCES = test-storage-mem.c
+
+test_uniqapp_SOURCES = test-uniqapp.c
 
 TESTS_ENVIRONMENT =					\
 	LD_LIBRARY_PATH="$(top_builddir)/bonobo/.libs:$$LD_LIBRARY_PATH"	\
Index: tests/test-uniqapp.c
===================================================================
RCS file: tests/test-uniqapp.c
diff -N tests/test-uniqapp.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/test-uniqapp.c	30 Apr 2003 11:23:39 -0000
@@ -0,0 +1,104 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <config.h>
+#include <libbonobo.h>
+#include <string.h>
+
+#define TEST_MESSAGE "test-message"
+
+
+static GValue *
+message_cb (BonoboAppClient *app_client, const gchar *message, GValueArray *args)
+{
+	GValue *retval = g_new0 (GValue, 1);
+
+	g_message ("message_cb: %s", message);
+
+	if (strcmp (message, TEST_MESSAGE) != 0)
+		return NULL;
+
+	g_value_init (retval, G_TYPE_FLOAT);
+	if (args->n_values == 1) {
+		g_value_set_float (retval, 2*g_value_get_float (
+					   g_value_array_get_nth (args, 0)));
+	} else {
+		g_warning ("Wrong arity!");
+		g_value_set_float (retval, 0);
+	}
+	return retval;
+}
+
+static void
+test_app_hook (BonoboApplication *app, gpointer data)
+{
+	g_message ("App '%s' created; data == %p", app->name, data);
+}
+
+static gint
+new_instance_cb (BonoboApplication *app, gint argc, char *argv[])
+{
+	int i;
+
+	g_message ("new-instance received. argc = %i; argv follows:", argc);
+	for (i = 0; i < argc; ++i)
+		g_message ("argv[%i] = \"%s\"", i, argv[i]);
+	g_message ("new-instance: returning argc (%i)", argc);
+	return argc;
+}
+
+int
+main (int argc, char *argv [])
+{
+	BonoboApplication *app;
+	BonoboAppClient   *client;
+	float              msg_arg = 3.141592654;
+
+	if (bonobo_init (&argc, argv) == FALSE)
+		g_error ("Can not bonobo_init");
+	bonobo_activate ();
+
+	bonobo_application_add_hook (test_app_hook, (gpointer) 0xdeadbeef);
+
+	app = bonobo_application_new ("Libbonobo-Test-Uniqapp");
+	bonobo_application_register_message (app, TEST_MESSAGE, G_TYPE_FLOAT,
+					     G_TYPE_FLOAT, G_TYPE_NONE);
+	client = bonobo_application_register_unique (app);
+
+	if (client)
+	{
+		BonoboAppClientMsgDesc const *msgdescs;
+		GValue                       *retval;
+		int                           i;
+
+		g_message ("I am an application client.");
+		bonobo_object_unref (BONOBO_OBJECT (app));
+
+		msgdescs = bonobo_app_client_msg_list (client);
+		g_assert (msgdescs);
+
+		for (i = 0; msgdescs[i].name; ++i)
+			g_message ("Application supports message '%s'", msgdescs[i].name);
+
+		g_message ("Sending message string '%s' with argument %f",
+			   TEST_MESSAGE, msg_arg);
+		retval = bonobo_app_client_msg_send (client, TEST_MESSAGE,
+						     G_TYPE_FLOAT, msg_arg,
+						     G_TYPE_NONE);
+		g_message ("Return value: %f", g_value_get_float (retval));
+
+		i = bonobo_app_client_new_instance (client, argc, argv);
+		g_message ("new-instance returned %i", i);
+
+	} else if (g_type_is_a (G_OBJECT_TYPE (app), BONOBO_TYPE_APPLICATION)) {
+		g_message ("I am an application server");
+		g_signal_connect (app, "message",
+				  G_CALLBACK (message_cb), NULL);
+		g_signal_connect (app, "new-instance",
+				  G_CALLBACK (new_instance_cb), NULL);
+		bonobo_application_new_instance (app, argc, argv);
+	} else
+		g_assert_not_reached ();
+
+	bonobo_main ();
+
+	return bonobo_debug_shutdown ();
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.