From 34f237461596f6e3b79b81a982b11113978b78a4 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 7 Jul 2003 16:59:00 +0000 Subject: [PATCH] * modules/control/corba/: Olivier Aubert's CORBA plugin. Almost verbatim, compiles cleanly (to build the medicacontrol.so library you need to cd to that directory and "make medicacontrol.so") but untested. * src/playlist/playlist.c: Mostly harmless fix to playlist.c suggested by Olivier. --- configure.ac | 34 +- modules/control/corba/.cvsignore | 11 + modules/control/corba/Modules.am | 25 + modules/control/corba/README | 64 ++ modules/control/corba/client.py | 34 + modules/control/corba/corba.c | 861 +++++++++++++++++++++ modules/control/corba/launch-vlc-corba | 7 + modules/control/corba/mediacontrol.idl | 55 ++ modules/control/corba/pyorbit-1.99.3.patch | 48 ++ modules/control/corba/simpleplayer.glade | 402 ++++++++++ modules/control/corba/simpleplayer.py | 298 +++++++ src/playlist/playlist.c | 3 +- 12 files changed, 1840 insertions(+), 2 deletions(-) create mode 100644 modules/control/corba/.cvsignore create mode 100644 modules/control/corba/Modules.am create mode 100644 modules/control/corba/README create mode 100644 modules/control/corba/client.py create mode 100644 modules/control/corba/corba.c create mode 100644 modules/control/corba/launch-vlc-corba create mode 100644 modules/control/corba/mediacontrol.idl create mode 100644 modules/control/corba/pyorbit-1.99.3.patch create mode 100644 modules/control/corba/simpleplayer.glade create mode 100644 modules/control/corba/simpleplayer.py diff --git a/configure.ac b/configure.ac index f423f7ac97..9abbd4c014 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ 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) @@ -2930,6 +2930,37 @@ then 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 @@ -3237,6 +3268,7 @@ AC_OUTPUT([ 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 diff --git a/modules/control/corba/.cvsignore b/modules/control/corba/.cvsignore new file mode 100644 index 0000000000..c930ed7c2c --- /dev/null +++ b/modules/control/corba/.cvsignore @@ -0,0 +1,11 @@ +.deps +.dirstamp +*.lo +*.la +*.dll +*.dylib +*.sl +*.so +Makefile.am +Makefile.in +Makefile diff --git a/modules/control/corba/Modules.am b/modules/control/corba/Modules.am new file mode 100644 index 0000000000..fe80bffaed --- /dev/null +++ b/modules/control/corba/Modules.am @@ -0,0 +1,25 @@ +## 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 + diff --git a/modules/control/corba/README b/modules/control/corba/README new file mode 100644 index 0000000000..aa99b49847 --- /dev/null +++ b/modules/control/corba/README @@ -0,0 +1,64 @@ +$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 (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 diff --git a/modules/control/corba/client.py b/modules/control/corba/client.py new file mode 100644 index 0000000000..d23006c3a0 --- /dev/null +++ b/modules/control/corba/client.py @@ -0,0 +1,34 @@ +#! /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 + diff --git a/modules/control/corba/corba.c b/modules/control/corba/corba.c new file mode 100644 index 0000000000..4288183f2c --- /dev/null +++ b/modules/control/corba/corba.c @@ -0,0 +1,861 @@ +/***************************************************************************** + * 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 + * + * 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 +#include +#include +#include + +#include /* malloc(), free() */ +#include + +#include /* ENOMEM */ +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_SYS_TIME_H +# include +#endif +#include + +/***************************************************************************** + * 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; +} diff --git a/modules/control/corba/launch-vlc-corba b/modules/control/corba/launch-vlc-corba new file mode 100644 index 0000000000..2647af395d --- /dev/null +++ b/modules/control/corba/launch-vlc-corba @@ -0,0 +1,7 @@ +#! /bin/sh +# Helper prog +VLCPATH=/usr/local/src/vlc +cd $VLCPATH +${VLCPATH}/vlc --intf corba & +exit 0 + diff --git a/modules/control/corba/mediacontrol.idl b/modules/control/corba/mediacontrol.idl new file mode 100644 index 0000000000..8fdda03011 --- /dev/null +++ b/modules/control/corba/mediacontrol.idl @@ -0,0 +1,55 @@ +/* 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 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 (); + }; +}; diff --git a/modules/control/corba/pyorbit-1.99.3.patch b/modules/control/corba/pyorbit-1.99.3.patch new file mode 100644 index 0000000000..7c4cefa9a0 --- /dev/null +++ b/modules/control/corba/pyorbit-1.99.3.patch @@ -0,0 +1,48 @@ +--- 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 } + }; + diff --git a/modules/control/corba/simpleplayer.glade b/modules/control/corba/simpleplayer.glade new file mode 100644 index 0000000000..da6aebc1c3 --- /dev/null +++ b/modules/control/corba/simpleplayer.glade @@ -0,0 +1,402 @@ + + + + + + + True + DVD Annote + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + gtk-quit + True + + + + + + + + + + + True + _Help + True + + + + + + + True + _About + True + + + + + + + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_SPREAD + 0 + + + + True + Rewind + True + True + Rewind + True + GTK_RELIEF_NORMAL + + + + + + + True + Play + True + True + Play + True + GTK_RELIEF_NORMAL + + + + + + + True + Pause + True + True + Pause + True + GTK_RELIEF_NORMAL + + + + + + + True + Stop + True + True + Stop + True + GTK_RELIEF_NORMAL + + + + + + + True + Forward + True + True + Forward + True + GTK_RELIEF_NORMAL + + + + + + + True + Add file + True + True + Add file... + True + GTK_RELIEF_NORMAL + + + + + + + True + Select DVD + True + True + Play DVD + True + GTK_RELIEF_NORMAL + + + + + + + True + Exit + True + True + gtk-quit + True + GTK_RELIEF_NORMAL + + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 1 + 2 + True + 0 + 10 + + + + True + Position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 2 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + N/C + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + + + True + Information + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + 100 + True + True + False + GTK_JUSTIFY_LEFT + GTK_WRAP_CHAR + False + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + 0 + True + True + + + + + + + + About + GTK_WINDOW_POPUP + GTK_WIN_POS_CENTER + False + True + False + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + 280 + 64 + True + DVD Annotation + +En cours de developpement... + False + True + GTK_JUSTIFY_CENTER + True + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + 1 + 54 + 34 + True + Close about box + True + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + + + + + + 0 + False + False + + + + + + + + + diff --git a/modules/control/corba/simpleplayer.py b/modules/control/corba/simpleplayer.py new file mode 100644 index 0000000000..d437119495 --- /dev/null +++ b/modules/control/corba/simpleplayer.py @@ -0,0 +1,298 @@ +#!/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 () diff --git a/src/playlist/playlist.c b/src/playlist/playlist.c index fe8ae74271..c6149d1357 100644 --- a/src/playlist/playlist.c +++ b/src/playlist/playlist.c @@ -2,7 +2,7 @@ * 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 * @@ -412,6 +412,7 @@ void playlist_Command( playlist_t * p_playlist, int i_command, int i_arg ) p_playlist->i_status = PLAYLIST_RUNNING; if( p_playlist->p_input ) { + PlayItem( p_playlist ); input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY ); } break;