~ubuntu-branches/ubuntu/quantal/libbonobo/quantal-201207170711

« back to all changes in this revision

Viewing changes to bonobo/bonobo-application.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-02-18 14:40:51 UTC
  • mto: (3.1.1 etch) (1.1.25 upstream)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20050218144051-fo4h9qh2gim8x3wt
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
#include "config.h"
 
3
#include "bonobo-application.h"
 
4
#include "bonobo-app-client.h"
 
5
#include <bonobo-exception.h>
 
6
#include "bonobo-marshal.h"
 
7
#include "bonobo-arg.h"
 
8
#include "bonobo-main.h"
 
9
#include "bonobo-i18n.h"
 
10
#include "bonobo-types.h"
 
11
#include <string.h>
 
12
 
 
13
 
 
14
enum SIGNALS {
 
15
        MESSAGE,
 
16
        NEW_INSTANCE,
 
17
        LAST_SIGNAL
 
18
};
 
19
 
 
20
enum PROPERTIES {
 
21
        PROP_0,
 
22
        PROP_NAME
 
23
};
 
24
 
 
25
static guint signals [LAST_SIGNAL] = { 0 };
 
26
 
 
27
typedef struct {
 
28
        BonoboAppHookFunc func;
 
29
        gpointer          data;
 
30
} BonoboAppHook;
 
31
 
 
32
 
 
33
typedef struct {
 
34
        GClosure *closure;
 
35
        GType     return_type;
 
36
} BonoboAppMessageDesc;
 
37
 
 
38
static GArray *bonobo_application_hooks = NULL;
 
39
 
 
40
/*
 
41
 * A pointer to our parent object class
 
42
 */
 
43
static gpointer parent_class;
 
44
 
 
45
 
 
46
/* ------------ Forward function declarations ------------ */
 
47
static void     bonobo_application_invoke_hooks (BonoboApplication *app);
 
48
 
 
49
 
 
50
static void bonobo_app_message_desc_free (BonoboAppMessageDesc *msgdesc)
 
51
{
 
52
        if (msgdesc->closure)
 
53
                g_closure_unref (msgdesc->closure);
 
54
        g_free (msgdesc);
 
55
}
 
56
 
 
57
 
 
58
static gboolean
 
59
_bonobo_application_message_accumulator(GSignalInvocationHint *ihint, 
 
60
                                        GValue                *return_accu, 
 
61
                                        const GValue          *handler_return, 
 
62
                                        gpointer               dummy)
 
63
{
 
64
        gboolean null_gvalue;
 
65
 
 
66
        null_gvalue = (G_VALUE_HOLDS (handler_return, G_TYPE_VALUE) &&
 
67
                       (g_value_peek_pointer (handler_return) == NULL));
 
68
 
 
69
        if (!null_gvalue) {
 
70
                g_value_copy (handler_return, return_accu);
 
71
                return FALSE;   /* stop emission */
 
72
        }
 
73
        return TRUE;            /* continue emission */
 
74
}
 
75
 
 
76
 
 
77
 
 
78
static void
 
79
bonobo_application_finalize (GObject *object)
 
80
{
 
81
        BonoboApplication *self = BONOBO_APPLICATION (object);
 
82
 
 
83
        if (self->message_list) {
 
84
                g_slist_foreach (self->message_list, (GFunc) CORBA_free, NULL);
 
85
                g_slist_free (self->message_list);
 
86
                self->message_list = NULL;
 
87
        }
 
88
 
 
89
        if (self->name) {
 
90
                g_free (self->name);
 
91
                self->name = NULL;
 
92
        }
 
93
 
 
94
        if (self->closure_hash) {
 
95
                g_hash_table_destroy (self->closure_hash);
 
96
                self->closure_hash = NULL;
 
97
        }
 
98
 
 
99
        G_OBJECT_CLASS (parent_class)->finalize (object);
 
100
}
 
101
 
 
102
 
 
103
static CORBA_any *
 
