Bonobo Unique Application v3.1

Gustavo J A M Carneiro <[email protected]>
Newsgroups gmane.comp.gnome.components
Organization INESC
Message-ID <[email protected]>
  Changes:
	- Message discovery capabilities
	- some more gtk-doc documentation comments.

-- 
Gustavo J. A. M. Carneiro
<[email protected]> <[email protected]>
bonobo-uniqapp-v3.1.diff (text/x-patch, 35.1 KB)
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	18 Apr 2003 20:14:02 -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: activation-server/activation-server-main.c
===================================================================
RCS file: /cvs/gnome/libbonobo/activation-server/activation-server-main.c,v
retrieving revision 1.48
diff -u -p -u -p -r1.48 activation-server-main.c
--- activation-server/activation-server-main.c	7 Apr 2003 11:33:29 -0000	1.48
+++ activation-server/activation-server-main.c	18 Apr 2003 20:14:03 -0000
@@ -218,7 +218,7 @@ main (int argc, char *argv[])
         PortableServer_POA            root_poa;
         CORBA_ORB                     orb;
         CORBA_Environment             real_ev, *ev;
-        CORBA_Object                  naming_service;
+        CORBA_Object                  naming_service, existing;
         Bonobo_ActivationEnvironment  environment;
         Bonobo_ObjectDirectory        od;
         poptContext                   ctx;
@@ -280,7 +280,9 @@ main (int argc, char *argv[])
         if (naming_service == NULL)
                 g_warning ("Failed to create naming service");
         Bonobo_ObjectDirectory_register_new 
