]> git.sesse.net Git - vlc/blob - modules/misc/lua/meta.c
Remove E_()
[vlc] / modules / misc / lua / meta.c
1 /*****************************************************************************
2  * meta.c: Get meta/artwork using lua scripts
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan tod org>
8  *          Pierre d'Herbemont <pdherbemont # videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifndef  _GNU_SOURCE
29 #   define  _GNU_SOURCE
30 #endif
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <vlc/vlc.h>
37 #include <vlc_input.h>
38 #include <vlc_playlist.h>
39 #include <vlc_meta.h>
40 #include <vlc_url.h>
41 #include <vlc_strings.h>
42 #include <vlc_stream.h>
43 #include <vlc_charset.h>
44
45 #include "vlc.h"
46
47
48 /*****************************************************************************
49  * Local prototypes
50  *****************************************************************************/
51 static int fetch_meta( vlc_object_t *p_this, const char * psz_filename,
52                        lua_State * L, void * user_data );
53 static int fetch_art( vlc_object_t *p_this, const char * psz_filename,
54                       lua_State * L, void * user_data );
55 static lua_State *vlclua_meta_init( vlc_object_t *p_this,
56                                     input_item_t * p_item );
57
58
59 /*****************************************************************************
60  * Lua function bridge
61  *****************************************************************************/
62 /* Functions to register */
63 static luaL_Reg p_reg[] =
64 {
65     /* TODO: make an object out of the stream stuff, so we can do something
66      * like:
67      *
68      * s = vlc.stream_new( "http://www.videolan.org" )
69      * page = s:read( 2^16 )
70      * s:delete()
71      *
72      * instead of (which could be problematic since we don't check if
73      * s is really a stream object):
74      *
75      * s = vlc.stream_new( "http://www.videolan.org" )
76      * page = vlc.stream_read( s, 2^16 )
77      * vlc.stream_delete( s )
78      */
79     { "stream_new", vlclua_stream_new },
80     { "stream_read", vlclua_stream_read },
81     { "stream_readline", vlclua_stream_readline },
82     { "stream_delete", vlclua_stream_delete },
83     { "decode_uri", vlclua_decode_uri },
84     { "resolve_xml_special_chars", vlclua_resolve_xml_special_chars },
85     { "msg_dbg", vlclua_msg_dbg },
86     { "msg_warn", vlclua_msg_warn },
87     { "msg_err", vlclua_msg_err },
88     { "msg_info", vlclua_msg_info },
89     { NULL, NULL }
90 };
91
92 /*****************************************************************************
93  * Init lua
94  *****************************************************************************/
95 static lua_State * vlclua_meta_init( vlc_object_t *p_this, input_item_t * p_item )
96 {
97     lua_State * L = luaL_newstate();
98     if( !L )
99     {
100         msg_Err( p_this, "Could not create new Lua State" );
101         return NULL;
102     }
103     char *psz_meta;
104
105     /* Load Lua libraries */
106     luaL_openlibs( L ); /* XXX: Don't open all the libs? */
107
108     luaL_register( L, "vlc", p_reg );
109
110     lua_pushlightuserdata( L, p_this );
111     lua_setfield( L, -2, "private" );
112
113     psz_meta = input_item_GetName( p_item );
114     lua_pushstring( L, psz_meta );
115     lua_setfield( L, -2, "name" );
116     free( psz_meta );
117
118     psz_meta = input_item_GetArtist( p_item );
119     lua_pushstring( L, psz_meta );
120     lua_setfield( L, -2, "artist" );
121     free( psz_meta );
122
123     psz_meta = input_item_GetTitle( p_item ) ;
124     lua_pushstring( L, psz_meta );
125     lua_setfield( L, -2, "title" );
126     free( psz_meta );
127
128     psz_meta = input_item_GetAlbum( p_item );
129     lua_pushstring( L, psz_meta );
130     lua_setfield( L, -2, "album" );
131     free( psz_meta );
132
133     psz_meta = input_item_GetArtURL( p_item );
134     lua_pushstring( L, psz_meta );
135     lua_setfield( L, -2, "arturl" );
136     free( psz_meta );
137     /* XXX: all should be passed ( could use macro ) */
138
139     return L;
140 }
141
142 /*****************************************************************************
143  * Called through lua_scripts_batch_execute to call 'fetch_art' on the script
144  * pointed by psz_filename.
145  *****************************************************************************/
146 static int fetch_art( vlc_object_t *p_this, const char * psz_filename,
147                       lua_State * L, void * user_data )
148 {
149     int i_ret = VLC_EGENERIC;
150     input_item_t * p_input = user_data;
151     int s;
152
153     /* Ugly hack to delete previous versions of the fetchart()
154     * functions. */
155     lua_pushnil( L );
156     lua_setglobal( L, "fetch_art" );
157
158     /* Load and run the script(s) */
159     if( luaL_dofile( L, psz_filename ) )
160     {
161         msg_Warn( p_this, "Error loading script %s: %s", psz_filename,
162                   lua_tostring( L, lua_gettop( L ) ) );
163         lua_pop( L, 1 );
164         return VLC_EGENERIC;
165     }
166
167     lua_getglobal( L, "fetch_art" );
168
169     if( !lua_isfunction( L, lua_gettop( L ) ) )
170     {
171         msg_Warn( p_this, "Error while runing script %s, "
172                   "function fetch_art() not found", psz_filename );
173         lua_pop( L, 1 );
174         return VLC_EGENERIC;
175     }
176
177     if( lua_pcall( L, 0, 1, 0 ) )
178     {
179         msg_Warn( p_this, "Error while runing script %s, "
180                   "function fetch_art(): %s", psz_filename,
181                   lua_tostring( L, lua_gettop( L ) ) );
182         lua_pop( L, 1 );
183         return VLC_EGENERIC;
184     }
185
186     if((s = lua_gettop( L )))
187     {
188         const char * psz_value;
189
190         if( lua_isstring( L, s ) )
191         {
192             psz_value = lua_tostring( L, s );
193             if( psz_value && *psz_value != 0 )
194             {
195                 lua_Dbg( p_this, "setting arturl: %s", psz_value );
196                 input_item_SetArtURL ( p_input, psz_value );
197                 i_ret = VLC_SUCCESS;
198             }
199         }
200         else if( !lua_isnil( L, s ) )
201         {
202             msg_Err( p_this, "Lua art fetcher script %s: "
203                  "didn't return a string", psz_filename );
204         }
205     }
206     else
207     {
208         msg_Err( p_this, "Script went completely foobar" );
209     }
210
211     return i_ret;
212 }
213
214 /*****************************************************************************
215  * Called through lua_scripts_batch_execute to call 'fetch_meta' on the script
216  * pointed by psz_filename.
217  *****************************************************************************/
218 static int fetch_meta( vlc_object_t *p_this, const char * psz_filename,
219                        lua_State * L, void * user_data )
220 {
221     input_item_t * p_input = user_data;
222
223     /* In lua, setting a variable to nil is equivalent to deleting it */
224     lua_pushnil( L );
225     lua_setglobal( L, "fetch_meta" );
226
227     /* Load and run the script(s) */
228     if( luaL_dofile( L, psz_filename ) )
229     {
230         msg_Warn( p_this, "Error loading script %s: %s", psz_filename,
231                   lua_tostring( L, lua_gettop( L ) ) );
232         lua_pop( L, 1 );
233         return VLC_EGENERIC;
234     }
235
236     lua_getglobal( L, "fetch_meta" );
237
238     if( !lua_isfunction( L, lua_gettop( L ) ) )
239     {
240         msg_Warn( p_this, "Error while runing script %s, "
241                   "function fetch_meta() not found", psz_filename );
242         lua_pop( L, 1 );
243         return VLC_EGENERIC;
244     }
245
246     if( lua_pcall( L, 0, 1, 0 ) )
247     {
248         msg_Warn( p_this, "Error while runing script %s, "
249                   "function fetch_meta(): %s", psz_filename,
250                   lua_tostring( L, lua_gettop( L ) ) );
251         lua_pop( L, 1 );
252         return VLC_EGENERIC;
253     }
254
255
256     if( lua_gettop( L ) )
257     {
258         if( lua_istable( L, -1 ) )
259         {
260             /* ... item */
261             vlclua_read_meta_data( p_this, L, p_input );
262             vlclua_read_custom_meta_data( p_this, L, p_input );
263         }
264         else
265         {
266             msg_Err( p_this, "Lua playlist script %s: "
267                      "didn't return a table", psz_filename );
268         }
269     }
270     else
271     {
272         msg_Err( p_this, "Script went completely foobar" );
273     }
274
275     /* We tell the batch thing to continue, hence all script
276      * will get the change to add its meta. This behaviour could
277      * be changed. */
278     return VLC_EGENERIC;
279 }
280
281 /*****************************************************************************
282  * Module entry point for art.
283  *****************************************************************************/
284 int FindArt( vlc_object_t *p_this )
285 {
286     playlist_t *p_playlist = (playlist_t *)p_this;
287     input_item_t *p_item = (input_item_t *)(p_playlist->p_private);
288     lua_State *L = vlclua_meta_init( p_this, p_item );
289
290     int i_ret = vlclua_scripts_batch_execute( p_this, "meta", &fetch_art, L, p_item );
291     lua_close( L );
292     return i_ret;
293 }
294