Commit 02474925 authored by Antoine Cellerier's avatar Antoine Cellerier

* New Lua based playlist demuxer. Code is far from being finished. It...

* New Lua based playlist demuxer. Code is far from being finished. It currently implements some url translation stuff similar to what videoportals.c does (in share/luaplaylist/test.lua). To test it, run: ./vlc --demux lua "http://www.youtube.com/watch?v=CPRC4glkvq0" --color -v -I dummy. The idea is to make it possible for users to add their own (text) playlist demuxers (including stuff like the video portals URL translation) without needing to recompile VLC.
parent 15249253
...@@ -1532,6 +1532,20 @@ if test "${enable_shout}" = "yes"; then ...@@ -1532,6 +1532,20 @@ if test "${enable_shout}" = "yes"; then
[AC_MSG_WARN(libshout library not found)]) [AC_MSG_WARN(libshout library not found)])
fi fi
dnl Lua playlist demux
AC_ARG_ENABLE(luaplaylist,
[ --enable-lua lua playlist demux plugin (default enabled)])
if test "${enable_lua}" != "no"
then
PKG_CHECK_MODULES(LUA, lua5.1,
[ AC_DEFINE(HAVE_LUA, [], [Define if you have the lua library])
VLC_ADD_PLUGINS([luaplaylist])
VLC_ADD_LDFLAGS([luaplaylist],[$LUA_LIBS])
VLC_ADD_CFLAGS([luaplaylist],[$LUA_CFLAGS])
],
[AC_MSG_WARN(lua 5.0 not found)])
fi
dnl dnl
dnl HTTP daemon dnl HTTP daemon
dnl dnl
......
...@@ -17,4 +17,4 @@ SOURCES_playlist = \ ...@@ -17,4 +17,4 @@ SOURCES_playlist = \
videoportals.c \ videoportals.c \
$(NULL) $(NULL)
SOURCES_luaplaylist = luaplaylist.c
/*****************************************************************************
* luaplaylist.c : Lua playlist demux module
*****************************************************************************
* Copyright (C) 2007 the VideoLAN team
* $Id$
*
* Authors: Antoine Cellerier <dionoea at videolan tod org>
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc_demux.h>
#include <vlc_url.h>
#include <vlc_strings.h>
#include <errno.h> /* ENOMEM */
#include "playlist.h"
#include <lua.h> /* Low level lua C API */
#include <lauxlib.h> /* Higher level C API */
#include <lualib.h> /* Lua libs */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int E_(Import_LuaPlaylist)( vlc_object_t *p_this );
static void E_(Close_LuaPlaylist)( vlc_object_t *p_this );
static int Demux( demux_t *p_demux );
static int Control( demux_t *p_demux, int i_query, va_list args );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
add_shortcut( "lua" );
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_DEMUX );
set_shortname( _("Lua Playlist") );
set_description( _("Lua Playlist Parser Interface") );
set_capability( "demux2", 0 );
set_callbacks( E_(Import_LuaPlaylist), E_(Close_LuaPlaylist) );
vlc_module_end();
/*****************************************************************************
*
*****************************************************************************/
struct demux_sys_t
{
lua_State *p_state;
};
static demux_t *vlclua_get_demux( lua_State *p_state )
{
demux_t *p_demux;
lua_getglobal( p_state, "vlc" );
lua_getfield( p_state, lua_gettop( p_state ), "private" );
p_demux = (demux_t*)lua_topointer( p_state, lua_gettop( p_state ) );
lua_pop( p_state, 2 );
return p_demux;
}
static int vlclua_peek( lua_State *p_state )
{
demux_t *p_demux = vlclua_get_demux( p_state );
int i = lua_gettop( p_state );
int n;
byte_t *p_peek;
int i_peek;
if( !i ) return 0;
n = lua_tonumber( p_state, 1 );
lua_pop( p_state, i );
i_peek = stream_Peek( p_demux->s, &p_peek, n );
lua_pushnumber( p_state, i_peek );
lua_pushlstring( p_state, (const char *)p_peek, i_peek );
return 2;
}
static int vlclua_readline( lua_State *p_state )
{
demux_t *p_demux = vlclua_get_demux( p_state );
char *psz_line = stream_ReadLine( p_demux->s );
lua_pushstring( p_state, psz_line );
return 1;
}
static int vlclua_decode_uri( lua_State *p_state )
{
int i = lua_gettop( p_state );
if( !i ) return 0;
const char *psz_cstring = lua_tostring( p_state, 1 );
if( !psz_cstring ) return 0;
char *psz_string = strdup( psz_cstring );
lua_pop( p_state, i );
decode_URI( psz_string );
lua_pushstring( p_state, psz_string );
free( psz_string );
return 1;
}
/*****************************************************************************
* Import_LuaPlaylist: main import function
*****************************************************************************/
int E_(Import_LuaPlaylist)( vlc_object_t *p_this )
{
demux_t *p_demux = (demux_t *)p_this;
lua_State *p_state;
p_demux->p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) );
if( !p_demux->p_sys )
{
return VLC_ENOMEM;
}
p_demux->pf_control = Control;
p_demux->pf_demux = Demux;
/* Initialise Lua state structure */
p_state = luaL_newstate();
if( !p_state )
{
msg_Err( p_demux, "Could not create new Lua State" );
free( p_demux->p_sys );
return VLC_EGENERIC;
}
p_demux->p_sys->p_state = p_state;
/* Load Lua libraries */
luaL_openlibs( p_state ); /* FIXME: Don't open all the libs? */
static luaL_Reg p_reg[] =
{
{ "readline", vlclua_readline },
{ "peek", vlclua_peek },
{ "decode_uri", vlclua_decode_uri }
};
luaL_register( p_state, "vlc", p_reg );
lua_pushlightuserdata( p_state, p_demux );
lua_setfield( p_state, lua_gettop( p_state ) - 1, "private" );
lua_pushstring( p_state, p_demux->psz_path );
lua_setfield( p_state, lua_gettop( p_state ) - 1, "path" );
lua_pushstring( p_state, p_demux->psz_access );
lua_setfield( p_state, lua_gettop( p_state ) - 1, "access" );
lua_pop( p_state, 1 );
{
const char *psz_filename = "share/luaplaylist/test.lua";
int i_ret;
/* Load and run the script(s) */
if( luaL_dofile( p_state, psz_filename ) )
{
msg_Warn( p_demux, "Error while runing script %s: %s", psz_filename, lua_tostring( p_state, lua_gettop( p_state ) ) );
return VLC_EGENERIC;
}
if( lua_gettop( p_state ) )
{
i_ret = lua_toboolean( p_state, 1 );
printf( "Script returned %d: %d\n", 1, i_ret );
while( lua_gettop( p_state ) != 1 )
{
printf( "Script returned %d: %s\n", lua_gettop( p_state ),
lua_tostring( p_state, lua_gettop( p_state ) ) );
lua_pop( p_state, 1 );
}
lua_pop( p_state, 1 );
if( !i_ret )
{
E_(Close_LuaPlaylist)( p_this );
return VLC_EGENERIC;
}
}
else
{
E_(Close_LuaPlaylist)( p_this );
return VLC_EGENERIC;
}
}
return VLC_SUCCESS;
}
/*****************************************************************************
* Deactivate: frees unused data
*****************************************************************************/
void E_(Close_LuaPlaylist)( vlc_object_t *p_this )
{
demux_t *p_demux = (demux_t *)p_this;
lua_close( p_demux->p_sys->p_state );
free( p_demux->p_sys );
}
static int Demux( demux_t *p_demux )
{
/*input_item_t *p_input;*/
INIT_PLAYLIST_STUFF;
#if 0
p_input = input_ItemNewExt( p_playlist, psz_url, psz_title, 0, NULL, -1 );
playlist_BothAddInput( p_playlist, p_input,
p_item_in_category,
PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
PLAYLIST_END, NULL, NULL, VLC_FALSE );
#endif
HANDLE_PLAY_AND_RELEASE;
return -1; /* Needed for correct operation of go back */
}
static int Control( demux_t *p_demux, int i_query, va_list args )
{
return VLC_EGENERIC;
}
-- $Id$
if vlc.access ~= "http"
then
return false
end
url = nil
title = nil
function get_url_param( url, name )
return string.gsub( vlc.path, "^.*"..name.."=([^&]*).*$", "%1" )
end
if string.match( vlc.path, "youtube.com" )
then
if string.match( vlc.path, "watch%?v=" )
then
url = string.gsub( vlc.path, "^(.*)watch%?v=([^&]*).*$", "http://%1v/%2" )
while not title
do
line = vlc.readline()
if not line
then
break
end
if string.match( line, "<meta name=\"title\"" )
then
title = string.gsub( line, "^.*content=\"([^\"]*).*$", "%1" )
end
end
elseif string.match( vlc.path, "watch_fullscreen%?video_id=" ) or string.match( vlc.path, "p.swf" ) or string.match( vlc.path, "player2.swf" )
then
video_id = get_url_param( vlc.path, "video_id" )
t = get_url_param( vlc.path, "t" )
url = "http://www.youtube.com/get_video.php?video_id="..video_id.."&t="..t
if string.match( vlc.path, "title=" )
then
title = get_url_param( vlc.path, "title" )
end
end
elseif string.match( vlc.path, "dailymotion.com" )
then
len, str = vlc.peek( 9 )
if str == "<!DOCTYPE"
then
while not url
do
line = vlc.readline()
if string.match( line, "param name=\"flashvars\" value=\"url=" )
then
url = vlc.decode_uri( string.gsub( line, "^.*param name=\"flashvars\" value=\"url=([^&]*).*$", "%1" ) )
end
end
end
elseif string.match( vlc.path, "video.google.com" ) and string.match( vlc.path, "videoplay" )
then
url = string.gsub( vlc.path, "^.*(docid=[^&]*).*$", "http://video.google.com/videogvp?%1" )
elseif string.match( vlc.path, "metacafe.com" )
then
if string.match( vlc.path, "watch/" )
then
url = string.gsub( vlc.path, "^.*watch/(.*[^/])/?$", "http://www.metacafe.com/fplayer/%1.swf" )
elseif string.match( vlc.path, "mediaURL=" )
then
url = string.gsub( vlc.path, "^.*mediaURL=([^&]*).*$", "%1" )
end
end
if url == nil
then
return false
else
return true, url, title
end
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