Bonobo Unique Application

"Gustavo J. A. M. " Carneiro <[email protected]>
Newsgroups gmane.comp.gnome.components
Organization INESC Porto
Message-ID <[email protected]>
  The following patches implement "Unique Application" (TM) in
libbonobo.  It is an attempt to automate/simplify the code that ensures
that only one application instance is running per display[1], as seen in
galeon and gnome-terminal, for example.

  Summary of bonobo-activation changes:
        - There is a special flag in
        Bonobo::ObjectDirectory::register_new to make it possible to
        register a server without a corresponding .server file;
        - Bonobo::ObjectDirectory::register_new also returns the
        existing object, in case one has been registered earlier.

  Summary of libbonobo changes:
        - A Bonobo::Application interface and BonoboApplication
        implementation, which represents the unique application server.
        - A BonoboAppClient which can send messages to the
        Bonobo::Application.  The relevant interface method is:

+       interface Application : Bonobo::Unknown {
+                typedef sequence<any> ArgList;
+                  // Send a message to the application
+               any message (in string msg, in ArgList args);
+
+       };

        So, you can send any message you like. There is an application
        API for sending messages, eg.
        
retval = bonobo_app_client_msg_send (client, "msg",
                                     G_TYPE_FLOAT, 1.0,
                                     G_TYPE_INT, 2,
                                     G_TYPE_NONE);
(retval is a GValue, the return value for the message)

        For receiving messages, connect the signal "message" on the
        BonoboApplication object:
+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;
+}

   See the patches, in particular tests/test-uniqapp.c, for more
details.
   Warning: with the bonobo-activation/libbonobo merge, these might not
work anymore.


[1] That is not entirely accurate. It is more 'per activation
environment'.

-- 
Gustavo João Alves Marques Carneiro
<[email protected]> <[email protected]>
bonobo-activation.diff (text/plain, 9.6 KB)
? autom4te.cache
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/bonobo-activation/ChangeLog,v
retrieving revision 1.356
diff -u -p -r1.356 ChangeLog
--- ChangeLog	7 Mar 2003 11:40:51 -0000	1.356
+++ ChangeLog	10 Mar 2003 14:18:08 -0000
@@ -1,3 +1,30 @@
+2003-03-10  Gustavo J. A. M. Carneiro  <[email protected]>
+
+	* server/object-directory-corba.c (impl_Bonobo_ObjectDirectory_register_new):
+	Honor the flag REGISTRATION_FLAG_NO_SERVERINFO and set output
+	variable 'existing'.
+
+	* server/activation-server-main.c (main): Changes for the new
+	ObjectDirectory::register_new API.
+
+	* idl/Bonobo_ObjectDirectory.idl: Added paramters in
+	RegistrationFlags flags, and out Object existing; existing is an
+	ouput variable to contain the object already registered if that is
+	the case.
+
+	* idl/Bonobo_Activation_types.idl: Define type
+	RegistrationFlags. The only existing flag right now is
+	REGISTRATION_FLAG_NO_SERVERINFO, which means to allow a server to
+	be registered even if it doesn't have a registered .server file.
+
+	* bonobo-activation/bonobo-activation-register.c
+	(bonobo_activation_register_active_server_extended):
+	New function that is like bonobo_activation_register_active_server
+	but takes extra parameters: 'flags', and 'existing'.
+	(bonobo_activation_register_active_server): Delegate to
+	bonobo_activation_register_active_server_extended with default
+	parameters.
+
 2003-03-07 Bill Haneman <[email protected]>
 
 	* idl/Bonobo_GenericFactory.idl:
