Bonobo Unique Application v5
- From: "Gustavo J. A. M. Carneiro" <gjc inescporto pt>
- To: gnome-components-list gnome org
- Cc: Michael Meeks <michael ximian com>, gnome-devel-list gnome org
- Subject: Bonobo Unique Application v5
- Date: Thu, 30 Oct 2003 22:27:17 +0000
Here's a fresh new patch to implement the "unique application" feature,
already discussed in this list.
Minor Changes:
1. No longer uses BonoboArg<->GValue conversion functions, since their
API basically sucks; instead I created new functions for the same
purpose, albeit based on the old ones.
2. A GValue containing a CORBA::any is now transported through CORBA
as one CORBA::any inside another CORBA::any. This is for compliance
with the principle of least surprise; for example, a CORBA::any
containing an integer before would turn up as GValue containing an
integer directly which, although convenient, may surprise the
programmer.
Comments are welcome. Regards.
--
Gustavo J. A. M. Carneiro
<gjc inescporto pt> <gustavo users sourceforge net>
? stamp-h1
? activation-server/test-performance
? tests/test-uniqapp
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 30 Oct 2003 22:14:31 -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.74
diff -u -p -r1.74 Makefile.am
--- bonobo/Makefile.am 15 Jul 2003 10:46:45 -0000 1.74
+++ bonobo/Makefile.am 30 Oct 2003 22:14:32 -0000
@@ -39,6 +39,7 @@ idls = \
$(top_srcdir)/idl/Bonobo_UI.idl \
$(top_srcdir)/idl/Bonobo_Zoomable.idl \
$(top_srcdir)/idl/Bonobo_Exception.idl \
+ $(top_srcdir)/idl/Bonobo_Application.idl \
$(top_srcdir)/idl/Bonobo_Clipboard.idl
idl_flags = -I$(top_srcdir)/idl -D__Bonobo_COMPILATION
@@ -88,6 +89,8 @@ libbonoboinclude_HEADERS = \
bonobo-storage-memory.h \
bonobo-xobject.h \
bonobo-i18n.h \
+ bonobo-application.h \
+ bonobo-app-client.h \
bonobo-types.h
noinst_HEADERS = \
@@ -125,6 +128,8 @@ libbonobo_src = \
bonobo-stream-memory.c \
bonobo-storage-memory.c \
bonobo-running-context.c \
+ bonobo-application.c \
+ bonobo-app-client.c \
bonobo-types.c \
bonobo-debug.c \
bonobo-debug.h
Index: bonobo/bonobo-app-client.c
===================================================================
RCS file: bonobo/bonobo-app-client.c
diff -N bonobo/bonobo-app-client.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.c 30 Oct 2003 22:14:32 -0000
@@ -0,0 +1,324 @@
+ /* -*- 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-application.h"
+#include "bonobo-exception.h"
+#include "bonobo-types.h"
+
+
+static void bonobo_app_client_class_init (BonoboAppClientClass *klass);
+static void bonobo_app_client_init (BonoboAppClient *app_client);
+static void bonobo_app_client_free_msgdescs (BonoboAppClient *self);
+
+static gpointer parent_class;
+
+GType
+bonobo_app_client_get_type (void)
+{
+ static GType app_client_type = 0;
+
+ if (!app_client_type)
+ {
+ static const GTypeInfo app_client_info =
+ {
+ sizeof (BonoboAppClientClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) bonobo_app_client_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (BonoboAppClient),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) bonobo_app_client_init,
+ };
+
+ app_client_type = g_type_register_static
+ (G_TYPE_OBJECT, "BonoboAppClient", &app_client_info, 0);
+ }
+
+ return app_client_type;
+}
+
+
+static void
+bonobo_app_client_finalize (GObject *object)
+{
+ BonoboAppClient *self = BONOBO_APP_CLIENT (object);
+
+ if (self->msgdescs)
+ bonobo_app_client_free_msgdescs (self);
+
+ if (G_OBJECT_CLASS(parent_class)->finalize)
+ G_OBJECT_CLASS(parent_class)->finalize (object);
+}
+
+
+static void
+bonobo_app_client_class_init (BonoboAppClientClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+ object_class->finalize = bonobo_app_client_finalize;
+}
+
+
+static void
+bonobo_app_client_init (BonoboAppClient *app_client)
+{
+
+}
+
+
+/**
+ * bonobo_app_client_new:
+
+ * @app_server: object reference to a Bonobo::Application; this
+ * function takes ownership of this reference (use
+ * bonobo_object_dup_ref if you want to keep your own reference.)
+ *
+ * Create an application client object connected to the remote (or
+ * local) Bonobo::Application object.
+ *
+ * Warning: Applications should not use this function. See
+ * bonobo_register_unique_application().
+ *
+ * Return value: a #BonoboAppClient object.
+ **/
+BonoboAppClient *
+bonobo_app_client_new (Bonobo_Application app_server)
+{
+ BonoboAppClient *app_client;
+
+ app_client = g_object_new (BONOBO_TYPE_APP_CLIENT, NULL);
+ app_client->app_server = app_server;
+ return app_client;
+}
+
+
+GValue *
+bonobo_app_client_msg_send_valist (BonoboAppClient *app_client,
+ const char *message,
+ va_list var_args)
+{
+ CORBA_any *ret;
+ Bonobo_Application_ArgList *args;
+ GValue *value, *rv;
+ GPtrArray *argv;
+ GType type;
+ gchar *err;
+ CORBA_Environment ev;
+ int i;
+
+ g_return_val_if_fail (app_client, NULL);
+ g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+ argv = g_ptr_array_new ();
+ while ((type = va_arg (var_args, GType)) != G_TYPE_NONE)
+ {
+ value = g_new0 (GValue, 1);
+ g_value_init (value, type);
+ G_VALUE_COLLECT(value, var_args, 0, &err);
+ if (err) g_error("error collecting value: %s", err);
+ g_ptr_array_add (argv, value);
+ }
+ args = Bonobo_Application_ArgList__alloc ();
+ args->_length = argv->len;
+ args->_buffer = Bonobo_Application_ArgList_allocbuf (argv->len);
+ for (i = 0; i < argv->len; ++i) {
+ value = g_ptr_array_index (argv, i);
+ if (!bonobo_gvalue_to_corba_any (value, &args->_buffer[i])) {
+ g_warning ("Failed to convert type '%s' to CORBA::any",
+ g_type_name (G_VALUE_TYPE (value)));
+ args->_buffer[i]._type = TC_void;
+ }
+ g_value_unset (value);
+ g_free (value);
+ }
+ CORBA_sequence_set_release (args, CORBA_TRUE);
+ g_ptr_array_free (argv, TRUE);
+
+ CORBA_exception_init (&ev);
+ g_message ("sending message '%s'", message);
+ ret = Bonobo_Application_message (app_client->app_server, message, args, &ev);
+ g_message ("message '%s' returned", message);
+ CORBA_free (args);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("error while sending message to application server: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+ CORBA_exception_free (&ev);
+
+ if (ret->_type != TC_void) {
+ rv = g_new0 (GValue, 1);
+ bonobo_corba_any_to_gvalue (rv, ret);
+ } else
+ rv = NULL;
+ CORBA_free (ret);
+ return rv;
+}
+
+
+/**
+ * bonobo_app_client_msg_send:
+ * @message: message name
+ *
+ * Send a message to the application server. Takes a variable length
+ * argument list of GType, value pairs, terminated with
+ * G_TYPE_NONE. Values are direct C values, not GValues! Example:
+ * <informalexample><programlisting>
+ * GValue *retval;
+ * retval = bonobo_app_client_msg_send (app_client, "openURL",
+ * G_TYPE_STRING, "http://www.gnome.org",
+ * G_TYPE_BOOLEAN, TRUE,
+ * G_TYPE_NONE);
+ * </programlisting></informalexample>
+ *
+ * Return value: a GValue containing the value returned from the
+ * aplication server.
+ **/
+GValue *
+bonobo_app_client_msg_send (BonoboAppClient *app_client,
+ const char *message,
+ ...)
+{
+ GValue *rv;
+ va_list var_args;
+
+ va_start (var_args, message);
+ rv = bonobo_app_client_msg_send_valist (app_client, message, var_args);
+ va_end (var_args);
+ return rv;
+}
+
+
+static __inline__ GType
+_typecode_to_gtype (CORBA_TypeCode tc)
+{
+ static GHashTable *hash = NULL;
+
+ if (!hash) {
+ hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(corba_type, gtype)\
+ g_hash_table_insert (hash, tc, GUINT_TO_POINTER(gtype));
+
+ mapping(G_TYPE_NONE, TC_void);
+ mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+ mapping(G_TYPE_INT, TC_CORBA_long);
+ mapping(G_TYPE_UINT, TC_CORBA_unsigned_long);
+ mapping(G_TYPE_LONG, TC_CORBA_long);
+ mapping(G_TYPE_ULONG, TC_CORBA_unsigned_long);
+ mapping(G_TYPE_FLOAT, TC_CORBA_float);
+ mapping(G_TYPE_DOUBLE, TC_CORBA_double);
+ mapping(G_TYPE_STRING, TC_CORBA_string);
+
+ mapping(BONOBO_TYPE_CORBA_ANY, TC_CORBA_any);
+#undef mapping
+ }
+ return GPOINTER_TO_UINT(g_hash_table_lookup (hash, tc));
+}
+
+static void
+bonobo_app_client_free_msgdescs (BonoboAppClient *self)
+{
+ int i;
+
+ for (i = 0; self->msgdescs[i].name; ++i) {
+ g_free (self->msgdescs[i].name);
+ g_free (self->msgdescs[i].types);
+ }
+ g_free (self->msgdescs);
+ self->msgdescs = NULL;
+}
+
+static void
+bonobo_app_client_get_msgdescs (BonoboAppClient *self)
+{
+ Bonobo_Application_MessageList *msglist;
+ CORBA_Environment ev;
+ int i, j;
+
+ g_return_if_fail(!self->msgdescs);
+ CORBA_exception_init (&ev);
+ msglist = Bonobo_Application_listMessages (self->app_server, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_warning ("Bonobo::Application::listMessages: %s",
+ bonobo_exception_get_text (&ev));
+ CORBA_exception_free (&ev);
+ return;
+ }
+ CORBA_exception_free (&ev);
+ g_return_if_fail (msglist);
+ self->msgdescs = g_new (BonoboAppClientMsgDesc, msglist->_length + 1);
+ for (i = 0; i < msglist->_length; ++i) {
+ self->msgdescs[i].name = g_strdup (msglist->_buffer[i].name);
+ self->msgdescs[i].return_type =
+ _typecode_to_gtype (msglist->_buffer[i].return_type);
+ self->msgdescs[i].types = g_new (GType, msglist->_buffer[i].types._length + 1);
+ for (j = 0; j < msglist->_length; ++j)
+ self->msgdescs[i].types[j] =
+ _typecode_to_gtype (msglist->_buffer[i].types._buffer[j]);
+ self->msgdescs[i].types[j] = G_TYPE_NONE;
+ self->msgdescs[i].description = g_strdup (msglist->_buffer[i].description);
+ }
+ self->msgdescs[i].name = NULL;
+ self->msgdescs[i].return_type = G_TYPE_NONE;
+ self->msgdescs[i].types = NULL;
+ CORBA_free (msglist);
+}
+
+
+/**
+ * bonobo_app_client_msg_list:
+ *
+ * Obtain a list of messages supported by the application server.
+ *
+ * Return value: a NULL terminated vector of strings; use g_strfreev()
+ * to free it.
+ **/
+BonoboAppClientMsgDesc const *
+bonobo_app_client_msg_list (BonoboAppClient *app_client)
+{
+
+ g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
+
+ if (!app_client->msgdescs)
+ bonobo_app_client_get_msgdescs (app_client);
+ return app_client->msgdescs;
+}
+
+
+gint
+bonobo_app_client_new_instance (BonoboAppClient *app_client,
+ int argc,
+ char *argv[])
+{
+ CORBA_any *any;
+ CORBA_sequence_CORBA_string *corba_argv;
+ int i;
+ GValue *rv;
+
+ corba_argv = CORBA_sequence_CORBA_string__alloc();
+ corba_argv->_buffer = CORBA_sequence_CORBA_string_allocbuf (argc);
+ corba_argv->_length = argc;
+ corba_argv->_maximum = argc;
+ for (i = 0; i < argc; ++i)
+ corba_argv->_buffer[i] = CORBA_string_dup (argv[i]);
+
+ any = CORBA_any__alloc();
+ any->_type = TC_CORBA_sequence_CORBA_string;
+ any->_value = corba_argv;
+ any->_release = CORBA_TRUE;
+
+ rv = bonobo_app_client_msg_send (app_client, "new-instance",
+ BONOBO_TYPE_CORBA_ANY, any,
+ G_TYPE_NONE);
+
+ CORBA_free (any);
+ return g_value_get_int (rv);
+}
+
+
Index: bonobo/bonobo-app-client.h
===================================================================
RCS file: bonobo/bonobo-app-client.h
diff -N bonobo/bonobo-app-client.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-app-client.h 30 Oct 2003 22:14:32 -0000
@@ -0,0 +1,66 @@
+/* -*- 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 */
+ gchar *description;
+};
+
+
+struct _BonoboAppClient
+{
+ GObject parent_instance;
+ /*< private >*/
+ Bonobo_Application app_server;
+ BonoboAppClientMsgDesc *msgdescs;
+};
+
+struct _BonoboAppClientClass
+{
+ GObjectClass parent_class;
+
+};
+
+
+GType bonobo_app_client_get_type (void) G_GNUC_CONST;
+BonoboAppClient* bonobo_app_client_new (Bonobo_Application app_server);
+GValue* bonobo_app_client_msg_send_valist (BonoboAppClient *app_client,
+ const char *message,
+ va_list var_args);
+GValue* bonobo_app_client_msg_send (BonoboAppClient *app_client,
+ const char *message,
+ ...);
+gint bonobo_app_client_new_instance (BonoboAppClient *app_client,
+ int argc,
+ char *argv[]);
+BonoboAppClientMsgDesc const *
+ bonobo_app_client_msg_list (BonoboAppClient *app_client);
+
+G_END_DECLS
+
+#endif /* __BONOBO_APP_CLIENT_H__ */
Index: bonobo/bonobo-application.c
===================================================================
RCS file: bonobo/bonobo-application.c
diff -N bonobo/bonobo-application.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.c 30 Oct 2003 22:14:33 -0000
@@ -0,0 +1,665 @@
+/* -*- 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 "bonobo-main.h"
+#include "bonobo-types.h"
+#include "bonobo-i18n.h"
+#include <string.h>
+
+
+enum SIGNALS {
+ MESSAGE,
+ NEW_INSTANCE,
+ LAST_SIGNAL
+};
+
+enum PROPERTIES {
+ PROP_0,
+ PROP_NAME,
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+typedef struct {
+ BonoboAppHookFunc func;
+ gpointer data;
+} BonoboAppHook;
+
+
+typedef struct {
+ GClosure *closure;
+ GType return_type;
+} BonoboAppMessageDesc;
+
+static GArray *bonobo_application_hooks = NULL;
+
+/*
+ * A pointer to our parent object class
+ */
+static gpointer parent_class;
+
+
+/* ------------ Forward function declarations ------------ */
+static void bonobo_application_invoke_hooks (BonoboApplication *app);
+/* ------------ ------------ ------------ ------------ */
+
+static void bonobo_app_message_desc_free (BonoboAppMessageDesc *msgdesc)
+{
+ if (msgdesc->closure)
+ g_closure_unref (msgdesc->closure);
+ g_free (msgdesc);
+}
+
+
+static gboolean
+_bonobo_application_message_accumulator(GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy)
+{
+ gboolean null_gvalue;
+
+ /* There is no good way to find out if a GValue contains a
+ * NULL GValue as value, if you understand what I'm saying :) */
+ /* This should ideally be:
+ * null_gvalue = G_VALUE_HOLDS_VALUE (handler_return) &&
+ * g_value_get_value (handler_return) == NULL; */
+ null_gvalue = (G_VALUE_HOLDS (handler_return, G_TYPE_VALUE) &&
+ (g_value_peek_pointer (handler_return) == NULL));
+
+ if (!null_gvalue) {
+ g_value_copy (handler_return, return_accu);
+ return FALSE; /* stop emission */
+ }
+ return TRUE; /* continue emission */
+}
+
+
+
+static void
+bonobo_application_finalize (GObject *object)
+{
+ BonoboApplication *self = BONOBO_APPLICATION (object);
+
+ if (self->message_list) {
+ g_slist_foreach (self->message_list, (GFunc) CORBA_free, NULL);
+ g_slist_free (self->message_list);
+ self->message_list = NULL;
+ }
+
+ if (self->name) {
+ g_free (self->name);
+ self->name = NULL;
+ }
+
+ if (self->closure_hash) {
+ g_hash_table_destroy (self->closure_hash);
+ self->closure_hash = NULL;
+ }
+
+ G_OBJECT_CLASS (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) {
+ if (bonobo_corba_any_to_gvalue (&value, &args->_buffer [i])) {
+ g_value_array_append (signal_args, &value);
+ g_value_unset (&value);
+ } else {
+ g_warning ("Failed to convert type '%s' to GValue",
+ args->_buffer[i]._type->name);
+ }
+ }
+
+ g_signal_emit (app, signals [MESSAGE],
+ g_quark_from_string (msg),
+ msg, signal_args, &signal_return);
+
+ g_value_array_free (signal_args);
+ rv = CORBA_any__alloc ();
+ if (signal_return) {
+ if (!bonobo_gvalue_to_corba_any (signal_return, rv)) {
+ g_warning ("Failed to convert type '%s' to CORBA::any",
+ g_type_name (G_VALUE_TYPE (signal_return)));
+ rv->_type = TC_void;
+ }
+ g_value_unset (signal_return);
+ g_free (signal_return);
+ } else
+ rv->_type = TC_void;
+
+ return rv;
+}
+
+gint bonobo_application_new_instance (BonoboApplication *app,
+ gint argc,
+ gchar *argv[])
+{
+ gint rv;
+ g_signal_emit (app, signals [NEW_INSTANCE], 0,
+ argc, argv, &rv);
+ return rv;
+}
+
+static GValue *
+bonobo_application_run_closures (BonoboApplication *self,
+ const char *name,
+ GValueArray *args)
+{
+ BonoboAppMessageDesc *desc;
+
+ desc = g_hash_table_lookup (self->closure_hash, name);
+
+ if (desc) {
+ GValue *retval = g_new0 (GValue, 1);
+ GValue *params = g_newa (GValue, args->n_values + 1);
+
+ memset (params + 0, 0, sizeof (GValue));
+ g_value_init (params + 0, G_TYPE_OBJECT);
+ g_value_set_object (params + 0, self);
+ memcpy (params + 1, args->values, args->n_values * sizeof (GValue));
+ g_value_init (retval, desc->return_type);
+ g_closure_invoke (desc->closure, retval, args->n_values + 1,
+ params, NULL /* invocation_hint */);
+ g_value_unset (params + 0);
+ return retval;
+ }
+
+ return NULL;
+}
+
+ /* Handle the "new-instance" standard message */
+static GValue *
+bonobo_application_real_message (BonoboApplication *app,
+ const char *name,
+ GValueArray *args)
+{
+ CORBA_any *any;
+ GValue *retval;
+ int rv;
+ CORBA_sequence_CORBA_string *argv;
+
+ if (strcmp (name, "new-instance") != 0)
+ return bonobo_application_run_closures (app, name, args);
+
+ g_return_val_if_fail (args->n_values == 1, NULL);
+ g_return_val_if_fail (BONOBO_VALUE_HOLDS_CORBA_ANY
+ (g_value_array_get_nth (args, 0)), NULL);
+ any = bonobo_value_get_corba_any (g_value_array_get_nth (args, 0));
+ if (!CORBA_TypeCode_equal (any->_type,
+ TC_CORBA_sequence_CORBA_string, NULL)) {
+ CORBA_free (any);
+ g_return_val_if_reached (NULL);
+ }
+ argv = (CORBA_sequence_CORBA_string *) any->_value;
+ rv = bonobo_application_new_instance (app, argv->_length,
+ argv->_buffer);
+ CORBA_free (any);
+ retval = g_new0 (GValue, 1);
+ g_value_init (retval, G_TYPE_INT);
+ g_value_set_int (retval, rv);
+ return retval;
+}
+
+
+static __inline__ void
+message_desc_copy(Bonobo_Application_MessageDesc *dest,
+ Bonobo_Application_MessageDesc *src)
+{
+ dest->name = CORBA_string_dup (src->name);
+ dest->return_type = src->return_type;
+ dest->types._buffer = src->types._buffer;
+ dest->types._length = src->types._length;
+ dest->types._maximum = src->types._maximum;
+ dest->types._release = CORBA_FALSE;
+ dest->description = CORBA_string_dup (src->description);
+}
+
+
+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
+set_property (GObject *g_object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BonoboApplication *self = (BonoboApplication *) g_object;
+
+ switch (prop_id) {
+ case PROP_NAME:
+ if (self->name) g_free (self->name);
+ self->name = g_strdup (g_value_get_string (value));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BonoboApplication *self = (BonoboApplication *) object;
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, self->name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+bonobo_application_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ BonoboApplication *self;
+
+ object = G_OBJECT_CLASS (parent_class)->constructor
+ (type, n_construct_properties, construct_properties);
+ self = BONOBO_APPLICATION (object);
+ bonobo_application_invoke_hooks (self);
+ return object;
+}
+
+static void
+bonobo_application_class_init (BonoboApplicationClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+ POA_Bonobo_Application__epv *epv = &klass->epv;
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = bonobo_application_finalize;
+ object_class->constructor = bonobo_application_constructor;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ signals [MESSAGE] = g_signal_new (
+ "message", BONOBO_TYPE_APPLICATION,
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (BonoboApplicationClass, message),
+ _bonobo_application_message_accumulator, NULL,
+ bonobo_marshal_BOXED__STRING_BOXED,
+ G_TYPE_VALUE, 2, /* return_type, nparams */
+ G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+ G_TYPE_VALUE_ARRAY);
+
+ signals [NEW_INSTANCE] = g_signal_new (
+ "new-instance", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (BonoboApplicationClass, new_instance),
+ NULL, NULL, /* accumulator and accumulator data */
+ bonobo_marshal_INT__INT_POINTER,
+ G_TYPE_INT, 2, /* return_type, nparams */
+ G_TYPE_INT, G_TYPE_POINTER);
+
+ g_object_class_install_property
+ (object_class, PROP_NAME,
+ g_param_spec_string
+ ("name", _("Name"), _("Application unique name"), NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ klass->message = bonobo_application_real_message;
+
+ epv->message = impl_Bonobo_Application_message;
+ epv->listMessages = impl_Bonobo_Application_listMessages;
+}
+
+static void
+bonobo_application_init (BonoboApplication *self)
+{
+ self->closure_hash = g_hash_table_new_full
+ (g_str_hash, g_str_equal,
+ g_free,(GDestroyNotify) bonobo_app_message_desc_free);
+}
+
+BONOBO_TYPE_FUNC_FULL (BonoboApplication,
+ Bonobo_Application,
+ BONOBO_TYPE_OBJECT,
+ bonobo_application);
+
+
+BonoboApplication *
+bonobo_application_new (const char *name)
+{
+ GObject *obj;
+ BonoboApplication *app;
+
+ obj = g_object_new (BONOBO_TYPE_APPLICATION,
+ "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_ALL_AT_IDLE),
+ "name", name,
+ NULL);
+ app = (BonoboApplication *) obj;
+ return app;
+}
+
+static __inline__ CORBA_TypeCode
+_gtype_to_typecode (GType gtype)
+{
+ static GHashTable *hash = NULL;
+
+ if (!hash) {
+ hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+#define mapping(gtype, corba_type)\
+ g_hash_table_insert (hash, GUINT_TO_POINTER(gtype), corba_type);
+
+ mapping(G_TYPE_NONE, TC_void);
+ mapping(G_TYPE_BOOLEAN, TC_CORBA_boolean);
+ mapping(G_TYPE_INT, TC_CORBA_long);
+ mapping(G_TYPE_UINT, TC_CORBA_unsigned_long);
+ mapping(G_TYPE_LONG, TC_CORBA_long);
+ mapping(G_TYPE_ULONG, TC_CORBA_unsigned_long);
+ mapping(G_TYPE_FLOAT, TC_CORBA_float);
+ mapping(G_TYPE_DOUBLE, TC_CORBA_double);
+ mapping(G_TYPE_STRING, TC_CORBA_string);
+
+ mapping(BONOBO_TYPE_CORBA_ANY, TC_CORBA_any);
+#undef mapping
+ }
+ return (CORBA_TypeCode) g_hash_table_lookup (hash, GUINT_TO_POINTER(G_TYPE_INT));
+}
+
+void
+bonobo_application_register_message_va (BonoboApplication *app,
+ const gchar *name,
+ const gchar *description,
+ GClosure *opt_closure,
+ 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);
+ msgdesc->description = CORBA_string_dup (description);
+
+ tmparray = g_ptr_array_new ();
+ if (first_arg_type != G_TYPE_NONE) {
+ g_ptr_array_add (tmparray, _gtype_to_typecode (first_arg_type));
+ while ((gtype = va_arg (var_args, GType)) != G_TYPE_NONE)
+ g_ptr_array_add (tmparray, _gtype_to_typecode (gtype));
+ }
+ msgdesc->types._length = msgdesc->types._maximum = tmparray->len;
+ msgdesc->types._buffer = CORBA_sequence_CORBA_TypeCode_allocbuf (tmparray->len);
+ memcpy(msgdesc->types._buffer, tmparray->pdata, sizeof(gpointer)*tmparray->len);
+ g_ptr_array_free (tmparray, TRUE);
+
+ app->message_list = g_slist_prepend (app->message_list, msgdesc);
+
+ if (opt_closure) {
+ BonoboAppMessageDesc *desc = g_new0 (BonoboAppMessageDesc, 1);
+ g_closure_ref (opt_closure);
+ g_closure_sink (opt_closure);
+ desc->closure = opt_closure;
+ desc->return_type = return_type;
+ g_hash_table_insert (app->closure_hash, g_strdup (name), desc);
+ }
+}
+
+
+void
+bonobo_application_register_message (BonoboApplication *app,
+ const gchar *name,
+ const gchar *description,
+ GClosure *opt_closure,
+ 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, description,
+ opt_closure, return_type,
+ first_arg_type, var_args);
+ va_end (var_args);
+}
+
+
+/**
+ * bonobo_application_register_unique:
+ * @app: a #BonoboApplication instance
+ *
+ * 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: %NULL 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. If the return value is
+ * non-%NULL, the programmer is responsible for freeing the
+ * #BonoboApplication with bonobo_object_unref().
+ **/
+BonoboAppClient *
+bonobo_application_register_unique (BonoboApplication *app)
+{
+ Bonobo_RegistrationResult reg_res;
+ gchar *iid, *description;
+ CORBA_Object remote_obj = CORBA_OBJECT_NIL;
+
+ iid = g_strdup_printf ("OAFIID:%s", app->name);
+ description = g_strdup_printf ("Unique Application instance: '%s'",
+ app->name);
+ reg_res = bonobo_activation_register_active_server_ext
+ (iid, bonobo_object_corba_objref (BONOBO_OBJECT (app)), NULL,
+ Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, &remote_obj,
+ description);
+ g_free (iid);
+ g_free (description);
+ 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;
+ }
+}
+
+
+/**
+ * bonobo_application_add_hook:
+ * @func: hook function
+ * @data: user data
+ *
+ * Add a hook function to be called whenever #BonoboApplication is
+ * instantiated.
+ **/
+void bonobo_application_add_hook (BonoboAppHookFunc func, gpointer data)
+{
+ BonoboAppHook hook;
+
+ if (bonobo_application_hooks == NULL)
+ bonobo_application_hooks = g_array_new (FALSE, FALSE, sizeof (BonoboAppHook));
+
+ hook.func = func;
+ hook.data = data;
+ g_array_append_val (bonobo_application_hooks, hook);
+}
+
+
+/**
+ * bonobo_application_remove_hook:
+ * @func: hook function
+ * @data: user data
+ *
+ * Removes a hook function previously set with bonobo_application_add_hook().
+ **/
+void bonobo_application_remove_hook (BonoboAppHookFunc func, gpointer data)
+{
+ BonoboAppHook *hook;
+ int i;
+
+ g_return_if_fail (bonobo_application_hooks);
+
+ for (i = 0; i < bonobo_application_hooks->len; ++i) {
+ hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+ if (hook->func == func && hook->data == data) {
+ g_array_remove_index (bonobo_application_hooks, i);
+ return;
+ }
+ }
+
+ g_warning ("bonobo_application_remove_hook: "
+ "(func, data) == (%p, %p) not found.", func, data);
+}
+
+
+static void
+bonobo_application_invoke_hooks (BonoboApplication *app)
+{
+ BonoboAppHook *hook;
+ int i;
+
+ if (!bonobo_application_hooks)
+ return;
+
+ for (i = 0; i < bonobo_application_hooks->len; ++i) {
+ hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
+ hook->func (app, hook->data);
+ }
+}
+
+gboolean
+bonobo_corba_any_to_gvalue (GValue *out_value, CORBA_any const *any)
+{
+#define MAPPING(gtypename, bonoboargname, typename, typecode) \
+ else if (CORBA_TypeCode_equal (any->_type, typecode, NULL)) { \
+ g_value_init (out_value, G_TYPE_##gtypename); \
+ g_value_set_##typename (out_value, BONOBO_ARG_GET_##bonoboargname(any)); \
+ return TRUE; \
+ }
+
+ if (0);
+ MAPPING (STRING, STRING, string, TC_CORBA_string)
+ MAPPING (CHAR, CHAR, char, TC_CORBA_char)
+ MAPPING (UCHAR, CHAR, uchar, TC_CORBA_char)
+ MAPPING (BOOLEAN, BOOLEAN, boolean, TC_CORBA_boolean)
+ MAPPING (INT, LONG, int, TC_CORBA_long)
+ MAPPING (UINT, ULONG, uint, TC_CORBA_unsigned_long)
+ MAPPING (LONG, LONG, long, TC_CORBA_long)
+ MAPPING (ULONG, ULONG, ulong, TC_CORBA_unsigned_long)
+ MAPPING (FLOAT, FLOAT, float, TC_CORBA_float)
+ MAPPING (DOUBLE, DOUBLE, double, TC_CORBA_double)
+#undef MAPPING
+ ;
+ if (CORBA_TypeCode_equal (any->_type, TC_CORBA_any, NULL)) {
+ g_value_init (out_value, BONOBO_TYPE_CORBA_ANY);
+ bonobo_value_set_corba_any (out_value, any->_value);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+bonobo_gvalue_to_corba_any (GValue const *value, CORBA_any *any)
+{
+ GType id;
+
+ g_return_val_if_fail (any, FALSE);
+ g_return_val_if_fail (value, FALSE);
+
+ id = G_VALUE_TYPE (value);
+
+ switch (id)
+ {
+
+ case G_TYPE_INVALID:
+ case G_TYPE_NONE:
+ g_warning ("Strange GValue type %s", g_type_name (id));
+ break;
+
+#define MAKE_FROM_GVALUE(gtype, gtypename, tcid, corbatype) \
+case G_TYPE_##gtype: \
+ any->_type = tcid; \
+ any->_value = ORBit_alloc_tcval (tcid, 1); \
+ *((corbatype *)any->_value) = (corbatype) g_value_get_##gtypename (value); \
+ return TRUE
+
+ MAKE_FROM_GVALUE (CHAR, char, TC_CORBA_char, CORBA_char);
+ MAKE_FROM_GVALUE (UCHAR, uchar, TC_CORBA_char, CORBA_char);
+ MAKE_FROM_GVALUE (BOOLEAN, boolean, TC_CORBA_boolean, CORBA_boolean);
+ MAKE_FROM_GVALUE (INT, int, TC_CORBA_long, CORBA_long);
+ MAKE_FROM_GVALUE (UINT, uint, TC_CORBA_unsigned_long, CORBA_unsigned_long);
+ MAKE_FROM_GVALUE (LONG, long, TC_CORBA_long, CORBA_long);
+ MAKE_FROM_GVALUE (ULONG, ulong, TC_CORBA_unsigned_long, CORBA_unsigned_long);
+ MAKE_FROM_GVALUE (FLOAT, float, TC_CORBA_float, CORBA_float);
+ MAKE_FROM_GVALUE (DOUBLE, double, TC_CORBA_double, CORBA_double);
+
+#undef MAKE_FROM_GVALUE
+
+ case G_TYPE_STRING:
+ if (G_VALUE_HOLDS_STRING (value))
+ *((CORBA_char **)any->_value) =
+ CORBA_string_dup (g_value_get_string (value));
+ else
+ *((CORBA_char **)any->_value) = CORBA_string_dup ("");
+ return TRUE;
+
+ }
+
+ if (G_VALUE_HOLDS_BOXED(value) && id == BONOBO_TYPE_CORBA_ANY) {
+ any->_release = CORBA_TRUE;
+ any->_type = TC_CORBA_any;
+ any->_value = bonobo_value_get_corba_any (value);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
Index: bonobo/bonobo-application.h
===================================================================
RCS file: bonobo/bonobo-application.h
diff -N bonobo/bonobo-application.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ bonobo/bonobo-application.h 30 Oct 2003 22:14:33 -0000
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#ifndef _BONOBO_APPLICATION_H_
+#define _BONOBO_APPLICATION_H_
+
+#include <bonobo/bonobo-object.h>
+
+G_BEGIN_DECLS
+
+#define BONOBO_TYPE_APPLICATION (bonobo_application_get_type ())
+#define BONOBO_APPLICATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o),\
+ BONOBO_TYPE_APPLICATION, BonoboApplication))
+#define BONOBO_APPLICATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k),\
+ BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+#define BONOBO_IS_APPLICATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o),\
+ BONOBO_TYPE_APPLICATION))
+#define BONOBO_IS_APPLICATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k),\
+ BONOBO_TYPE_APPLICATION))
+#define BONOBO_APPLICATION_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o),\
+ BONOBO_TYPE_APPLICATION, BonoboApplicationClass))
+
+typedef struct _BonoboApplication BonoboApplication;
+typedef struct _BonoboApplicationClass BonoboApplicationClass;
+
+typedef void (*BonoboAppHookFunc) (BonoboApplication *app, gpointer data);
+
+
+#include <bonobo/bonobo-app-client.h>
+
+
+struct _BonoboApplication {
+ BonoboObject parent;
+ GSList *message_list;
+ gchar *name;
+ GHashTable *closure_hash;
+};
+
+struct _BonoboApplicationClass {
+ BonoboObjectClass parent_class;
+
+ GValue* (*message) (BonoboApplication *app, const char *name, GValueArray *args);
+ gint (*new_instance) (BonoboApplication *app, gint argc, gchar *argv[]);
+
+ gpointer unimplemented[8];
+
+ POA_Bonobo_Application__epv epv;
+};
+
+
+GType bonobo_application_get_type (void) G_GNUC_CONST;
+BonoboApplication* bonobo_application_new (const char *name);
+void bonobo_application_register_message (BonoboApplication *app,
+ const gchar *name,
+ const gchar *description,
+ GClosure *opt_closure,
+ GType return_type,
+ GType first_arg_type,
+ ...);
+void bonobo_application_register_message_va (BonoboApplication *app,
+ const gchar *name,
+ const gchar *description,
+ GClosure *opt_closure,
+ GType return_type,
+ GType first_arg_type,
+ va_list var_args);
+BonoboAppClient* bonobo_application_register_unique (BonoboApplication *app);
+void bonobo_application_add_hook (BonoboAppHookFunc func,
+ gpointer data);
+void bonobo_application_remove_hook (BonoboAppHookFunc func,
+ gpointer data);
+gint bonobo_application_new_instance (BonoboApplication *app,
+ gint argc,
+ gchar *argv[]);
+
+ /* Utility functions (similar to bonobo_arg_xxx, but slightly different API) */
+gboolean bonobo_corba_any_to_gvalue (GValue *out_value,
+ CORBA_any const *any);
+gboolean bonobo_gvalue_to_corba_any (GValue const *value,
+ CORBA_any *any);
+
+G_END_DECLS
+
+#endif /* _BONOBO_APPLICATION_H_ */
+
Index: bonobo/bonobo-arg.h
===================================================================
RCS file: /cvs/gnome/libbonobo/bonobo/bonobo-arg.h,v
retrieving revision 1.29
diff -u -p -r1.29 bonobo-arg.h
--- bonobo/bonobo-arg.h 11 Mar 2003 17:55:59 -0000 1.29
+++ bonobo/bonobo-arg.h 30 Oct 2003 22:14:33 -0000
@@ -51,6 +51,8 @@ typedef CORBA_TypeCode BonoboArgType;
#define BONOBO_ARG_SET_INT(a,v) (BONOBO_ARG_SET_GENERAL (a, v, TC_CORBA_long, CORBA_long, NULL))
#define BONOBO_ARG_GET_LONG(a) (BONOBO_ARG_GET_GENERAL (a, TC_CORBA_long, CORBA_long, NULL))
#define BONOBO_ARG_SET_LONG(a,v) (BONOBO_ARG_SET_GENERAL (a, v, TC_CORBA_long, CORBA_long, NULL))
+#define BONOBO_ARG_GET_ULONG(a) (BONOBO_ARG_GET_GENERAL (a, TC_CORBA_unsigned_long, CORBA_unsigned_long, NULL))
+#define BONOBO_ARG_SET_ULONG(a,v) (BONOBO_ARG_SET_GENERAL (a, v, TC_CORBA_unsigned_long, CORBA_unsigned_long, NULL))
#define BONOBO_ARG_GET_LONGLONG(a) (BONOBO_ARG_GET_GENERAL (a, TC_CORBA_long_long, CORBA_long_long, NULL))
#define BONOBO_ARG_SET_LONGLONG(a,v) (BONOBO_ARG_SET_GENERAL (a, v, TC_CORBA_long_long, CORBA_long_long, NULL))
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 30 Oct 2003 22:14:33 -0000
@@ -2,3 +2,6 @@ BOXED:STRING,BOOLEAN,BOXED
VOID:STRING,BOXED,BOXED
VOID:BOXED,UINT,BOXED
OBJECT:STRING
+BOXED:STRING,BOXED
+INT:INT,POINTER
+FLOAT:INT,FLOAT
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 30 Oct 2003 22:14:33 -0000
@@ -49,6 +49,8 @@
/* Clipboard */
#include <Bonobo_Clipboard.idl>
+#include <Bonobo_Application.idl>
+
#ifndef __Bonobo_COMPILATION
#ifdef __ORBIT_IDL__
#pragma inhibit pop
Index: idl/Bonobo_Application.idl
===================================================================
RCS file: idl/Bonobo_Application.idl
diff -N idl/Bonobo_Application.idl
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ idl/Bonobo_Application.idl 30 Oct 2003 22:14:33 -0000
@@ -0,0 +1,47 @@
+/* -*- 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;
+ string description;
+ };
+
+ 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.53
diff -u -p -r1.53 Makefile.am
--- idl/Makefile.am 15 Jul 2003 10:46:47 -0000 1.53
+++ idl/Makefile.am 30 Oct 2003 22:14:33 -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.29
diff -u -p -r1.29 Makefile.am
--- tests/Makefile.am 23 Sep 2003 15:28:51 -0000 1.29
+++ tests/Makefile.am 30 Oct 2003 22:14:34 -0000
@@ -10,7 +10,8 @@ check_PROGRAMS = \
test-stream-mem \
test-storage-mem \
test-generic-factory \
- generic-factory
+ generic-factory \
+ test-uniqapp
INCLUDES = \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
@@ -37,6 +38,8 @@ test_event_source_SOURCES = test-event-s
test_stream_mem_SOURCES = test-stream-mem.c
test_storage_mem_SOURCES = test-storage-mem.c
+
+test_uniqapp_SOURCES = test-uniqapp.c
TESTS_ENVIRONMENT = \
LD_LIBRARY_PATH="$(top_builddir)/bonobo/.libs:$$LD_LIBRARY_PATH" \
Index: tests/test-uniqapp.c
===================================================================
RCS file: tests/test-uniqapp.c
diff -N tests/test-uniqapp.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/test-uniqapp.c 30 Oct 2003 22:14:34 -0000
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+#include <config.h>
+#include <libbonobo.h>
+#include <string.h>
+#include "bonobo/bonobo-marshal.h"
+
+#define TEST_MESSAGE "test-message"
+#define CLOSURE_MESSAGE "closure-message"
+
+
+static GValue *
+message_cb (BonoboAppClient *app_client, const gchar *message, GValueArray *args)
+{
+ GValue *retval;
+
+ g_return_val_if_fail (strcmp (message, TEST_MESSAGE) == 0, NULL);
+ g_return_val_if_fail (args->n_values == 1, NULL);
+ g_return_val_if_fail (G_VALUE_HOLDS_FLOAT (&args->values[0]), NULL);
+
+ g_message ("message_cb: %s", message);
+
+ retval = g_new0 (GValue, 1);
+ g_value_init (retval, G_TYPE_FLOAT);
+ g_value_set_float (retval, 2 * g_value_get_float (&args->values[0]));
+ return retval;
+}
+
+static void
+test_app_hook (BonoboApplication *app, gpointer data)
+{
+ g_message ("App '%s' created; data == %p", app->name, data);
+}
+
+static gint
+new_instance_cb (BonoboApplication *app, gint argc, char *argv[])
+{
+ int i;
+
+ g_message ("new-instance received. argc = %i; argv follows:", argc);
+ for (i = 0; i < argc; ++i)
+ g_message ("argv[%i] = \"%s\"", i, argv[i]);
+ g_message ("new-instance: returning argc (%i)", argc);
+ return argc;
+}
+
+
+static gfloat
+closure_message_cb (BonoboApplication *app, gint arg_1, gfloat arg_2, gpointer data2)
+{
+ g_message("closure_message_cb: %p, %i, %f, %p",
+ app, arg_1, arg_2, data2);
+ return arg_1 * arg_2;
+}
+
+
+int
+main (int argc, char *argv [])
+{
+ BonoboApplication *app;
+ BonoboAppClient *client;
+ float msg_arg = 3.141592654;
+ GClosure *closure;
+
+ if (bonobo_init (&argc, argv) == FALSE)
+ g_error ("Can not bonobo_init");
+ bonobo_activate ();
+
+ bonobo_application_add_hook (test_app_hook, (gpointer) 0xdeadbeef);
+
+ app = bonobo_application_new ("Libbonobo-Test-Uniqapp");
+
+ closure = g_cclosure_new (G_CALLBACK (closure_message_cb),
+ (gpointer) 0xdeadbeef, NULL);
+ g_closure_set_marshal (closure, bonobo_marshal_FLOAT__INT_FLOAT);
+ bonobo_application_register_message (app, CLOSURE_MESSAGE,
+ "This is a test message",
+ closure,
+ G_TYPE_FLOAT, G_TYPE_INT,
+ G_TYPE_FLOAT, G_TYPE_NONE);
+
+ client = bonobo_application_register_unique (app);
+
+ if (client)
+ {
+ BonoboAppClientMsgDesc const *msgdescs;
+ GValue *retval;
+ int i;
+
+ g_message ("I am an application client.");
+ bonobo_object_unref (BONOBO_OBJECT (app));
+
+ msgdescs = bonobo_app_client_msg_list (client);
+ g_assert (msgdescs);
+
+ for (i = 0; msgdescs[i].name; ++i)
+ g_message ("Application supports message '%s'", msgdescs[i].name);
+
+ g_message ("Sending message string '%s' with argument %f",
+ TEST_MESSAGE, msg_arg);
+ retval = bonobo_app_client_msg_send (client, TEST_MESSAGE,
+ G_TYPE_FLOAT, msg_arg,
+ G_TYPE_NONE);
+ g_message ("Return value: %f", g_value_get_float (retval));
+
+
+ g_message ("Sending message string '%s' with arguments %i and %f",
+ CLOSURE_MESSAGE, 10, 3.141592654);
+ retval = bonobo_app_client_msg_send (client, CLOSURE_MESSAGE,
+ G_TYPE_INT, 10,
+ G_TYPE_FLOAT, 3.141592654,
+ G_TYPE_NONE);
+ g_message ("Return value: %f", g_value_get_float (retval));
+
+ g_message ("Sending new-instance, with argc/argv");
+ i = bonobo_app_client_new_instance (client, argc, argv);
+ g_message ("new-instance returned %i", i);
+
+ } else {
+ g_message ("I am an application server");
+ g_signal_connect (app, "message::test-message",
+ G_CALLBACK (message_cb), NULL);
+ g_signal_connect (app, "new-instance",
+ G_CALLBACK (new_instance_cb), NULL);
+ bonobo_application_new_instance (app, argc, argv);
+ }
+
+ bonobo_main ();
+
+ return bonobo_debug_shutdown ();
+}
[
Date Prev][Date Next] [
Thread Prev][Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]