104
impl_Bonobo_Application_message (PortableServer_Servant            servant,
 
105
                                 const CORBA_char                 *msg,
 
106
                                 const Bonobo_Application_ArgList *args,
 
107
                                 CORBA_Environment                *ev)
 
108
{
 
109
        BonoboApplication  *app = BONOBO_APPLICATION (bonobo_object (servant));
 
110
        GValue             *signal_return = NULL;
 
111
        GValueArray        *signal_args;
 
112
        int                 i;
 
113
        CORBA_any          *rv;
 
114
        GValue              value;
 
115
 
 
116
        signal_args = g_value_array_new (args->_length);
 
117
        memset (&value, 0, sizeof (value));
 
118
        for (i = 0; i < args->_length; ++i) {
 
119
                if (bonobo_arg_to_gvalue_alloc (&args->_buffer [i], &value)) {
 
120
                        g_value_array_append (signal_args, &value);
 
121
                        g_value_unset (&value);
 
122
                } else {
 
123
                        g_warning ("Failed to convert type '%s' to GValue",
 
124
                                   args->_buffer[i]._type->name);
 
125
                }
 
126
        }
 
127
 
 
128
        g_signal_emit (app, signals [MESSAGE],
 
129
                       g_quark_from_string (msg),
 
130
                       msg, signal_args, &signal_return);
 
131
 
 
132
        g_value_array_free (signal_args);
 
133
        rv = CORBA_any__alloc ();
 
134
        if (signal_return) {
 
135
                if (!bonobo_arg_from_gvalue_alloc (rv, signal_return)) {
 
136
                        g_warning ("Failed to convert type '%s' to CORBA::any",
 
137
                                   g_type_name (G_VALUE_TYPE (signal_return)));
 
138
                        rv->_type = TC_void;
 
139
                }
 
140
                g_value_unset (signal_return);
 
141
                g_free (signal_return);
 
142
        } else
 
143
                rv->_type = TC_void;
 
144
 
 
145
        return rv;
 
146
}
 
147
 
 
148
/**
 
149
 * bonobo_application_new_instance:
 
150
 * @app: a #BonoboApplication
 
151
 * @argc: number of elements in @argv
 
152
 * @argv: array of strings (command-line arguments)
 
153
 * 
 
154
 * Emit the "new-instance" signal of the #BonoboApplication with the
 
155
 * given arguments.
 
156
 * 
 
157
 * Return value: signal return value
 
158
 **/
 
159
gint bonobo_application_new_instance (BonoboApplication *app,
 
160
                                      gint               argc,
 
161
                                      gchar             *argv[])
 
162
{
 
163
        gint         rv;
 
164
        gchar **new_argv = g_new (gchar *, argc + 1);
 
165
 
 
166
        memcpy (new_argv, argv, argc * sizeof(gchar *));
 
167
        new_argv[argc] = NULL;
 
168
        g_signal_emit (app, signals [NEW_INSTANCE], 0,
 
169
                       argc, new_argv, &rv);
 
170
        g_free (new_argv);
 
171
        return rv;
 
172
}
 
173
 
 
174
static GValue *
 
175
bonobo_application_run_closures (BonoboApplication *self,
 
176
                                 const char        *name,
 
177
                                 GValueArray       *args)
 
178
{
 
179
        BonoboAppMessageDesc *desc;
 
180
 
 
181
        desc = g_hash_table_lookup (self->closure_hash, name);
 
182
 
 
183
        if (desc) {
 
184
                GValue *retval = g_new0 (GValue, 1);
 
185
                GValue *params = g_newa (GValue, args->n_values + 1);
 
186
 
 
187
                memset (params + 0, 0, sizeof (GValue));
 
188
                g_value_init (params + 0, G_TYPE_OBJECT);
 
189
                g_value_set_object (params + 0, self);
 
190
                memcpy (params + 1, args->values, args->n_values * sizeof (GValue));
 
191
                g_value_init (retval, desc->return_type);
 
192
                g_closure_invoke (desc->closure, retval, args->n_values + 1,
 
193
                                  params, NULL /* invocation_hint */);
 
194
                g_value_unset (params + 0);
 
195
                return retval;
 
196
        }
 
197
 
 
198
        return NULL;
 
199
}
 
