/* -*- 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-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)
{
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 (self->app_server != CORBA_OBJECT_NIL) {
bonobo_object_release_unref (self->app_server, NULL);
self->app_server = CORBA_OBJECT_NIL;
}
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_application_register_unique().</warning>
*
* 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;
}
/**
* bonobo_app_client_msg_send_argv:
* @app_client: client
* @message: message name
* @argv: %NULL-terminated vector of pointers to GValue, the arguments
* to pass with the message.
*
* Like bonobo_app_client_msg_send(), except that it receives a single
* argument vector instead of a variable number of arguments.
*
* Return value: the message return value
**/
GValue *
bonobo_app_client_msg_send_argv (BonoboAppClient *app_client,
const char *message,
const GValue *argv[],
CORBA_Environment *opt_env)
{
CORBA_any *ret;
Bonobo_Application_ArgList *args;
GValue *rv;
CORBA_Environment ev1, *ev;
int i, argv_len;
g_return_val_if_fail (app_client, NULL);
g_return_val_if_fail (BONOBO_IS_APP_CLIENT (app_client), NULL);
for (argv_len = -1; argv[++argv_len];);
args = Bonobo_Application_ArgList__alloc ();
args->_length = argv_len;
args->_buffer = Bonobo_Application_ArgList_allocbuf (argv_len);
for (i = 0; i < argv_len; ++i) {
if (!bonobo_arg_from_gvalue_alloc (&args->_buffer[i], argv[i])) {
g_warning ("Failed to convert type '%s' to CORBA::any",
g_type_name (G_VALUE_TYPE (argv[i])));
args->_buffer[i]._type = TC_void;
}
}
CORBA_sequence_set_release (args, CORBA_TRUE);
if (opt_env)
ev = opt_env;
else {
CORBA_exception_init (&ev1);
ev = &ev1;
}
ret = Bonobo_Application_message (app_client->app_server, message, args, ev);
CORBA_free (args);
if (ev->_major != CORBA_NO_EXCEPTION) {
if (!opt_env) {
char *text = bonobo_exception_get_text (ev);
g_warning ("error while sending message to application server: %s",
text);
g_free (text);
CORBA_exception_free (&ev1);
}
return NULL;
}
if (!opt_env)
CORBA_exception_free (&ev1);
if (ret->_type != TC_void) {
rv = g_new0 (GValue, 1);
bonobo_arg_to_gvalue_alloc (ret, rv);
} else
rv = NULL;
CORBA_free (ret);
return rv;
}
/**
* bonobo_app_client_msg_send_valist:
* @app_client: client
* @message: message name
* @opt_env: optional corba environment
* @first_arg_type: first message parameter
* @var_args: remaining parameters
*
* See bonobo_app_client_msg_send().
*
* Return value: return value
**/
GValue *
bonobo_app_client_msg_send_valist (BonoboAppClient *app_client,
const char *message,
CORBA_Environment *opt_env,
GType first_arg_type,
va_list var_args)
{
GValue *value, *rv;
GPtrArray *argv;
GType type;
gchar *err;
int i;
gboolean first_arg = TRUE;
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 = (first_arg? first_arg_type :
va_arg (var_args, GType))) != G_TYPE_NONE)
{
first_arg = FALSE;
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);
}
g_ptr_array_add (argv, NULL);
rv = bonobo_app_client_msg_send_argv (app_client, message,
(const GValue **) argv->pdata,
opt_env);
for (i = 0; i < argv->len - 1; ++i) {
value = g_ptr_array_index (argv, i);
g_value_unset (value);
g_free (value);
}
g_ptr_array_free (argv, TRUE);
return rv;
}
/**
* bonobo_app_client_msg_send:
* @app_client: the client interface associated with the application
* to which we wish to send a message
* @message: message name
* @...: arguments
*
* 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,
CORBA_Environment *opt_env,
GType first_arg_type,
...)
{
GValue *rv;
va_list var_args;
va_start (var_args, first_arg_type);
rv = bonobo_app_client_msg_send_valist (app_client, message, opt_env,
first_arg_type, 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(gtype, corba_type)\
g_hash_table_insert (hash, corba_type, GUINT_TO_POINTER (gtype));
mapping (G_TYPE_NONE, TC_void);
mapping (G_TYPE_BOOLEAN, TC_CORBA_boolean);
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) {
char *text = bonobo_exception_get_text (&ev);
g_warning ("Bonobo::Application::listMessages: %s", text);
g_free (text);
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->_buffer[i].types._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;
}
/**
* bonobo_app_client_new_instance:
* @app_client: a #BonoboAppClient
* @argc: length of @argv
* @argv: array of command-line arguments
* @opt_env: a #CORBA_Environment, or %NULL.
*
* Ask the application server to emit a "new-instance" signal
* containing the specified string vector.
*
* Return value: the message return value
**/
gint
bonobo_app_client_new_instance (BonoboAppClient *app_client,
int argc,
char *argv[],
CORBA_Environment *opt_env)
{
CORBA_sequence_CORBA_string *corba_argv;
int i;
gint rv;
CORBA_Environment *ev, ev1;
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]);
if (opt_env)
ev = opt_env;
else {
CORBA_exception_init (&ev1);
ev = &ev1;
}
rv = Bonobo_Application_newInstance (app_client->app_server, corba_argv, ev);
CORBA_free (corba_argv);
if (!opt_env) {
if (ev->_major != CORBA_NO_EXCEPTION) {
char *text = bonobo_exception_get_text (ev);
g_warning ("newInstance failed: %s", text);
g_free (text);
}
CORBA_exception_free (&ev1);
}
return rv;
}
syntax highlighted by Code2HTML, v. 0.9.1