* ALL: bumped version number to 0.6.3-cvs
[vlc.git] / modules / control / corba / corba.c
1 /*****************************************************************************
2  * corba.c : CORBA (ORBit) remote control plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: corba.c,v 1.2 2003/07/23 01:13:47 gbazin Exp $
6  *
7  * Authors: Olivier Aubert <oaubert at lisi dot univ-lyon1 dot fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 /* For CORBA */
28 #include "mediacontrol.h"
29 #include "orbit/poa/portableserver-poa-type.h"
30 #define VLC_IOR_FILE "/tmp/vlc-ior.ref"
31
32 #define handle_exception(m) if(ev->_major != CORBA_NO_EXCEPTION) \
33     { \
34       msg_Err (servant->p_intf, m); \
35       return; \
36     }
37
38
39 #define handle_exception_no_servant(p,m) if(ev->_major != CORBA_NO_EXCEPTION) \
40     { \
41       msg_Err (p, m); \
42       return; \
43     }
44
45 #include <vlc/vlc.h>
46 #include <vlc/intf.h>
47 #include <vlc/vout.h>
48 #include <vlc/aout.h>
49
50 #include <stdlib.h>                                      /* malloc(), free() */
51 #include <string.h>
52
53 #include <errno.h>                                                 /* ENOMEM */
54 #include <stdio.h>
55 #include <ctype.h>
56
57 #ifdef HAVE_UNISTD_H
58 #    include <unistd.h>
59 #endif
60
61 #ifdef HAVE_SYS_TIME_H
62 #    include <sys/time.h>
63 #endif
64 #include <sys/types.h>
65
66 /*****************************************************************************
67  * intf_sys_t: description and status of corba interface
68  *****************************************************************************/
69 struct intf_sys_t
70 {
71   CORBA_ORB                 orb;
72   VLC_MediaControl          mc;
73   PortableServer_POA        root_poa;
74   PortableServer_POAManager root_poa_manager;
75   GMainLoop*                corbaloop;
76
77   vlc_bool_t          b_playing;
78
79   input_thread_t *    p_input;                /* The input thread */
80
81   msg_subscription_t* p_sub;                  /* message bank subscription */
82 };
83
84 /* Convert an offset into seconds. Taken from input_ext-intf.c.
85    The 50 hardcoded constant comes from the definition of i_mux_rate :
86    i_mux_rate : the rate we read the stream (in units of 50 bytes/s) ;
87    0 if undef */
88 long long offsetToSeconds (input_thread_t *p_input, off_t l_offset)
89 {
90   long long l_res;
91
92   l_res = -1;
93   if (p_input != NULL && p_input->stream.i_mux_rate != 0)
94     {
95       l_res = (long long) l_offset / 50 / p_input->stream.i_mux_rate;
96     }
97   return l_res;
98 }
99
100 /* Convert an offset into milliseconds */
101 long long offsetToMilliseconds (input_thread_t *p_input, off_t l_offset)
102 {
103   long long l_res;
104
105   l_res = -1;
106   if (p_input != NULL && p_input->stream.i_mux_rate != 0)
107     {
108       l_res = (long long) 1000 * l_offset / 50 / p_input->stream.i_mux_rate;
109     }
110   return l_res;
111 }
112
113 /* Convert seconds to an offset */
114 off_t secondsToOffset (input_thread_t *p_input, long long l_seconds)
115 {
116   off_t l_res;
117
118   l_res = -1;
119
120   if (p_input != NULL)
121     {
122       l_res = (off_t) l_seconds * 50 * p_input->stream.i_mux_rate;
123     }
124   return l_res;
125 }
126
127
128 /* Convert milliseconds to an offset */
129 off_t millisecondsToOffset (input_thread_t *p_input, long long l_milliseconds)
130 {
131   off_t l_res;
132
133   l_res = -1;
134   if (p_input != NULL)
135     {
136       l_res = (off_t) l_milliseconds * 50 * p_input->stream.i_mux_rate / 1000;
137     }
138   return l_res;
139 }
140
141 /* Returns the current offset. */
142 off_t currentOffset (input_thread_t *p_input)
143 {
144   off_t l_offset;
145
146   if( p_input == NULL )
147     {
148       return -1;
149     }
150
151   /* offset contient la valeur en unités arbitraires (cf
152      include/input_ext-intf.h) */
153   vlc_mutex_lock( &p_input->stream.stream_lock );
154
155 #define A p_input->stream.p_selected_area
156   l_offset = A->i_tell + A->i_start;
157 #undef A
158   vlc_mutex_unlock( &p_input->stream.stream_lock );
159
160   return l_offset;
161 }
162
163 /*** App-specific servant structures ***/
164
165 /* We can add attributes to this structure, which is both a pointer on a
166    specific structure, and on a POA_VLC_MediaControl (servant). Cf
167    http://developer.gnome.org/doc/guides/corba/html/corba-poa-example.html */
168
169 typedef struct
170 {
171   POA_VLC_MediaControl servant;
172   PortableServer_POA poa;
173   /* Ajouter ici les attributs utiles */
174   intf_thread_t *p_intf;
175 }
176 impl_POA_VLC_MediaControl;
177
178 /* Beginning of the CORBA code generated in Mediacontrol-skelimpl.c */
179 /* BEGIN INSERT */
180
181 /*** Implementation stub prototypes ***/
182
183 static void impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl *
184                                            servant, CORBA_Environment * ev);
185
186 static VLC_Position
187 impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant,
188                                          const VLC_PositionOrigin an_origin,
189                                          const VLC_PositionKey a_key,
190                                          CORBA_Environment * ev);
191
192 static void
193 impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant,
194                                          const VLC_Position * a_position,
195                                          CORBA_Environment * ev);
196
197 static void
198 impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant,
199                             const VLC_Position * a_position,
200                             CORBA_Environment * ev);
201
202 static void
203 impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant,
204                             const VLC_Position * a_position,
205                             CORBA_Environment * ev);
206
207 static void
208 impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant,
209                              const VLC_Position * a_position,
210                              CORBA_Environment * ev);
211
212 static void
213 impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant,
214                            const VLC_Position * a_position,
215                            CORBA_Environment * ev);
216
217 static void
218 impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
219                            CORBA_Environment * ev);
220
221 static void
222 impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant,
223                                       const CORBA_char * a_file,
224                                       CORBA_Environment * ev);
225
226 static VLC_PlaylistSeq
227    *impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant,
228                                        CORBA_Environment * ev);
229
230 /*** epv structures ***/
231
232 static PortableServer_ServantBase__epv impl_VLC_MediaControl_base_epv = {
233    NULL,                        /* _private data */
234    NULL,                        /* finalize routine */
235    NULL,                        /* default_POA routine */
236 };
237 static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = {
238    NULL,                        /* _private */
239
240    (gpointer) & impl_VLC_MediaControl_get_media_position,
241
242    (gpointer) & impl_VLC_MediaControl_set_media_position,
243
244    (gpointer) & impl_VLC_MediaControl_start,
245
246    (gpointer) & impl_VLC_MediaControl_pause,
247
248    (gpointer) & impl_VLC_MediaControl_resume,
249
250    (gpointer) & impl_VLC_MediaControl_stop,
251
252    (gpointer) & impl_VLC_MediaControl_exit,
253
254    (gpointer) & impl_VLC_MediaControl_add_to_playlist,
255
256    (gpointer) & impl_VLC_MediaControl_get_playlist,
257
258 };
259
260 /*** vepv structures ***/
261
262 static POA_VLC_MediaControl__vepv impl_VLC_MediaControl_vepv = {
263    &impl_VLC_MediaControl_base_epv,
264    &impl_VLC_MediaControl_epv,
265 };
266
267 /*** Stub implementations ***/
268
269 static VLC_MediaControl
270 impl_VLC_MediaControl__create(PortableServer_POA poa, CORBA_Environment * ev)
271 {
272    VLC_MediaControl retval;
273    impl_POA_VLC_MediaControl *newservant;
274    PortableServer_ObjectId *objid;
275
276    newservant = g_new0(impl_POA_VLC_MediaControl, 1);
277    newservant->servant.vepv = &impl_VLC_MediaControl_vepv;
278    newservant->poa = poa;
279    POA_VLC_MediaControl__init((PortableServer_Servant) newservant, ev);
280    objid = PortableServer_POA_activate_object(poa, newservant, ev);
281    CORBA_free(objid);
282    retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
283
284    return retval;
285 }
286
287 static void
288 impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl * servant,
289                                CORBA_Environment * ev)
290 {
291    PortableServer_ObjectId *objid;
292
293    objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
294    PortableServer_POA_deactivate_object(servant->poa, objid, ev);
295    CORBA_free(objid);
296
297    POA_VLC_MediaControl__fini((PortableServer_Servant) servant, ev);
298    g_free(servant);
299 }
300
301 /* END INSERT */
302 /* Beginning of the CORBA functions that we define */
303
304 /* Returns the current position in the stream. The returned value can
305    be relative or absolute (according to PositionOrigin) and the unit
306    is set by PositionKey */
307 static VLC_Position
308 impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant,
309                                      const VLC_PositionOrigin an_origin,
310                                      const VLC_PositionKey a_key,
311                                      CORBA_Environment * ev)
312 {
313   VLC_Position retval;
314   off_t l_offset;
315   VLC_PositionKeyNotSupported *exception;
316   input_thread_t * p_input = servant->p_intf->p_sys->p_input;
317
318   /*  msg_Warn (servant->p_intf, "Calling MediaControl::get_media_position"); */
319
320   retval.origin = an_origin;
321   retval.key = a_key;
322
323   if ( an_origin == VLC_RelativePosition
324        || an_origin == VLC_ModuloPosition )
325     {
326       /* Relative or ModuloPosition make no sense */
327       /* FIXME: should we return 0 or raise an exception ? */
328       retval.value = 0;
329       return retval;
330     }
331
332   if ( p_input == NULL )
333     {
334       /* FIXME: should we return 0 or raise an exception ? */
335       retval.value = 0;
336       return retval;
337     }
338
339   /* We are asked for an AbsolutePosition. */
340   /* Cf plugins/gtk/gtk_display.c */
341
342   /* The lock is taken by the currentOffset function */
343   l_offset = currentOffset (p_input);
344
345   if (a_key == VLC_ByteCount)
346     {
347       retval.value = l_offset;
348       return retval;
349     }
350   if (a_key == VLC_MediaTime)
351     {
352       retval.value = offsetToSeconds (p_input, l_offset);
353       return retval;
354     }
355   if (a_key == VLC_SampleCount)
356     {
357       /* Raising exceptions in C : cf the good explanations in
358          http://developer.gnome.org/doc/guides/corba/html/corba-module-complete-helloworld.html
359       */
360       exception = VLC_PositionKeyNotSupported__alloc ();
361       memcpy (&exception->key, &a_key, sizeof (a_key));
362       CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
363                            ex_VLC_PositionKeyNotSupported,
364                            exception);
365       retval.value = 0;
366       return retval;
367     }
368
369   /* http://catb.org/~esr/jargon/html/entry/can't-happen.html */
370   return retval;
371 }
372
373 /* Sets the media position */
374 static void
375 impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant,
376                                          const VLC_Position * a_position,
377                                          CORBA_Environment * ev)
378 {
379   VLC_InvalidPosition *pe_exception;
380   VLC_PositionKeyNotSupported *pe_key_exception;
381   off_t l_offset_destination = 0;
382   int i_whence = 0;
383   input_thread_t * p_input = servant->p_intf->p_sys->p_input;
384
385   msg_Warn (servant->p_intf, "Calling MediaControl::set_media_position");
386
387   if( p_input == NULL )
388       return;
389
390   if ( !p_input->stream.b_seekable )
391     {
392       pe_exception = VLC_InvalidPosition__alloc ();
393       memcpy (&pe_exception->key, &a_position->key, sizeof (&a_position->key));
394       CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
395                            ex_VLC_InvalidPosition,
396                            pe_exception);
397       return;
398     }
399
400   switch ( a_position->key )
401     {
402     case VLC_SampleCount:
403       /* The SampleCount unit is still a bit mysterious... */
404       pe_key_exception = VLC_PositionKeyNotSupported__alloc ();
405       memcpy (&pe_key_exception->key, &a_position->key, sizeof (&a_position->key));
406       CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
407                            ex_VLC_PositionKeyNotSupported,
408                            pe_key_exception);
409       return;
410       break;
411     case VLC_MediaTime:
412       i_whence |= INPUT_SEEK_SECONDS;
413       break;
414     case VLC_ByteCount:
415       i_whence |= INPUT_SEEK_BYTES;
416       break;
417     default:
418       i_whence |= INPUT_SEEK_BYTES;
419       break;
420     }
421
422   switch ( a_position->origin)
423     {
424     case VLC_RelativePosition:
425       i_whence |= INPUT_SEEK_CUR;
426       break;
427     case VLC_ModuloPosition:
428       i_whence |= INPUT_SEEK_END;
429       break;
430     case VLC_AbsolutePosition:
431       i_whence |= INPUT_SEEK_SET;
432       break;
433     default:
434       i_whence |= INPUT_SEEK_SET;
435       break;
436     }
437
438   l_offset_destination = a_position->value;
439
440   /* msg_Warn (servant->p_intf, "Offset destination : %d", l_offset_destination); */
441   /* Now we can set the position. The lock is taken in the input_Seek
442      function (cf input_ext-intf.c) */
443   input_Seek (p_input, l_offset_destination, i_whence);
444   return;
445 }
446
447 /* Starts playing a stream */
448 static void
449 impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant,
450                             const VLC_Position * a_position, CORBA_Environment * ev)
451 {
452   intf_thread_t *  p_intf = servant->p_intf;
453   playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
454                                              FIND_ANYWHERE );
455
456   msg_Warn (servant->p_intf, "Calling MediaControl::start");
457
458   if( p_playlist == NULL )
459     {
460       /* FIXME: we should raise an appropriate exception, but we must
461          define it in the IDL first */
462       msg_Err (servant->p_intf, "Error: no playlist available.");
463       return;
464     }
465
466     vlc_mutex_lock( &p_playlist->object_lock );
467     if( p_playlist->i_size )
468     {
469         vlc_mutex_unlock( &p_playlist->object_lock );
470         playlist_Play( p_playlist );
471         vlc_object_release( p_playlist );
472     }
473     else
474     {
475         vlc_mutex_unlock( &p_playlist->object_lock );
476         vlc_object_release( p_playlist );
477         msg_Err (servant->p_intf, "Error: playlist empty.");
478     }
479
480   return;
481 }
482
483 static void
484 impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant,
485                         const VLC_Position * a_position, CORBA_Environment * ev)
486 {
487   input_thread_t *p_input = servant->p_intf->p_sys->p_input;
488
489   msg_Warn (servant->p_intf, "Calling MediaControl::pause");
490
491   if( p_input != NULL )
492     {
493       input_SetStatus( p_input, INPUT_STATUS_PAUSE );
494     }
495
496     return;
497 }
498
499 static void
500 impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant,
501                          const VLC_Position * a_position, CORBA_Environment * ev)
502 {
503   input_thread_t *p_input = servant->p_intf->p_sys->p_input;
504
505   msg_Warn (servant->p_intf, "Calling MediaControl::resume");
506
507   if( p_input != NULL )
508     {
509       input_SetStatus( p_input, INPUT_STATUS_PAUSE );
510     }
511
512     return;
513 }
514
515 static void
516 impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant,
517                        const VLC_Position * a_position, CORBA_Environment * ev)
518 {
519   intf_thread_t *  p_intf = servant->p_intf;
520   playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
521                                              FIND_ANYWHERE );
522
523   msg_Warn (servant->p_intf, "Calling MediaControl::stop");
524
525   if( p_playlist != NULL )
526     {
527       playlist_Stop( p_playlist );
528       vlc_object_release( p_playlist );
529     }
530
531   return;
532 }
533
534 static void
535 impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
536                            CORBA_Environment * ev)
537 {
538   msg_Warn (servant->p_intf, "Calling MediaControl::exit");
539
540   vlc_mutex_lock( &servant->p_intf->change_lock );
541   servant->p_intf->b_die = TRUE;
542   vlc_mutex_unlock( &servant->p_intf->change_lock );
543 }
544
545 static void
546 impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant,
547                                       const CORBA_char * psz_file,
548                                       CORBA_Environment * ev)
549 {
550   intf_thread_t *  p_intf = servant->p_intf;
551   playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
552                                              FIND_ANYWHERE );
553
554   msg_Warn (servant->p_intf, "Calling MediaControl::add_to_playlist %s", psz_file);
555
556   if ( p_playlist == NULL )
557     {
558       msg_Err (servant->p_intf, "Error: no playlist defined");
559       /* FIXME: should return an exception */
560       return;
561     }
562
563   playlist_Add (p_playlist, psz_file, 0, 0, PLAYLIST_REPLACE, 0);
564   vlc_object_release( p_playlist );
565
566   return;
567 }
568
569 static VLC_PlaylistSeq *
570 impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant,
571                                    CORBA_Environment * ev)
572 {
573    VLC_PlaylistSeq *retval;
574    int i_index;
575    intf_thread_t *  p_intf = servant->p_intf;
576    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
577                                               FIND_ANYWHERE );
578    int i_playlist_size;
579
580    msg_Warn (servant->p_intf, "Calling MediaControl::get_playlist");
581
582    vlc_mutex_lock( &p_playlist->object_lock );
583    i_playlist_size = p_playlist->i_size;
584
585    retval = VLC_PlaylistSeq__alloc ();
586    retval->_buffer = VLC_PlaylistSeq_allocbuf (i_playlist_size);
587    retval->_length = i_playlist_size;
588
589    for (i_index = 0 ; i_index < i_playlist_size ; i_index++)
590      {
591        retval->_buffer[i_index] =
592          CORBA_string_dup (p_playlist->pp_items[i_index]->psz_name);
593      }
594    vlc_mutex_unlock( &p_playlist->object_lock );
595    vlc_object_release( p_playlist );
596
597    CORBA_sequence_set_release (retval, TRUE);
598    return retval;
599 }
600
601 /* (Real) end of the CORBA code generated in Mediacontrol-skelimpl.c */
602
603 /*****************************************************************************
604  * Local prototypes.
605  *****************************************************************************/
606 static int  Open         ( vlc_object_t * );
607 static void Close        ( vlc_object_t * );
608 static void Run          ( intf_thread_t * );
609
610 /*****************************************************************************
611  * Module descriptor
612  *****************************************************************************/
613 vlc_module_begin();
614     add_category_hint( N_("Corba control"), NULL, VLC_FALSE );
615     set_description( _("corba control module") );
616     set_capability( "interface", 10 );
617     set_callbacks( Open, Close );
618 vlc_module_end();
619
620 /*****************************************************************************
621  * intf_Open: initialize and create stuff
622  *****************************************************************************/
623 static int Open( vlc_object_t *p_this )
624 {
625   intf_thread_t *p_intf = (intf_thread_t *)p_this;
626
627   /* Allocate instance and initialize some members */
628   p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
629   if( p_intf->p_sys == NULL )
630     {
631       msg_Err( p_intf, "out of memory" );
632       return VLC_ENOMEM;
633     }
634
635   /* Initialize the fields of the p_intf struct */
636   p_intf->pf_run = Run;
637   p_intf->p_sys->b_playing = VLC_FALSE;
638   p_intf->p_sys->p_input = NULL;
639
640   p_intf->p_sys->orb = NULL;
641   p_intf->p_sys->mc = NULL;
642   p_intf->p_sys->root_poa = NULL;
643   p_intf->p_sys->root_poa_manager = NULL;
644   p_intf->p_sys->corbaloop = NULL;
645
646   return VLC_SUCCESS;
647 }
648
649
650
651 /*****************************************************************************
652  * intf_Close: destroy interface
653  *****************************************************************************/
654 static void Close( vlc_object_t *p_this )
655 {
656   intf_thread_t *p_intf = (intf_thread_t *)p_this;
657   CORBA_Environment*        ev = NULL;
658
659   ev = CORBA_exception__alloc ();
660   CORBA_ORB_shutdown (p_intf->p_sys->orb, FALSE, ev);
661   handle_exception_no_servant (p_intf, "Erreur dans Close");
662
663   if( p_intf->p_sys->p_input )
664     {
665       vlc_object_release( p_intf->p_sys->p_input );
666     }
667
668   /* Destroy structure */
669   free( p_intf->p_sys );
670 }
671
672 /*
673   Function called regularly to handle various tasks (mainly CORBA calls)
674  */
675 static gboolean Manage (gpointer p_interface)
676 {
677   intf_thread_t *p_intf = (intf_thread_t*)p_interface;
678   CORBA_boolean b_work_pending;
679   CORBA_Environment* ev;
680
681   ev = CORBA_exception__alloc ();
682
683   /* CORBA */
684   b_work_pending = CORBA_ORB_work_pending (p_intf->p_sys->orb, ev);
685   if(ev->_major != CORBA_NO_EXCEPTION)
686     {
687       msg_Err (p_intf, "Exception dans la vérif d'événements CORBA");
688       return FALSE;
689     }
690
691   vlc_mutex_lock( &p_intf->change_lock );
692
693   /* Update the input */
694   if( p_intf->p_sys->p_input == NULL )
695     {
696       p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
697                                                 FIND_ANYWHERE );
698     }
699   else if( p_intf->p_sys->p_input->b_dead )
700     {
701       vlc_object_release( p_intf->p_sys->p_input );
702       p_intf->p_sys->p_input = NULL;
703     }
704
705   if( p_intf->p_sys->p_input )
706     {
707       input_thread_t  *p_input = p_intf->p_sys->p_input;
708
709       vlc_mutex_lock( &p_input->stream.stream_lock );
710
711       if ( !p_input->b_die )
712         {
713           /* New input or stream map change */
714           if( p_input->stream.b_changed )
715             {
716               /* FIXME: We should notify our client that the input changed */
717               /* E_(GtkModeManage)( p_intf ); */
718               p_intf->p_sys->b_playing = 1;
719             }
720         }
721       vlc_mutex_unlock( &p_input->stream.stream_lock );
722     }
723   else if( p_intf->p_sys->b_playing && !p_intf->b_die )
724     {
725       /* FIXME: We should notify our client that the input changed */
726       /* E_(GtkModeManage)( p_intf ); */
727       p_intf->p_sys->b_playing = 0;
728     }
729
730   /* CORBA calls handling. Beware: no lock is taken (since p_pinput
731      can be null) */
732   if (b_work_pending)
733     CORBA_ORB_perform_work (p_intf->p_sys->orb, ev);
734
735   if( p_intf->b_die )
736     {
737       vlc_mutex_unlock( &p_intf->change_lock );
738       g_main_loop_quit (p_intf->p_sys->corbaloop);
739       /* Just in case */
740       return( FALSE );
741     }
742
743   vlc_mutex_unlock( &p_intf->change_lock );
744
745   return TRUE;
746 }
747
748 /*****************************************************************************
749  * Run: main loop
750  *****************************************************************************
751  * this part of the interface is in a separate thread so that we can call
752  * g_main_loop_run() from within it without annoying the rest of the program.
753  *****************************************************************************/
754 static void Run ( intf_thread_t *p_intf )
755 {
756   CORBA_Environment*        ev = NULL;
757   guint                     i_event_source;
758   CORBA_char*               psz_objref;
759   impl_POA_VLC_MediaControl *servant = NULL;
760   int i_argc = 1;
761   char* ppsz_argv[] = { "mc" };
762
763   msg_Warn (p_intf, "Entering Run");
764
765   ev = CORBA_exception__alloc ();
766
767   /* To be able to use CORBA in a MT app */
768   linc_set_threaded (TRUE);
769
770   p_intf->p_sys->orb = CORBA_ORB_init(&i_argc, ppsz_argv, "orbit-local-orb", ev);
771
772   /* Should be cleaner this way (cf
773      http://www.fifi.org/doc/gnome-dev-doc/html/C/orbitgtk.html) but it
774      functions well enough in the ugly way so that I do not bother
775      cleaning it */
776   /* p_intf->p_sys->orb = gnome_CORBA_init ("VLC", NULL, &argc, &argv, 0, NULL, ev); */
777
778   handle_exception_no_servant (p_intf, "Exception during CORBA_ORB_init");
779
780   p_intf->p_sys->root_poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(p_intf->p_sys->orb, "RootPOA", ev);
781   handle_exception ("Exception during RootPOA initialization");
782
783   p_intf->p_sys->mc = impl_VLC_MediaControl__create(p_intf->p_sys->root_poa, ev);
784   handle_exception ("Exception during MediaControl initialization");
785
786   servant = (impl_POA_VLC_MediaControl*)PortableServer_POA_reference_to_servant(p_intf->p_sys->root_poa, p_intf->p_sys->mc, ev);
787   handle_exception ("Exception during MediaControl access");
788
789   servant->p_intf = p_intf;
790
791   psz_objref = CORBA_ORB_object_to_string(p_intf->p_sys->orb, p_intf->p_sys->mc, ev);
792   handle_exception ("Exception during IOR generation");
793
794   msg_Warn (p_intf, "MediaControl IOR :");
795   msg_Warn (p_intf, psz_objref);
796
797   /* We write the IOR in a file. */
798   {
799     FILE* fp;
800     fp = fopen (VLC_IOR_FILE, "w");
801     if (fp == NULL)
802       {
803         msg_Err (servant->p_intf, "Cannot write the IOR to %s (%d).", VLC_IOR_FILE, errno);
804       }
805     else
806       {
807         fprintf (fp, "%s", psz_objref);
808         fclose (fp);
809         msg_Warn (servant->p_intf, "IOR written to %s", VLC_IOR_FILE);
810       }
811   }
812
813   msg_Warn (p_intf, "get_the_POAManager (state  %s)", p_intf->p_sys->root_poa);
814   p_intf->p_sys->root_poa_manager = PortableServer_POA__get_the_POAManager(p_intf->p_sys->root_poa, ev);
815   handle_exception ("Exception during POAManager resolution");
816
817   msg_Warn (p_intf, "Activating POAManager");
818   PortableServer_POAManager_activate(p_intf->p_sys->root_poa_manager, ev);
819   handle_exception ("Exception during POAManager activation");
820
821   msg_Info(p_intf, "corba remote control interface initialized" );
822
823   /*
824     // Tentative de gestion du nommage...
825   {
826     CosNaming_NamingContext name_service;
827     CosNaming_NameComponent name_component[3] = {{"GNOME", "subcontext"},
828                                                  {"Servers", "subcontext"},
829                                                  {"vlc", "server"} };
830     CosNaming_Name name = {3, 3, name_component, CORBA_FALSE};
831
832     name_service = CORBA_ORB_resolve_initial_references (p_intf->p_sys->orb,
833                                                          "NameService",
834                                                          ev);
835     handle_exception ("Error: could not get name service: %s\n",
836                    CORBA_exception_id(ev));
837     msg_Warn (p_intf, "Name service OK");
838
839     CosNaming_NamingContext_bind (name_service, &name, p_intf->p_sys->mc, ev);
840       handle_exception ("Error: could not register object: %s\n",
841       CORBA_exception_id(ev));
842   }
843     */
844
845   /* The time factor should be 1/1000 but it is a little too
846      slow. Make it 1/10000 */
847   i_event_source = g_timeout_add (INTF_IDLE_SLEEP / 10000,
848                                 Manage,
849                                 p_intf);
850   msg_Warn (p_intf, "Entering mainloop");
851
852   p_intf->p_sys->corbaloop = g_main_loop_new (NULL, FALSE);
853   g_main_loop_run (p_intf->p_sys->corbaloop);
854
855   /* Cleaning */
856   g_source_remove( i_event_source );
857   unlink (VLC_IOR_FILE);
858
859   msg_Warn (p_intf, "Normal termination of VLC corba plugin");
860   return;
861 }