1 /*****************************************************************************
2 * meta.c: Get meta/artwork using lua scripts
3 *****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
6 * Authors: Antoine Cellerier <dionoea at videolan tod org>
7 * Pierre d'Herbemont <pdherbemont # videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
38 /*****************************************************************************
40 *****************************************************************************/
41 static const luaL_Reg p_reg
[] = { { NULL
, NULL
} };
43 static lua_State
* init( vlc_object_t
*p_this
, input_item_t
* p_item
, const char *psz_filename
)
45 lua_State
* L
= luaL_newstate();
48 msg_Err( p_this
, "Could not create new Lua State" );
52 vlclua_set_this( L
, p_this
);
54 /* Load Lua libraries */
55 luaL_openlibs( L
); /* XXX: Don't open all the libs? */
57 luaL_register_namespace( L
, "vlc", p_reg
);
62 luaopen_variables( L
);
65 luaopen_input_item( L
, p_item
);
67 if( vlclua_add_modules_path( L
, psz_filename
) )
69 msg_Warn( p_this
, "Error while setting the module search path for %s",
78 /*****************************************************************************
79 * Run a lua entry point function
80 *****************************************************************************/
81 static int run( vlc_object_t
*p_this
, const char * psz_filename
,
82 lua_State
* L
, const char *luafunction
,
83 const luabatch_context_t
*p_context
)
85 /* Ugly hack to delete previous versions of the fetchart()
88 lua_setglobal( L
, luafunction
);
90 /* Load and run the script(s) */
91 if( vlclua_dofile( p_this
, L
, psz_filename
) )
93 msg_Warn( p_this
, "Error loading script %s: %s", psz_filename
,
94 lua_tostring( L
, lua_gettop( L
) ) );
99 meta_fetcher_scope_t e_scope
= FETCHER_SCOPE_NETWORK
; /* default to restricted one */
100 lua_getglobal( L
, "descriptor" );
101 if( lua_isfunction( L
, lua_gettop( L
) ) && !lua_pcall( L
, 0, 1, 0 ) )
103 lua_getfield( L
, -1, "scope" );
104 char *psz_scope
= luaL_strdupornull( L
, -1 );
105 if ( psz_scope
&& !strcmp( psz_scope
, "local" ) )
106 e_scope
= FETCHER_SCOPE_LOCAL
;
112 if ( p_context
&& p_context
->pf_validator
&& !p_context
->pf_validator( p_context
, e_scope
) )
114 msg_Dbg( p_this
, "skipping script (unmatched scope) %s", psz_filename
);
118 lua_getglobal( L
, luafunction
);
120 if( !lua_isfunction( L
, lua_gettop( L
) ) )
122 msg_Warn( p_this
, "Error while running script %s, "
123 "function %s() not found", psz_filename
, luafunction
);
127 if( lua_pcall( L
, 0, 1, 0 ) )
129 msg_Warn( p_this
, "Error while running script %s, "
130 "function %s(): %s", psz_filename
, luafunction
,
131 lua_tostring( L
, lua_gettop( L
) ) );
141 /*****************************************************************************
142 * Called through lua_scripts_batch_execute to call 'fetch_art' on the script
143 * pointed by psz_filename.
144 *****************************************************************************/
145 static bool validate_scope( const luabatch_context_t
*p_context
, meta_fetcher_scope_t e_scope
)
147 if ( p_context
->e_scope
== FETCHER_SCOPE_ANY
)
150 return ( p_context
->e_scope
== e_scope
);
153 static int fetch_art( vlc_object_t
*p_this
, const char * psz_filename
,
154 const luabatch_context_t
*p_context
)
156 lua_State
*L
= init( p_this
, p_context
->p_item
, psz_filename
);
160 int i_ret
= run(p_this
, psz_filename
, L
, "fetch_art", p_context
);
161 if(i_ret
!= VLC_SUCCESS
)
169 const char * psz_value
;
171 if( lua_isstring( L
, -1 ) )
173 psz_value
= lua_tostring( L
, -1 );
174 if( psz_value
&& *psz_value
!= 0 )
176 lua_Dbg( p_this
, "setting arturl: %s", psz_value
);
177 input_item_SetArtURL ( p_context
->p_item
, psz_value
);
182 else if( !lua_isnoneornil( L
, -1 ) )
184 msg_Err( p_this
, "Lua art fetcher script %s: "
185 "didn't return a string", psz_filename
);
190 msg_Err( p_this
, "Script went completely foobar" );
197 /*****************************************************************************
198 * Called through lua_scripts_batch_execute to call 'read_meta' on the script
199 * pointed by psz_filename.
200 *****************************************************************************/
201 static int read_meta( vlc_object_t
*p_this
, const char * psz_filename
,
202 const luabatch_context_t
*p_context
)
204 /* FIXME: merge with finder */
205 demux_meta_t
*p_demux_meta
= (demux_meta_t
*)p_this
;
206 VLC_UNUSED( p_context
);
208 lua_State
*L
= init( p_this
, p_demux_meta
->p_item
, psz_filename
);
212 int i_ret
= run(p_this
, psz_filename
, L
, "read_meta", NULL
);
215 // Continue even if an error occurred: all "meta reader" are always run.
216 return i_ret
== VLC_SUCCESS
? VLC_EGENERIC
: i_ret
;
220 /*****************************************************************************
221 * Called through lua_scripts_batch_execute to call 'fetch_meta' on the script
222 * pointed by psz_filename.
223 *****************************************************************************/
224 static int fetch_meta( vlc_object_t
*p_this
, const char * psz_filename
,
225 const luabatch_context_t
*p_context
)
227 lua_State
*L
= init( p_this
, p_context
->p_item
, psz_filename
);
231 int ret
= run(p_this
, psz_filename
, L
, "fetch_meta", p_context
);
237 /*****************************************************************************
239 *****************************************************************************/
241 int ReadMeta( demux_meta_t
*p_this
)
243 if( lua_Disabled( p_this
) )
246 return vlclua_scripts_batch_execute( VLC_OBJECT(p_this
), "meta"DIR_SEP
"reader",
247 (void*) &read_meta
, NULL
);
251 /*****************************************************************************
253 *****************************************************************************/
255 int FetchMeta( meta_fetcher_t
*p_finder
)
257 if( lua_Disabled( p_finder
) )
260 luabatch_context_t context
= { p_finder
->p_item
, p_finder
->e_scope
, validate_scope
};
262 return vlclua_scripts_batch_execute( VLC_OBJECT(p_finder
), "meta"DIR_SEP
"fetcher",
263 &fetch_meta
, (void*)&context
);
267 /*****************************************************************************
268 * Module entry point for art.
269 *****************************************************************************/
270 int FindArt( meta_fetcher_t
*p_finder
)
272 if( lua_Disabled( p_finder
) )
275 luabatch_context_t context
= { p_finder
->p_item
, p_finder
->e_scope
, validate_scope
};
277 return vlclua_scripts_batch_execute( VLC_OBJECT(p_finder
), "meta"DIR_SEP
"art",
278 &fetch_art
, (void*)&context
);