Commit 4e88f3b2 authored by Olivier Aubert's avatar Olivier Aubert

python bindings: add support for the new libvlc API

parent c340ebcb
......@@ -2,7 +2,10 @@
# Building the Python binding
###############################################################################
EXTRA_DIST = vlcglue.c vlcglue.h setup.py vlcwrapper.py
EXTRA_DIST = vlcglue.h setup.py vlcwrapper.py \
vlc_module.c vlc_object.c \
vlc_mediacontrol.c vlc_position.c \
vlc_instance.c vlc_input.c
if BUILD_PYTHON
......
* Compilation
* Testing
If you try to compile the bindings from a development tree, you will
have to specify the path for VLC modules, which cannot be guessed by
the extension module.
For vlc.MediaControl:
mc=vlc.MediaControl('--plugin-path /path/to/vlc/directory'.split())
For vlc.Instance:
i=vlc.Instance('--plugin-path /path/to/vlc/directory'.split())
* Skeleton generation :
** For method bindings:
perl -n -e 'print "static PyObject *\nvlcInput_$2( PyObject *self, PyObject *args )\n{\n libvlc_exception_t ex;\n LIBVLC_TRY;\n $1_$2( self->p_input, &ex); LIBVLC_EXCEPT;\n Py_INCREF( Py_None );\n return Py_None;\n}\n\n" if /(libvlc_input)_(\w+)/ and ($2 ne "t")' ../../include/vlc/libvlc.h
** For method table:
perl -n -e 'print " { \"$2\", $1_$2, METH_VARARGS,\n \"$2()\" },\n" if /^(vlcInput)_(\w+)/' vlc_instance.c
......@@ -21,15 +21,8 @@ except KeyError:
if not srcdir:
srcdir = '.'
#if os.sys.platform in ('win32', 'darwin'):
# Do not use PIC version on win32 and Mac OS X
if True:
# PIC version seems to be disabled on all platforms
vlclib=os.path.join( top_builddir, 'src', 'libvlc.a' )
picflag=''
else:
vlclib=os.path.join( top_builddir, 'src', 'libvlc_pic.a' )
picflag='pic'
vlclib="-lvlc"
picflag=''
def get_vlcconfig():
vlcconfig=None
......@@ -69,39 +62,47 @@ def get_ldflags():
ldflags = []
if os.sys.platform == 'darwin':
ldflags = "-read_only_relocs warning".split()
ldflags.extend(os.popen('%s --libs vlc %s builtin' % (vlcconfig,
ldflags.extend(os.popen('%s --libs vlc %s' % (vlcconfig,
picflag),
'r').readline().rstrip().split())
if os.sys.platform == 'darwin':
ldflags.append('-lstdc++')
return ldflags
#source_files = [ 'vlc_module.c', 'vlc_object.c', 'vlc_mediacontrol.c',
# 'vlc_position.c', 'vlc_instance.c', 'vlc_input.c' ]
source_files = [ 'vlc_module.c' ]
# To compile in a local vlc tree
vlclocal = Extension('vlc',
sources = [ os.path.join( srcdir, 'vlcglue.c'),
os.path.join( srcdir, '../../src/control/mediacontrol_init.c')],
include_dirs = [ top_builddir,
os.path.join( srcdir, '../../include'),
os.path.join( srcdir, '../../', '/usr/win32/include') ],
sources = [ os.path.join( srcdir, f ) for f in source_files ] +
[ os.path.join( top_builddir, 'src/control/mediacontrol_init.c') ],
include_dirs = [ top_builddir,
os.path.join( top_builddir, 'include' ),
srcdir,
'/usr/win32/include' ],
extra_objects = [ vlclib ],
extra_compile_args = get_cflags(),
extra_link_args = [ '-L' + top_builddir ] + get_ldflags(),
)
setup (name = 'MediaControl',
setup (name = 'VLC Bindings',
version = get_vlc_version(),
scripts = [ os.path.join( srcdir, 'vlcwrapper.py') ],
#scripts = [ os.path.join( srcdir, 'vlcwrapper.py') ],
keywords = [ 'vlc', 'video' ],
license = "GPL",
description = """VLC bindings for python.
This module provides a MediaControl object, which implements an API
inspired from the OMG Audio/Video Stream 1.0 specification. Moreover,
the module provides a Object type, which gives a low-level access to
the vlc objects and their variables.
This module provides bindings for the native libvlc API of the VLC
video player. Documentation can be found on the VLC wiki :
http://wiki.videolan.org/index.php/ExternalAPI
Documentation can be found on the VLC wiki :
The module also provides a Object type, which gives a low-level access
to the vlc objects and their variables.
This module also provides a MediaControl object, which implements an
API inspired from the OMG Audio/Video Stream 1.0 specification.
Documentation can be found on the VLC wiki :
http://wiki.videolan.org/index.php/PythonBinding
Example session:
......@@ -135,5 +136,6 @@ o.info()
i=o.find_object('input')
i.list()
i.get('time')
""",
ext_modules = [ vlclocal ])
/*****************************************************************************
* vlc_input.c: vlc.Input binding
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id: $
*
* Authors: Olivier Aubert <oaubert at bat710.univ-lyon1.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "vlcglue.h"
/***********************************************************************
* vlc.Input
***********************************************************************/
static PyObject *
vlcInput_get_length( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
vlc_int64_t i_ret;
LIBVLC_TRY;
i_ret = libvlc_input_get_length( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "L", i_ret );
}
static PyObject *
vlcInput_get_time( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
vlc_int64_t i_ret;
LIBVLC_TRY;
i_ret = libvlc_input_get_time( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "L", i_ret );
}
static PyObject *
vlcInput_set_time( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
vlc_int64_t i_time;
if( !PyArg_ParseTuple( args, "L", &i_time ) )
return NULL;
LIBVLC_TRY;
libvlc_input_set_time( LIBVLC_INPUT->p_input, i_time, &ex);
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInput_get_position( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
float f_ret;
LIBVLC_TRY;
f_ret = libvlc_input_get_position( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "f", f_ret );
}
static PyObject *
vlcInput_set_position( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
float f_pos;
if( !PyArg_ParseTuple( args, "f", &f_pos ) )
return NULL;
LIBVLC_TRY;
libvlc_input_set_position( LIBVLC_INPUT->p_input, f_pos, &ex);
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInput_will_play( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_ret;
LIBVLC_TRY;
i_ret = libvlc_input_will_play( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInput_get_rate( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
float f_ret;
LIBVLC_TRY;
f_ret = libvlc_input_get_rate( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "f", f_ret );
}
static PyObject *
vlcInput_set_rate( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
float f_rate;
if( !PyArg_ParseTuple( args, "f", &f_rate ) )
return NULL;
LIBVLC_TRY;
libvlc_input_set_rate( LIBVLC_INPUT->p_input, f_rate, &ex);
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInput_get_state( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_ret;
LIBVLC_TRY;
i_ret = libvlc_input_get_state( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInput_has_vout( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_ret;
LIBVLC_TRY;
i_ret = libvlc_input_has_vout( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInput_get_fps( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
float f_ret;
LIBVLC_TRY;
f_ret = libvlc_input_get_fps( LIBVLC_INPUT->p_input, &ex);
LIBVLC_EXCEPT;
return Py_BuildValue( "f", f_ret );
}
static PyMethodDef vlcInput_methods[] =
{
{ "get_length", vlcInput_get_length, METH_VARARGS,
"get_length() -> long" },
{ "get_time", vlcInput_get_time, METH_VARARGS,
"get_time() -> long" },
{ "set_time", vlcInput_set_time, METH_VARARGS,
"set_time(long)" },
{ "get_position", vlcInput_get_position, METH_VARARGS,
"get_position() -> float" },
{ "set_position", vlcInput_set_position, METH_VARARGS,
"set_position(float)" },
{ "will_play", vlcInput_will_play, METH_VARARGS,
"will_play() -> int" },
{ "get_rate", vlcInput_get_rate, METH_VARARGS,
"get_rate() -> float" },
{ "set_rate", vlcInput_set_rate, METH_VARARGS,
"set_rate(float)" },
{ "get_state", vlcInput_get_state, METH_VARARGS,
"get_state() -> int" },
{ "has_vout", vlcInput_has_vout, METH_VARARGS,
"has_vout() -> int" },
{ "get_fps", vlcInput_get_fps, METH_VARARGS,
"get_fps() -> float" },
{ NULL } /* Sentinel */
};
static PyTypeObject vlcInput_Type =
{
PyObject_HEAD_INIT( NULL )
0, /*ob_size*/
"vlc.Input", /*tp_name*/
sizeof( vlcInput_Type ), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"vlc.Input object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
vlcInput_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
/*****************************************************************************
* vlc_instance.c: vlc.Instance binding
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
* $Id: $
*
* Authors: Olivier Aubert <oaubert at bat710.univ-lyon1.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "vlcglue.h"
/*****************************************************************************
* Instance object implementation
*****************************************************************************/
static PyObject *
vlcInstance_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
{
vlcInstance *self;
libvlc_exception_t ex;
PyObject* py_list = NULL;
char** ppsz_args = NULL;
int i_size = 0;
self = PyObject_New( vlcInstance, &vlcInstance_Type );
if( PyArg_ParseTuple( args, "O", &py_list ) )
{
int i_index;
Py_INCREF( py_list );
if( ! PySequence_Check( py_list ) )
{
PyErr_SetString( PyExc_TypeError, "Parameter must be a sequence." );
return NULL;
}
i_size = PySequence_Size( py_list );
ppsz_args = malloc( ( i_size + 2 ) * sizeof( char * ) );
if( ! ppsz_args )
{
PyErr_SetString( PyExc_MemoryError, "Out of memory" );
return NULL;
}
/* FIXME: we define a default args[0], since the libvlc API
needs one. But it would be cleaner to fix the libvlc API.
*/
ppsz_args[0] = strdup("vlc");
for ( i_index = 0; i_index < i_size; i_index++ )
{
ppsz_args[i_index + 1] =
strdup( PyString_AsString( PyObject_Str(
PySequence_GetItem( py_list,
i_index ) ) ) );
}
ppsz_args[i_size + 1] = NULL;
/* Since we prepended the arg[0] */
i_size += 1;
Py_DECREF( py_list );
}
else
{
/* No arguments were given. Clear the exception raised
by PyArg_ParseTuple. */
PyErr_Clear( );
}
Py_BEGIN_ALLOW_THREADS
LIBVLC_TRY
LIBVLC_INSTANCE->p_instance = libvlc_new( i_size, ppsz_args, &ex );
LIBVLC_EXCEPT
Py_END_ALLOW_THREADS
Py_INCREF( self );
return ( PyObject * )self;
}
static void
vlcInstance_dealloc( PyObject *self )
{
libvlc_exception_t ex;
libvlc_destroy( LIBVLC_INSTANCE->p_instance, &ex );
PyMem_DEL( self );
}
static PyObject *
vlcInstance_get_vlc_id( PyObject *self, PyObject *args )
{
return Py_BuildValue( "i", libvlc_get_vlc_id( LIBVLC_INSTANCE->p_instance ) );
}
/* Playlist play. 2 parameters: i_id, the id to play
l_options: a list of options */
static PyObject *
vlcInstance_playlist_play( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_id = -1;
PyObject *py_options = NULL;
int i_size = 0;
char** ppsz_args = NULL;
if( !PyArg_ParseTuple( args, "|iO", &i_id, &py_options ) )
return NULL;
if( py_options )
{
/* Options were given. Convert them to a char** */
int i_index;
Py_INCREF( py_options );
if( ! PySequence_Check( py_options ) )
{
PyErr_SetString( PyExc_TypeError, "Parameter must be a sequence." );
return NULL;
}
i_size = PySequence_Size( py_options );
ppsz_args = malloc( ( i_size + 1 ) * sizeof( char * ) );
if( ! ppsz_args )
{
PyErr_SetString( PyExc_MemoryError, "Out of memory" );
return NULL;
}
for ( i_index = 0; i_index < i_size; i_index++ )
{
ppsz_args[i_index] =
strdup( PyString_AsString( PyObject_Str(
PySequence_GetItem( py_options,
i_index ) ) ) );
}
ppsz_args[i_size] = NULL;
Py_DECREF( py_options );
}
LIBVLC_TRY;
libvlc_playlist_play( LIBVLC_INSTANCE->p_instance, i_id, i_size, ppsz_args, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInstance_playlist_pause( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
LIBVLC_TRY;
libvlc_playlist_pause( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInstance_playlist_isplaying( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_ret;
LIBVLC_TRY;
i_ret = libvlc_playlist_isplaying( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInstance_playlist_items_count( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_ret;
LIBVLC_TRY;
i_ret = libvlc_playlist_items_count( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInstance_playlist_stop( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
LIBVLC_TRY;
libvlc_playlist_stop( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInstance_playlist_next( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
LIBVLC_TRY;
libvlc_playlist_next( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInstance_playlist_prev( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
LIBVLC_TRY;
libvlc_playlist_prev( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
static PyObject *
vlcInstance_playlist_clear( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
LIBVLC_TRY;
libvlc_playlist_clear( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
Py_INCREF( Py_None );
return Py_None;
}
/* Add a playlist item. Main parameter: URI.
Optional parameters: name, options */
static PyObject *
vlcInstance_playlist_add( PyObject *self, PyObject *args)
{
libvlc_exception_t ex;
int i_ret;
char* psz_uri = NULL;
char* psz_name = NULL;
PyObject *py_options = NULL;
int i_size = 0;
char** ppsz_args = NULL;
if( !PyArg_ParseTuple( args, "s|sO", &psz_uri, &psz_name, &py_options ) )
return NULL;
if( !psz_name )
{
/* Set a default name */
psz_name = strdup( psz_uri );
}
if( py_options )
{
/* Options were given. Convert them to a char** */
int i_index;
Py_INCREF( py_options );
if( ! PySequence_Check( py_options ) )
{
PyErr_SetString( PyExc_TypeError, "Parameter must be a sequence." );
return NULL;
}
i_size = PySequence_Size( py_options );
ppsz_args = malloc( ( i_size + 1 ) * sizeof( char * ) );
if( ! ppsz_args )
{
PyErr_SetString( PyExc_MemoryError, "Out of memory" );
return NULL;
}
for ( i_index = 0; i_index < i_size; i_index++ )
{
ppsz_args[i_index] =
strdup( PyString_AsString( PyObject_Str(
PySequence_GetItem( py_options,
i_index ) ) ) );
}
ppsz_args[i_size] = NULL;
Py_DECREF( py_options );
}
LIBVLC_TRY;
if( ppsz_args )
{
i_ret = libvlc_playlist_add_extended( LIBVLC_INSTANCE->p_instance,
psz_uri,
psz_name,
i_size,
ppsz_args,
&ex );
}
else
{
i_ret = libvlc_playlist_add( LIBVLC_INSTANCE->p_instance,
psz_uri,
psz_name,
&ex );
}
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInstance_playlist_delete_item( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_id;
int i_ret;
if( !PyArg_ParseTuple( args, "i", &i_id ) )
return NULL;
LIBVLC_TRY;
i_ret = libvlc_playlist_delete_item( LIBVLC_INSTANCE->p_instance, i_id, &ex );
LIBVLC_EXCEPT;
return Py_BuildValue( "i", i_ret );
}
static PyObject *
vlcInstance_playlist_get_input( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
libvlc_input_t *p_input;
vlcInput *p_ret;
LIBVLC_TRY;
p_input = libvlc_playlist_get_input( LIBVLC_INSTANCE->p_instance, &ex );
LIBVLC_EXCEPT;
p_ret = PyObject_New( vlcInput, &vlcInput_Type );
p_ret->p_input = p_input;
Py_INCREF( p_ret ); /* Ah bon ? */
return ( PyObject * )p_ret;
}
static PyObject *
vlcInstance_video_set_parent( PyObject *self, PyObject *args )
{
libvlc_exception_t ex;
int i_drawable;
if( !PyArg_ParseTuple( args, "i", &i_drawable ) )
return NULL;
LIBVLC_TRY;