dnl Autoconf settings for vlc
-dnl $Id: configure.ac,v 1.26 2003/07/07 14:56:22 massiot Exp $
+dnl $Id: configure.ac,v 1.27 2003/07/07 16:59:00 sam Exp $
AC_INIT(vlc,0.6.0)
fi
fi
+dnl
+dnl corba (ORBit) plugin
+dnl
+AC_ARG_ENABLE(corba,
+ [ --enable-corba corba interface support (default disabled)])
+if test "${enable_corba}" = "yes"; then
+ ORBIT_PATH="${PATH}"
+ AC_ARG_WITH(orbit-config-path,
+ [ --with-orbit-config-path=PATH orbit-config path (default search in \$PATH)])
+ if test "${with_orbit_config_path}" != "no"; then
+ ORBIT_PATH="${with_orbit_config_path}:${PATH}"
+ fi
+ # look for orbit2-config
+ AC_PATH_PROG(ORBIT_CONFIG, orbit2-config, no, ${ORBIT_PATH})
+ if test "${ORBIT_CONFIG}" != "no"; then
+ AX_ADD_CFLAGS(corba,[`${ORBIT_CONFIG} --cflags server`])
+ AX_ADD_LDFLAGS(corba,[`${ORBIT_CONFIG} --libs server | sed 's,-rdynamic,,'`])
+ # now look for the orbit.h header
+ CPPFLAGS="${CPPFLAGS_save} ${CFLAGS_corba}"
+ ac_cv_corba_headers=yes
+ AC_CHECK_HEADERS(orbit/orbit.h, , [
+ ac_cv_corba_headers=no
+ AC_MSG_ERROR([Could not find corba development headers])
+ ])
+ if test "${ac_cv_corba_headers}" = "yes"; then
+ AX_ADD_PLUGINS(corba)
+ fi
+ CPPFLAGS="${CPPFLAGS_save}"
+ fi
+fi
+
AC_ARG_WITH(,[Misc options:])
dnl
modules/codec/mpeg_video/motion/Makefile
modules/codec/spudec/Makefile
modules/control/Makefile
+ modules/control/corba/Makefile
modules/control/lirc/Makefile
modules/control/rc/Makefile
modules/demux/Makefile
--- /dev/null
+.deps
+.dirstamp
+*.lo
+*.la
+*.dll
+*.dylib
+*.sl
+*.so
+Makefile.am
+Makefile.in
+Makefile
--- /dev/null
+## corba module declaration
+
+SOURCES_corba = corba.c
+
+nodist_SOURCES_corba = \
+ mediacontrol-common.c \
+ mediacontrol-skels.c \
+ mediacontrol.h \
+ $(NULL)
+
+ORBITIDL = orbit-idl-2
+
+mediacontrol-common.c mediacontrol-skels.c mediacontrol-stubs.c mediacontrol.h:
+ $(ORBITIDL) --skeleton-impl mediacontrol.idl
+
+mediacontrol-imodule.c:
+ $(ORBITIDL) --imodule mediacontrol.idl
+
+mediacontrol.so: mediacontrol-imodule.c
+ gcc -fPIC -o mediacontrol-imodule.o -c mediacontrol-imodule.c `pkg-config --cflags ORBit-2.0`
+ gcc -shared -o $@ mediacontrol-imodule.o `pkg-config --libs ORBit-2.0`
+
+clean:
+ rm -f mediacontrol-stubs.c mediacontrol-imodule.c mediacontrol-skelimpl.c
+
--- /dev/null
+$Id: README,v 1.1 2003/07/07 16:59:00 sam Exp $
+* Module (server) side
+** Dependencies
+
+To compile the CORBA plugin, you need the orbit2 developpement files
+(for Debian, install the package liborbi2-dev)
+
+** How to run it ?
+
+You run the CORBA module with the following command line :
+
+vlc --intf corba
+
+The CORBA module is initialized and saves its IOR into the file
+/tmp/vlc-ior.ref
+
+
+* Client side
+
+A sample client application is provided, using python-orbit
+
+** Dependencies
+
+The python client uses the pyorbit library developped by James
+Henstridge <james at daa dot com dot au> (source:
+http://ftp.gnome.org/pub/GNOME/sources/pyorbit/1.99/pyorbit-1.99.3.tar.gz).
+
+To interoperate with gtk, the original pyorbit-1.99.3 needs a patch to
+implement the bindings to OR_work_pending and ORB_perform_work (see
+pyorbit-1.99.3.patch)
+
+The gtk simpleplayer example uses the python-glade module by James
+Henstridge.
+
+** Typelib information
+
+To simply access the server, you do not need any reference to the IDL
+(CORBA2.0 provides introspection facilities). However, if you want to
+use the structures defined in the IDL (Position, Origin, ...), you
+need to use the IDL information, and compile a dynamic lib
+(MediaControl.so) from the IDL.
+
+To build the library, you can use the Makefile :
+
+make corba-generate-typelib
+
+which will generate MediaControl.so
+
+* Interesting pointers
+
+- GLib reference manual
+http://developer.gnome.org/doc/API/glib/
+
+- IDL quickref :
+http://www.cs.rpi.edu/~musser/dsc/idl/idl-overview.html
+
+- Python-Bonobo
+http://www.pycage.de/howto_bonobo.html
+
+* How to add the module to the original sources (vlc-0.5.x) :
+- copy the directory modules/control/corba
+- add configuration lines relative to corba in configure.ac.in
+- add a reference to control/corba/Modules.am in
+ modules/Makefile.am
--- /dev/null
+#! /usr/bin/python
+
+# Simple CLI client for the corba module of vlc. Depends on pyorbit.
+# Best used with IPython (completion, ...)
+
+import sys
+import ORBit, CORBA
+
+def quit ():
+ try:
+ mc.exit()
+ except:
+ pass
+
+print "Chargement de l'IDL"
+ORBit.load_typelib ("./MediaControl.so")
+import VLC
+
+if len(sys.argv) < 1:
+ print "Usage: %s" % sys.argv[0]
+ sys.exit(1)
+
+print "Initialisation de l'ORB"
+orb = CORBA.ORB_init()
+
+ior = open("/tmp/vlc-ior.ref").readline()
+mc = orb.string_to_object(ior)
+
+print "Objet mc %s" % mc
+
+pos = mc.get_media_position (0,0)
+print "pos = mc.get_media_position (0,0)"
+print pos
+
--- /dev/null
+/*****************************************************************************
+ * corba.c : CORBA (ORBit) remote control plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2001 VideoLAN
+ * $Id: corba.c,v 1.1 2003/07/07 16:59:00 sam Exp $
+ *
+ * Authors: Olivier Aubert <oaubert at lisi dot univ-lyon1 dot fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+/* For CORBA */
+#include "mediacontrol.h"
+#include "orbit/poa/portableserver-poa-type.h"
+#define VLC_IOR_FILE "/tmp/vlc-ior.ref"
+
+#define handle_exception(m) if(ev->_major != CORBA_NO_EXCEPTION) \
+ { \
+ msg_Err (servant->p_intf, m); \
+ return; \
+ }
+
+
+#define handle_exception_no_servant(p,m) if(ev->_major != CORBA_NO_EXCEPTION) \
+ { \
+ msg_Err (p, m); \
+ return; \
+ }
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+#include <vlc/vout.h>
+#include <vlc/aout.h>
+
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <errno.h> /* ENOMEM */
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <sys/types.h>
+
+/*****************************************************************************
+ * intf_sys_t: description and status of corba interface
+ *****************************************************************************/
+struct intf_sys_t
+{
+ CORBA_ORB orb;
+ VLC_MediaControl mc;
+ PortableServer_POA root_poa;
+ PortableServer_POAManager root_poa_manager;
+ GMainLoop* corbaloop;
+
+ vlc_bool_t b_playing;
+
+ input_thread_t * p_input; /* The input thread */
+
+ msg_subscription_t* p_sub; /* message bank subscription */
+};
+
+/* Convert an offset into seconds. Taken from input_ext-intf.c.
+ The 50 hardcoded constant comes from the definition of i_mux_rate :
+ i_mux_rate : the rate we read the stream (in units of 50 bytes/s) ;
+ 0 if undef */
+long long offsetToSeconds (input_thread_t *p_input, off_t l_offset)
+{
+ long long l_res;
+
+ l_res = -1;
+ if (p_input != NULL && p_input->stream.i_mux_rate != 0)
+ {
+ l_res = (long long) l_offset / 50 / p_input->stream.i_mux_rate;
+ }
+ return l_res;
+}
+
+/* Convert an offset into milliseconds */
+long long offsetToMilliseconds (input_thread_t *p_input, off_t l_offset)
+{
+ long long l_res;
+
+ l_res = -1;
+ if (p_input != NULL && p_input->stream.i_mux_rate != 0)
+ {
+ l_res = (long long) 1000 * l_offset / 50 / p_input->stream.i_mux_rate;
+ }
+ return l_res;
+}
+
+/* Convert seconds to an offset */
+off_t secondsToOffset (input_thread_t *p_input, long long l_seconds)
+{
+ off_t l_res;
+
+ l_res = -1;
+
+ if (p_input != NULL)
+ {
+ l_res = (off_t) l_seconds * 50 * p_input->stream.i_mux_rate;
+ }
+ return l_res;
+}
+
+
+/* Convert milliseconds to an offset */
+off_t millisecondsToOffset (input_thread_t *p_input, long long l_milliseconds)
+{
+ off_t l_res;
+
+ l_res = -1;
+ if (p_input != NULL)
+ {
+ l_res = (off_t) l_milliseconds * 50 * p_input->stream.i_mux_rate / 1000;
+ }
+ return l_res;
+}
+
+/* Returns the current offset. */
+off_t currentOffset (input_thread_t *p_input)
+{
+ off_t l_offset;
+
+ if( p_input == NULL )
+ {
+ return -1;
+ }
+
+ /* offset contient la valeur en unités arbitraires (cf
+ include/input_ext-intf.h) */
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+#define A p_input->stream.p_selected_area
+ l_offset = A->i_tell + A->i_start;
+#undef A
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ return l_offset;
+}
+
+/*** App-specific servant structures ***/
+
+/* We can add attributes to this structure, which is both a pointer on a
+ specific structure, and on a POA_VLC_MediaControl (servant). Cf
+ http://developer.gnome.org/doc/guides/corba/html/corba-poa-example.html */
+
+typedef struct
+{
+ POA_VLC_MediaControl servant;
+ PortableServer_POA poa;
+ /* Ajouter ici les attributs utiles */
+ intf_thread_t *p_intf;
+}
+impl_POA_VLC_MediaControl;
+
+/* Beginning of the CORBA code generated in Mediacontrol-skelimpl.c */
+/* BEGIN INSERT */
+
+/*** Implementation stub prototypes ***/
+
+static void impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl *
+ servant, CORBA_Environment * ev);
+
+static VLC_Position
+impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant,
+ const VLC_PositionOrigin an_origin,
+ const VLC_PositionKey a_key,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
+ CORBA_Environment * ev);
+
+static void
+impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant,
+ const CORBA_char * a_file,
+ CORBA_Environment * ev);
+
+static VLC_PlaylistSeq
+ *impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant,
+ CORBA_Environment * ev);
+
+/*** epv structures ***/
+
+static PortableServer_ServantBase__epv impl_VLC_MediaControl_base_epv = {
+ NULL, /* _private data */
+ NULL, /* finalize routine */
+ NULL, /* default_POA routine */
+};
+static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = {
+ NULL, /* _private */
+
+ (gpointer) & impl_VLC_MediaControl_get_media_position,
+
+ (gpointer) & impl_VLC_MediaControl_set_media_position,
+
+ (gpointer) & impl_VLC_MediaControl_start,
+
+ (gpointer) & impl_VLC_MediaControl_pause,
+
+ (gpointer) & impl_VLC_MediaControl_resume,
+
+ (gpointer) & impl_VLC_MediaControl_stop,
+
+ (gpointer) & impl_VLC_MediaControl_exit,
+
+ (gpointer) & impl_VLC_MediaControl_add_to_playlist,
+
+ (gpointer) & impl_VLC_MediaControl_get_playlist,
+
+};
+
+/*** vepv structures ***/
+
+static POA_VLC_MediaControl__vepv impl_VLC_MediaControl_vepv = {
+ &impl_VLC_MediaControl_base_epv,
+ &impl_VLC_MediaControl_epv,
+};
+
+/*** Stub implementations ***/
+
+static VLC_MediaControl
+impl_VLC_MediaControl__create(PortableServer_POA poa, CORBA_Environment * ev)
+{
+ VLC_MediaControl retval;
+ impl_POA_VLC_MediaControl *newservant;
+ PortableServer_ObjectId *objid;
+
+ newservant = g_new0(impl_POA_VLC_MediaControl, 1);
+ newservant->servant.vepv = &impl_VLC_MediaControl_vepv;
+ newservant->poa = poa;
+ POA_VLC_MediaControl__init((PortableServer_Servant) newservant, ev);
+ objid = PortableServer_POA_activate_object(poa, newservant, ev);
+ CORBA_free(objid);
+ retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
+
+ return retval;
+}
+
+static void
+impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl * servant,
+ CORBA_Environment * ev)
+{
+ PortableServer_ObjectId *objid;
+
+ objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev);
+ PortableServer_POA_deactivate_object(servant->poa, objid, ev);
+ CORBA_free(objid);
+
+ POA_VLC_MediaControl__fini((PortableServer_Servant) servant, ev);
+ g_free(servant);
+}
+
+/* END INSERT */
+/* Beginning of the CORBA functions that we define */
+
+/* Returns the current position in the stream. The returned value can
+ be relative or absolute (according to PositionOrigin) and the unit
+ is set by PositionKey */
+static VLC_Position
+impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant,
+ const VLC_PositionOrigin an_origin,
+ const VLC_PositionKey a_key,
+ CORBA_Environment * ev)
+{
+ VLC_Position retval;
+ off_t l_offset;
+ VLC_PositionKeyNotSupported *exception;
+ input_thread_t * p_input = servant->p_intf->p_sys->p_input;
+
+ /* msg_Warn (servant->p_intf, "Calling MediaControl::get_media_position"); */
+
+ retval.origin = an_origin;
+ retval.key = a_key;
+
+ if ( an_origin == VLC_RelativePosition
+ || an_origin == VLC_ModuloPosition )
+ {
+ /* Relative or ModuloPosition make no sense */
+ /* FIXME: should we return 0 or raise an exception ? */
+ retval.value = 0;
+ return retval;
+ }
+
+ if ( p_input == NULL )
+ {
+ /* FIXME: should we return 0 or raise an exception ? */
+ retval.value = 0;
+ return retval;
+ }
+
+ /* We are asked for an AbsolutePosition. */
+ /* Cf plugins/gtk/gtk_display.c */
+
+ /* The lock is taken by the currentOffset function */
+ l_offset = currentOffset (p_input);
+
+ if (a_key == VLC_ByteCount)
+ {
+ retval.value = l_offset;
+ return retval;
+ }
+ if (a_key == VLC_MediaTime)
+ {
+ retval.value = offsetToSeconds (p_input, l_offset);
+ return retval;
+ }
+ if (a_key == VLC_SampleCount)
+ {
+ /* Raising exceptions in C : cf the good explanations in
+ http://developer.gnome.org/doc/guides/corba/html/corba-module-complete-helloworld.html
+ */
+ exception = VLC_PositionKeyNotSupported__alloc ();
+ memcpy (&exception->key, &a_key, sizeof (a_key));
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_VLC_PositionKeyNotSupported,
+ exception);
+ retval.value = 0;
+ return retval;
+ }
+
+ /* http://catb.org/~esr/jargon/html/entry/can't-happen.html */
+ return retval;
+}
+
+/* Sets the media position */
+static void
+impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position,
+ CORBA_Environment * ev)
+{
+ VLC_InvalidPosition *pe_exception;
+ VLC_PositionKeyNotSupported *pe_key_exception;
+ off_t l_offset_destination = 0;
+ int i_whence = 0;
+ input_thread_t * p_input = servant->p_intf->p_sys->p_input;
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::set_media_position");
+
+ if( p_input == NULL )
+ return;
+
+ if ( !p_input->stream.b_seekable )
+ {
+ pe_exception = VLC_InvalidPosition__alloc ();
+ memcpy (&pe_exception->key, &a_position->key, sizeof (&a_position->key));
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_VLC_InvalidPosition,
+ pe_exception);
+ return;
+ }
+
+ switch ( a_position->key )
+ {
+ case VLC_SampleCount:
+ /* The SampleCount unit is still a bit mysterious... */
+ pe_key_exception = VLC_PositionKeyNotSupported__alloc ();
+ memcpy (&pe_key_exception->key, &a_position->key, sizeof (&a_position->key));
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_VLC_PositionKeyNotSupported,
+ pe_key_exception);
+ return;
+ break;
+ case VLC_MediaTime:
+ i_whence |= INPUT_SEEK_SECONDS;
+ break;
+ case VLC_ByteCount:
+ i_whence |= INPUT_SEEK_BYTES;
+ break;
+ default:
+ i_whence |= INPUT_SEEK_BYTES;
+ break;
+ }
+
+ switch ( a_position->origin)
+ {
+ case VLC_RelativePosition:
+ i_whence |= INPUT_SEEK_CUR;
+ break;
+ case VLC_ModuloPosition:
+ i_whence |= INPUT_SEEK_END;
+ break;
+ case VLC_AbsolutePosition:
+ i_whence |= INPUT_SEEK_SET;
+ break;
+ default:
+ i_whence |= INPUT_SEEK_SET;
+ break;
+ }
+
+ l_offset_destination = a_position->value;
+
+ /* msg_Warn (servant->p_intf, "Offset destination : %d", l_offset_destination); */
+ /* Now we can set the position. The lock is taken in the input_Seek
+ function (cf input_ext-intf.c) */
+ input_Seek (p_input, l_offset_destination, i_whence);
+ return;
+}
+
+/* Starts playing a stream */
+static void
+impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position, CORBA_Environment * ev)
+{
+ intf_thread_t * p_intf = servant->p_intf;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::start");
+
+ if( p_playlist == NULL )
+ {
+ /* FIXME: we should raise an appropriate exception, but we must
+ define it in the IDL first */
+ msg_Err (servant->p_intf, "Error: no playlist available.");
+ return;
+ }
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+ if( p_playlist->i_size )
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ playlist_Play( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+ else
+ {
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+ msg_Err (servant->p_intf, "Error: playlist empty.");
+ }
+
+ return;
+}
+
+static void
+impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position, CORBA_Environment * ev)
+{
+ input_thread_t *p_input = servant->p_intf->p_sys->p_input;
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::pause");
+
+ if( p_input != NULL )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+ }
+
+ return;
+}
+
+static void
+impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position, CORBA_Environment * ev)
+{
+ input_thread_t *p_input = servant->p_intf->p_sys->p_input;
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::resume");
+
+ if( p_input != NULL )
+ {
+ input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+ }
+
+ return;
+}
+
+static void
+impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant,
+ const VLC_Position * a_position, CORBA_Environment * ev)
+{
+ intf_thread_t * p_intf = servant->p_intf;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::stop");
+
+ if( p_playlist != NULL )
+ {
+ playlist_Stop( p_playlist );
+ vlc_object_release( p_playlist );
+ }
+
+ return;
+}
+
+static void
+impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
+ CORBA_Environment * ev)
+{
+ msg_Warn (servant->p_intf, "Calling MediaControl::exit");
+
+ vlc_mutex_lock( &servant->p_intf->change_lock );
+ servant->p_intf->b_die = TRUE;
+ vlc_mutex_unlock( &servant->p_intf->change_lock );
+}
+
+static void
+impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant,
+ const CORBA_char * psz_file,
+ CORBA_Environment * ev)
+{
+ intf_thread_t * p_intf = servant->p_intf;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::add_to_playlist %s", psz_file);
+
+ if ( p_playlist == NULL )
+ {
+ msg_Err (servant->p_intf, "Error: no playlist defined");
+ /* FIXME: should return an exception */
+ return;
+ }
+
+ playlist_Add (p_playlist, psz_file, PLAYLIST_REPLACE, 0);
+ vlc_object_release( p_playlist );
+
+ return;
+}
+
+static VLC_PlaylistSeq *
+impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant,
+ CORBA_Environment * ev)
+{
+ VLC_PlaylistSeq *retval;
+ int i_index;
+ intf_thread_t * p_intf = servant->p_intf;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ int i_playlist_size;
+
+ msg_Warn (servant->p_intf, "Calling MediaControl::get_playlist");
+
+ vlc_mutex_lock( &p_playlist->object_lock );
+ i_playlist_size = p_playlist->i_size;
+
+ retval = VLC_PlaylistSeq__alloc ();
+ retval->_buffer = VLC_PlaylistSeq_allocbuf (i_playlist_size);
+ retval->_length = i_playlist_size;
+
+ for (i_index = 0 ; i_index < i_playlist_size ; i_index++)
+ {
+ retval->_buffer[i_index] =
+ CORBA_string_dup (p_playlist->pp_items[i_index]->psz_name);
+ }
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ vlc_object_release( p_playlist );
+
+ CORBA_sequence_set_release (retval, TRUE);
+ return retval;
+}
+
+/* (Real) end of the CORBA code generated in Mediacontrol-skelimpl.c */
+
+/*****************************************************************************
+ * Local prototypes.
+ *****************************************************************************/
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run ( intf_thread_t * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+ add_category_hint( N_("Corba control"), NULL, VLC_FALSE );
+ set_description( _("corba control module") );
+ set_capability( "interface", 10 );
+ set_callbacks( Open, Close );
+vlc_module_end();
+
+/*****************************************************************************
+ * intf_Open: initialize and create stuff
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+ /* Allocate instance and initialize some members */
+ p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
+ if( p_intf->p_sys == NULL )
+ {
+ msg_Err( p_intf, "out of memory" );
+ return VLC_ENOMEM;
+ }
+
+ /* Initialize the fields of the p_intf struct */
+ p_intf->pf_run = Run;
+ p_intf->p_sys->b_playing = VLC_FALSE;
+ p_intf->p_sys->p_input = NULL;
+
+ p_intf->p_sys->orb = NULL;
+ p_intf->p_sys->mc = NULL;
+ p_intf->p_sys->root_poa = NULL;
+ p_intf->p_sys->root_poa_manager = NULL;
+ p_intf->p_sys->corbaloop = NULL;
+
+ return VLC_SUCCESS;
+}
+
+
+
+/*****************************************************************************
+ * intf_Close: destroy interface
+ *****************************************************************************/
+static void Close( vlc_object_t *p_this )
+{
+ intf_thread_t *p_intf = (intf_thread_t *)p_this;
+ CORBA_Environment* ev = NULL;
+
+ ev = CORBA_exception__alloc ();
+ CORBA_ORB_shutdown (p_intf->p_sys->orb, FALSE, ev);
+ handle_exception_no_servant (p_intf, "Erreur dans Close");
+
+ if( p_intf->p_sys->p_input )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ }
+
+ /* Destroy structure */
+ free( p_intf->p_sys );
+}
+
+/*
+ Function called regularly to handle various tasks (mainly CORBA calls)
+ */
+static gboolean Manage (gpointer p_interface)
+{
+ intf_thread_t *p_intf = (intf_thread_t*)p_interface;
+ CORBA_boolean b_work_pending;
+ CORBA_Environment* ev;
+
+ ev = CORBA_exception__alloc ();
+
+ /* CORBA */
+ b_work_pending = CORBA_ORB_work_pending (p_intf->p_sys->orb, ev);
+ if(ev->_major != CORBA_NO_EXCEPTION)
+ {
+ msg_Err (p_intf, "Exception dans la vérif d'événements CORBA");
+ return FALSE;
+ }
+
+ vlc_mutex_lock( &p_intf->change_lock );
+
+ /* Update the input */
+ if( p_intf->p_sys->p_input == NULL )
+ {
+ p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+ FIND_ANYWHERE );
+ }
+ else if( p_intf->p_sys->p_input->b_dead )
+ {
+ vlc_object_release( p_intf->p_sys->p_input );
+ p_intf->p_sys->p_input = NULL;
+ }
+
+ if( p_intf->p_sys->p_input )
+ {
+ input_thread_t *p_input = p_intf->p_sys->p_input;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+
+ if ( !p_input->b_die )
+ {
+ /* New input or stream map change */
+ if( p_input->stream.b_changed )
+ {
+ /* FIXME: We should notify our client that the input changed */
+ /* E_(GtkModeManage)( p_intf ); */
+ p_intf->p_sys->b_playing = 1;
+ }
+ }
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+ }
+ else if( p_intf->p_sys->b_playing && !p_intf->b_die )
+ {
+ /* FIXME: We should notify our client that the input changed */
+ /* E_(GtkModeManage)( p_intf ); */
+ p_intf->p_sys->b_playing = 0;
+ }
+
+ /* CORBA calls handling. Beware: no lock is taken (since p_pinput
+ can be null) */
+ if (b_work_pending)
+ CORBA_ORB_perform_work (p_intf->p_sys->orb, ev);
+
+ if( p_intf->b_die )
+ {
+ vlc_mutex_unlock( &p_intf->change_lock );
+ g_main_loop_quit (p_intf->p_sys->corbaloop);
+ /* Just in case */
+ return( FALSE );
+ }
+
+ vlc_mutex_unlock( &p_intf->change_lock );
+
+ return TRUE;
+}
+
+/*****************************************************************************
+ * Run: main loop
+ *****************************************************************************
+ * this part of the interface is in a separate thread so that we can call
+ * g_main_loop_run() from within it without annoying the rest of the program.
+ *****************************************************************************/
+static void Run ( intf_thread_t *p_intf )
+{
+ CORBA_Environment* ev = NULL;
+ guint i_event_source;
+ CORBA_char* psz_objref;
+ impl_POA_VLC_MediaControl *servant = NULL;
+ int i_argc = 1;
+ char* ppsz_argv[] = { "mc" };
+
+ msg_Warn (p_intf, "Entering Run");
+
+ ev = CORBA_exception__alloc ();
+
+ /* To be able to use CORBA in a MT app */
+ linc_set_threaded (TRUE);
+
+ p_intf->p_sys->orb = CORBA_ORB_init(&i_argc, ppsz_argv, "orbit-local-orb", ev);
+
+ /* Should be cleaner this way (cf
+ http://www.fifi.org/doc/gnome-dev-doc/html/C/orbitgtk.html) but it
+ functions well enough in the ugly way so that I do not bother
+ cleaning it */
+ /* p_intf->p_sys->orb = gnome_CORBA_init ("VLC", NULL, &argc, &argv, 0, NULL, ev); */
+
+ handle_exception_no_servant (p_intf, "Exception during CORBA_ORB_init");
+
+ p_intf->p_sys->root_poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(p_intf->p_sys->orb, "RootPOA", ev);
+ handle_exception ("Exception during RootPOA initialization");
+
+ p_intf->p_sys->mc = impl_VLC_MediaControl__create(p_intf->p_sys->root_poa, ev);
+ handle_exception ("Exception during MediaControl initialization");
+
+ servant = (impl_POA_VLC_MediaControl*)PortableServer_POA_reference_to_servant(p_intf->p_sys->root_poa, p_intf->p_sys->mc, ev);
+ handle_exception ("Exception during MediaControl access");
+
+ servant->p_intf = p_intf;
+
+ psz_objref = CORBA_ORB_object_to_string(p_intf->p_sys->orb, p_intf->p_sys->mc, ev);
+ handle_exception ("Exception during IOR generation");
+
+ msg_Warn (p_intf, "MediaControl IOR :");
+ msg_Warn (p_intf, psz_objref);
+
+ /* We write the IOR in a file. */
+ {
+ FILE* fp;
+ fp = fopen (VLC_IOR_FILE, "w");
+ if (fp == NULL)
+ {
+ msg_Err (servant->p_intf, "Cannot write the IOR to %s (%d).", VLC_IOR_FILE, errno);
+ }
+ else
+ {
+ fprintf (fp, "%s", psz_objref);
+ fclose (fp);
+ msg_Warn (servant->p_intf, "IOR written to %s", VLC_IOR_FILE);
+ }
+ }
+
+ msg_Warn (p_intf, "get_the_POAManager (state %s)", p_intf->p_sys->root_poa);
+ p_intf->p_sys->root_poa_manager = PortableServer_POA__get_the_POAManager(p_intf->p_sys->root_poa, ev);
+ handle_exception ("Exception during POAManager resolution");
+
+ msg_Warn (p_intf, "Activating POAManager");
+ PortableServer_POAManager_activate(p_intf->p_sys->root_poa_manager, ev);
+ handle_exception ("Exception during POAManager activation");
+
+ msg_Info(p_intf, "corba remote control interface initialized" );
+
+ /*
+ // Tentative de gestion du nommage...
+ {
+ CosNaming_NamingContext name_service;
+ CosNaming_NameComponent name_component[3] = {{"GNOME", "subcontext"},
+ {"Servers", "subcontext"},
+ {"vlc", "server"} };
+ CosNaming_Name name = {3, 3, name_component, CORBA_FALSE};
+
+ name_service = CORBA_ORB_resolve_initial_references (p_intf->p_sys->orb,
+ "NameService",
+ ev);
+ handle_exception ("Error: could not get name service: %s\n",
+ CORBA_exception_id(ev));
+ msg_Warn (p_intf, "Name service OK");
+
+ CosNaming_NamingContext_bind (name_service, &name, p_intf->p_sys->mc, ev);
+ handle_exception ("Error: could not register object: %s\n",
+ CORBA_exception_id(ev));
+ }
+ */
+
+ /* The time factor should be 1/1000 but it is a little too
+ slow. Make it 1/10000 */
+ i_event_source = g_timeout_add (INTF_IDLE_SLEEP / 10000,
+ Manage,
+ p_intf);
+ msg_Warn (p_intf, "Entering mainloop");
+
+ p_intf->p_sys->corbaloop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (p_intf->p_sys->corbaloop);
+
+ /* Cleaning */
+ g_source_remove( i_event_source );
+ unlink (VLC_IOR_FILE);
+
+ msg_Warn (p_intf, "Normal termination of VLC corba plugin");
+ return;
+}
--- /dev/null
+#! /bin/sh
+# Helper prog
+VLCPATH=/usr/local/src/vlc
+cd $VLCPATH
+${VLCPATH}/vlc --intf corba &
+exit 0
+
--- /dev/null
+/* Cf
+ http://www.cs.rpi.edu/~musser/dsc/idl/idl-overview.html
+ pour une intro à la syntaxe */
+
+module VLC {
+ enum PositionOrigin {
+ AbsolutePosition, RelativePosition, ModuloPosition
+ };
+
+ enum PositionKey {
+ ByteCount, SampleCount, MediaTime
+ };
+
+ struct Position {
+ PositionOrigin origin;
+ PositionKey key;
+ long value;
+ };
+
+ exception PositionKeyNotSupported { PositionKey key;};
+ exception InvalidPosition { PositionKey key;};
+
+ typedef sequence<string> PlaylistSeq;
+
+ // MediaControl interface is similar to
+ // ControlledStream interface in MSS.
+ // It can be inherited by flow endpoints or
+ // FlowConnection interfaces.
+ interface MediaControl
+ {
+
+ exception PositionKeyNotSupported { PositionKey key;};
+
+ Position get_media_position(
+ in PositionOrigin an_origin,
+ in PositionKey a_key)
+ raises (PositionKeyNotSupported);
+
+ void set_media_position(in Position a_position)
+ raises (PositionKeyNotSupported, InvalidPosition);
+
+ void start(in Position a_position)
+ raises(InvalidPosition);
+ void pause(in Position a_position)
+ raises(InvalidPosition);
+ void resume(in Position a_position)
+ raises(InvalidPosition);
+ void stop(in Position a_position)
+ raises(InvalidPosition);
+ void exit (); // Exits the player (not in the original spec)
+ void add_to_playlist (in string a_file);
+ // Returns the list of files in playlist
+ PlaylistSeq get_playlist ();
+ };
+};
--- /dev/null
+--- pyorbit-1.99.3/src/pycorba-orb.c 2002-11-16 07:51:41.000000000 +0100
++++ pyorbit-1.99.3-modif/src/pycorba-orb.c 2003-01-22 14:43:30.000000000 +0100
+@@ -154,6 +154,36 @@
+ return Py_None;
+ }
+
++static PyObject *
++pycorba_orb_work_pending(PyCORBA_ORB *self)
++{
++ CORBA_boolean ret;
++ CORBA_Environment ev;
++ PyObject *py_ret;
++
++ CORBA_exception_init(&ev);
++ ret = CORBA_ORB_work_pending (self->orb, &ev);
++
++ if (pyorbit_check_ex(&ev))
++ return NULL;
++ py_ret = ret ? Py_True : Py_False;
++ Py_INCREF(py_ret);
++ return py_ret;
++}
++
++static PyObject *
++pycorba_orb_perform_work (PyCORBA_ORB *self)
++{
++ CORBA_Environment ev;
++
++ CORBA_exception_init(&ev);
++ CORBA_ORB_perform_work (self->orb, &ev);
++ if (pyorbit_check_ex(&ev))
++ return NULL;
++ Py_INCREF(Py_None);
++ return Py_None;
++}
++
+ static PyMethodDef pycorba_orb_methods[] = {
+ { "object_to_string", (PyCFunction)pycorba_orb_object_to_string, METH_VARARGS },
+ { "string_to_object", (PyCFunction)pycorba_orb_string_to_object, METH_VARARGS },
+@@ -161,6 +191,8 @@
+ { "resolve_initial_references", (PyCFunction)pycorba_orb_resolve_initial_references, METH_VARARGS },
+ { "run", (PyCFunction)pycorba_orb_run, METH_NOARGS },
+ { "shutdown", (PyCFunction)pycorba_orb_shutdown, METH_VARARGS },
++ { "work_pending", (PyCFunction)pycorba_orb_work_pending, METH_VARARGS },
++ { "perform_work", (PyCFunction)pycorba_orb_perform_work, METH_VARARGS },
+ { NULL, NULL, 0 }
+ };
+
--- /dev/null
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="win">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">DVD Annote</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <signal name="delete_event" handler="on_exit" object="win" last_modification_time="Mon, 27 Jan 2003 14:07:29 GMT"/>
+ <signal name="key_press_event" handler="on_win_key_press_event" last_modification_time="Mon, 17 Feb 2003 16:23:35 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem1_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="quit1">
+ <property name="visible">True</property>
+ <property name="label">gtk-quit</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_exit" last_modification_time="Mon, 27 Jan 2003 14:07:57 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menuitem4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menuitem4_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="about1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_About</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_about1_activate" last_modification_time="Mon, 27 Jan 2003 14:07:57 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox2">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="b_rewind">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Rewind</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Rewind</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_rewind_clicked" last_modification_time="Mon, 27 Jan 2003 14:19:30 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_play">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Play</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Play</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_play_clicked" last_modification_time="Mon, 27 Jan 2003 14:19:50 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_pause">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Pause</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Pause</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_pause_clicked" last_modification_time="Mon, 27 Jan 2003 14:19:56 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_stop">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Stop</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Stop</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_stop_clicked" last_modification_time="Mon, 27 Jan 2003 14:20:03 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_forward">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Forward</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Forward</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_forward_clicked" last_modification_time="Mon, 27 Jan 2003 14:20:10 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_addfile">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Add file</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Add file...</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_addfile_clicked" last_modification_time="Mon, 27 Jan 2003 14:20:15 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_selectdvd">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Select DVD</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Play DVD</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_selectdvd_clicked" last_modification_time="Mon, 27 Jan 2003 14:20:15 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="b_exit">
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Exit</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-quit</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="on_b_exit_clicked" last_modification_time="Mon, 27 Jan 2003 14:20:26 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="Information">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">1</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">True</property>
+ <property name="row_spacing">0</property>
+ <property name="column_spacing">10</property>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Position</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">10</property>
+ <property name="ypad">2</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="position_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">N/C</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Information</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTextView" id="logmessages">
+ <property name="height_request">100</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">False</property>
+ <property name="justification">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap_mode">GTK_WRAP_CHAR</property>
+ <property name="cursor_visible">False</property>
+ <property name="pixels_above_lines">0</property>
+ <property name="pixels_below_lines">0</property>
+ <property name="pixels_inside_wrap">0</property>
+ <property name="left_margin">0</property>
+ <property name="right_margin">0</property>
+ <property name="indent">0</property>
+ <property name="text" translatable="yes"></property>
+ <signal name="insert_at_cursor" handler="on_logmessages_insert_at_cursor" last_modification_time="Mon, 27 Jan 2003 14:09:43 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="about">
+ <property name="title" translatable="yes">About</property>
+ <property name="type">GTK_WINDOW_POPUP</property>
+ <property name="window_position">GTK_WIN_POS_CENTER</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="width_request">280</property>
+ <property name="height_request">64</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">DVD Annotation
+
+En cours de developpement...</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button1">
+ <property name="border_width">1</property>
+ <property name="width_request">54</property>
+ <property name="height_request">34</property>
+ <property name="visible">True</property>
+ <property name="tooltip" translatable="yes">Close about box</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_focus">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <signal name="clicked" handler="about_hide" object="about" last_modification_time="Wed, 29 Jan 2003 12:52:15 GMT"/>
+ <accelerator key="Escape" modifiers="0" signal="clicked"/>
+ <accelerator key="Return" modifiers="0" signal="clicked"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
--- /dev/null
+#!/usr/bin/env python
+
+import sys, time
+
+# For gtk/glade
+import pygtk
+pygtk.require ('2.0')
+import gtk
+import gtk.glade
+
+# For CORBA
+import ORBit, CORBA
+# FIXME: How do we make this portable to windows ?
+ORBit.load_typelib ("./MediaControl.so")
+import VLC
+
+class Connect:
+ """Abstract class defining helper functions to interconnect
+ glade XML files and methods of a python class."""
+ def create_dictionary (self):
+ """Create a (name, function) dictionnary for the current class"""
+ dict = {}
+ self.create_dictionary_for_class (self.__class__, dict)
+ return dict
+
+ def create_dictionary_for_class (self, a_class, dict):
+ """Create a (name, function) dictionnary for the specified class"""
+ bases = a_class.__bases__
+ for iteration in bases:
+ self.create_dictionary_for_class (iteration, dict)
+ for iteration in dir(a_class):
+ dict[iteration] = getattr(self, iteration)
+
+ def connect (self):
+ """Connects the class methods with the UI"""
+ self.gui.signal_autoconnect(self.create_dictionary ())
+
+ def gtk_widget_hide (self, widget):
+ widget.hide ()
+ return gtk.TRUE
+
+ def on_exit(self, source=None, event=None):
+ """Generic exit callback"""
+ gtk.main_quit()
+
+class DVDControl (Connect):
+ def __init__ (self, gladefile):
+ """Initializes the GUI and other attributes"""
+ # Glade init.
+ self.gui = gtk.glade.XML(gladefile)
+ self.connect ()
+ # Frequently used GUI widgets
+ self.gui.logmessages = self.gui.get_widget("logmessages")
+ self.gui.position_label = self.gui.get_widget("position_label")
+ self.gui.fs = gtk.FileSelection ("Select a file")
+ self.gui.fs.ok_button.connect_after ("clicked", lambda win: self.gui.fs.hide ())
+ self.gui.fs.cancel_button.connect ("clicked", lambda win: self.gui.fs.destroy ())
+
+ # CORBA init.
+ self.mc = None
+ self.currentpos = None
+ self.status = None
+ # FIXME: portability
+ self.iorfile = "/tmp/vlc-ior.ref"
+
+ # Various
+ # Default FF/RW time : 5 seconds
+ self.default_time_increment = 5
+
+ def update_title (self, title):
+ # Update the title of the main window
+ self.gui.get_widget ("win").set_title (title)
+
+ def launch_player (self):
+ """Launch the VLC corba plugin"""
+ #print "Launching vlc server..."
+ # FIXME: spawn is portable, but how can we make sure that
+ # launch-vlc-corba launches the application in the background ?
+ # FIXME: portability
+ import distutils.spawn
+ distutils.spawn.spawn (["launch-vlc-corba"], True, True)
+ # Wait a little for the server to initialize. We could instead test
+ # on the existence and validity of self.iorfile
+ time.sleep (2)
+ return
+
+ def main (self):
+ """Mainloop : CORBA initalization and Gtk mainloop setup"""
+ self.orb = CORBA.ORB_init(sys.argv)
+
+ errormessage = """Unable to get a MediaControl object
+Please try to run the following command:
+vlc --intf corba"""
+
+ try:
+ ior = open(self.iorfile).readline()
+ except:
+ # The iorfile does not existe : the player is maybe not active
+ self.launch_player ()
+ try:
+ ior = open(self.iorfile).readline()
+ except:
+ print errormessage
+ sys.exit(1)
+
+ self.mc = self.orb.string_to_object(ior)
+
+ if self.mc._non_existent ():
+ # The remote object is not available. Let's run the
+ # VLC server
+ self.launch_player ()
+ try:
+ ior = open(self.iorfile).readline()
+ except:
+ print errormessage
+ sys.exit(1)
+ self.mc = self.orb.string_to_object(ior)
+ if self.mc._non_existent ():
+ print errormessage
+ sys.exit(1)
+
+ self.currentpos = VLC.Position ()
+ self.currentpos.value = 0
+ self.currentpos.key = VLC.MediaTime
+ self.currentpos.origin = VLC.RelativePosition
+
+ gtk.timeout_add (20, self.update_display, self.orb)
+ gtk.main ()
+
+ def log (self, msg):
+ """Adds a new log message to the logmessage window"""
+ buf = self.gui.logmessages.get_buffer ()
+ mes = str(msg) + "\n"
+ buf.insert_at_cursor (mes, len(mes))
+
+ endmark = buf.create_mark ("end",
+ buf.get_end_iter (),
+ gtk.TRUE)
+ self.gui.logmessages.scroll_mark_onscreen (endmark)
+ return
+
+ def on_exit (self, source=None, event=None):
+ """General exit callback"""
+ self.status = "Stop"
+ # Terminate the VLC server
+ try:
+ self.mc.exit()
+ except:
+ pass
+ gtk.main_quit ()
+
+ def file_selector (self, callback=None, label="Select a file",
+ default=""):
+ """Display the file selector"""
+ self.gui.fs.set_property ("title", label)
+ self.gui.fs.set_property ("filename", default)
+ self.gui.fs.set_property ("select-multiple", False)
+ self.gui.fs.set_property ("show-fileops", False)
+
+ if callback:
+ # Disconnecting the old callback
+ try:
+ self.gui.fs.ok_button.disconnect (self.gui.fs.connect_id)
+ except:
+ pass
+ # Connecting the new one
+ self.gui.fs.connect_id = self.gui.fs.ok_button.connect ("clicked", callback, self.gui.fs)
+ self.gui.fs.show ()
+ return gtk.TRUE
+
+ def file_selected_cb (self, button, fs):
+ """Open and play the selected movie file"""
+ file = self.gui.fs.get_property ("filename")
+ self.mc.add_to_playlist (file)
+ self.status = "Play"
+ return gtk.TRUE
+
+ def move_position (self, value):
+ """Helper function : fast forward or rewind by value seconds"""
+ print "Moving by %d seconds" % value
+ pos = VLC.Position ()
+ pos.value = value
+ pos.key = VLC.MediaTime
+ pos.origin = VLC.RelativePosition
+ self.mc.set_media_position (pos)
+ return
+
+ def update_display (self, orb):
+ """Update the interface"""
+ if self.status == "Play":
+ pos = self.mc.get_media_position (VLC.AbsolutePosition,
+ VLC.ByteCount)
+ self.gui.position_label.set_text (str(pos.value))
+ elif self.status == "Stop":
+ self.gui.position_label.set_text ("N/C")
+ return gtk.TRUE
+
+ # Callbacks function. Skeletons can be generated by glade2py
+ def on_win_key_press_event (self, win=None, event=None):
+ # Navigation keys
+ if event.keyval == gtk.keysyms.Tab:
+ self.on_b_pause_clicked (win, event)
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.Right:
+ self.on_b_forward_clicked (win, event)
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.Left:
+ self.on_b_rewind_clicked (win, event)
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.Home:
+ pos = VLC.Position ()
+ pos.value = 0
+ pos.key = VLC.MediaTime
+ pos.origin = VLC.AbsolutePosition
+ self.mc.set_media_position (pos)
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.End:
+ pos = VLC.Position ()
+ pos.value = -self.default_time_increment
+ pos.key = VLC.MediaTime
+ pos.origin = VLC.ModuloPosition
+ self.mc.set_media_position (pos)
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.Page_Down:
+ # FIXME: Next chapter
+ return gtk.TRUE
+ elif event.keyval == gtk.keysyms.Page_Up:
+ # FIXME: Previous chapter
+ return gtk.TRUE
+ return gtk.TRUE
+
+ def on_quit1_activate (self, button=None, data=None):
+ """Gtk callback to quit"""
+ self.on_exit (button, data)
+ return gtk.TRUE
+
+ def on_about1_activate (self, button=None, data=None):
+ self.gui.get_widget("about").show ()
+ return gtk.TRUE
+
+ def about_hide (self, button=None, data=None):
+ self.gui.get_widget("about").hide ()
+ return gtk.TRUE
+
+ def on_b_rewind_clicked (self, button=None, data=None):
+ if self.status == "Play":
+ self.move_position (-self.default_time_increment)
+ return gtk.TRUE
+
+ def on_b_play_clicked (self, button=None, data=None):
+ if self.status != "Play":
+ self.mc.start (self.currentpos)
+ self.status = "Play"
+ return gtk.TRUE
+
+ def on_b_pause_clicked (self, button=None, data=None):
+ if self.status == "Play":
+ self.mc.pause (self.currentpos)
+ self.status = "Pause"
+ elif self.status == "Pause":
+ self.mc.pause (self.currentpos)
+ self.status = "Play"
+ return gtk.TRUE
+
+ def on_b_stop_clicked (self, button=None, data=None):
+ self.mc.stop (self.currentpos)
+ self.status = "Stop"
+ return gtk.TRUE
+
+ def on_b_forward_clicked (self, button=None, data=None):
+ if self.status == "Play":
+ self.move_position (self.default_time_increment)
+ return gtk.TRUE
+
+ def on_b_addfile_clicked (self, button=None, data=None):
+ self.file_selector (callback=self.file_selected_cb,
+ label="Play a movie file")
+ return gtk.TRUE
+
+ def on_b_selectdvd_clicked (self, button=None, data=None):
+ """Play a DVD"""
+ self.mc.add_to_playlist ("dvd:///dev/dvd at 1,1")
+ self.mc.start (self.currentpos)
+ self.status = "Play"
+ return gtk.TRUE
+
+ def on_b_exit_clicked (self, button=None, data=None):
+ self.on_exit (button, data)
+ return gtk.TRUE
+
+ def on_logmessages_insert_at_cursor (self, button=None, data=None):
+ print "on_logmessages_insert_at_cursor activated (%s, %s, %s)" % (self, button, data)
+ # FIXME: faire défiler la scrollmark (cf gtkshell)
+ return gtk.TRUE
+
+if __name__ == '__main__':
+ v = DVDControl ("simpleplayer.glade")
+ v.main ()
* playlist.c : Playlist management functions
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: playlist.c,v 1.40 2003/06/27 13:38:54 sam Exp $
+ * $Id: playlist.c,v 1.41 2003/07/07 16:59:00 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
p_playlist->i_status = PLAYLIST_RUNNING;
if( p_playlist->p_input )
{
+ PlayItem( p_playlist );
input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY );
}
break;