From 1179afb6e19691d095fd1fc876b411cce15065c7 Mon Sep 17 00:00:00 2001 From: Pierre d'Herbemont Date: Mon, 13 Aug 2007 21:46:27 +0000 Subject: [PATCH] modules/meta_engine/luameta.c: Get meta (untested) and artwork using lua scripts. --- Makefile.am | 4 + configure.ac | 6 +- modules/meta_engine/luameta.c | 597 ++++++++++++++++++++++++++++++++++ share/Makefile.am | 2 + share/luameta/README.txt | 53 +++ share/luameta/googleimage.lua | 22 ++ 6 files changed, 681 insertions(+), 3 deletions(-) create mode 100644 modules/meta_engine/luameta.c create mode 100644 share/luameta/README.txt create mode 100644 share/luameta/googleimage.lua diff --git a/Makefile.am b/Makefile.am index aff9b4b18e..8f455cf98e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -424,6 +424,10 @@ VLC-release.app: vlc for i in $(srcdir)/share/luaplaylist/*.* ; do \ $(INSTALL) -m 644 $${i} $(top_builddir)/VLC-release.app/Contents/MacOS/share/luaplaylist/`basename $${i}` ; \ done ; \ + $(INSTALL) -d $(top_builddir)/VLC-release.app/Contents/MacOS/share/luameta + for i in $(srcdir)/share/luameta/*.* ; do \ + $(INSTALL) -m 644 $${i} $(top_builddir)/VLC-release.app/Contents/MacOS/share/luameta/`basename $${i}` ; \ + done ; \ $(INSTALL) -d $(top_builddir)/VLC-release.app/Contents/MacOS/share/http/dialogs $(INSTALL) -d $(top_builddir)/VLC-release.app/Contents/MacOS/share/http/js $(INSTALL) -d $(top_builddir)/VLC-release.app/Contents/MacOS/share/http/old diff --git a/configure.ac b/configure.ac index 9c3a336d08..4036c4818f 100644 --- a/configure.ac +++ b/configure.ac @@ -1652,9 +1652,9 @@ then ]) if test "x${have_lua}" = "xyes" ; then 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]) + VLC_ADD_PLUGINS([luaplaylist luameta]) + VLC_ADD_LDFLAGS([luaplaylist luameta],[$LUA_LIBS]) + VLC_ADD_CFLAGS([luaplaylist luameta],[$LUA_CFLAGS]) fi fi diff --git a/modules/meta_engine/luameta.c b/modules/meta_engine/luameta.c new file mode 100644 index 0000000000..62bffb485d --- /dev/null +++ b/modules/meta_engine/luameta.c @@ -0,0 +1,597 @@ +/***************************************************************************** + * googleimage.c + ***************************************************************************** + * Copyright (C) 2006 the VideoLAN team + * $Id$ + * + * Authors: Pierre d'Herbemont + * + * 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 /* malloc(), free() */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_STAT_H +# include +#endif + +#include /* Low level lua C API */ +#include /* Higher level C API */ +#include /* Lua libs */ + +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int FindArt( vlc_object_t * ); +static int FindMeta( vlc_object_t *p_this ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ + +vlc_module_begin(); + set_shortname( N_( "Lua Meta" ) ); + set_description( _("Fetch Artwork using lua scripts") ); + set_capability( "meta fetcher", 10 ); + set_callbacks( FindMeta, NULL ); + add_submodule(); + set_capability( "art finder", 10 ); + set_callbacks( FindArt, NULL ); +vlc_module_end(); + +/***************************************************************************** + * Lua function bridge + *****************************************************************************/ +static vlc_object_t * vlclua_get_this( lua_State *p_state ) +{ + vlc_object_t * p_this; + lua_getglobal( p_state, "vlc" ); + lua_getfield( p_state, lua_gettop( p_state ), "private" ); + p_this = (vlc_object_t*)lua_topointer( p_state, lua_gettop( p_state ) ); + lua_pop( p_state, 2 ); + return p_this; +} + +static int vlclua_stream_new( lua_State *p_state ) +{ + vlc_object_t * p_this = vlclua_get_this( p_state ); + int i = lua_gettop( p_state ); + stream_t * p_stream; + const char * psz_url; + if( !i ) return 0; + psz_url = lua_tostring( p_state, 1 ); + lua_pop( p_state, i ); + p_stream = stream_UrlNew( p_this, psz_url ); + lua_pushlightuserdata( p_state, p_stream ); + return 1; +} + +static int vlclua_stream_read( lua_State *p_state ) +{ + int i = lua_gettop( p_state ); + stream_t * p_stream; + int n; + byte_t *p_read; + int i_read; + if( !i ) return 0; + p_stream = (stream_t *)lua_topointer( p_state, 1 ); + n = lua_tonumber( p_state, 2 ); + lua_pop( p_state, i ); + p_read = malloc( n ); + if( !p_read ) return 0; + i_read = stream_Read( p_stream, p_read, n ); + lua_pushlstring( p_state, (const char *)p_read, i_read ); + free( p_read ); + return 1; +} + +static int vlclua_stream_readline( lua_State *p_state ) +{ + int i = lua_gettop( p_state ); + stream_t * p_stream; + if( !i ) return 0; + p_stream = (stream_t *)lua_topointer( p_state, 1 ); + lua_pop( p_state, i ); + char *psz_line = stream_ReadLine( p_stream ); + if( psz_line ) + { + lua_pushstring( p_state, psz_line ); + free( psz_line ); + } + else + { + lua_pushnil( p_state ); + } + return 1; +} + +static int vlclua_stream_delete( lua_State *p_state ) +{ + int i = lua_gettop( p_state ); + stream_t * p_stream; + if( !i ) return 0; + p_stream = (stream_t *)lua_topointer( p_state, 1 ); + lua_pop( p_state, i ); + stream_Delete( p_stream ); + return 1; +} + +static int vlclua_msg_dbg( lua_State *p_state ) +{ + vlc_object_t *p_this = vlclua_get_this( 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; + msg_Dbg( p_this, "%s", psz_cstring ); + return 0; +} +static int vlclua_msg_warn( lua_State *p_state ) +{ + vlc_object_t *p_this = vlclua_get_this( 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; + msg_Warn( p_this, "%s", psz_cstring ); + return 0; +} +static int vlclua_msg_err( lua_State *p_state ) +{ + vlc_object_t *p_this = vlclua_get_this( 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; + msg_Err( p_this, "%s", psz_cstring ); + return 0; +} +static int vlclua_msg_info( lua_State *p_state ) +{ + vlc_object_t *p_this = vlclua_get_this( 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; + msg_Info( p_this, "%s", psz_cstring ); + return 0; +} + +/* Functions to register */ +static luaL_Reg p_reg[] = +{ + { "stream_new", vlclua_stream_new }, + { "stream_read", vlclua_stream_read }, + { "stream_readline", vlclua_stream_readline }, + { "stream_delete", vlclua_stream_delete }, + { "msg_dbg", vlclua_msg_dbg }, + { "msg_warn", vlclua_msg_warn }, + { "msg_err", vlclua_msg_err }, + { "msg_info", vlclua_msg_info }, + { NULL, NULL } +}; +/***************************************************************************** + * + *****************************************************************************/ +static int file_select( const char *file ) +{ + int i = strlen( file ); + return i > 4 && !strcmp( file+i-4, ".lua" ); +} + +static int file_compare( const char **a, const char **b ) +{ + return strcmp( *a, *b ); +} + +/***************************************************************************** + * Init lua + *****************************************************************************/ +static lua_State * vlclua_meta_init( vlc_object_t *p_this, input_item_t * p_item ) +{ + lua_State * p_state = luaL_newstate(); + if( !p_state ) + { + msg_Err( p_this, "Could not create new Lua State" ); + return NULL; + } + + /* Load Lua libraries */ + luaL_openlibs( p_state ); /* XXX: Don't open all the libs? */ + + luaL_register( p_state, "vlc", p_reg ); + + lua_pushlightuserdata( p_state, p_this ); + lua_setfield( p_state, lua_gettop( p_state ) - 1, "private" ); + + lua_pushstring( p_state, p_item->psz_name ); + lua_setfield( p_state, lua_gettop( p_state ) - 1, "name" ); + + lua_pushstring( p_state, p_item->p_meta->psz_title ); + lua_setfield( p_state, lua_gettop( p_state ) - 1, "title" ); + + lua_pushstring( p_state, p_item->p_meta->psz_album ); + lua_setfield( p_state, lua_gettop( p_state ) - 1, "album" ); + + lua_pushstring( p_state, p_item->p_meta->psz_arturl ); + lua_setfield( p_state, lua_gettop( p_state ) - 1, "arturl" ); + /* XXX: all should be passed */ + + return p_state; +} + +/***************************************************************************** + * Will execute func on all scripts in luadirname, and stop if func returns + * success. + *****************************************************************************/ +static int vlclua_scripts_batch_execute( vlc_object_t *p_this, + const char * luadirname, + int (*func)(vlc_object_t *, const char *, lua_State *, void *), + lua_State * p_state, + void * user_data) +{ + int i_ret = VLC_EGENERIC; + + DIR *dir = NULL; + char **ppsz_filelist = NULL; + char **ppsz_fileend = NULL; + char **ppsz_file; + + char *ppsz_dir_list[] = { NULL, NULL, NULL }; + char **ppsz_dir; + + ppsz_dir_list[0] = malloc( strlen( p_this->p_libvlc->psz_homedir ) + + strlen( "/"CONFIG_DIR"/" ) + strlen( luadirname ) + 1 ); + sprintf( ppsz_dir_list[0], "%s/"CONFIG_DIR"/%s", + p_this->p_libvlc->psz_homedir, luadirname ); + +# if defined(__APPLE__) || defined(SYS_BEOS) || defined(WIN32) + { + const char *psz_vlcpath = config_GetDataDir( p_this ); + ppsz_dir_list[1] = malloc( strlen( psz_vlcpath ) + strlen( luadirname ) + 1 ); + if( !ppsz_dir_list[1] ) return VLC_ENOMEM; + sprintf( ppsz_dir_list[1], "%s/%s", psz_vlcpath, luadirname ); + } +# endif + + for( ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) + { + int i_files; + + if( ppsz_filelist ) + { + for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; + ppsz_file++ ) + free( *ppsz_file ); + free( ppsz_filelist ); + ppsz_filelist = NULL; + } + + if( dir ) + { + closedir( dir ); + } + + msg_Dbg( p_this, "Trying Lua scripts in %s", *ppsz_dir ); + dir = utf8_opendir( *ppsz_dir ); + + if( !dir ) continue; + i_files = utf8_loaddir( dir, &ppsz_filelist, file_select, file_compare ); + if( i_files < 1 ) continue; + ppsz_fileend = ppsz_filelist + i_files; + + for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; ppsz_file++ ) + { + char *psz_filename; + asprintf( &psz_filename, "%s/%s", *ppsz_dir, *ppsz_file ); + msg_Dbg( p_this, "Trying Lua playlist script %s", psz_filename ); + + i_ret = func( p_this, psz_filename, p_state, user_data ); + + free( psz_filename ); + + if( i_ret == VLC_SUCCESS ) break; + } + if( i_ret == VLC_SUCCESS ) break; + } + + if( ppsz_filelist ) + { + for( ppsz_file = ppsz_filelist; ppsz_file < ppsz_fileend; + ppsz_file++ ) + free( *ppsz_file ); + free( ppsz_filelist ); + } + for( ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ ) + free( *ppsz_dir ); + + if( dir ) closedir( dir ); + + return i_ret; +} + +/***************************************************************************** + * Meta data setters utility. + *****************************************************************************/ +static inline void read_meta_data( vlc_object_t *p_this, + lua_State *p_state, int o, int t, + input_item_t *p_input ) +{ + const char *psz_value; +#define TRY_META( a, b ) \ + lua_getfield( p_state, o, a ); \ + if( lua_isstring( p_state, t ) ) \ + { \ + psz_value = lua_tostring( p_state, t ); \ + msg_Dbg( p_this, #b ": %s", psz_value ); \ + vlc_meta_Set ## b ( p_input->p_meta, psz_value ); \ + } \ + lua_pop( p_state, 1 ); /* pop a */ + TRY_META( "title", Title ); + TRY_META( "artist", Artist ); + TRY_META( "genre", Genre ); + TRY_META( "copyright", Copyright ); + TRY_META( "album", Album ); + TRY_META( "tracknum", Tracknum ); + TRY_META( "description", Description ); + TRY_META( "rating", Rating ); + TRY_META( "date", Date ); + TRY_META( "setting", Setting ); + TRY_META( "url", URL ); + TRY_META( "language", Language ); + TRY_META( "nowplaying", NowPlaying ); + TRY_META( "publisher", Publisher ); + TRY_META( "encodedby", EncodedBy ); + TRY_META( "arturl", ArtURL ); + TRY_META( "trackid", TrackID ); +} + +static inline void read_custom_meta_data( vlc_object_t *p_this, + lua_State *p_state, int o, int t, + input_item_t *p_input ) +{ + lua_getfield( p_state, o, "meta" ); + if( lua_istable( p_state, t ) ) + { + lua_pushnil( p_state ); + while( lua_next( p_state, t ) ) + { + if( !lua_isstring( p_state, t+1 ) ) + { + msg_Warn( p_this, "Custom meta data category name must be " + "a string" ); + } + else if( !lua_istable( p_state, t+2 ) ) + { + msg_Warn( p_this, "Custom meta data category contents " + "must be a table" ); + } + else + { + const char *psz_meta_category = lua_tostring( p_state, t+1 ); + msg_Dbg( p_this, "Found custom meta data category: %s", + psz_meta_category ); + lua_pushnil( p_state ); + while( lua_next( p_state, t+2 ) ) + { + if( !lua_isstring( p_state, t+3 ) ) + { + msg_Warn( p_this, "Custom meta category item name " + "must be a string." ); + } + else if( !lua_isstring( p_state, t+4 ) ) + { + msg_Warn( p_this, "Custom meta category item value " + "must be a string." ); + } + else + { + const char *psz_meta_name = + lua_tostring( p_state, t+3 ); + const char *psz_meta_value = + lua_tostring( p_state, t+4 ); + msg_Dbg( p_this, "Custom meta %s, %s: %s", + psz_meta_category, psz_meta_name, + psz_meta_value ); + input_ItemAddInfo( p_input, psz_meta_category, + psz_meta_name, psz_meta_value ); + } + lua_pop( p_state, 1 ); /* pop item */ + } + } + lua_pop( p_state, 1 ); /* pop category */ + } + } + lua_pop( p_state, 1 ); /* pop "meta" */ +} + +/***************************************************************************** + * Called through lua_scripts_batch_execute to call 'fetch_art' on the script + * pointed by psz_filename. + *****************************************************************************/ +static int fetch_art( vlc_object_t *p_this, const char * psz_filename, + lua_State * p_state, void * user_data ) +{ + int i_ret = VLC_EGENERIC; + input_item_t * p_input = user_data; + int s; + + /* Ugly hack to delete previous versions of the fetchart() + * functions. */ + lua_pushnil( p_state ); + lua_setglobal( p_state, "fetch_art" ); + + /* Load and run the script(s) */ + if( luaL_dofile( p_state, psz_filename ) ) + { + msg_Warn( p_this, "Error loading script %s: %s", psz_filename, + lua_tostring( p_state, lua_gettop( p_state ) ) ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + lua_getglobal( p_state, "fetch_art" ); + + if( !lua_isfunction( p_state, lua_gettop( p_state ) ) ) + { + msg_Warn( p_this, "Error while runing script %s, " + "function fetch_art() not found", psz_filename ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + if( lua_pcall( p_state, 0, 1, 0 ) ) + { + msg_Warn( p_this, "Error while runing script %s, " + "function fetch_art(): %s", psz_filename, + lua_tostring( p_state, lua_gettop( p_state ) ) ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + if((s = lua_gettop( p_state ))) + { + const char * psz_value; + + if( lua_isstring( p_state, s ) ) + { + psz_value = lua_tostring( p_state, s ); + if( psz_value && *psz_value != 0 ) + { + msg_Dbg( p_this, "setting arturl: %s", psz_value ); + vlc_meta_SetArtURL ( p_input->p_meta, psz_value ); + i_ret = VLC_SUCCESS; + } + } + else + { + msg_Err( p_this, "Lua playlist script %s: " + "didn't return a string", psz_filename ); + } + } + else + { + msg_Err( p_this, "Script went completely foobar" ); + } + + return i_ret; +} + +/***************************************************************************** + * Called through lua_scripts_batch_execute to call 'fetch_meta' on the script + * pointed by psz_filename. + *****************************************************************************/ +static int fetch_meta( vlc_object_t *p_this, const char * psz_filename, + lua_State * p_state, void * user_data ) +{ + input_item_t * p_input = user_data; + int t; + + /* Ugly hack to delete previous versions of the fetchmeta() + * functions. */ + lua_pushnil( p_state ); + lua_setglobal( p_state, "fetch_meta" ); + + /* Load and run the script(s) */ + if( luaL_dofile( p_state, psz_filename ) ) + { + msg_Warn( p_this, "Error loading script %s: %s", psz_filename, + lua_tostring( p_state, lua_gettop( p_state ) ) ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + lua_getglobal( p_state, "fetch_meta" ); + + if( !lua_isfunction( p_state, lua_gettop( p_state ) ) ) + { + msg_Warn( p_this, "Error while runing script %s, " + "function fetch_meta() not found", psz_filename ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + if( lua_pcall( p_state, 0, 1, 0 ) ) + { + msg_Warn( p_this, "Error while runing script %s, " + "function fetch_meta(): %s", psz_filename, + lua_tostring( p_state, lua_gettop( p_state ) ) ); + lua_pop( p_state, 1 ); + return VLC_EGENERIC; + } + + + if((t = lua_gettop( p_state ))) + { + if( lua_istable( p_state, t ) ) + { + read_meta_data( p_this, p_state, t, t+1, p_input ); + read_custom_meta_data( p_this, p_state, t, t+1, p_input ); + } + else + { + msg_Err( p_this, "Lua playlist script %s: " + "didn't return a table", psz_filename ); + } + } + else + { + msg_Err( p_this, "Script went completely foobar" ); + } + + /* We tell the batch thing to continue, hence all script + * will get the change to add its meta. This behaviour could + * be changed. */ + return VLC_EGENERIC; +} + +/***************************************************************************** + * Module entry point for meta. + *****************************************************************************/ +static int FindMeta( vlc_object_t *p_this ) +{ + meta_engine_t *p_me = (meta_engine_t *)p_this; + input_item_t *p_item = p_me->p_item; + lua_State *p_state = vlclua_meta_init( p_this, p_item ); + + int i_ret = vlclua_scripts_batch_execute( p_this, "luameta", &fetch_meta, p_state, p_item ); + lua_close( p_state ); + return i_ret; +} + +/***************************************************************************** + * Module entry point for art. + *****************************************************************************/ +static int FindArt( vlc_object_t *p_this ) +{ + playlist_t *p_playlist = (playlist_t *)p_this; + input_item_t *p_item = (input_item_t *)(p_playlist->p_private); + lua_State *p_state = vlclua_meta_init( p_this, p_item ); + + int i_ret = vlclua_scripts_batch_execute( p_this, "luameta", &fetch_art, p_state, p_item ); + lua_close( p_state ); + return i_ret; +} + diff --git a/share/Makefile.am b/share/Makefile.am index 20971f6661..973d8e25e5 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -245,6 +245,8 @@ DIST_osdmenu_minimal = \ osdmenu/minimal/fs_panel_mockup.png DIST_lua= \ + luameta/README.txt \ + luameta/googleimage.lua \ luaplaylist/README.txt \ luaplaylist/dailymotion.lua \ luaplaylist/youtube.lua \ diff --git a/share/luameta/README.txt b/share/luameta/README.txt new file mode 100644 index 0000000000..9ee05a3280 --- /dev/null +++ b/share/luameta/README.txt @@ -0,0 +1,53 @@ +Instructions to code your own VLC Lua meta script. +$$ + +Examples: See googleimage.lua . + +VLC Lua meta modules should define one of the following functions: + * fetch_art(): returns a path to an artwork for the given item + * fetch_meta(): returns a table with the following items: + .path: the item's full path / URL + .name: the item's name in playlist (OPTIONAL) + .title: the item's Title (OPTIONAL, meta data) + .artist: the item's Artist (OPTIONAL, meta data) + .genre: the item's Genre (OPTIONAL, meta data) + .copyright: the item's Copyright (OPTIONAL, meta data) + .album: the item's Album (OPTIONAL, meta data) + .tracknum: the item's Tracknum (OPTIONAL, meta data) + .description: the item's Description (OPTIONAL, meta data) + .rating: the item's Rating (OPTIONAL, meta data) + .date: the item's Date (OPTIONAL, meta data) + .setting: the item's Setting (OPTIONAL, meta data) + .url: the item's URL (OPTIONAL, meta data) + .language: the item's Language (OPTIONAL, meta data) + .nowplaying: the item's NowPlaying (OPTIONAL, meta data) + .publisher: the item's Publisher (OPTIONAL, meta data) + .encodedby: the item's EncodedBy (OPTIONAL, meta data) + .arturl: the item's ArtURL (OPTIONAL, meta data) + .trackid: the item's TrackID (OPTIONAL, meta data) + .options: a list of VLC options (OPTIONAL) + example: .options = { "fullscreen" } + .duration: stream duration in seconds (OPTIONAL) + .meta: custom meta data (OPTIONAL, meta data) + A .meta field is a table of custom meta categories which + each have custom meta properties. + example: .meta = { ["Google video"] = { ["docid"] = "-5784010886294950089"; ["GVP version"] = "1.1" }; ["misc"] = { "Hello" = "World!" } } + Invalid playlist items will be discarded by VLC. + +VLC defines a global vlc object with the following members: + * vlc.stream_new + * vlc.stream_delete + * vlc.stream_readline + * vlc.stream_read + * vlc.msg_dbg( ): print a debug message. + * vlc.msg_warn( ): print a warning message. + * vlc.msg_err( ): print an error message. + * vlc.msg_info( ): print an info message. + +Lua scripts are tried in alphabetical order in the user's VLC config +director luameta/ subdirectory, then in the global VLC luameta/ +directory. + +Lua documentation is available on http://www.lua.org . +VLC uses Lua 5.1 +All the Lua standard libraries are available. diff --git a/share/luameta/googleimage.lua b/share/luameta/googleimage.lua new file mode 100644 index 0000000000..22bf50be5e --- /dev/null +++ b/share/luameta/googleimage.lua @@ -0,0 +1,22 @@ +-- Get's an artwork from images.google.com +-- $Id$ + +-- Replace non alphanumeric char by + +function get_query( ) + if vlc.title then + title = vlc.title + else + title = vlc.name + end + vlc.msg_dbg( title ) + return title:gsub( "[^(a-z|A-Z|0-9)]", "+" ) +end + +-- Return the artwork +function fetch_art() + fd = vlc.stream_new( "http://images.google.com/images?q=" .. get_query( ) ) + page = vlc.stream_read( fd, 65653 ) + vlc.stream_delete( fd ) + _, _, arturl = string.find( page, "imgurl=([^&]+)" ) + return arturl +end -- 2.39.5