Bonobo Unique Application v4

Gustavo J A M Carneiro <[email protected]>
Newsgroups gmane.comp.gnome.components
Organization INESC
Message-ID <[email protected]>
	Hi Michael,
	I changed the API a bit, to allow for registration of messages with
name, return type, argument types.  I try to map GType's  to
CORBA_TypeCode's, to make a more GLib-ish API.  You think it's better to
deal with typecodes directly?  It would give us more power (all CORBA
types available), but...
	A lot of work still to do, but take a look at this if you have time. 
Thanks.

-- 
Gustavo J. A. M. Carneiro
<[email protected]> <[email protected]>
bonobo-uniqapp-v4.diff (text/x-patch, 29.5 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	29 Apr 2003 12:58:18 -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	29 Apr 2003 12:58:18 -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	29 Apr 2003 12:58:22 -0000
@@ -0,0 +1,280 @@
+  /* -*- 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"
+
+
+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);
+	
+	rv = g_new0 (GValue, 1);
+	bonobo_arg_to_gvalue (rv, ret);
+	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);
+		
+#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;
+}
+
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	29 Apr 2003 12:58:22 -0000
@@ -0,0 +1,61 @@
+/* -*- 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,
+						    ...);
+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	29 Apr 2003 12:58:22 -0000
@@ -0,0 +1,264 @@
+/* -*- 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 <string.h>
+
+
+enum SIGNALS {
+	MESSAGE,
+	LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+
+/*
+ * A pointer to our parent object class
+ */
+static GObjectClass *bonobo_application_parent_class;
+
+
+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;
+	}
+
+	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 ();
+	bonobo_arg_from_gvalue (rv, signal_return);
+	g_value_unset (signal_return);
+	g_free (signal_return);
+
+	return rv;
+}
+
+static __inline__ void
+message_desc_copy(Bonobo_Application_MessageDesc *dest,
+		  Bonobo_Application_MessageDesc *src)
+{
+
+}
+
+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),
+		NULL, 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);
+
+	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 (void)
+{
+	GObject *obj;
+	obj = g_object_new (BONOBO_TYPE_APPLICATION,
+			    "poa", bonobo_poa_get_threaded (BONOBO_POA_ALL_AT_IDLE),
+			    NULL);
+	return (BonoboApplication *) obj;
+}
+
+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);
+		
+#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_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);
+}
+
+
+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,
+				    const gchar       *name)
+{
+	Bonobo_RegistrationResult  reg_res;
+	gchar                     *iid;
+	CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
+
+	g_return_val_if_fail (name, NULL);
+	
+	iid     = g_strdup_printf ("OAFIID:%s", 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;
+	}
+}
+
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	29 Apr 2003 12:58:22 -0000
@@ -0,0 +1,61 @@
+/* -*- 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;
+
+#include <bonobo/bonobo-app-client.h>
+
+
+struct _BonoboApplication {
+	BonoboObject  parent;
+	GSList       *message_list;
+};
+
+struct _BonoboApplicationClass {
+	BonoboObjectClass parent_class;
+
+	GValue (*message) (const char *name, GValueArray *args);
+
+	gpointer unimplemented[8];
+
+	POA_Bonobo_Application__epv epv;
+};
+
+
+GType              bonobo_application_get_type            (void) G_GNUC_CONST;
+BonoboApplication* bonobo_application_new                 (void);
+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,
+							   const gchar       *name);
+
+G_END_DECLS
+
+#endif /* _BONOBO_APPLICATION_H_ */
+
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	29 Apr 2003 12:58:22 -0000
@@ -2,3 +2,4 @@ BOXED:STRING,BOOLEAN,BOXED
 VOID:STRING,BOXED,BOXED
 VOID:BOXED,UINT,BOXED
 OBJECT:STRING
+BOXED:STRING,BOXED
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	29 Apr 2003 12:58:23 -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	29 Apr 2003 12:58:23 -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	29 Apr 2003 12:58:23 -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	29 Apr 2003 12:58:23 -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	29 Apr 2003 12:58:24 -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	29 Apr 2003 12:58:24 -0000
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <config.h>
+#include <libbonobo.h>
+
+
+static GValue *
+message_cb (BonoboAppClient *app_client, const gchar *message, GValueArray *args)
+{
+	GValue *retval = g_new0 (GValue, 1);
+
+	g_message ("message_cb: %s", message);
+	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;
+}
+
+
+int
+main (int argc, char *argv [])
+{
+	BonoboApplication *app;
+	BonoboAppClient   *client;
+	const char        *msg = "Hail to you, Master!";
+	float              msg_arg = 3.141592654;
+
+	if (bonobo_init (&argc, argv) == FALSE)
+		g_error ("Can not bonobo_init");
+	bonobo_activate ();
+
+	app = bonobo_application_new ();
+	bonobo_application_register_message (app, msg, G_TYPE_FLOAT,
+					     G_TYPE_FLOAT, G_TYPE_NONE);
+
+	client = bonobo_application_register_unique (app, "Libbonobo-Test-Uniqapp");
+
+	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);
+
+		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",
+			   msg, msg_arg);
+		retval = bonobo_app_client_msg_send (client, msg,
+						     G_TYPE_FLOAT, msg_arg,
+						     G_TYPE_NONE);
+		g_message ("Return value: %f", g_value_get_float (retval));
+	} 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);
+	} 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.