-                (od, NAMING_CONTEXT_IID, &environment, naming_service, ev);
+                (od, NAMING_CONTEXT_IID, &environment, naming_service, 0, &existing, ev);
+	if (existing != CORBA_OBJECT_NIL)
+		CORBA_Object_release (existing, NULL);
 
         if (ior_fd < 0 && !server_ac)
                 g_error ("\n\n-- \nThe bonobo-activation-server must be forked by\n"
Index: activation-server/object-directory-corba.c
===================================================================
RCS file: /cvs/gnome/libbonobo/activation-server/object-directory-corba.c,v
retrieving revision 1.56
diff -u -p -u -p -r1.56 object-directory-corba.c
--- activation-server/object-directory-corba.c	24 Feb 2003 11:51:10 -0000	1.56
+++ activation-server/object-directory-corba.c	18 Apr 2003 20:14:05 -0000
@@ -702,21 +702,26 @@ impl_Bonobo_ObjectDirectory_register_new
 	const CORBA_char                   *iid,
 	const Bonobo_ActivationEnvironment *environment,
 	const CORBA_Object                  obj,
+        Bonobo_RegistrationFlags            flags,
+        CORBA_Object                       *existing,
 	CORBA_Environment                  *ev)
 {
 	impl_POA_Bonobo_ObjectDirectory *servant = _servant;
 	CORBA_Object                     oldobj;
 
 	oldobj = od_get_active_server (servant, iid, environment);
+        *existing = oldobj;
 
 	if (oldobj != CORBA_OBJECT_NIL) {
-		CORBA_Object_release (oldobj, NULL);
-		if (!CORBA_Object_non_existent (oldobj, ev))
+		if (!CORBA_Object_non_existent (oldobj, ev)) {
 			return Bonobo_ACTIVATION_REG_ALREADY_ACTIVE;
+                }
 	}
 
-	if (!g_hash_table_lookup (servant->by_iid, iid))
-		return Bonobo_ACTIVATION_REG_NOT_LISTED;
+        if (!g_hash_table_lookup (servant->by_iid, iid)) {
+                if (!(flags&Bonobo_REGISTRATION_FLAG_NO_SERVERINFO))
+                        return Bonobo_ACTIVATION_REG_NOT_LISTED;
+        }
 
 #ifdef BONOBO_ACTIVATION_DEBUG
         g_warning ("Server register. '%s' : %p", iid, obj);
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	18 Apr 2003 20:14:05 -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	18 Apr 2003 20:14:06 -0000
@@ -0,0 +1,203 @@
+  /* -*- 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);
+
+
+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_class_init (BonoboAppClientClass *class)
+{
+
+}
+
+
+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;
+}
+
+
+/**
+ * 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.
+ **/
+gchar**
+bonobo_app_client_msg_list (BonoboAppClient *app_client)
+{
+	Bonobo_Application_MessageList  *msglist;
+	CORBA_Environment                ev;
+	gchar                          **rv;
+	int                              i;
+
+	CORBA_exception_init (&ev);
+	msglist = Bonobo_Application_listMessages (app_client->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 NULL;
+	}
+	CORBA_exception_free (&ev);
+	g_return_val_if_fail (msglist, NULL);
+	rv = g_new (gchar *, msglist->_length + 1);
+	for (i = 0; i < msglist->_length; ++i)
+		rv[i] = g_strdup (msglist->_buffer[i]);
+	rv[i] = NULL;
+	CORBA_free (msglist);
+	return 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	18 Apr 2003 20:14:06 -0000
@@ -0,0 +1,51 @@
+/* -*- 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;
+
+struct _BonoboAppClient
+{
+	GObject            parent_instance;
+	  /*< private >*/
+	Bonobo_Application app_server;
+};
+
+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,
+						    ...);
+gchar**          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	18 Apr 2003 20:14:06 -0000
@@ -0,0 +1,257 @@
+/* -*- 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->msglist) {
+		g_slist_foreach (self->msglist, (GFunc) g_free, NULL);
+		g_slist_free (self->msglist);
+		self->msglist = 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 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->msglist);
+	msglist = Bonobo_Application_MessageList__alloc ();
+	msglist->_length = msglist->_maximum = nmessages;
+	msglist->_buffer = Bonobo_Application_MessageList_allocbuf (nmessages);
+	for (l = app->msglist, i = 0; l; l = l->next, ++i)
+		msglist->_buffer[i] = CORBA_string_dup ((gchar *) 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);
+
+
+static PortableServer_POA
+get_custom_poa(void)
+{
+	PortableServer_POA  poa;
+	CORBA_Environment   ev;
+	CORBA_PolicyList   *policies;
+
+	CORBA_exception_init (&ev);
+
+	/* (Copy-paste from ORBit2/test/poa/poatest-basic08.c) */
+
+	/*
+	 * Create child POA with MULTIPLE_ID Object Id Uniqueness policy and
+	 * IMLICIT_ACTIVATION Implicit Activation policy.
+	 */
+	policies           = CORBA_PolicyList__alloc ();
+	policies->_maximum = 2;
+	policies->_length  = 2;
+	policies->_buffer  = CORBA_PolicyList_allocbuf (2);
+	CORBA_sequence_set_release (policies, CORBA_TRUE);
+	policies->_buffer[0] = (CORBA_Policy)
+		PortableServer_POA_create_id_uniqueness_policy (
+			bonobo_poa (),
+			PortableServer_MULTIPLE_ID,
+			&ev);
+	policies->_buffer[1] = (CORBA_Policy)
+		PortableServer_POA_create_implicit_activation_policy (
+			bonobo_poa (),
+			PortableServer_IMPLICIT_ACTIVATION,
+			&ev);
+
+	poa = PortableServer_POA_create_POA (bonobo_poa (), "BonoboApplicationPOA",
+					     bonobo_poa_manager (), policies, &ev);
+	CORBA_free (policies);
+
+	if (ev._major == CORBA_NO_EXCEPTION) {
+		ORBit_ObjectAdaptor_set_thread_hint ((ORBit_ObjectAdaptor) poa,
+						     ORBIT_THREAD_HINT_ALL_AT_IDLE);
+	} else {
+		if (strcmp (CORBA_exception_id (&ev),
+			    ex_PortableServer_POA_AdapterAlreadyExists) == 0)
+		{
+			CORBA_exception_free (&ev);
+			poa = PortableServer_POA_find_POA (bonobo_poa (),
+							   "BonoboApplicationPOA",
+							   CORBA_FALSE, &ev);
+		}
+	}
+	CORBA_exception_free (&ev);
+	if (!poa)
+		g_warning ("Could not create/get BonoboApplicationPOA");
+	return poa;
+}
+
+/**
+ * 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.
+ **/
+GObject *
+bonobo_register_unique_application (const gchar *name,
+				    const gchar *first_message_name,
+				    ...)
+{
+	GObject                   *gobj;
+	BonoboObject              *bobj;
+	BonoboApplication         *app;
+	Bonobo_RegistrationResult  reg_res;
+	gchar                     *iid;
+	CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
+	PortableServer_POA         poa;
+	va_list                    var_args;
+	const gchar               *message_name;
+
+	g_return_val_if_fail (name, NULL);
+	
+	poa = get_custom_poa ();
+	g_return_val_if_fail (poa, NULL);
+	gobj = g_object_new (BONOBO_TYPE_APPLICATION, "poa", poa, NULL);
+	bobj = BONOBO_OBJECT (gobj);
+	app  = BONOBO_APPLICATION (bobj);
+
+	if (first_message_name) {
+		app->msglist = g_slist_prepend (app->msglist,
+						g_strdup (first_message_name));
+		va_start (var_args, first_message_name);
+		while ((message_name = va_arg (var_args, const gchar *)))
+			app->msglist = g_slist_prepend (app->msglist,
+							g_strdup (message_name));
+		va_end (var_args);
+	}
+
+	iid     = g_strdup_printf ("OAFIID:%s", name);
+	reg_res = bonobo_activation_register_active_server_ext
+		(iid, bonobo_object_corba_objref (bobj), NULL,
+		 Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, &remote_obj);
+	g_free (iid);
+	if (reg_res == Bonobo_ACTIVATION_REG_SUCCESS)
+		return gobj;
+	else if (reg_res == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE) {
+		bonobo_object_unref (bobj);
+		return G_OBJECT (bonobo_app_client_new ((Bonobo_Application) remote_obj));
+	} else {
+		g_warning ("bonobo_register_unique_application failed"
+			   " with error code %i", reg_res);
+		bonobo_object_unref (bobj);
+		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	18 Apr 2003 20:14:06 -0000
@@ -0,0 +1,48 @@
+/* -*- 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;
+
+
+struct _BonoboApplication {
+	BonoboObject  parent;
+	GSList       *msglist;
+};
+
+struct _BonoboApplicationClass {
+	BonoboObjectClass parent_class;
+
+	GValue (*message) (const char *name, GValueArray *args);
+
+	POA_Bonobo_Application__epv epv;
+};
+
+
+GType    bonobo_application_get_type        (void) G_GNUC_CONST;
+GObject* bonobo_register_unique_application (const gchar *name,
+					     const gchar *first_message_name,
+					     ...);
+
+
+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.27
diff -u -p -u -p -r1.27 bonobo-arg.c
--- bonobo/bonobo-arg.c	21 Nov 2001 02:16:33 -0000	1.27
+++ bonobo/bonobo-arg.c	18 Apr 2003 20:14:07 -0000
@@ -192,6 +192,9 @@ bonobo_arg_type_to_gtype (BonoboArgType 
 
 #define MAKE_FROM_GVALUE(gtype,gtypename,tcid,unionid,corbatype,corbakind)	\
 	case G_TYPE_##gtype:							\
+		a->_value = ORBit_alloc_tcval(tcid, 1);				\
+		a->_type = tcid;						\
+		a->_release = CORBA_TRUE;					\
 		*((corbatype *)a->_value) = (corbatype)g_value_get_##gtypename (value);	\
 		break;
 
@@ -258,6 +261,7 @@ bonobo_arg_from_gvalue (BonoboArg *a, co
 
 #define MAKE_TO_GVALUE(gtype,gtypename,tcid,unionid,corbatype,corbakind)	\
 	case corbakind:								\
+		g_value_init (value, G_TYPE_##gtype);				\
 		g_value_set_##gtypename (value, *((corbatype *)arg->_value));	\
 		break;
 
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	18 Apr 2003 20:14:07 -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/bonobo-activation-register.c
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo-activation/bonobo-activation-register.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 bonobo-activation-register.c
--- bonobo-activation/bonobo-activation-register.c	17 Dec 2002 11:02:07 -0000	1.36
+++ bonobo-activation/bonobo-activation-register.c	18 Apr 2003 20:14:09 -0000
@@ -217,11 +217,55 @@ bonobo_activation_register_active_server
 					  CORBA_Object  obj,
 					  GSList       *reg_env)
 {
+        Bonobo_RegistrationResult rv;
+        CORBA_Object              existing;
+        rv = bonobo_activation_register_active_server_ext
+                (iid, obj, reg_env, 0, &existing);
+	if (existing != CORBA_OBJECT_NIL)
+		CORBA_Object_release (existing, NULL);
+        return rv;
+}
+
+/**
+ * bonobo_activation_register_active_server_ext:
+ * @iid: IID of the server to register.
+ * @obj: CORBA::Object to register.
+ * @reg_env: the registration environment.
+ * @flags: registration flags
+ * @existing: in case an object with the same IID has already been
+ * registered, *existing will contain a reference to the existing
+ * object.
+ * 
+ * This function is the same as
+ * bonobo_activation_register_active_server(), except that: 1. you can
+ * specify registration flags; 2. in case registration fails because
+ * there is already an object registered with that IID, a reference to
+ * the first object registered is returned.
+ *
+ * At the moment, only the only flag available is
+ * Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, which means to allow
+ * registration of an active server which doesn't have a corresponding
+ * .server.  Note that bonobo activation queries will ignore objects
+ * registered this way.  This feature is not meant to be used directly
+ * by applications, so beware!
+ * 
+ * Return value: status of the registration.
+ **/
+Bonobo_RegistrationResult
+bonobo_activation_register_active_server_ext (const char               *iid,
+                                              CORBA_Object              obj,
+                                              GSList                   *reg_env,
+                                              Bonobo_RegistrationFlags  flags,
+                                              CORBA_Object             *existing)
+{
 	Bonobo_ObjectDirectory     od;
 	CORBA_Environment          ev;
 	Bonobo_RegistrationResult  retval;
 	const char                *actid;
 
+        g_return_val_if_fail(existing != NULL, Bonobo_ACTIVATION_REG_ERROR);
+        *existing = CORBA_OBJECT_NIL;
+
 	CORBA_exception_init (&ev);
 
 #ifdef BONOBO_ACTIVATION_DEBUG
@@ -251,7 +295,7 @@ bonobo_activation_register_active_server
                 retval = Bonobo_ObjectDirectory_register_new (
 					od, iid,
 					reg_env ? &environment : &global_reg_env,
-				        obj, &ev);
+				        obj, flags, existing, &ev);
 
 		if (reg_env)
 			CORBA_free (environment._buffer);
Index: bonobo-activation/bonobo-activation-register.h
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo-activation/bonobo-activation-register.h,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 bonobo-activation-register.h
--- bonobo-activation/bonobo-activation-register.h	13 Mar 2003 10:48:55 -0000	1.8
+++ bonobo-activation/bonobo-activation-register.h	18 Apr 2003 20:14:09 -0000
@@ -33,6 +33,12 @@ Bonobo_RegistrationResult
 	bonobo_activation_register_active_server      (const char   *iid,
 						       CORBA_Object  obj,
 						       GSList       *reg_env);
+Bonobo_RegistrationResult
+        bonobo_activation_register_active_server_ext  (const char               *iid,
+                                                       CORBA_Object              obj,
+                                                       GSList                   *reg_env,
+                                                       Bonobo_RegistrationFlags  flags,
+                                                       CORBA_Object             *existing);
 void    bonobo_activation_unregister_active_server    (const char   *iid, 
 						       CORBA_Object  obj);
 
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	18 Apr 2003 20:14:09 -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_Activation_types.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo_Activation_types.idl,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 Bonobo_Activation_types.idl
--- idl/Bonobo_Activation_types.idl	17 Oct 2002 23:11:01 -0000	1.5
+++ idl/Bonobo_Activation_types.idl	18 Apr 2003 20:14:09 -0000
@@ -39,6 +39,8 @@ module Bonobo {
         const ActivationFlags ACTIVATION_FLAG_NO_LOCAL = 1<<0; // No shared libraries
         const ActivationFlags ACTIVATION_FLAG_PRIVATE = 1<<1; // start a new server and don't register it
         const ActivationFlags ACTIVATION_FLAG_EXISTING_ONLY = 1<<2; // don't start the server if not started
+        typedef long RegistrationFlags;
+        const RegistrationFlags REGISTRATION_FLAG_NO_SERVERINFO = 1<<0; // no .server file
 
 	struct ActivationEnvValue {
 		string  name;
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	18 Apr 2003 20:14:09 -0000
@@ -0,0 +1,27 @@
+/* -*- 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;
+                typedef sequence<string> MessageList;
+                  // Send a message to the application
+	        any         message      (in string  msg,
+                                          in ArgList args);
+                MessageList listMessages ();
+  	};
+
+};
+
+#endif /* BONOBO_APPLICATION_IDL */
+
Index: idl/Bonobo_ObjectDirectory.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo_ObjectDirectory.idl,v
retrieving revision 1.7
diff -u -p -u -p -r1.7 Bonobo_ObjectDirectory.idl
--- idl/Bonobo_ObjectDirectory.idl	17 Oct 2002 23:11:01 -0000	1.7
+++ idl/Bonobo_ObjectDirectory.idl	18 Apr 2003 20:14:10 -0000
@@ -73,9 +73,11 @@ module Bonobo {
                                  in ActivationFlags               flags)
                         context ("username", "hostname");
 
-                RegistrationResult register_new (in ImplementationID              iid,
-                                                 in Bonobo::ActivationEnvironment environment,
-                                                 in Object                        obj);
+                RegistrationResult register_new (in  ImplementationID              iid,
+                                                 in  Bonobo::ActivationEnvironment environment,
+                                                 in  Object                        obj,
+						 in  RegistrationFlags             flags,
+                                                 out Object                        existing);
                 void               unregister   (in ImplementationID              iid,
                                                  in Object                        obj)
                         raises (NotRegistered);
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	18 Apr 2003 20:14:10 -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	18 Apr 2003 20:14:10 -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	18 Apr 2003 20:14:10 -0000
@@ -0,0 +1,66 @@
+/* -*- 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 [])
+{
+	GObject           *app;
+	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_register_unique_application ("Libbonobo-Test-Uniqapp",
+						  msg, NULL);
+
+	if (g_type_is_a (G_OBJECT_TYPE (app), BONOBO_TYPE_APP_CLIENT))
+	{
+		BonoboAppClient  *client = BONOBO_APP_CLIENT (app);
+		GValue           *retval;
+		gchar           **msglist, **msg1;
+
+		g_message ("I am an application client.");
+		msglist = bonobo_app_client_msg_list (client);
+		for (msg1 = msglist; *msg1; ++msg1)
+			g_message ("Application supports message '%s'", *msg1);
+		g_strfreev (msglist);
+
+		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.