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 $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
......
.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