200
 
 
201
  /* Handle the "new-instance" standard message */
 
202
static GValue *
 
203
bonobo_application_real_message (BonoboApplication *app,
 
204
                                 const char        *name,
 
205
                                 GValueArray       *args)
 
206
{
 
207
        return bonobo_application_run_closures (app, name, args);
 
208
}
 
209
 
 
210
 
 
211
static CORBA_long
 
212
impl_Bonobo_Application_newInstance (PortableServer_Servant           servant,
 
213
                                     Bonobo_Application_argv_t const *argv,
 
214
                                     CORBA_Environment               *ev)
 
215
{
 
216
        BonoboApplication *app = BONOBO_APPLICATION (bonobo_object (servant));
 
217
        CORBA_long         retval;
 
218
 
 
219
        retval = bonobo_application_new_instance
 
220
                (app, argv->_length, argv->_buffer);
 
221
        return retval;
 
222
}
 
223
 
 
224
static inline void
 
225
message_desc_copy (Bonobo_Application_MessageDesc *dest,
 
226
                   Bonobo_Application_MessageDesc *src)
 
227
{
 
228
        dest->name           = CORBA_string_dup (src->name);
 
229
        dest->return_type    = src->return_type;
 
230
        dest->types._buffer  = src->types._buffer;
 
231
        dest->types._length  = src->types._length;
 
232
        dest->types._maximum = src->types._maximum;
 
233
        dest->types._release = CORBA_FALSE;
 
234
        dest->description    = CORBA_string_dup (src->description);
 
235
}
 
236
 
 
237
 
 
238
static Bonobo_Application_MessageList *
 
239
impl_Bonobo_Application_listMessages (PortableServer_Servant  servant,
 
240
                                      CORBA_Environment      *ev)
 
241
{
 
242
        BonoboApplication *app = BONOBO_APPLICATION (bonobo_object (servant));
 
243
        int                nmessages;
 
244
        GSList            *l;
 
245
        int                i;
 
246
        Bonobo_Application_MessageList *msglist;
 
247
 
 
248
        nmessages = g_slist_length (app->message_list);
 
249
        msglist = Bonobo_Application_MessageList__alloc ();
 
250
        msglist->_length = msglist->_maximum = nmessages;
 
251
        msglist->_buffer = Bonobo_Application_MessageList_allocbuf (nmessages);
 
252
        for (l = app->message_list, i = 0; l; l = l->next, ++i)
 
253
                message_desc_copy (&msglist->_buffer [i],
 
254
                                   (Bonobo_Application_MessageDesc *) l->data);
 
255
        CORBA_sequence_set_release (msglist, CORBA_TRUE);
 
256
        return msglist;
 
257
}
 
258
 
 
259
static CORBA_string
 
260
impl_Bonobo_Application_getName (PortableServer_Servant  servant,
 
261
                                 CORBA_Environment      *ev)
 
262
{
 
263
        BonoboApplication *app = BONOBO_APPLICATION (bonobo_object (servant));
 
264
        return CORBA_string_dup (app->name);
 
265
}
 
266
 
 
267
static void
 
268
set_property (GObject      *g_object,
 
269
              guint         prop_id,
 
270
              const GValue *value,
 
271
              GParamSpec   *pspec)
 
272
{
 
273
        BonoboApplication *self = (BonoboApplication *) g_object;
 
274
 
 
275
        switch (prop_id) {
 
276
        case PROP_NAME:
 
277
                if (self->name) g_free (self->name);
 
278
                self->name = g_strdup (g_value_get_string (value));
 
279
                break;
 
280
        default:
 
281
                break;
 
282
        }
 
283
}
 
284
 
 
285
static void
 
286
get_property (GObject    *object,
 
287
              guint       prop_id,
 
288
              GValue     *value,
 
289
              GParamSpec *pspec)
 
290
{
 
291
        BonoboApplication *self = (BonoboApplication *) object;
 
292
 
 
293
        switch (prop_id) {
 
294
        case PROP_NAME:
 
295
                g_value_set_string (value, self->name);
 
296
                break;
 
297
        default:
 
298
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
299
                break;
 
300
        }
 
301
}
 
302
 
 
303
static GObject *
 
304
bonobo_application_constructor (GType                  type,
 
305
                                guint                  n_construct_properties,
 
306
                                GObjectConstructParam *construct_properties)
 
307
{
 
308
        GObject           *object;
 
309
        BonoboApplication *self;
 
310
 
 
311
        object = G_OBJECT_CLASS (parent_class)->constructor
 
312
                (type, n_construct_properties, construct_properties);
 
313
        self = BONOBO_APPLICATION (object);
 
314
        bonobo_application_invoke_hooks (self);
 
315
        return object;
 
316
}
 
317
 
 
318
static void
 
319
bonobo_application_class_init (BonoboApplicationClass *klass)
 
320
{
 
321
        GObjectClass *object_class = (GObjectClass *) klass;
 
322
        POA_Bonobo_Application__epv *epv = &klass->epv;
 
323
 
 
324
        parent_class = g_type_class_peek_parent (klass);
 
325
 
 
326
        object_class->finalize     = bonobo_application_finalize;
 
327
        object_class->constructor  = bonobo_application_constructor;
 
328
        object_class->set_property = set_property;
 
329
        object_class->get_property = get_property;
 
330
 
 
331
        signals [MESSAGE] = g_signal_new (
 
332
                "message", BONOBO_TYPE_APPLICATION,
 
333
                G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
 
334
                G_STRUCT_OFFSET (BonoboApplicationClass, message),
 
335
                _bonobo_application_message_accumulator, NULL,
 
336
                bonobo_marshal_BOXED__STRING_BOXED,
 
337
                G_TYPE_VALUE, 2, /* return_type, nparams */
 
338
                G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
 
339
                G_TYPE_VALUE_ARRAY);
 
340
 
 
341
        signals [NEW_INSTANCE] = g_signal_new (
 
342
                "new-instance", BONOBO_TYPE_APPLICATION, G_SIGNAL_RUN_LAST,
 
343
                G_STRUCT_OFFSET (BonoboApplicationClass, new_instance),
 
344
                NULL, NULL,     /* accumulator and accumulator data */
 
345
                bonobo_marshal_INT__INT_BOXED,
 
346
                G_TYPE_INT, 2, /* return_type, nparams */
 
347
                G_TYPE_INT, G_TYPE_STRV);
 
348
 
 
349
        g_object_class_install_property
 
350
                (object_class, PROP_NAME,
 
351
                 g_param_spec_string
 
352
                 ("name", _("Name"), _("Application unique name"), NULL,
 
353
                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
354
 
 
355
        klass->message = bonobo_application_real_message;
 
356
 
 
357
        epv->message      = impl_Bonobo_Application_message;
 
358
        epv->listMessages = impl_Bonobo_Application_listMessages;
 
359
        epv->newInstance  = impl_Bonobo_Application_newInstance;
 
360
        epv->getName      = impl_Bonobo_Application_getName;
 
361
}
 
362
 
 
363
static void
 
364
bonobo_application_init (BonoboApplication *self)
 
365
{
 
366
        self->closure_hash = g_hash_table_new_full
 
367
                (g_str_hash, g_str_equal,
 
368
                 g_free,(GDestroyNotify) bonobo_app_message_desc_free);
 
369
}
 
370
 
 
371
BONOBO_TYPE_FUNC_FULL (BonoboApplication,
 
372
                       Bonobo_Application,
 
373
                       BONOBO_TYPE_OBJECT,
 
374
                       bonobo_application)
 
375
 
 
376
 
 
377
/**
 
378
 * bonobo_application_new:
 
379
 * @name: application name
 
380
 * 
 
381
 * Creates a new #BonoboApplication object.
 
382
 * 
 
383
 * Return value: a new #BonoboApplication
 
384
 **/
 
385
BonoboApplication *
 
386
bonobo_application_new (const char *name)
 
387
{
 
388
        GObject           *obj;
 
389
        BonoboApplication *app;
 
390
 
 
391
        obj = g_object_new (BONOBO_TYPE_APPLICATION,
 
392
                            "poa", bonobo_poa_get_threaded (ORBIT_THREAD_HINT_ALL_AT_IDLE),
 
393
                            "name", name,
 
394
                            NULL);
 
395
        app = (BonoboApplication *) obj;
 
396
        return app;
 
397
}
 
398
 
 
399
static inline CORBA_TypeCode
 
400
_gtype_to_typecode (GType gtype)
 
401
{
 
402
        static GHashTable *hash = NULL;
 
403
 
 
404
        if (!hash) {
 
405
                hash = g_hash_table_new (g_direct_hash, g_direct_equal);
 
406
#define mapping(gtype_, corba_type)\
 
407
                g_hash_table_insert (hash, GUINT_TO_POINTER (gtype_), corba_type);
 
408
                
 
409
                mapping (G_TYPE_NONE,    TC_void);
 
410
                mapping (G_TYPE_BOOLEAN, TC_CORBA_boolean);
 
411
                mapping (G_TYPE_INT,     TC_CORBA_long);
 
412
                mapping (G_TYPE_UINT,    TC_CORBA_unsigned_long);
 
413
                mapping (G_TYPE_LONG,    TC_CORBA_long);
 
414
                mapping (G_TYPE_ULONG,   TC_CORBA_unsigned_long);
 
415
                mapping (G_TYPE_FLOAT,   TC_CORBA_float);
 
416
                mapping (G_TYPE_DOUBLE,  TC_CORBA_double);
 
417
                mapping (G_TYPE_STRING,  TC_CORBA_string);
 
418
                
 
419
                mapping (BONOBO_TYPE_CORBA_ANY,  TC_CORBA_any);
 
420
#undef mapping
 
421
        }
 
422
        return (CORBA_TypeCode) g_hash_table_lookup (hash, GUINT_TO_POINTER (G_TYPE_INT));
 
423
}
 
424
 
 
425
/**
 
426
 * bonobo_application_register_message_v:
 
427
 * @app: a #BonoboApplication
 
428
 * @name: message string identifier
 
429
 * @description: a string containing a human readable description of the message
 
430
 * @opt_closure: a #GClosure that will be called for this message, or %NULL;
 
431
 * Function takes ownership of this closure.
 
432
 * @return_type: Message return #GType.
 
433
 * @arg_types: %G_TYPE_NONE -terminated vector of argument #GType's
 
434
 * 
 
435
 * See bonobo_application_register_message().
 
436
 **/
 
437
void
 
438
bonobo_application_register_message_v (BonoboApplication *app,
 
439
                                       const gchar       *name,
 
440
                                       const gchar       *description,
 
441
                                       GClosure          *opt_closure,
 
442
                                       GType              return_type,
 
443
                                       GType const        arg_types[])
 
444
{
 
445
        Bonobo_Application_MessageDesc *msgdesc;
 
446
        int i, arg_types_len;
 
447
 
 
448
        for (arg_types_len = -1; arg_types[++arg_types_len] != G_TYPE_NONE;);
 
449
 
 
450
        msgdesc = Bonobo_Application_MessageDesc__alloc ();
 
451
 
 
452
        msgdesc->return_type = _gtype_to_typecode (return_type);
 
453
        msgdesc->name        = CORBA_string_dup (name);
 
454
        msgdesc->description = CORBA_string_dup (description);
 
455
 
 
456
        msgdesc->types._length = msgdesc->types._maximum = arg_types_len;
 
457
        msgdesc->types._buffer =
 
458
                CORBA_sequence_CORBA_TypeCode_allocbuf (arg_types_len);
 
459
 
 
460
        for (i = 0; arg_types[i] != G_TYPE_NONE; ++i)
 
461
                msgdesc->types._buffer[i] = _gtype_to_typecode (arg_types[i]);
 
462
 
 
463
        app->message_list = g_slist_prepend (app->message_list, msgdesc);
 
464
 
 
465
        if (opt_closure) {
 
466
                BonoboAppMessageDesc *desc = g_new0 (BonoboAppMessageDesc, 1);
 
467
                g_closure_ref (opt_closure);
 
468
                g_closure_sink (opt_closure);
 
469
                desc->closure = opt_closure;
 
470
                desc->return_type = return_type;
 
471
                g_hash_table_insert (app->closure_hash, g_strdup (name), desc);
 
472
        }
 
473
}
 
474
 
 
475
 
 
476
/**
 
477
 * bonobo_application_register_message_va:
 
478
 * @app: a #BonoboApplication
 
479
 * @name: message string identifier
 
480
 * @description: a string containing a human readable description of the message
 
481
 * @opt_closure: a #GClosure that will be called for this message, or
 
482
 * %NULL; Function takes ownership of this closure.
 
483
 * @return_type: Message return #GType.
 
484
 * @first_arg_type: #GType of first argument of message, or %G_TYPE_NONE
 
485
 * @var_args: %G_TYPE_NONE -terminated valist of argument #GType's
 
486
 * 
 
487
 * See bonobo_application_register_message().
 
488
 **/
 
489
void
 
490
bonobo_application_register_message_va (BonoboApplication *app,
 
491
                                        const gchar       *name,
 
492
                                        const gchar       *description,
 
493
                                        GClosure          *opt_closure,
 
494
                                        GType              return_type,
 
495
                                        GType              first_arg_type,
 
496
                                        va_list            var_args)
 
497
{
 
498
        GArray *arg_types;
 
499
        GType   gtype;
 
500
 
 
501
        arg_types = g_array_new (FALSE, FALSE, sizeof(GType));
 
502
        if (first_arg_type != G_TYPE_NONE) {
 
503
                g_array_append_val (arg_types, first_arg_type);
 
504
                while ((gtype = va_arg (var_args, GType)) != G_TYPE_NONE)
 
505
                        g_array_append_val (arg_types, gtype);
 
506
        }
 
507
        gtype = G_TYPE_NONE; g_array_append_val (arg_types, gtype);
 
508
 
 
509
        bonobo_application_register_message_v (app, name, description,
 
510
                                               opt_closure, return_type,
 
511
                                               (const GType *) arg_types->data);
 
512
 
 
513
        g_array_free (arg_types, TRUE);
 
514
}
 
515
 
 
516
/**
 
517
 * bonobo_application_register_message:
 
518
 * @app: a #BonoboApplication
 
519
 * @name: message string identifier
 
520
 * @description: a string containing a human readable description of the message
 
521
 * @opt_closure: a #GClosure that will be called for this message, or
 
522
 * %NULL; Function takes ownership of this closure.
 
523
 * @return_type: Message return #GType.
 
524
 * @first_arg_type: #GType of first argument of message, or %G_TYPE_NONE.
 
525
 * @...: %G_TYPE_NONE -terminated list of argument #GType's
 
526
 * 
 
527
 * Registers a new message type that the application supports.
 
528
 **/
 
529
void
 
530
bonobo_application_register_message (BonoboApplication *app,
 
531
                                     const gchar       *name,
 
532
                                     const gchar       *description,
 
533
                                     GClosure          *opt_closure,
 
534
                                     GType              return_type,
 
535
                                     GType              first_arg_type,
 
536
                                     ...)
 
537
{
 
538
        va_list var_args;
 
539
 
 
540
        va_start (var_args, first_arg_type);
 
541
        bonobo_application_register_message_va (app, name, description,
 
542
                                                opt_closure, return_type,
 
543
                                                first_arg_type, var_args);
 
544
        va_end (var_args);
 
545
}
 
546
 
 
547
 
 
548
/**
 
549
 * bonobo_application_create_serverinfo:
 
550
 * @app: a #BonoboApplication
 
551
 * @envp: %NULL-terminated string vector, containing the enviroment
 
552
 * variables we wish to include in the server description.
 
553
 * 
 
554
 * This utility function provides a simple way to contruct a valid
 
555
 * serverinfo XML string.
 
556
 * 
 
557
 * Return value: a newly allocated string; caller must g_free() it.
 
558
 **/
 
559
gchar *
 
560
bonobo_application_create_serverinfo (BonoboApplication *app,
 
561
                                      gchar const       *envp[])
 
562
{
 
563
        GString *description;
 
564
        int      i;
 
565
        gchar   *rv;
 
566
 
 
567
        description = g_string_new ("<oaf_info>\n");
 
568
        g_string_append_printf (description,
 
569
                "  <oaf_server iid=\"OAFIID:%s\" location=\"unknown\" type=\"runtime\">\n"
 
570
                "    <oaf_attribute name=\"repo_ids\" type=\"stringv\">\n"
 
571
                "       <item value=\"IDL:Bonobo/Unknown:1.0\"/>\n"
 
572
                "       <item value=\"IDL:Bonobo/Application:1.0\"/>\n"
 
573
                "    </oaf_attribute>\n"
 
574
                "    <oaf_attribute name=\"name\" type=\"string\" value=\"%s\"/>\n"
 
575
                "    <oaf_attribute name=\"description\" type=\"string\" "
 
576
                " value=\"%s application instance\"/>\n",
 
577
                app->name, app->name, app->name);
 
578
 
 
579
        if (envp && envp[0]) {
 
580
                g_string_append (description, "    <oaf_attribute name="
 
581
                                 "\"bonobo:environment\" type=\"stringv\">\n");
 
582
                for (i = 0; envp[i]; ++i)
 
583
                        g_string_append_printf (description,
 
584
                                                "       <item value=\"%s\"/>\n",
 
585
                                                envp[i]);
 
586
                g_string_append (description, "    </oaf_attribute>");
 
587
        }
 
588
        g_string_append (description,
 
589
                         "  </oaf_server>\n"
 
590
                         "</oaf_info>");
 
591
        rv = description->str;
 
592
        g_string_free (description, FALSE);
 
593
        return rv;
 
594
}
 
595
 
 
596
/**
 
597
 * bonobo_application_register_unique:
 
598
 * @app: a #BonoboApplication instance
 
599
 * @serverinfo: the XML server
 
600
 * description. bonobo_application_create_server_description() may be
 
601
 * used to easily create such description.
 
602
 * @client: output parameter that will contain a client object, in
 
603
 * case another instance has already running, or %NULL if we are the
 
604
 * first to register.
 
605
 * 
 
606
 * Try to register the running application, or check for an existing
 
607
 * application already registered and get a reference to it.
 
608
 * Applications already running but on different environments (as
 
609
 * defined by the bonobo:environenment server property) than this one
 
610
 * are ignored and do not interfere.
 
611
 *
 
612
 * If the registration attempt indicates that another instance of this
 
613
 * application is already running, then the output variable
 
614
 * @client will receive a newly created #BonoboAppClient
 
615
 * associated with the running application.  Otherwise, *@client is
 
616
 * set to %NULL.
 
617
 * 
 
618
 * Return value: the registration result.
 
619
 * %Bonobo_ACTIVATION_REG_SUCCESS means the application was registered,
 
620
 * since no other running instance was detected.  If, however, a
 
621
 * running application is detected,
 
622
 * %Bonobo_ACTIVATION_REG_ALREADY_ACTIVE is returned.
 
623
 **/
 
624
Bonobo_RegistrationResult
 
625
bonobo_application_register_unique (BonoboApplication  *app,
 
626
                                    gchar const        *serverinfo,
 
627
                                    BonoboAppClient   **client)
 
628
{
 
629
        Bonobo_RegistrationResult  reg_res;
 
630
        gchar                     *iid;
 
631
        CORBA_Object               remote_obj = CORBA_OBJECT_NIL;
 
632
        CORBA_Environment          ev;
 
633
        int                        tries = 10;
 
634
 
 
635
        g_return_val_if_fail (app, Bonobo_ACTIVATION_REG_ERROR);
 
636
        g_return_val_if_fail (BONOBO_IS_APPLICATION (app), Bonobo_ACTIVATION_REG_ERROR);
 
637
        g_return_val_if_fail (serverinfo, Bonobo_ACTIVATION_REG_ERROR);
 
638
        g_return_val_if_fail (client, Bonobo_ACTIVATION_REG_ERROR);
 
639
 
 
640
        iid     = g_strdup_printf ("OAFIID:%s", app->name);
 
641
        *client = NULL;
 
642
        while (tries--)
 
643
        {
 
644
                reg_res = bonobo_activation_register_active_server_ext
 
645
                        (iid, bonobo_object_corba_objref (BONOBO_OBJECT (app)), NULL,
 
646
                         Bonobo_REGISTRATION_FLAG_NO_SERVERINFO, &remote_obj,
 
647
                         serverinfo);
 
648
                if (reg_res == Bonobo_ACTIVATION_REG_SUCCESS)
 
649
                        break;
 
650
                else if (reg_res == Bonobo_ACTIVATION_REG_ALREADY_ACTIVE) {
 
651
                        CORBA_exception_init (&ev);
 
652
                        Bonobo_Unknown_ref (remote_obj, &ev);
 
653
                        if (ev._major != CORBA_NO_EXCEPTION) {
 
654
                                  /* Likely cause: server has quit, leaving a
 
655
                                   * stale reference.  Solution: keep trying
 
656
                                   * to register as application server. */
 
657
                                CORBA_exception_free (&ev);
 
658
                                continue;
 
659
                        }
 
660
                        *client = bonobo_app_client_new ((Bonobo_Application) remote_obj);
 
661
                        break;
 
662
                }
 
663
        }
 
664
        g_free (iid);
 
665
        return reg_res;
 
666
}
 
667
 
 
668
 
 
669
/**
 
670
 * bonobo_application_add_hook:
 
671
 * @func: hook function
 
672
 * @data: user data
 
673
 * 
 
674
 * Add a hook function to be called whenever a new #BonoboApplication
 
675
 * instance is created.
 
676
 **/
 
677
void bonobo_application_add_hook (BonoboAppHookFunc func, gpointer data)
 
678
{
 
679
        BonoboAppHook hook;
 
680
 
 
681
        if (bonobo_application_hooks == NULL)
 
682
                bonobo_application_hooks = g_array_new (FALSE, FALSE, sizeof (BonoboAppHook));
 
683
        
 
684
        hook.func = func;
 
685
        hook.data = data;
 
686
        g_array_append_val (bonobo_application_hooks, hook);
 
687
}
 
688
 
 
689
 
 
690
/**
 
691
 * bonobo_application_remove_hook:
 
692
 * @func: hook function
 
693
 * @data: user data
 
694
 * 
 
695
 * Removes a hook function previously set with bonobo_application_add_hook().
 
696
 **/
 
697
void bonobo_application_remove_hook (BonoboAppHookFunc func, gpointer data)
 
698
{
 
699
        BonoboAppHook *hook;
 
700
        int            i;
 
701
 
 
702
        g_return_if_fail (bonobo_application_hooks);
 
703
 
 
704
        for (i = 0; i < bonobo_application_hooks->len; ++i) {
 
705
                hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
 
706
                if (hook->func == func && hook->data == data) {
 
707
                        g_array_remove_index (bonobo_application_hooks, i);
 
708
                        return;
 
709
                }
 
710
        }
 
711
 
 
712
        g_warning ("bonobo_application_remove_hook: "
 
713
                   "(func, data) == (%p, %p) not found.", func, data);
 
714
}
 
715
 
 
716
 
 
717
static void
 
718
bonobo_application_invoke_hooks (BonoboApplication *app)
 
719
{
 
720
        BonoboAppHook *hook;
 
721
        int            i;
 
722
 
 
723
        if (!bonobo_application_hooks)
 
724
                return;
 
725
 
 
726
        for (i = 0; i < bonobo_application_hooks->len; ++i) {
 
727
                hook = &g_array_index (bonobo_application_hooks, BonoboAppHook, i);
 
728
                hook->func (app, hook->data);
 
729
        }
 
730
}
 
731