Index: bonobo-activation/bonobo-activation-register.c
===================================================================
RCS file: /cvs/gnome/bonobo-activation/bonobo-activation/bonobo-activation-register.c,v
retrieving revision 1.36
diff -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	10 Mar 2003 14:18:08 -0000
@@ -217,6 +217,22 @@ bonobo_activation_register_active_server
 					  CORBA_Object  obj,
 					  GSList       *reg_env)
 {
+        Bonobo_RegistrationResult rv;
+        CORBA_Object              existing;
+        rv = bonobo_activation_register_active_server_extended
+                (iid, obj, reg_env, 0, &existing);
+	if (existing != CORBA_OBJECT_NIL)
+		CORBA_Object_release (existing, NULL);
+        return rv;
+}
+
+Bonobo_RegistrationResult
+bonobo_activation_register_active_server_extended (const char               *iid,
+                                                   CORBA_Object              obj,
+                                                   GSList                   *reg_env,
+                                                   Bonobo_RegistrationFlags  flags,
+                                                   CORBA_Object             *existing)
+{
 	Bonobo_ObjectDirectory     od;
 	CORBA_Environment          ev;
 	Bonobo_RegistrationResult  retval;
@@ -251,7 +267,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/bonobo-activation/bonobo-activation/bonobo-activation-register.h,v
retrieving revision 1.7
diff -u -p -r1.7 bonobo-activation-register.h
--- bonobo-activation/bonobo-activation-register.h	17 Oct 2002 23:10:59 -0000	1.7
+++ bonobo-activation/bonobo-activation-register.h	10 Mar 2003 14:18:08 -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_extended (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_Activation_types.idl
===================================================================
RCS file: /cvs/gnome/bonobo-activation/idl/Bonobo_Activation_types.idl,v
retrieving revision 1.5
diff -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	10 Mar 2003 14:18:08 -0000
@@ -40,6 +40,9 @@ module Bonobo {
         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;
 		string  value;
Index: idl/Bonobo_ObjectDirectory.idl
===================================================================
RCS file: /cvs/gnome/bonobo-activation/idl/Bonobo_ObjectDirectory.idl,v
retrieving revision 1.7
diff -u -p -r1.7 Bonobo_ObjectDirectory.idl
--- idl/Bonobo_ObjectDirectory.idl	17 Oct 2002 23:11:01 -0000	1.7
+++ idl/Bonobo_ObjectDirectory.idl	10 Mar 2003 14:18:08 -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: server/activation-server-main.c
===================================================================
RCS file: /cvs/gnome/bonobo-activation/server/activation-server-main.c,v
retrieving revision 1.47
diff -u -p -r1.47 activation-server-main.c
--- server/activation-server-main.c	17 Oct 2002 23:11:02 -0000	1.47
+++ server/activation-server-main.c	10 Mar 2003 14:18:09 -0000
@@ -179,7 +179,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;
@@ -242,7 +242,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: server/object-directory-corba.c
===================================================================
RCS file: /cvs/gnome/bonobo-activation/server/object-directory-corba.c,v
retrieving revision 1.56
diff -u -p -r1.56 object-directory-corba.c
--- server/object-directory-corba.c	24 Feb 2003 11:51:10 -0000	1.56
+++ server/object-directory-corba.c	10 Mar 2003 14:18:09 -0000
@@ -702,21 +702,27 @@ 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);
libbonobo-uniqapp.diff (text/x-patch, 20.1 KB)
Index: libbonobo.h
===================================================================
RCS file: /cvs/gnome/libbonobo/libbonobo.h,v
retrieving revision 1.60
diff -u -p -r1.60 libbonobo.h
--- libbonobo.h	19 Nov 2001 00:13:33 -0000	1.60
+++ libbonobo.h	24 Mar 2003 11:43:25 -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.64
diff -u -p -r1.64 Makefile.am
--- bonobo/Makefile.am	18 Oct 2002 10:25:53 -0000	1.64
+++ bonobo/Makefile.am	24 Mar 2003 11:43:25 -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 -I $(BONOBO_ACTIVATION_IDL_DIR) -D__Bonobo_COMPILATION
@@ -84,6 +85,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 =			\
@@ -120,6 +123,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	24 Mar 2003 11:43:25 -0000
@@ -0,0 +1,148 @@
+  /* -*- 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.
+ * 
+ * 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;
+}
+
+
+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;
+}
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	24 Mar 2003 11:43:25 -0000
@@ -0,0 +1,50 @@
+/* -*- 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,
+						    ...);
+
+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	24 Mar 2003 11:43:25 -0000
@@ -0,0 +1,155 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+#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 <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 *bonobo_application = BONOBO_APPLICATION (object); */
+
+	  /* ... */
+
+	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 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;
+}
+
+static void
+bonobo_application_init (BonoboApplication *bonobo_application)
+{
+	  /* ... */
+}
+
+BONOBO_TYPE_FUNC_FULL (BonoboApplication,
+		       Bonobo_Application,
+		       BONOBO_TYPE_OBJECT,
+		       bonobo_application);
+
+
+/**
+ * bonobo_register_unique_application:
+ * @name: Unique name of the application, eg. "GNOME_Terminal".
+ * 
+ * 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 environment 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)
+{
+	GObject                   *gobj;
+	BonoboObject              *bobj;
+	BonoboApplication         *app;
+	Bonobo_RegistrationResult  reg_res;
+	gchar                     *iid;
+	CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
+
+	g_return_val_if_fail (name, NULL);
+
+	gobj = g_object_new (BONOBO_TYPE_APPLICATION, NULL);
+	bobj = BONOBO_OBJECT (gobj);
+	app  = BONOBO_APPLICATION (bobj);
+
+	iid     = g_strdup_printf ("OAFIID:%s", name);
+	reg_res = bonobo_activation_register_active_server_extended 
+		(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	24 Mar 2003 11:43:25 -0000
@@ -0,0 +1,46 @@
+/* -*- 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;
+
+};
+
+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);
+
+
+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 -r1.27 bonobo-arg.c
--- bonobo/bonobo-arg.c	21 Nov 2001 02:16:33 -0000	1.27
+++ bonobo/bonobo-arg.c	24 Mar 2003 11:43:25 -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 -r1.10 bonobo-marshal.list
--- bonobo/bonobo-marshal.list	30 Oct 2001 02:32:09 -0000	1.10
+++ bonobo/bonobo-marshal.list	24 Mar 2003 11:43:25 -0000
@@ -2,3 +2,4 @@ BOXED:STRING,BOOLEAN,BOXED
 VOID:STRING,BOXED,BOXED
 VOID:BOXED,UINT,BOXED
 OBJECT:STRING
+BOXED:STRING,BOXED
Index: idl/Bonobo.idl
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Bonobo.idl,v
retrieving revision 1.55
diff -u -p -r1.55 Bonobo.idl
--- idl/Bonobo.idl	7 Mar 2003 12:09:42 -0000	1.55
+++ idl/Bonobo.idl	24 Mar 2003 11:43:25 -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	24 Mar 2003 11:43:25 -0000
@@ -0,0 +1,25 @@
+/* -*- 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;
+                  // Send a message to the application
+	        any message (in string msg, in ArgList args);
+
+  	};
+
+};
+
+#endif /* BONOBO_APPLICATION_IDL */
+
Index: idl/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/idl/Makefile.am,v
retrieving revision 1.49
diff -u -p -r1.49 Makefile.am
--- idl/Makefile.am	15 Jan 2002 18:29:19 -0000	1.49
+++ idl/Makefile.am	24 Mar 2003 11:43:25 -0000
@@ -20,6 +20,7 @@ idl_DATA =				\
 	Bonobo_Zoomable.idl		\
 	Bonobo_Exception.idl		\
 	Bonobo_Clipboard.idl		\
+	Bonobo_Application.idl		\
 	$(NULL)
 
 EXTRA_DIST = $(idl_DATA)
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/libbonobo/tests/Makefile.am,v
retrieving revision 1.17
diff -u -p -r1.17 Makefile.am
--- tests/Makefile.am	23 Sep 2002 14:14:14 -0000	1.17
+++ tests/Makefile.am	24 Mar 2003 11:43:26 -0000
@@ -5,7 +5,8 @@ noinst_PROGRAMS =		\
 	test-event-source	\
 	test-object		\
 	test-stream-mem		\
-	test-storage-mem
+	test-storage-mem	\
+	test-uniqapp
 
 INCLUDES =	\
         -DGNOMELOCALEDIR=\""$(datadir)/locale"\"        \
@@ -30,6 +31,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	24 Mar 2003 11:43:26 -0000
@@ -0,0 +1,59 @@
+/* -*- 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");
+
+	if (g_type_is_a (G_OBJECT_TYPE (app), BONOBO_TYPE_APP_CLIENT))
+	{
+		BonoboAppClient *client = BONOBO_APP_CLIENT (app);
+		GValue          *retval;
+
+		g_message ("I am an application client");
+		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.