1 /*****************************************************************************
2 * meta.c: Get meta/artwork using lua scripts
3 *****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod org>
8 * Pierre d'Herbemont <pdherbemont # videolan.org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
39 /*****************************************************************************
41 *****************************************************************************/
42 static const luaL_Reg p_reg
[] = { { NULL
, NULL
} };
44 static lua_State
* init( vlc_object_t
*p_this
, input_item_t
* p_item
, const char *psz_filename
)
46 lua_State
* L
= luaL_newstate();
49 msg_Err( p_this
, "Could not create new Lua State" );
53 vlclua_set_this( L
, p_this
);
55 /* Load Lua libraries */
56 luaL_openlibs( L
); /* XXX: Don't open all the libs? */
58 luaL_register_namespace( L
, "vlc", p_reg
);
63 luaopen_variables( L
);
66 luaopen_input_item( L
, p_item
);
68 if( vlclua_add_modules_path( L
, psz_filename
) )
70 msg_Warn( p_this
, "Error while setting the module search path for %s",
79 /*****************************************************************************
80 * Run a lua entry point function
81 *****************************************************************************/
82 static int run( vlc_object_t
*p_this
, const char * psz_filename
,
83 lua_State
* L
, const char *luafunction
,
84 const luabatch_context_t
*p_context
)
86 /* Ugly hack to delete previous versions of the fetchart()
89 lua_setglobal( L
, luafunction
);
91 /* Load and run the script(s) */
92 if( vlclua_dofile( p_this
, L
, psz_filename
) )
94 msg_Warn( p_this
, "Error loading script %s: %s", psz_filename
,
95 lua_tostring( L
, lua_gettop( L
) ) );
100 meta_fetcher_scope_t e_scope
= FETCHER_SCOPE_NETWORK
; /* default to restricted one */
101 lua_getglobal( L
, "descriptor" );
102 if( lua_isfunction( L
, lua_gettop( L
) ) && !lua_pcall( L
, 0, 1, 0 ) )
104 lua_getfield( L
, -1, "scope" );
105 char *psz_scope
= luaL_strdupornull( L
, -1 );
106 if ( psz_scope
&& !strcmp( psz_scope
, "local" ) )
107 e_scope
= FETCHER_SCOPE_LOCAL
;
113 if ( p_context
&& p_context
->pf_validator
&& !p_context
->pf_validator( p_context
, e_scope
) )
115 msg_Dbg( p_this
, "skipping script (unmatched scope) %s", psz_filename
);
119 lua_getglobal( L
, luafunction
);
121 if( !lua_isfunction( L
, lua_gettop( L
) ) )
123 msg_Warn( p_this
, "Error while running script %s, "
124 "function %s() not found", psz_filename
, luafunction
);
128 if( lua_pcall( L
, 0, 1, 0 ) )
130 msg_Warn( p_this
, "Error while running script %s, "
131 "function %s(): %s", psz_filename
, luafunction
,
132 lua_tostring( L
, lua_gettop( L
) ) );
142 /*****************************************************************************
143 * Called through lua_scripts_batch_execute to call 'fetch_art' on the script
144 * pointed by psz_filename.
145 *****************************************************************************/
146 static bool validate_scope( const luabatch_context_t
*p_context
, meta_fetcher_scope_t e_scope
)
148 if ( p_context
->e_scope
== FETCHER_SCOPE_ANY
)
151 return ( p_context
->e_scope
== e_scope
);
154 static int fetch_art( vlc_object_t
*p_this
, const char * psz_filename
,
155 const luabatch_context_t
*p_context
)
157 lua_State
*L
= init( p_this
, p_context
->p_item
, psz_filename
);
161 int i_ret
= run(p_this
, psz_filename
, L
, "fetch_art", p_context
);
162 if(i_ret
!= VLC_SUCCESS
)
170 const char * psz_value
;
172 if( lua_isstring( L
, -1 ) )
174 psz_value
= lua_tostring( L
, -1 );
175 if( psz_value
&& *psz_value
!= 0 )
177 lua_Dbg( p_this
, "setting arturl: %s", psz_value
);
178 input_item_SetArtURL ( p_context
->p_item
, psz_value
);
183 else if( !lua_isnoneornil( L
, -1 ) )
185 msg_Err( p_this
, "Lua art fetcher script %s: "
186 "didn't return a string", psz_filename
);
191 msg_Err( p_this
, "Script went completely foobar" );
198 /*****************************************************************************
199 * Called through lua_scripts_batch_execute to call 'read_meta' on the script
200 * pointed by psz_filename.
201 *****************************************************************************/
202 static int read_meta( vlc_object_t
*p_this
, const char * psz_filename
,
203 const luabatch_context_t
*p_context
)
205 /* FIXME: merge with finder */
206 demux_meta_t
*p_demux_meta
= (demux_meta_t
*)p_this
;
207 VLC_UNUSED( p_context
);
209 lua_State
*L
= init( p_this
, p_demux_meta
->p_item
, psz_filename
);
213 int i_ret
= run(p_this
, psz_filename
, L
, "read_meta", NULL
);
216 // Continue even if an error occurred: all "meta reader" are always run.
217 return i_ret
== VLC_SUCCESS
? VLC_EGENERIC
: i_ret
;
221 /*****************************************************************************
222 * Called through lua_scripts_batch_execute to call 'fetch_meta' on the script
223 * pointed by psz_filename.
224 *****************************************************************************/
225 static int fetch_meta( vlc_object_t
*p_this
, const char * psz_filename
,
226 const luabatch_context_t
*p_context
)
228 lua_State
*L
= init( p_this
, p_context
->p_item
, psz_filename
);
232 int ret
= run(p_this
, psz_filename
, L
, "fetch_meta", p_context
);
238 /*****************************************************************************
240 *****************************************************************************/
242 int ReadMeta( demux_meta_t
*p_this
)
244 if( lua_Disabled( p_this
) )
247 return vlclua_scripts_batch_execute( VLC_OBJECT(p_this
), "meta"DIR_SEP
"reader",
248 (void*) &read_meta
, NULL
);
252 /*****************************************************************************
254 *****************************************************************************/
256 int FetchMeta( meta_fetcher_t
*p_finder
)
258 if( lua_Disabled( p_finder
) )
261 luabatch_context_t context
= { p_finder
->p_item
, p_finder
->e_scope
, validate_scope
};
263 return vlclua_scripts_batch_execute( VLC_OBJECT(p_finder
), "meta"DIR_SEP
"fetcher",
264 &fetch_meta
, (void*)&context
);
268 /*****************************************************************************
269 * Module entry point for art.
270 *****************************************************************************/
271 int FindArt( meta_fetcher_t
*p_finder
)
273 if( lua_Disabled( p_finder
) )
276 luabatch_context_t context
= { p_finder
->p_item
, p_finder
->e_scope
, validate_scope
};
278 return vlclua_scripts_batch_execute( VLC_OBJECT(p_finder
), "meta"DIR_SEP
"art",
279 &fetch_art
, (void*)&context
);