Commit 34f23746 authored by Sam Hocevar's avatar Sam Hocevar

* 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.
parent 76bbfbac
dnl Autoconf settings for vlc 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) AC_INIT(vlc,0.6.0)
...@@ -2930,6 +2930,37 @@ then ...@@ -2930,6 +2930,37 @@ then
fi fi
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:]) AC_ARG_WITH(,[Misc options:])
dnl dnl
...@@ -3237,6 +3268,7 @@ AC_OUTPUT([ ...@@ -3237,6 +3268,7 @@ AC_OUTPUT([
modules/codec/mpeg_video/motion/Makefile modules/codec/mpeg_video/motion/Makefile
modules/codec/spudec/Makefile modules/codec/spudec/Makefile
modules/control/Makefile modules/control/Makefile
modules/control/corba/Makefile
modules/control/lirc/Makefile modules/control/lirc/Makefile
modules/control/rc/Makefile modules/control/rc/Makefile
modules/demux/Makefile modules/demux/Makefile
......
.deps
.dirstamp
*.lo
*.la
*.dll
*.dylib
*.sl
*.so
Makefile.am
Makefile.in
Makefile
## 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
$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
#! /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
/*****************************************************************************
* 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 units 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 vrif d'vnements 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;
}
#! /bin/sh
# Helper prog
VLCPATH=/usr/local/src/vlc
cd $VLCPATH
${VLCPATH}/vlc --intf corba &
exit 0
/* 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 ();
};
};
--- 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 }
};
<?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>
#!/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 dfiler la scrollmark (cf gtkshell)
return gtk.TRUE
if __name__ == '__main__':
v = DVDControl ("simpleplayer.glade")
v.main ()
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* playlist.c : Playlist management functions * playlist.c : Playlist management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * 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> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -412,6 +412,7 @@ void playlist_Command( playlist_t * p_playlist, int i_command, int i_arg ) ...@@ -412,6 +412,7 @@ void playlist_Command( playlist_t * p_playlist, int i_command, int i_arg )
p_playlist->i_status = PLAYLIST_RUNNING; p_playlist->i_status = PLAYLIST_RUNNING;
if( p_playlist->p_input ) if( p_playlist->p_input )
{ {
PlayItem( p_playlist );
input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY ); input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY );
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment