Commit 12535c3e authored by Olivier Aubert's avatar Olivier Aubert

CORBA module update:

- the VLC-specific code has been isolated in mediacontrol-core.c so that
  corba.c only has to glue CORBA calls to C calls.
- the IDL has been modified:
  - snapshot support
  - text display support
  - access to stream information
  - access to volume information
parent 00048eb9
/* Cf /*
http://www.cs.rpi.edu/~musser/dsc/idl/idl-overview.html Module inspired by the MediaControl IDL
pour une intro à la syntaxe */ */
module VLC { module VLC {
const float VERSION = 0.1;
enum PositionOrigin { enum PositionOrigin {
AbsolutePosition, RelativePosition, ModuloPosition AbsolutePosition, RelativePosition, ModuloPosition
}; };
...@@ -14,13 +16,37 @@ module VLC { ...@@ -14,13 +16,37 @@ module VLC {
struct Position { struct Position {
PositionOrigin origin; PositionOrigin origin;
PositionKey key; PositionKey key;
long value; long long value;
}; };
exception PositionKeyNotSupported { PositionKey key;}; exception PositionKeyNotSupported { string message; };
exception InvalidPosition { PositionKey key;}; exception PositionOriginNotSupported { string message; };
exception InvalidPosition { string message; };
exception PlaylistException { string message; };
exception InternalException { string message; };
typedef sequence<string> PlaylistSeq; typedef sequence<string> PlaylistSeq;
typedef sequence<octet> ByteSeq;
struct RGBPicture {
short width;
short height;
long type;
ByteSeq data;
long long date;
};
typedef sequence<RGBPicture> RGBPictureSeq;
/* Cf stream_control.h */
enum PlayerStatus { PlayingStatus, PauseStatus, ForwardStatus, BackwardStatus, InitStatus, EndStatus, UndefinedStatus };
struct StreamInformation {
PlayerStatus streamstatus;
string url; /* The URL of the current media stream */
long long position; /* actual location in the stream (in ms) */
long long length; /* total length of the stream (in ms) */
};
// MediaControl interface is similar to // MediaControl interface is similar to
// ControlledStream interface in MSS. // ControlledStream interface in MSS.
...@@ -28,28 +54,51 @@ module VLC { ...@@ -28,28 +54,51 @@ module VLC {
// FlowConnection interfaces. // FlowConnection interfaces.
interface MediaControl interface MediaControl
{ {
Position get_media_position(in PositionOrigin an_origin,
exception PositionKeyNotSupported { PositionKey key;};
Position get_media_position(
in PositionOrigin an_origin,
in PositionKey a_key) in PositionKey a_key)
raises (PositionKeyNotSupported); raises (InternalException, PositionKeyNotSupported);
void set_media_position(in Position a_position) void set_media_position(in Position a_position)
raises (PositionKeyNotSupported, InvalidPosition); raises (InternalException, PositionKeyNotSupported, InvalidPosition);
void start(in Position a_position) void start(in Position a_position)
raises(InvalidPosition); raises (InternalException, InvalidPosition, PlaylistException);
void pause(in Position a_position) void pause(in Position a_position)
raises(InvalidPosition); raises (InternalException, InvalidPosition);
void resume(in Position a_position) void resume(in Position a_position)
raises(InvalidPosition); raises (InternalException, InvalidPosition);
void stop(in Position a_position) void stop(in Position a_position)
raises(InvalidPosition); raises (InternalException, InvalidPosition);
void exit (); // Exits the player (not in the original spec)
void add_to_playlist (in string a_file); oneway void exit (); // Exits the player (not in the original spec)
void playlist_add_item (in string a_file)
raises (PlaylistException);
void playlist_clear ()
raises (PlaylistException);
// Returns the list of files in playlist // Returns the list of files in playlist
PlaylistSeq get_playlist (); PlaylistSeq playlist_get_list ()
raises (PlaylistException);
// Returns a snapshot of the currently displayed picture
RGBPicture snapshot (in Position a_position)
raises (InternalException);
RGBPictureSeq all_snapshots ()
raises (InternalException);
// Displays the message string, between "begin" and "end" positions
void display_text (in string message, in Position begin, in Position end)
raises (InternalException);
StreamInformation get_stream_information ()
raises (InternalException);
unsigned short sound_get_volume()
raises (InternalException);
void sound_set_volume(in unsigned short volume)
raises (InternalException);
}; };
}; };
## corba module declaration ## corba module declaration
SOURCES_corba = corba.c SOURCES_corba = corba.c mediacontrol-core.c mediacontrol-plugin.c
EXTRA_DIST = MediaControl.so
nodist_SOURCES_corba = \ nodist_SOURCES_corba = \
mediacontrol-common.c \ MediaControl-common.c \
mediacontrol-skels.c \ MediaControl-skels.c \
mediacontrol.h \ MediaControl.h \
$(NULL) $(NULL)
ORBITIDL = orbit-idl-2 ORBITIDL = orbit-idl-2
mediacontrol-common.c mediacontrol-skels.c mediacontrol-stubs.c mediacontrol.h: GENERATEDFILES=MediaControl-common.c MediaControl-skels.c MediaControl.h MediaControl-imodule.c
$(ORBITIDL) --skeleton-impl mediacontrol.idl
corba.c: MediaControl.h MediaControl-common.c
$(GENERATEDFILES): MediaControl.idl
$(ORBITIDL) --skeleton-impl MediaControl.idl
mediacontrol-imodule.c: MediaControl-imodule.c:
$(ORBITIDL) --imodule mediacontrol.idl $(ORBITIDL) --imodule MediaControl.idl
mediacontrol.so: mediacontrol-imodule.c MediaControl.so: MediaControl-imodule.c
gcc -fPIC -o mediacontrol-imodule.o -c mediacontrol-imodule.c `pkg-config --cflags ORBit-2.0` $(CC) -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` $(CC) -shared -o $@ MediaControl-imodule.o `pkg-config --libs ORBit-2.0`
clean: clean:
rm -f mediacontrol-stubs.c mediacontrol-imodule.c mediacontrol-skelimpl.c $(RM) -f $(GENERATEDFILES)
$Id: README,v 1.2 2004/01/25 16:17:03 anil Exp $ * Corba module (server) side
* Module (server) side
** Dependencies ** Dependencies
To compile the CORBA module, you need the orbit2 developpement files To compile the CORBA plugin, you need the orbit2 developpement files
(for Debian, install the package liborbi2-dev) (for Debian, install the package liborbit2-dev)
** How to run it ? ** How to run it ?
...@@ -13,24 +13,27 @@ vlc --intf corba ...@@ -13,24 +13,27 @@ vlc --intf corba
The CORBA module is initialized and saves its IOR into the file The CORBA module is initialized and saves its IOR into the file
/tmp/vlc-ior.ref /tmp/vlc-ior.ref
(it will soon move to $HOME/.vlc-ior.ref)
** Code architecture
The binding between VLC and the MediaControl API (at C-level) is done
through the mediacontrol-core.c file. This file implements an
object-oriented layer API accessible in C.
The corba.c itself only translates calls from CORBA to this C API,
which makes the code clearer overall. Moreover, the same
mediacontrol-core.c file is used by the vlc-python module to implement the
same API.
* Client side * Client side
A sample client application is provided, using python-orbit A sample client code can be found at http://liris.cnrs.fr/advene/
** Dependencies ** Dependencies
The python client uses the pyorbit library developped by James The python client uses the pyorbit library developped by James
Henstridge <james at daa dot com dot au> (source: Henstridge <james@daa.com.au>
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 ** Typelib information
...@@ -40,12 +43,6 @@ use the structures defined in the IDL (Position, Origin, ...), you ...@@ -40,12 +43,6 @@ use the structures defined in the IDL (Position, Origin, ...), you
need to use the IDL information, and compile a dynamic lib need to use the IDL information, and compile a dynamic lib
(MediaControl.so) from the IDL. (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 * Interesting pointers
- GLib reference manual - GLib reference manual
...@@ -54,11 +51,3 @@ http://developer.gnome.org/doc/API/glib/ ...@@ -54,11 +51,3 @@ http://developer.gnome.org/doc/API/glib/
- IDL quickref : - IDL quickref :
http://www.cs.rpi.edu/~musser/dsc/idl/idl-overview.html 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
/***************************************************************************** /*****************************************************************************
* corba.c : CORBA (ORBit) remote control module for vlc * corba.c : CORBA (ORBit) remote control plugin for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: corba.c,v 1.4 2004/01/25 16:17:03 anil Exp $ * $Id$
* *
* Authors: Olivier Aubert <oaubert at lisi dot univ-lyon1 dot fr> * Authors: Olivier Aubert <oaubert@lisi.univ-lyon1.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -25,9 +25,33 @@ ...@@ -25,9 +25,33 @@
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
/* For CORBA */ /* For CORBA */
#include "mediacontrol.h" #include "MediaControl.h"
#include "orbit/poa/portableserver-poa-type.h" #include "orbit/poa/portableserver-poa-type.h"
#include "mediacontrol-core.h"
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/vout.h>
#include <vlc/aout.h>
#include <errno.h>
#include <unistd.h>
/* FIXME: replace this to ~/.vlc/vlc-ior.ref thanks to
config_GetHomeDir() */
#ifndef __WIN32__
#define VLC_IOR_FILE "/tmp/vlc-ior.ref" #define VLC_IOR_FILE "/tmp/vlc-ior.ref"
#else
#define VLC_IOR_FILE "vlc-ior-ref"
#endif
#define MC_TRY exception=mediacontrol_exception_init(exception)
#define MC_EXCEPT(return_value) \
if (exception->code) { \
corba_raise(ev, exception); \
mediacontrol_exception_free(exception); \
return return_value; \
} else { mediacontrol_exception_free(exception); }
#define handle_exception(m) if(ev->_major != CORBA_NO_EXCEPTION) \ #define handle_exception(m) if(ev->_major != CORBA_NO_EXCEPTION) \
{ \ { \
...@@ -35,130 +59,81 @@ ...@@ -35,130 +59,81 @@
return; \ return; \
} }
#define handle_exception_no_servant(p,m) if(ev->_major != CORBA_NO_EXCEPTION) \ #define handle_exception_no_servant(p,m) if(ev->_major != CORBA_NO_EXCEPTION) \
{ \ { \
msg_Err (p, m); \ msg_Err (p, m); \
return; \ return; \
} }
#include <vlc/vlc.h> static void corba_raise(CORBA_Environment *ev, mediacontrol_Exception *exception)
#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; char *corba_exception=NULL;
char* i_type = NULL;
l_res = -1; switch (exception->code)
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; case mediacontrol_InternalException:
corba_exception = (char*)VLC_InternalException__alloc ();
i_type = ex_VLC_InternalException;
break;
case mediacontrol_PlaylistException:
corba_exception = (char*)VLC_PlaylistException__alloc ();
i_type = ex_VLC_PlaylistException;
break;
case mediacontrol_InvalidPosition:
corba_exception = (char*)VLC_InvalidPosition__alloc ();
i_type = ex_VLC_InvalidPosition;
break;
case mediacontrol_PositionKeyNotSupported:
corba_exception = (char*)VLC_PositionKeyNotSupported__alloc ();
i_type = ex_VLC_PositionKeyNotSupported;
break;
case mediacontrol_PositionOriginNotSupported:
corba_exception = (char*)VLC_PositionOriginNotSupported__alloc ();
i_type = ex_VLC_PositionOriginNotSupported;
break;
} }
return l_res; ((VLC_InternalException*)corba_exception)->message = CORBA_string_dup(exception->message);
CORBA_exception_set (ev, CORBA_USER_EXCEPTION, i_type, corba_exception);
return;
} }
/* Convert seconds to an offset */ static mediacontrol_Position* corba_position_corba_to_c (const VLC_Position* position)
off_t secondsToOffset (input_thread_t *p_input, long long l_seconds)
{ {
off_t l_res; mediacontrol_Position* retval;
l_res = -1; retval = (mediacontrol_Position*)malloc(sizeof(mediacontrol_Position));
if (! retval)
if (p_input != NULL) return NULL;
{ retval->origin = position->origin;
l_res = (off_t) l_seconds * 50 * p_input->stream.i_mux_rate; retval->key = position->key;
} retval->value = position->value;
return l_res; return retval;
} }
static VLC_Position* corba_position_c_to_corba(const mediacontrol_Position* position)
/* Convert milliseconds to an offset */
off_t millisecondsToOffset (input_thread_t *p_input, long long l_milliseconds)
{ {
off_t l_res; VLC_Position* retval;
l_res = -1; retval = (VLC_Position*)malloc(sizeof(VLC_Position));
if (p_input != NULL) if (! retval)
{ return NULL;
l_res = (off_t) l_milliseconds * 50 * p_input->stream.i_mux_rate / 1000; retval->origin = position->origin;
} retval->key = position->key;
return l_res; retval->value = position->value;
return retval;
} }
/* Returns the current offset. */ /*****************************************************************************
off_t currentOffset (input_thread_t *p_input) * intf_sys_t: description and status of corba interface
*****************************************************************************/
struct intf_sys_t
{ {
off_t l_offset; CORBA_ORB orb;
GMainLoop* corbaloop;
if( p_input == NULL ) mediacontrol_Instance *mc;
{ msg_subscription_t* p_sub; /* message bank subscription */
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 ***/ /*** App-specific servant structures ***/
...@@ -171,13 +146,12 @@ typedef struct ...@@ -171,13 +146,12 @@ typedef struct
POA_VLC_MediaControl servant; POA_VLC_MediaControl servant;
PortableServer_POA poa; PortableServer_POA poa;
/* Ajouter ici les attributs utiles */ /* Ajouter ici les attributs utiles */
mediacontrol_Instance *mc;
intf_thread_t *p_intf; intf_thread_t *p_intf;
} } impl_POA_VLC_MediaControl;
impl_POA_VLC_MediaControl;
/* Beginning of the CORBA code generated in Mediacontrol-skelimpl.c */ /* Beginning of the CORBA code generated in Mediacontrol-skelimpl.c */
/* BEGIN INSERT */ /* BEGIN INSERT */
/*** Implementation stub prototypes ***/ /*** Implementation stub prototypes ***/
static void impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl * static void impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl *
...@@ -219,19 +193,53 @@ impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant, ...@@ -219,19 +193,53 @@ impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev); CORBA_Environment * ev);
static void static void
impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_playlist_add_item(impl_POA_VLC_MediaControl * servant,
const CORBA_char * a_file, const CORBA_char * a_file,
CORBA_Environment * ev); CORBA_Environment * ev);
static void
impl_VLC_MediaControl_playlist_clear(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev);
static VLC_PlaylistSeq static VLC_PlaylistSeq
*impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant, *impl_VLC_MediaControl_playlist_get_list(impl_POA_VLC_MediaControl *
servant, CORBA_Environment * ev);
static VLC_RGBPicture
*impl_VLC_MediaControl_snapshot(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position,
CORBA_Environment * ev);
static VLC_RGBPictureSeq
*impl_VLC_MediaControl_all_snapshots(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev);
static void
impl_VLC_MediaControl_display_text(impl_POA_VLC_MediaControl * servant,
const CORBA_char * message,
const VLC_Position * begin,
const VLC_Position * end,
CORBA_Environment * ev);
static VLC_StreamInformation
*impl_VLC_MediaControl_get_stream_information(impl_POA_VLC_MediaControl *
servant,
CORBA_Environment * ev);
static CORBA_unsigned_short
impl_VLC_MediaControl_sound_get_volume(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev);
static void
impl_VLC_MediaControl_sound_set_volume(impl_POA_VLC_MediaControl * servant,
const CORBA_unsigned_short volume,
CORBA_Environment * ev); CORBA_Environment * ev);
/*** epv structures ***/ /*** epv structures ***/
static PortableServer_ServantBase__epv impl_VLC_MediaControl_base_epv = { static PortableServer_ServantBase__epv impl_VLC_MediaControl_base_epv = {
NULL, /* _private data */ NULL, /* _private data */
NULL, /* finalize routine */ (gpointer) & impl_VLC_MediaControl__destroy, /* finalize routine */
NULL, /* default_POA routine */ NULL, /* default_POA routine */
}; };
static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = { static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = {
...@@ -251,9 +259,23 @@ static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = { ...@@ -251,9 +259,23 @@ static POA_VLC_MediaControl__epv impl_VLC_MediaControl_epv = {
(gpointer) & impl_VLC_MediaControl_exit, (gpointer) & impl_VLC_MediaControl_exit,
(gpointer) & impl_VLC_MediaControl_add_to_playlist, (gpointer) & impl_VLC_MediaControl_playlist_add_item,
(gpointer) & impl_VLC_MediaControl_playlist_clear,
(gpointer) & impl_VLC_MediaControl_get_playlist, (gpointer) & impl_VLC_MediaControl_playlist_get_list,
(gpointer) & impl_VLC_MediaControl_snapshot,
(gpointer) & impl_VLC_MediaControl_all_snapshots,
(gpointer) & impl_VLC_MediaControl_display_text,
(gpointer) & impl_VLC_MediaControl_get_stream_information,
(gpointer) & impl_VLC_MediaControl_sound_get_volume,
(gpointer) & impl_VLC_MediaControl_sound_set_volume,
}; };
...@@ -275,8 +297,16 @@ impl_VLC_MediaControl__create(PortableServer_POA poa, CORBA_Environment * ev) ...@@ -275,8 +297,16 @@ impl_VLC_MediaControl__create(PortableServer_POA poa, CORBA_Environment * ev)
newservant = g_new0(impl_POA_VLC_MediaControl, 1); newservant = g_new0(impl_POA_VLC_MediaControl, 1);
newservant->servant.vepv = &impl_VLC_MediaControl_vepv; newservant->servant.vepv = &impl_VLC_MediaControl_vepv;
newservant->poa = poa; newservant->poa =
(PortableServer_POA) CORBA_Object_duplicate((CORBA_Object) poa, ev);
POA_VLC_MediaControl__init((PortableServer_Servant) newservant, ev); POA_VLC_MediaControl__init((PortableServer_Servant) newservant, ev);
/* Before servant is going to be activated all
* private attributes must be initialized. */
/* ------ init private attributes here ------ */
newservant->mc = NULL;
/* ------ ---------- end ------------- ------ */
objid = PortableServer_POA_activate_object(poa, newservant, ev); objid = PortableServer_POA_activate_object(poa, newservant, ev);
CORBA_free(objid); CORBA_free(objid);
retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
...@@ -288,17 +318,18 @@ static void ...@@ -288,17 +318,18 @@ static void
impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl__destroy(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
PortableServer_ObjectId *objid; CORBA_Object_release((CORBA_Object) servant->poa, ev);
objid = PortableServer_POA_servant_to_id(servant->poa, servant, ev); /* No further remote method calls are delegated to
PortableServer_POA_deactivate_object(servant->poa, objid, ev); * servant and you may free your private attributes. */
CORBA_free(objid); /* ------ free private attributes here ------ */
/* ------ ---------- end ------------- ------ */
POA_VLC_MediaControl__fini((PortableServer_Servant) servant, ev); POA_VLC_MediaControl__fini((PortableServer_Servant) servant, ev);
g_free(servant);
} }
/* END INSERT */ /* END INSERT */
/* Beginning of the CORBA functions that we define */ /* Beginning of the CORBA functions that we define */
/* Returns the current position in the stream. The returned value can /* Returns the current position in the stream. The returned value can
...@@ -310,64 +341,17 @@ impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant, ...@@ -310,64 +341,17 @@ impl_VLC_MediaControl_get_media_position(impl_POA_VLC_MediaControl * servant,
const VLC_PositionKey a_key, const VLC_PositionKey a_key,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
VLC_Position retval; VLC_Position* retval = NULL;
off_t l_offset; mediacontrol_Position *p_pos;
VLC_PositionKeyNotSupported *exception; mediacontrol_Exception *exception = NULL;
input_thread_t * p_input = servant->p_intf->p_sys->p_input;
/* msg_Warn (servant->p_intf, "Calling MediaControl::get_media_position"); */ MC_TRY;
p_pos = mediacontrol_get_media_position(servant->mc, an_origin, a_key, exception);
MC_EXCEPT(*retval);
retval.origin = an_origin; retval = corba_position_c_to_corba(p_pos);
retval.key = a_key; free(p_pos);
return *retval;
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 modules/gui/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 */ /* Sets the media position */
...@@ -376,71 +360,16 @@ impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant, ...@@ -376,71 +360,16 @@ impl_VLC_MediaControl_set_media_position(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position, const VLC_Position * a_position,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
VLC_InvalidPosition *pe_exception; mediacontrol_Position *p_pos;
VLC_PositionKeyNotSupported *pe_key_exception; mediacontrol_Exception *exception = NULL;
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 ) p_pos = corba_position_corba_to_c(a_position);
{
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) MC_TRY;
{ mediacontrol_set_media_position(servant->mc, p_pos, exception);
case VLC_RelativePosition: MC_EXCEPT();
i_whence |= INPUT_SEEK_CUR; free(p_pos);
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; return;
} }
...@@ -449,34 +378,16 @@ static void ...@@ -449,34 +378,16 @@ static void
impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_start(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position, CORBA_Environment * ev) const VLC_Position * a_position, CORBA_Environment * ev)
{ {
intf_thread_t * p_intf = servant->p_intf; mediacontrol_Position *p_pos;
playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, mediacontrol_Exception *exception = NULL;
FIND_ANYWHERE );
msg_Warn (servant->p_intf, "Calling MediaControl::start");
if( p_playlist == NULL ) p_pos = corba_position_corba_to_c(a_position);
{
/* FIXME: we should raise an appropriate exception, but we must
define it in the IDL first */
msg_Err (servant->p_intf, "no playlist available");
return;
}
vlc_mutex_lock( &p_playlist->object_lock ); MC_TRY;
if( p_playlist->i_size ) mediacontrol_start(servant->mc, p_pos, exception);
{ MC_EXCEPT();
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, "playlist empty");
}
free(p_pos);
return; return;
} }
...@@ -484,15 +395,16 @@ static void ...@@ -484,15 +395,16 @@ static void
impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_pause(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position, CORBA_Environment * ev) const VLC_Position * a_position, CORBA_Environment * ev)
{ {
input_thread_t *p_input = servant->p_intf->p_sys->p_input; mediacontrol_Position *p_pos;
mediacontrol_Exception *exception = NULL;
msg_Warn (servant->p_intf, "calling MediaControl::pause"); p_pos = corba_position_corba_to_c(a_position);
if( p_input != NULL ) MC_TRY;
{ mediacontrol_pause(servant->mc, p_pos, exception);
input_SetStatus( p_input, INPUT_STATUS_PAUSE ); MC_EXCEPT();
}
free(p_pos);
return; return;
} }
...@@ -500,15 +412,16 @@ static void ...@@ -500,15 +412,16 @@ static void
impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_resume(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position, CORBA_Environment * ev) const VLC_Position * a_position, CORBA_Environment * ev)
{ {
input_thread_t *p_input = servant->p_intf->p_sys->p_input; mediacontrol_Position *p_pos;
mediacontrol_Exception *exception = NULL;
msg_Warn (servant->p_intf, "calling MediaControl::resume"); p_pos = corba_position_corba_to_c(a_position);
if( p_input != NULL ) MC_TRY;
{ mediacontrol_resume(servant->mc, p_pos, exception);
input_SetStatus( p_input, INPUT_STATUS_PAUSE ); MC_EXCEPT();
}
free(p_pos);
return; return;
} }
...@@ -516,18 +429,16 @@ static void ...@@ -516,18 +429,16 @@ static void
impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_stop(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position, CORBA_Environment * ev) const VLC_Position * a_position, CORBA_Environment * ev)
{ {
intf_thread_t * p_intf = servant->p_intf; mediacontrol_Position *p_pos;
playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, mediacontrol_Exception *exception = NULL;
FIND_ANYWHERE );
msg_Warn (servant->p_intf, "calling MediaControl::stop"); p_pos = corba_position_corba_to_c(a_position);
if( p_playlist != NULL ) MC_TRY;
{ mediacontrol_pause(servant->mc, p_pos, exception);
playlist_Stop( p_playlist ); MC_EXCEPT();
vlc_object_release( p_playlist );
}
free(p_pos);
return; return;
} }
...@@ -535,69 +446,228 @@ static void ...@@ -535,69 +446,228 @@ static void
impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_exit(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
msg_Warn (servant->p_intf, "calling MediaControl::exit"); mediacontrol_exit(servant->mc);
return;
vlc_mutex_lock( &servant->p_intf->change_lock );
servant->p_intf->b_die = TRUE;
vlc_mutex_unlock( &servant->p_intf->change_lock );
} }
static void static void
impl_VLC_MediaControl_add_to_playlist(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_playlist_add_item(impl_POA_VLC_MediaControl * servant,
const CORBA_char * psz_file, const CORBA_char * psz_file,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
intf_thread_t * p_intf = servant->p_intf; mediacontrol_Exception *exception = NULL;
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); MC_TRY;
mediacontrol_playlist_add_item(servant->mc, psz_file, exception);
MC_EXCEPT();
if ( p_playlist == NULL )
{
msg_Err (servant->p_intf, "no playlist defined");
/* FIXME: should return an exception */
return; return;
} }
playlist_Add (p_playlist, psz_file, psz_file , PLAYLIST_REPLACE, 0); static void
vlc_object_release( p_playlist ); impl_VLC_MediaControl_playlist_clear(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev)
{
mediacontrol_Exception *exception = NULL;
MC_TRY;
mediacontrol_playlist_clear(servant->mc, exception);
MC_EXCEPT();
return; return;
} }
static VLC_PlaylistSeq * static VLC_PlaylistSeq *
impl_VLC_MediaControl_get_playlist(impl_POA_VLC_MediaControl * servant, impl_VLC_MediaControl_playlist_get_list(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev) CORBA_Environment * ev)
{ {
VLC_PlaylistSeq *retval; VLC_PlaylistSeq *retval = NULL;
mediacontrol_Exception *exception = NULL;
mediacontrol_PlaylistSeq* p_ps;
int i_index; 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 ); MC_TRY;
i_playlist_size = p_playlist->i_size; p_ps = mediacontrol_playlist_get_list(servant->mc, exception);
MC_EXCEPT(retval);
retval = VLC_PlaylistSeq__alloc (); retval = VLC_PlaylistSeq__alloc ();
retval->_buffer = VLC_PlaylistSeq_allocbuf (i_playlist_size); retval->_buffer = VLC_PlaylistSeq_allocbuf (p_ps->size);
retval->_length = i_playlist_size; retval->_length = p_ps->size;
for (i_index = 0 ; i_index < i_playlist_size ; i_index++) for (i_index = 0 ; i_index < p_ps->size ; i_index++)
{ {
retval->_buffer[i_index] = retval->_buffer[i_index] = CORBA_string_dup (p_ps->data[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); CORBA_sequence_set_release (retval, TRUE);
mediacontrol_PlaylistSeq__free(p_ps);
return retval;
}
VLC_RGBPicture*
createRGBPicture (mediacontrol_RGBPicture* p_pic)
{
VLC_RGBPicture *retval;
retval = VLC_RGBPicture__alloc ();
if (retval)
{
retval->width = p_pic->width;
retval->height = p_pic->height;
retval->type = p_pic->type;
retval->date = p_pic->date;
retval->data._maximum = p_pic->size;
retval->data._length = p_pic->size;
retval->data._buffer = VLC_ByteSeq_allocbuf (p_pic->size);
memcpy (retval->data._buffer, p_pic->data, p_pic->size);
/* CORBA_sequence_set_release (&(retval->data), FALSE); */
}
return retval;
}
static VLC_RGBPicture *
impl_VLC_MediaControl_snapshot(impl_POA_VLC_MediaControl * servant,
const VLC_Position * a_position,
CORBA_Environment * ev)
{
VLC_RGBPicture *retval = NULL;
mediacontrol_RGBPicture* p_pic = NULL;
mediacontrol_Position *p_pos;
mediacontrol_Exception *exception = NULL;
p_pos = corba_position_corba_to_c(a_position);
MC_TRY;
p_pic = mediacontrol_snapshot(servant->mc, p_pos, exception);
MC_EXCEPT(retval);
retval = createRGBPicture(p_pic);
mediacontrol_RGBPicture__free(p_pic);
return retval; return retval;
} }
static VLC_RGBPictureSeq *
impl_VLC_MediaControl_all_snapshots(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev)
{
VLC_RGBPictureSeq *retval = NULL;
mediacontrol_RGBPicture** p_piclist = NULL;
mediacontrol_RGBPicture** p_tmp = NULL;
mediacontrol_Exception *exception = NULL;
int i_size = 0;
int i_index;
MC_TRY;
p_piclist = mediacontrol_all_snapshots(servant->mc, exception);
MC_EXCEPT(retval);
for (p_tmp = p_piclist ; *p_tmp != NULL ; p_tmp++)
i_size++;
retval = VLC_RGBPictureSeq__alloc ();
retval->_buffer = VLC_RGBPictureSeq_allocbuf (i_size);
retval->_length = i_size;
for (i_index = 0 ; i_index < i_size ; i_index++)
{
mediacontrol_RGBPicture *p_pic = p_piclist[i_index];
VLC_RGBPicture *p_rgb;
p_rgb = &(retval->_buffer[i_index]);
p_rgb->width = p_pic->width;
p_rgb->height = p_pic->height;
p_rgb->type = p_pic->type;
p_rgb->date = p_pic->date;
p_rgb->data._maximum = p_pic->size;
p_rgb->data._length = p_pic->size;
p_rgb->data._buffer = VLC_ByteSeq_allocbuf (p_pic->size);
memcpy (p_rgb->data._buffer, p_pic->data, p_pic->size);
mediacontrol_RGBPicture__free(p_pic);
}
free(p_piclist);
return retval;
}
static void
impl_VLC_MediaControl_display_text(impl_POA_VLC_MediaControl * servant,
const CORBA_char * message,
const VLC_Position * begin,
const VLC_Position * end,
CORBA_Environment * ev)
{
mediacontrol_Position *p_begin = NULL;
mediacontrol_Position *p_end = NULL;
mediacontrol_Exception *exception = NULL;
p_begin = corba_position_corba_to_c(begin);
p_end = corba_position_corba_to_c(end);
MC_TRY;
mediacontrol_display_text(servant->mc, message, p_begin, p_end, exception);
MC_EXCEPT();
free(p_begin);
free(p_end);
return;
}
static VLC_StreamInformation *
impl_VLC_MediaControl_get_stream_information(impl_POA_VLC_MediaControl *
servant, CORBA_Environment * ev)
{
mediacontrol_Exception *exception = NULL;
mediacontrol_StreamInformation *p_si = NULL;
VLC_StreamInformation *retval = NULL;
MC_TRY;
p_si = mediacontrol_get_stream_information(servant->mc, mediacontrol_MediaTime, exception);
MC_EXCEPT(retval);
retval = VLC_StreamInformation__alloc();
if (! retval)
{
return NULL;
}
retval->streamstatus = p_si->streamstatus;
retval->url = CORBA_string_dup (p_si->url);
retval->position = p_si->position;
retval->length = p_si->length;
free(p_si->url);
free(p_si);
return retval;
}
static CORBA_unsigned_short
impl_VLC_MediaControl_sound_get_volume(impl_POA_VLC_MediaControl * servant,
CORBA_Environment * ev)
{
CORBA_short retval = 0;
mediacontrol_Exception *exception = NULL;
MC_TRY;
retval = mediacontrol_sound_get_volume(servant->mc, exception);
MC_EXCEPT(retval);
return retval;
}
static void
impl_VLC_MediaControl_sound_set_volume(impl_POA_VLC_MediaControl * servant,
const CORBA_unsigned_short volume,
CORBA_Environment * ev)
{
mediacontrol_Exception *exception = NULL;
MC_TRY;
mediacontrol_sound_set_volume(servant->mc, volume, exception);
MC_EXCEPT();
}
/* (Real) end of the CORBA code generated in Mediacontrol-skelimpl.c */ /* (Real) end of the CORBA code generated in Mediacontrol-skelimpl.c */
/***************************************************************************** /*****************************************************************************
...@@ -611,8 +681,11 @@ static void Run ( intf_thread_t * ); ...@@ -611,8 +681,11 @@ static void Run ( intf_thread_t * );
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
vlc_module_begin(); vlc_module_begin();
set_description( _("Corba control module") ); add_category_hint( N_("Corba control"), NULL, VLC_FALSE );
set_description( _("corba control module") );
set_capability( "interface", 10 ); set_capability( "interface", 10 );
add_integer( "corba-reactivity", 5000, NULL, "Internal reactivity factor", "Internal reactivity factor (gtk timeout is INTF_IDLE_SLEEP / factor)", VLC_TRUE );
set_callbacks( Open, Close ); set_callbacks( Open, Close );
vlc_module_end(); vlc_module_end();
...@@ -627,26 +700,20 @@ static int Open( vlc_object_t *p_this ) ...@@ -627,26 +700,20 @@ static int Open( vlc_object_t *p_this )
p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
if( p_intf->p_sys == NULL ) if( p_intf->p_sys == NULL )
{ {
msg_Err( p_intf, "out of memory" ); msg_Err( p_intf, "Out of memory" );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
/* Initialize the fields of the p_intf struct */ /* Initialize the fields of the p_intf struct */
p_intf->pf_run = Run; 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->mc = NULL;
p_intf->p_sys->root_poa = NULL; p_intf->p_sys->orb = NULL;
p_intf->p_sys->root_poa_manager = NULL;
p_intf->p_sys->corbaloop = NULL; p_intf->p_sys->corbaloop = NULL;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* intf_Close: destroy interface * intf_Close: destroy interface
*****************************************************************************/ *****************************************************************************/
...@@ -657,12 +724,7 @@ static void Close( vlc_object_t *p_this ) ...@@ -657,12 +724,7 @@ static void Close( vlc_object_t *p_this )
ev = CORBA_exception__alloc (); ev = CORBA_exception__alloc ();
CORBA_ORB_shutdown (p_intf->p_sys->orb, FALSE, ev); CORBA_ORB_shutdown (p_intf->p_sys->orb, FALSE, ev);
handle_exception_no_servant (p_intf, "erreur dans Close"); handle_exception_no_servant (p_intf, "Error in Close");
if( p_intf->p_sys->p_input )
{
vlc_object_release( p_intf->p_sys->p_input );
}
/* Destroy structure */ /* Destroy structure */
free( p_intf->p_sys ); free( p_intf->p_sys );
...@@ -683,60 +745,22 @@ static gboolean Manage (gpointer p_interface) ...@@ -683,60 +745,22 @@ static gboolean Manage (gpointer p_interface)
b_work_pending = CORBA_ORB_work_pending (p_intf->p_sys->orb, ev); b_work_pending = CORBA_ORB_work_pending (p_intf->p_sys->orb, ev);
if(ev->_major != CORBA_NO_EXCEPTION) if(ev->_major != CORBA_NO_EXCEPTION)
{ {
msg_Err (p_intf, "exception in the CORBA events check"); msg_Err (p_intf, "Exception in CORBA events check loop");
return FALSE; return FALSE;
} }
vlc_mutex_lock( &p_intf->change_lock ); 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) if (b_work_pending)
CORBA_ORB_perform_work (p_intf->p_sys->orb, ev); CORBA_ORB_perform_work (p_intf->p_sys->orb, ev);
if( p_intf->b_die ) if( p_intf->b_die )
{ {
vlc_mutex_unlock( &p_intf->change_lock ); vlc_mutex_unlock( &p_intf->change_lock );
CORBA_ORB_shutdown (p_intf->p_sys->orb, TRUE, ev);
g_main_loop_quit (p_intf->p_sys->corbaloop); g_main_loop_quit (p_intf->p_sys->corbaloop);
/* Just in case */ /* Just in case */
return( FALSE ); return( TRUE );
} }
vlc_mutex_unlock( &p_intf->change_lock ); vlc_mutex_unlock( &p_intf->change_lock );
...@@ -753,19 +777,20 @@ static gboolean Manage (gpointer p_interface) ...@@ -753,19 +777,20 @@ static gboolean Manage (gpointer p_interface)
static void Run ( intf_thread_t *p_intf ) static void Run ( intf_thread_t *p_intf )
{ {
CORBA_Environment* ev = NULL; CORBA_Environment* ev = NULL;
PortableServer_POA root_poa;
PortableServer_POAManager root_poa_manager;
guint i_event_source; guint i_event_source;
CORBA_char* psz_objref; CORBA_char* psz_objref;
impl_POA_VLC_MediaControl *servant = NULL; impl_POA_VLC_MediaControl *servant = NULL;
VLC_MediaControl corba_instance;
mediacontrol_Instance *mc_instance;
mediacontrol_Exception *exception = NULL;
int i_argc = 1; int i_argc = 1;
char* ppsz_argv[] = { "mc" }; char* ppsz_argv[] = { "mc" };
int i_reactivity;
msg_Warn (p_intf, "Entering Run");
ev = CORBA_exception__alloc (); 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); p_intf->p_sys->orb = CORBA_ORB_init(&i_argc, ppsz_argv, "orbit-local-orb", ev);
/* Should be cleaner this way (cf /* Should be cleaner this way (cf
...@@ -774,21 +799,28 @@ static void Run ( intf_thread_t *p_intf ) ...@@ -774,21 +799,28 @@ static void Run ( intf_thread_t *p_intf )
cleaning it */ cleaning it */
/* p_intf->p_sys->orb = gnome_CORBA_init ("VLC", NULL, &argc, &argv, 0, NULL, ev); */ /* 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"); 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); root_poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(p_intf->p_sys->orb, "RootPOA", ev);
handle_exception ("exception during RootPOA initialization"); handle_exception ("Exception during RootPOA initialization");
p_intf->p_sys->mc = impl_VLC_MediaControl__create(p_intf->p_sys->root_poa, ev); corba_instance = impl_VLC_MediaControl__create(root_poa, ev);
handle_exception ("exception during MediaControl initialization"); 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); servant = (impl_POA_VLC_MediaControl*)PortableServer_POA_reference_to_servant(root_poa, corba_instance, ev);
handle_exception ("exception during MediaControl access"); handle_exception ("Exception during MediaControl access");
MC_TRY;
mc_instance = mediacontrol_new_from_object((vlc_object_t*)p_intf, exception);
MC_EXCEPT();
p_intf->p_sys->mc = mc_instance;
servant->p_intf = p_intf; servant->p_intf = p_intf;
servant->mc = p_intf->p_sys->mc;
psz_objref = CORBA_ORB_object_to_string(p_intf->p_sys->orb, p_intf->p_sys->mc, ev); psz_objref = CORBA_ORB_object_to_string(p_intf->p_sys->orb, corba_instance, ev);
handle_exception ("exception during IOR generation"); handle_exception ("Exception during IOR generation");
msg_Warn (p_intf, "MediaControl IOR :"); msg_Warn (p_intf, "MediaControl IOR :");
msg_Warn (p_intf, psz_objref); msg_Warn (p_intf, psz_objref);
...@@ -799,23 +831,21 @@ static void Run ( intf_thread_t *p_intf ) ...@@ -799,23 +831,21 @@ static void Run ( intf_thread_t *p_intf )
fp = fopen (VLC_IOR_FILE, "w"); fp = fopen (VLC_IOR_FILE, "w");
if (fp == NULL) if (fp == NULL)
{ {
msg_Err (servant->p_intf, "cannot write the IOR to %s (%d).", VLC_IOR_FILE, errno); msg_Err (p_intf, "Cannot write the IOR to %s (%d).", VLC_IOR_FILE, errno);
} }
else else
{ {
fprintf (fp, "%s", psz_objref); fprintf (fp, "%s", psz_objref);
fclose (fp); fclose (fp);
msg_Warn (servant->p_intf, "IOR written to %s", VLC_IOR_FILE); msg_Warn (p_intf, "IOR written to %s", VLC_IOR_FILE);
} }
} }
msg_Warn (p_intf, "get_the_POAManager (state %s)", p_intf->p_sys->root_poa); root_poa_manager = PortableServer_POA__get_the_POAManager(root_poa, ev);
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");
handle_exception ("exception during POAManager resolution");
msg_Warn (p_intf, "activating POAManager"); PortableServer_POAManager_activate(root_poa_manager, ev);
PortableServer_POAManager_activate(p_intf->p_sys->root_poa_manager, ev); handle_exception ("Exception during POAManager activation");
handle_exception ("exception during POAManager activation");
msg_Info(p_intf, "corba remote control interface initialized" ); msg_Info(p_intf, "corba remote control interface initialized" );
...@@ -831,23 +861,20 @@ static void Run ( intf_thread_t *p_intf ) ...@@ -831,23 +861,20 @@ static void Run ( intf_thread_t *p_intf )
name_service = CORBA_ORB_resolve_initial_references (p_intf->p_sys->orb, name_service = CORBA_ORB_resolve_initial_references (p_intf->p_sys->orb,
"NameService", "NameService",
ev); ev);
handle_exception ("could not get name service: %s\n", handle_exception ("Error: could not get name service: %s\n",
CORBA_exception_id(ev)); CORBA_exception_id(ev));
msg_Warn (p_intf, "Name service OK"); msg_Warn (p_intf, "Name service OK");
CosNaming_NamingContext_bind (name_service, &name, p_intf->p_sys->mc, ev); CosNaming_NamingContext_bind (name_service, &name, p_intf->p_sys->mc, ev);
handle_exception ("could not register object: %s\n", handle_exception ("Error: could not register object: %s\n",
CORBA_exception_id(ev)); CORBA_exception_id(ev));
} }
*/ */
/* The time factor should be 1/1000 but it is a little too /* The time factor should be 1/1000 but it is a little too
slow. Make it 1/10000 */ slow. Make it 1/10000 */
i_event_source = g_timeout_add (INTF_IDLE_SLEEP / 10000, i_reactivity = config_GetInt( p_intf, "corba-reactivity" );
Manage, i_event_source = g_timeout_add (INTF_IDLE_SLEEP / i_reactivity, Manage, p_intf);
p_intf);
msg_Warn (p_intf, "entering mainloop");
p_intf->p_sys->corbaloop = g_main_loop_new (NULL, FALSE); p_intf->p_sys->corbaloop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (p_intf->p_sys->corbaloop); g_main_loop_run (p_intf->p_sys->corbaloop);
...@@ -855,6 +882,8 @@ static void Run ( intf_thread_t *p_intf ) ...@@ -855,6 +882,8 @@ static void Run ( intf_thread_t *p_intf )
g_source_remove( i_event_source ); g_source_remove( i_event_source );
unlink (VLC_IOR_FILE); unlink (VLC_IOR_FILE);
msg_Warn (p_intf, "normal termination of VLC corba module"); /* Make sure we exit (In case other interfaces have been spawned) */
mediacontrol_exit(p_intf->p_sys->mc);
return; return;
} }
#include "mediacontrol-core.h"
#include <vlc/intf.h>
#include <vlc/vout.h>
#include <vlc/aout.h>
#include <osd.h>
#define HAS_SNAPSHOT 1
#ifdef HAS_SNAPSHOT
#include <snapshot.h>
#endif
#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>
#define RAISE(c, m) exception->code = c; \
exception->message = strdup(m);
long long mediacontrol_unit_convert (input_thread_t *p_input,
mediacontrol_PositionKey from,
mediacontrol_PositionKey to,
long long value)
{
if (to == from)
return value;
/* For all conversions, we need data from p_input */
if (!p_input)
return 0;
switch (from)
{
case mediacontrol_MediaTime:
if (to == mediacontrol_ByteCount)
return value * 50 * p_input->stream.i_mux_rate / 1000;
if (to == mediacontrol_SampleCount)
{
double f_fps;
if (demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1)
return 0;
else
return (value * f_fps / 1000.0);
}
/* Cannot happen */
/* See http://catb.org/~esr/jargon/html/entry/can't-happen.html */
break;
case mediacontrol_SampleCount:
{
double f_fps;
if (demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1)
return 0;
if (to == mediacontrol_ByteCount)
return (long long)(value * 50 * p_input->stream.i_mux_rate / f_fps);
if (to == mediacontrol_MediaTime)
return (long long)(value * 1000.0 / (double)f_fps );
/* Cannot happen */
break;
}
case mediacontrol_ByteCount:
if (p_input->stream.i_mux_rate == 0)
return 0;
/* Convert an offset into milliseconds. 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 */
if (to == mediacontrol_MediaTime)
return (long long) (1000 * value / 50 / p_input->stream.i_mux_rate);
if (to == mediacontrol_SampleCount)
{
double f_fps;
if (demux_Control( p_input, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1)
return 0;
else
return (long long)(value * f_fps / 50 / p_input->stream.i_mux_rate);
}
/* Cannot happen */
break;
}
/* Cannot happen */
return 0;
}
/* Converts a mediacontrol_Position into a time in microseconds in
movie clock time */
long long
mediacontrol_position2microsecond (input_thread_t* p_input, const mediacontrol_Position * pos)
{
switch (pos->origin)
{
case mediacontrol_AbsolutePosition:
return (1000 * mediacontrol_unit_convert(p_input,
pos->key, /* from */
mediacontrol_MediaTime, /* to */
pos->value));
break;
case mediacontrol_RelativePosition:
{
off_t l_offset;
long long l_current;
long long l_pos;
vlc_mutex_lock( &p_input->stream.stream_lock );
l_offset = p_input->stream.p_selected_area->i_tell;
vlc_mutex_unlock( &p_input->stream.stream_lock );
l_current = 1000 * mediacontrol_unit_convert(p_input,
mediacontrol_ByteCount,
mediacontrol_MediaTime,
l_offset);
l_pos = 1000 * mediacontrol_unit_convert(p_input,
pos->key,
mediacontrol_MediaTime,
pos->value);
return l_current + l_pos;
break;
}
case mediacontrol_ModuloPosition:
{
long long l_duration;
long long l_pos;
l_duration = 1000 * mediacontrol_unit_convert(p_input,
mediacontrol_ByteCount,
mediacontrol_MediaTime,
p_input->stream.p_selected_area->i_size);
l_pos = (1000 * mediacontrol_unit_convert(p_input,
pos->key, /* from */
mediacontrol_MediaTime, /* to */
pos->value));
return l_pos % l_duration;
break;
}
}
return 0;
}
mediacontrol_RGBPicture*
mediacontrol_RGBPicture__alloc (int datasize)
{
mediacontrol_RGBPicture* pic;
pic = (mediacontrol_RGBPicture*)malloc(sizeof(mediacontrol_RGBPicture));
if (! pic)
return NULL;
pic->size = datasize;
pic->data = (char*)malloc(datasize);
return pic;
}
void
mediacontrol_RGBPicture__free (mediacontrol_RGBPicture* pic)
{
if (pic)
free(pic->data);
free(pic);
}
mediacontrol_PlaylistSeq*
mediacontrol_PlaylistSeq__alloc (int size)
{
mediacontrol_PlaylistSeq* ps;
ps = (mediacontrol_PlaylistSeq*)malloc(sizeof(mediacontrol_PlaylistSeq));
if (! ps)
return NULL;
ps->size = size;
ps->data = (char**)malloc(size * sizeof(char*));
return ps;
}
void
mediacontrol_PlaylistSeq__free (mediacontrol_PlaylistSeq* ps)
{
if (ps)
{
int i;
for (i = 0; i < ps->size; i++)
free(ps->data[i]);
}
free(ps->data);
free(ps);
}
mediacontrol_Exception*
mediacontrol_exception_init(mediacontrol_Exception *exception)
{
if (exception == NULL)
{
exception = (mediacontrol_Exception*)malloc(sizeof(mediacontrol_Exception));
}
exception->code = 0;
exception->message = NULL;
return exception;
}
void
mediacontrol_exception_free(mediacontrol_Exception *exception)
{
if (! exception)
return;
free(exception->message);
free(exception);
}
mediacontrol_Instance* mediacontrol_new_from_object(vlc_object_t* p_object,
mediacontrol_Exception *exception)
{
mediacontrol_Instance* retval;
vlc_object_t *p_vlc;
p_vlc = vlc_object_find(p_object, VLC_OBJECT_ROOT, FIND_PARENT);
if (! p_vlc)
{
RAISE(mediacontrol_InternalException, "Unable to initialize VLC");
return NULL;
}
retval = (mediacontrol_Instance*)malloc(sizeof(mediacontrol_Instance));
retval->p_vlc = p_vlc;
retval->vlc_object_id = p_vlc->i_object_id;
/* We can keep references on these, which should not change. Is it true ? */
retval->p_playlist = vlc_object_find(p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE);
retval->p_intf = vlc_object_find(p_vlc, VLC_OBJECT_INTF, FIND_ANYWHERE);
if (! retval->p_playlist || ! retval->p_intf)
{
RAISE(mediacontrol_InternalException, "No available interface");
return NULL;
}
return retval;
};
/* 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 */
mediacontrol_Position*
mediacontrol_get_media_position(mediacontrol_Instance *self,
const mediacontrol_PositionOrigin an_origin,
const mediacontrol_PositionKey a_key,
mediacontrol_Exception *exception)
{
mediacontrol_Position* retval;
off_t l_offset;
input_thread_t * p_input = self->p_playlist->p_input;;
exception=mediacontrol_exception_init(exception);
retval = (mediacontrol_Position*)malloc(sizeof(mediacontrol_Position));
retval->origin = an_origin;
retval->key = a_key;
if (! p_input)
{
/*
RAISE(mediacontrol_InternalException, "No input thread.");
return(NULL);
*/
retval->value = 0;
return retval;
}
if ( an_origin == mediacontrol_RelativePosition
|| an_origin == mediacontrol_ModuloPosition )
{
/* Relative or ModuloPosition make no sense */
retval->value = 0;
return retval;
}
/* We are asked for an AbsolutePosition. */
vlc_mutex_lock( &p_input->stream.stream_lock );
l_offset = p_input->stream.p_selected_area->i_tell;
vlc_mutex_unlock( &p_input->stream.stream_lock );
retval->value = mediacontrol_unit_convert(p_input,
mediacontrol_ByteCount,
a_key,
l_offset);
return retval;
}
/* Sets the media position */
void
mediacontrol_set_media_position(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
off_t l_offset_destination = 0;
int i_whence = 0;
input_thread_t * p_input = self->p_playlist->p_input;
exception=mediacontrol_exception_init(exception);
if (! p_input)
{
RAISE(mediacontrol_InternalException, "No input thread.");
return;
}
if ( !p_input->stream.b_seekable )
{
RAISE(mediacontrol_InvalidPosition, "Stream not seekable");
return;
}
l_offset_destination = a_position->value;
i_whence |= INPUT_SEEK_BYTES;
l_offset_destination = mediacontrol_unit_convert(p_input,
a_position->key,
mediacontrol_ByteCount,
l_offset_destination);
switch ( a_position->origin)
{
case mediacontrol_RelativePosition:
i_whence |= INPUT_SEEK_CUR;
break;
case mediacontrol_ModuloPosition:
i_whence |= INPUT_SEEK_END;
break;
case mediacontrol_AbsolutePosition:
i_whence |= INPUT_SEEK_SET;
break;
default:
i_whence |= INPUT_SEEK_SET;
break;
}
/* 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 */
void
mediacontrol_start(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
playlist_t * p_playlist = self->p_playlist;
exception=mediacontrol_exception_init(exception);
if (! p_playlist)
{
RAISE(mediacontrol_PlaylistException, "No available playlist");
return;
}
vlc_mutex_lock( &p_playlist->object_lock );
if (p_playlist->i_size)
{
vlc_value_t val;
vlc_mutex_unlock( &p_playlist->object_lock );
/* Set start time */
val.i_int = mediacontrol_position2microsecond(p_playlist->p_input, a_position) / 1000000;
var_Set (p_playlist, "start-time", val);
playlist_Play( p_playlist );
}
else
{
RAISE(mediacontrol_PlaylistException, "Empty playlist.");
vlc_mutex_unlock( &p_playlist->object_lock );
return;
}
return;
}
void
mediacontrol_pause(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
input_thread_t *p_input = self->p_playlist->p_input;;
/* FIXME: use the a_position parameter */
exception=mediacontrol_exception_init(exception);
if (p_input != NULL)
{
input_SetStatus( p_input, INPUT_STATUS_PAUSE );
}
else
{
RAISE(mediacontrol_InternalException, "No input");
}
return;
}
void
mediacontrol_resume(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
input_thread_t *p_input = self->p_playlist->p_input;
/* FIXME: use the a_position parameter */
exception=mediacontrol_exception_init(exception);
if (p_input != NULL)
{
input_SetStatus( p_input, INPUT_STATUS_PAUSE );
}
else
{
RAISE(mediacontrol_InternalException, "No input");
}
return;
}
void
mediacontrol_stop(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
/* FIXME: use the a_position parameter */
exception=mediacontrol_exception_init(exception);
if (!self->p_playlist)
{
RAISE(mediacontrol_PlaylistException, "No playlist");
return;
}
playlist_Stop( self->p_playlist );
return;
}
void
mediacontrol_playlist_add_item(mediacontrol_Instance *self,
const char * psz_file,
mediacontrol_Exception *exception)
{
exception=mediacontrol_exception_init(exception);
if (!self->p_playlist)
{
RAISE(mediacontrol_InternalException, "No playlist");
return;
}
playlist_Add (self->p_playlist, psz_file, psz_file , PLAYLIST_REPLACE, 0);
return;
}
void
mediacontrol_playlist_clear(mediacontrol_Instance *self,
mediacontrol_Exception *exception)
{
int i_index;
exception=mediacontrol_exception_init(exception);
if (!self->p_playlist)
{
RAISE(mediacontrol_PlaylistException, "No playlist");
return;
}
for (i_index = 0 ; i_index < self->p_playlist->i_size ; i_index++)
{
playlist_Delete (self->p_playlist, i_index);
}
return;
}
mediacontrol_PlaylistSeq *
mediacontrol_playlist_get_list(mediacontrol_Instance *self,
mediacontrol_Exception *exception)
{
mediacontrol_PlaylistSeq *retval;
int i_index;
playlist_t * p_playlist = self->p_playlist;;
int i_playlist_size;
exception=mediacontrol_exception_init(exception);
if (!p_playlist)
{
RAISE(mediacontrol_PlaylistException, "No playlist");
return NULL;
}
vlc_mutex_lock( &p_playlist->object_lock );
i_playlist_size = p_playlist->i_size;
retval = mediacontrol_PlaylistSeq__alloc(i_playlist_size);
for (i_index = 0 ; i_index < i_playlist_size ; i_index++)
{
retval->data[i_index] = strdup (p_playlist->pp_items[i_index]->input.psz_uri);
}
vlc_mutex_unlock( &p_playlist->object_lock );
return retval;
}
mediacontrol_RGBPicture*
_mediacontrol_createRGBPicture (int i_width, int i_height, long i_chroma, long long l_date,
char* p_data, int i_datasize)
{
mediacontrol_RGBPicture *retval;
retval = mediacontrol_RGBPicture__alloc (i_datasize);
if (retval)
{
retval->width = i_width;
retval->height = i_height;
retval->type = i_chroma;
retval->date = l_date;
retval->size = i_datasize;
memcpy (retval->data, p_data, i_datasize);
}
return retval;
}
mediacontrol_RGBPicture *
mediacontrol_snapshot(mediacontrol_Instance *self,
const mediacontrol_Position * a_position,
mediacontrol_Exception *exception)
{
mediacontrol_RGBPicture *retval = NULL;
input_thread_t* p_input = self->p_playlist->p_input;
vout_thread_t *p_vout = NULL;
int i_datasize;
snapshot_t **pointer;
vlc_value_t val;
int i_index;
snapshot_t *p_best_snapshot;
long searched_date;
#ifdef HAS_SNAPSHOT
int i_cachesize;
#endif
exception=mediacontrol_exception_init(exception);
/*
if (var_Get (self->p_vlc, "snapshot-id", &val) == VLC_SUCCESS)
p_vout = vlc_object_get (self->p_vlc, val.i_int);
*/
/* FIXME: if in p_libvlc, we cannot have multiple video outputs */
/* Once corrected, search for snapshot-id to modify all instances */
if (var_Get (p_input, "snapshot-id", &val) != VLC_SUCCESS)
{
RAISE(mediacontrol_InternalException, "No snapshot-id in p_input");
return NULL;
}
p_vout = vlc_object_get (self->p_vlc, val.i_int);
if (! p_vout)
{
RAISE(mediacontrol_InternalException, "No snapshot module");
return NULL;
}
#ifdef HAS_SNAPSHOT
/* We test if the vout is a snapshot module. We cannot test
pvout_psz_object_name (which is NULL). But we can check if
there are snapshot-specific variables */
if (var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS)
{
RAISE(mediacontrol_InternalException, "No snapshot module");
vlc_object_release(p_vout);
return NULL;
}
i_datasize = val.i_int;
/* Handle the a_position parameter */
if (! (a_position->origin == mediacontrol_RelativePosition
&& a_position->value == 0))
{
/* The position is not the current one. Go to it. */
mediacontrol_set_media_position (self, (mediacontrol_Position*)a_position, exception);
if (exception->code)
{
vlc_object_release(p_vout);
return NULL;
}
}
/* FIXME: We should not go further until we got past the position
(which means that we had the possibility to capture the right
picture). */
vlc_mutex_lock( &p_vout->picture_lock );
searched_date = mediacontrol_position2microsecond (p_input,
(mediacontrol_Position *)a_position);
var_Get( p_vout, "snapshot-cache-size", &val );
i_cachesize = val.i_int ;
var_Get( p_vout, "snapshot-list-pointer", &val );
pointer = (snapshot_t **)val.p_address;
if (! pointer)
{
RAISE(mediacontrol_InternalException, "No available snapshot");
vlc_mutex_unlock( &p_vout->picture_lock );
vlc_object_release( p_vout );
return NULL;
}
/* Find the more appropriate picture, based on date */
p_best_snapshot = pointer[0];
for (i_index = 1 ; i_index < i_cachesize ; i_index++)
{
long l_diff = pointer[i_index]->date - searched_date;
if (l_diff > 0 && l_diff < abs(p_best_snapshot->date - searched_date))
{
/* This one is closer, and _after_ the requested position */
p_best_snapshot = pointer[i_index];
}
}
/* FIXME: add a test for the case that no picture matched the test
(we have p_best_snapshot == pointer[0] */
retval = _mediacontrol_createRGBPicture (p_best_snapshot->i_width,
p_best_snapshot->i_height,
p_vout->output.i_chroma,
p_best_snapshot->date,
p_best_snapshot->p_data,
i_datasize);
vlc_mutex_unlock( &p_vout->picture_lock );
vlc_object_release( p_vout );
#endif
return retval;
}
mediacontrol_RGBPicture **
mediacontrol_all_snapshots(mediacontrol_Instance *self,
mediacontrol_Exception *exception)
{
mediacontrol_RGBPicture **retval = NULL;
vout_thread_t *p_vout = NULL;
int i_datasize;
int i_cachesize;
vlc_value_t val;
int i_index;
#ifdef HAS_SNAPSHOT
snapshot_t **pointer;
#endif
exception=mediacontrol_exception_init(exception);
if (var_Get (self->p_playlist->p_input, "snapshot-id", &val) == VLC_SUCCESS)
p_vout = vlc_object_get (self->p_vlc, val.i_int);
if (! p_vout)
{
RAISE(mediacontrol_InternalException, "No snapshot module");
return NULL;
}
#ifdef HAS_SNAPSHOT
/* We test if the vout is a snapshot module. We cannot test
pvout_psz_object_name (which is NULL). But we can check if
there are snapshot-specific variables */
if (var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS)
{
RAISE(mediacontrol_InternalException, "No snapshot module");
vlc_object_release(p_vout);
return NULL;
}
i_datasize = val.i_int;
vlc_mutex_lock( &p_vout->picture_lock );
var_Get( p_vout, "snapshot-cache-size", &val );
i_cachesize = val.i_int ;
var_Get( p_vout, "snapshot-list-pointer", &val );
pointer = (snapshot_t **)val.p_address;
if (! pointer)
{
RAISE(mediacontrol_InternalException, "No available picture");
vlc_mutex_unlock( &p_vout->picture_lock );
vlc_object_release( p_vout );
return NULL;
}
retval = (mediacontrol_RGBPicture**)malloc((i_cachesize + 1) * sizeof(char*));
for (i_index = 0 ; i_index < i_cachesize ; i_index++)
{
snapshot_t *p_s = pointer[i_index];
mediacontrol_RGBPicture *p_rgb;
p_rgb = _mediacontrol_createRGBPicture (p_s->i_width,
p_s->i_height,
p_vout->output.i_chroma,
p_s->date,
p_s->p_data,
i_datasize);
retval[i_index] = p_rgb;
}
retval[i_cachesize] = NULL;
vlc_mutex_unlock( &p_vout->picture_lock );
vlc_object_release( p_vout );
#endif
return retval;
}
void
mediacontrol_display_text(mediacontrol_Instance *self,
const char * message,
const mediacontrol_Position * begin,
const mediacontrol_Position * end,
mediacontrol_Exception *exception)
{
input_thread_t *p_input = NULL;
vout_thread_t *p_vout = NULL;
p_vout = vlc_object_find( self->p_vlc, VLC_OBJECT_VOUT, FIND_ANYWHERE );
if (! p_vout)
{
RAISE(mediacontrol_InternalException, "No video output");
return;
}
if (begin->origin == mediacontrol_RelativePosition &&
begin->value == 0 &&
end->origin == mediacontrol_RelativePosition)
{
mtime_t i_duration = 0;
i_duration = 1000 * mediacontrol_unit_convert(self->p_playlist->p_input,
end->key,
mediacontrol_MediaTime,
end->value);
vout_ShowTextRelative( p_vout, (char*)message, NULL,
OSD_ALIGN_BOTTOM|OSD_ALIGN_LEFT, 20, 20,
i_duration );
}
else
{
mtime_t i_debut, i_fin, i_now;
p_input = self->p_playlist->p_input;
if (! p_input)
{
RAISE(mediacontrol_InternalException, "No input");
vlc_object_release(p_vout);
return;
}
i_now = input_ClockGetTS (p_input, NULL, 0);
i_debut = mediacontrol_position2microsecond (p_input, (mediacontrol_Position *) begin);
i_debut += i_now;
i_fin = mediacontrol_position2microsecond (p_input, (mediacontrol_Position *) end);
i_fin += i_now;
vout_ShowTextAbsolute( p_vout, (char*)message, NULL,
OSD_ALIGN_BOTTOM|OSD_ALIGN_LEFT, 20, 20,
i_debut, i_fin );
}
vlc_object_release( p_vout );
}
mediacontrol_StreamInformation *
mediacontrol_get_stream_information(mediacontrol_Instance *self,
mediacontrol_PositionKey a_key,
mediacontrol_Exception *exception)
{
mediacontrol_StreamInformation *retval;
input_thread_t *p_input = self->p_playlist->p_input;
retval = (mediacontrol_StreamInformation*)malloc(sizeof(mediacontrol_StreamInformation));
if (! retval)
{
RAISE(mediacontrol_InternalException, "Out of memory");
return NULL;
}
if (! p_input)
{
/* No p_input defined */
retval->streamstatus = mediacontrol_UndefinedStatus;
retval->url = strdup ("None");
retval->position = 0;
retval->length = 0;
}
else
{
switch (p_input->stream.control.i_status)
{
case UNDEF_S :
retval->streamstatus = mediacontrol_UndefinedStatus;
break;
case PLAYING_S :
retval->streamstatus = mediacontrol_PlayingStatus;
break;
case PAUSE_S :
retval->streamstatus = mediacontrol_PauseStatus;
break;
case FORWARD_S :
retval->streamstatus = mediacontrol_ForwardStatus;
break;
case BACKWARD_S :
retval->streamstatus = mediacontrol_BackwardStatus;
break;
case INIT_S :
retval->streamstatus = mediacontrol_InitStatus;
break;
case END_S :
retval->streamstatus = mediacontrol_EndStatus;
break;
default :
retval->streamstatus = mediacontrol_UndefinedStatus;
break;
}
retval->url = strdup (p_input->psz_source);
demux_Control(p_input, DEMUX_GET_TIME, &(retval->position));
demux_Control(p_input, DEMUX_GET_LENGTH, &(retval->length));
/* TIME and LENGTH are in microseconds. We want them in ms */
retval->position /= 1000;
retval->length /= 1000;
retval->position = mediacontrol_unit_convert(p_input,
mediacontrol_MediaTime, a_key,
retval->position);
retval->length = mediacontrol_unit_convert(p_input,
mediacontrol_MediaTime, a_key,
retval->length);
}
return retval;
}
unsigned short
mediacontrol_sound_get_volume(mediacontrol_Instance *self,
mediacontrol_Exception *exception)
{
short retval;
audio_volume_t i_volume;
if (!self->p_intf)
{
RAISE(mediacontrol_InternalException, "No interface module");
return 0;
}
aout_VolumeGet( self->p_intf, &i_volume );
retval = i_volume;
return retval;
}
void
mediacontrol_sound_set_volume(mediacontrol_Instance *self,
const unsigned short volume,
mediacontrol_Exception *exception)
{
if (!self->p_intf)
{
RAISE(mediacontrol_InternalException, "No interface module");
return;
}
aout_VolumeSet( self->p_intf, (audio_volume_t)volume );
}
#ifndef __mediacontrol_core_h
#define __mediacontrol_core_h
#ifndef __VLC__
#define __VLC__
#endif
#include <vlc/vlc.h>
/************************************************************************
* Position Object Manipulation
*************************************************************************/
typedef enum {
mediacontrol_AbsolutePosition,
mediacontrol_RelativePosition,
mediacontrol_ModuloPosition
} mediacontrol_PositionOrigin;
typedef enum {
mediacontrol_ByteCount,
mediacontrol_SampleCount,
mediacontrol_MediaTime
} mediacontrol_PositionKey;
typedef struct {
mediacontrol_PositionOrigin origin;
mediacontrol_PositionKey key;
long value;
} mediacontrol_Position;
typedef struct {
int width;
int height;
long type;
long long date;
int size;
char* data;
} mediacontrol_RGBPicture;
typedef struct {
int size;
char** data;
} mediacontrol_PlaylistSeq;
typedef struct {
int code;
char* message;
} mediacontrol_Exception;
/* Exception codes */
#define mediacontrol_PositionKeyNotSupported 1
#define mediacontrol_PositionOriginNotSupported 2
#define mediacontrol_InvalidPosition 3
#define mediacontrol_PlaylistException 4
#define mediacontrol_InternalException 5
typedef struct {
vlc_object_t *p_vlc;
playlist_t *p_playlist;
intf_thread_t *p_intf;
int vlc_object_id;
} mediacontrol_Instance;
/* Cf stream_control.h */
enum mediacontrol_PlayerStatusList
{
mediacontrol_PlayingStatus, mediacontrol_PauseStatus,
mediacontrol_ForwardStatus, mediacontrol_BackwardStatus,
mediacontrol_InitStatus, mediacontrol_EndStatus,
mediacontrol_UndefinedStatus
};
typedef enum mediacontrol_PlayerStatusList mediacontrol_PlayerStatus;
typedef struct {
mediacontrol_PlayerStatus streamstatus;
char* url; /* The URL of the current media stream */
long long position; /* actual location in the stream (in ms) */
long long length; /* total length of the stream (in ms) */
} mediacontrol_StreamInformation;
/* Helper functions */
long long mediacontrol_unit_convert (input_thread_t *p_input,
mediacontrol_PositionKey from,
mediacontrol_PositionKey to,
long long value);
long long
mediacontrol_position2microsecond (input_thread_t* p_input, const mediacontrol_Position * pos);
mediacontrol_RGBPicture* mediacontrol_RGBPicture__alloc (int datasize);
void mediacontrol_RGBPicture__free (mediacontrol_RGBPicture* pic);
mediacontrol_PlaylistSeq* mediacontrol_PlaylistSeq__alloc (int size);
void mediacontrol_PlaylistSeq__free (mediacontrol_PlaylistSeq* ps);
mediacontrol_Exception* mediacontrol_exception_init(mediacontrol_Exception *exception);
void mediacontrol_exception_free(mediacontrol_Exception *exception);
mediacontrol_Instance* mediacontrol_new(char** args, mediacontrol_Exception *exception);
mediacontrol_Instance* mediacontrol_new_from_object(vlc_object_t* p_object,
mediacontrol_Exception *exception);
mediacontrol_Position* mediacontrol_get_media_position(mediacontrol_Instance *self,
mediacontrol_PositionOrigin an_origin,
mediacontrol_PositionKey a_key,
mediacontrol_Exception *exception);
void mediacontrol_set_media_position(mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
void mediacontrol_start(mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
void mediacontrol_pause(mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
void mediacontrol_resume(mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
void mediacontrol_stop(mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
void mediacontrol_exit(mediacontrol_Instance *self);
void mediacontrol_playlist_add_item (mediacontrol_Instance *self,
const char* psz_file,
mediacontrol_Exception *exception);
void mediacontrol_playlist_clear (mediacontrol_Instance *self,
mediacontrol_Exception *exception);
mediacontrol_PlaylistSeq* mediacontrol_playlist_get_list (mediacontrol_Instance *self,
mediacontrol_Exception *exception);
mediacontrol_RGBPicture* mediacontrol_snapshot (mediacontrol_Instance *self,
const mediacontrol_Position* a_position,
mediacontrol_Exception *exception);
/* Return a NULL terminated list */
mediacontrol_RGBPicture** mediacontrol_all_snapshots (mediacontrol_Instance *self,
mediacontrol_Exception *exception);
// Displays the message string, between "begin" and "end" positions
void mediacontrol_display_text (mediacontrol_Instance *self,
const char* message,
const mediacontrol_Position* begin,
const mediacontrol_Position* end,
mediacontrol_Exception *exception);
mediacontrol_StreamInformation*
mediacontrol_get_stream_information(mediacontrol_Instance* self,
mediacontrol_PositionKey a_key,
mediacontrol_Exception *exception);
unsigned short mediacontrol_sound_get_volume(mediacontrol_Instance* self,
mediacontrol_Exception *exception);
void mediacontrol_sound_set_volume(mediacontrol_Instance* self,
const unsigned short volume,
mediacontrol_Exception *exception);
#endif
#include "mediacontrol-core.h"
mediacontrol_Instance* mediacontrol_new(char** args, mediacontrol_Exception *exception)
{
mediacontrol_Instance* retval;
vlc_object_t *p_vlc;
int p_vlc_id;
char **ppsz_argv;
int i_count = 0;
int i_index;
char **p_tmp;
if (args)
{
for (p_tmp = args ; *p_tmp != NULL; p_tmp++)
i_count++;
}
ppsz_argv = malloc(i_count + 2);
ppsz_argv[0] = strdup("vlc");
for (i_index = 0; i_index < i_count; i_index++)
ppsz_argv[i_index+1] = strdup(args[i_index]);
ppsz_argv[i_count + 1] = NULL;
p_vlc_id = VLC_Create();
p_vlc = (vlc_object_t*)vlc_current_object (p_vlc_id);
if (! p_vlc)
{
exception->code = mediacontrol_InternalException;
exception->message = strdup("Unable to initialize VLC");
return NULL;
}
retval = (mediacontrol_Instance*)malloc(sizeof(mediacontrol_Instance));
VLC_Init(p_vlc_id, i_count + 1, ppsz_argv);
retval->p_vlc = p_vlc;
retval->vlc_object_id = p_vlc_id;
/* We can keep references on these, which should not change. Is it true ? */
retval->p_playlist = vlc_object_find(p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE);
retval->p_intf = vlc_object_find(p_vlc, VLC_OBJECT_INTF, FIND_ANYWHERE);
if (! retval->p_playlist || ! retval->p_intf)
{
exception->code=mediacontrol_InternalException;
exception->message=strdup("No available interface");
return NULL;
}
return retval;
};
void
mediacontrol_exit(mediacontrol_Instance *self)
{
vlc_object_release((vlc_object_t*)self->p_playlist);
vlc_object_release((vlc_object_t*)self->p_intf);
VLC_Stop(self->vlc_object_id);
VLC_Destroy(self->vlc_object_id);
}
#include "mediacontrol-core.h"
#include <vlc/intf.h>
mediacontrol_Instance* mediacontrol_new(char** args, mediacontrol_Exception *exception)
{
exception->code = mediacontrol_InternalException;
exception->message = strdup("The mediacontrol extension was compiled for plugin use only.");
return NULL;
};
void
mediacontrol_exit(mediacontrol_Instance *self)
{
vlc_object_release(self->p_playlist);
vlc_mutex_lock( &self->p_intf->change_lock );
self->p_intf->b_die = 1;
vlc_mutex_unlock( &self->p_intf->change_lock );
vlc_object_release(self->p_intf);
vlc_object_release(self->p_vlc);
}
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