1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
7 * Authors: Antoine Cellerier <dionoea at videolan tod 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 *****************************************************************************/
35 #include <vlc_common.h>
38 #include <vlc_playlist.h>
45 #include "../extension.h"
47 static input_item_t
* vlclua_input_item_get_internal( lua_State
*L
);
49 input_thread_t
* vlclua_get_input_internal( lua_State
*L
)
51 extension_t
*p_extension
= vlclua_extension_get( L
);
54 input_thread_t
*p_input
= p_extension
->p_sys
->p_input
;
57 vlc_object_hold(p_input
);
62 playlist_t
*p_playlist
= vlclua_get_playlist_internal( L
);
63 if( p_playlist
!= NULL
)
65 input_thread_t
*p_input
= playlist_CurrentInput( p_playlist
);
73 static int vlclua_input_item_info( lua_State
*L
)
75 input_item_t
*p_item
= vlclua_input_item_get_internal( L
);
78 i_cat
= p_item
->i_categories
;
79 lua_createtable( L
, 0, i_cat
);
80 for( i
= 0; i
< i_cat
; i
++ )
82 info_category_t
*p_category
= p_item
->pp_categories
[i
];
83 int i_infos
= p_category
->i_infos
;
85 lua_pushstring( L
, p_category
->psz_name
);
86 lua_createtable( L
, 0, i_infos
);
87 for( j
= 0; j
< i_infos
; j
++ )
89 info_t
*p_info
= p_category
->pp_infos
[j
];
90 lua_pushstring( L
, p_info
->psz_name
);
91 lua_pushstring( L
, p_info
->psz_value
);
92 lua_settable( L
, -3 );
94 lua_settable( L
, -3 );
99 static int vlclua_input_is_playing( lua_State
*L
)
101 input_thread_t
* p_input
= vlclua_get_input_internal( L
);
102 lua_pushboolean( L
, !!p_input
);
104 vlc_object_release( p_input
);
108 static int vlclua_input_metas_internal( lua_State
*L
, input_item_t
*p_item
)
117 const char *psz_meta
;
119 char* psz_uri
= input_item_GetURI( p_item
);
120 char* psz_filename
= psz_uri
? strrchr( psz_uri
, '/' ) : NULL
;
122 if( psz_filename
&& psz_filename
[1] == '\0' )
124 /* trailing slash, get the preceeding data */
125 psz_filename
[0] = '\0';
126 psz_filename
= strrchr( psz_uri
, '/' );
131 /* url decode, without leading slash */
132 psz_filename
= vlc_uri_decode( psz_filename
+ 1 );
135 lua_pushstring( L
, psz_filename
);
136 lua_setfield( L
, -2, "filename" );
140 #define PUSH_META( n, m ) \
141 psz_meta = vlc_meta_Get( p_item->p_meta, vlc_meta_ ## n ); \
142 lua_pushstring( L, psz_meta ); \
143 lua_setfield( L, -2, m )
145 vlc_mutex_lock(&p_item
->lock
);
149 PUSH_META( Title
, "title" );
150 PUSH_META( Artist
, "artist" );
151 PUSH_META( Genre
, "genre" );
152 PUSH_META( Copyright
, "copyright" );
153 PUSH_META( Album
, "album" );
154 PUSH_META( TrackNumber
, "track_number" );
155 PUSH_META( Description
, "description" );
156 PUSH_META( Rating
, "rating" );
157 PUSH_META( Date
, "date" );
158 PUSH_META( Setting
, "setting" );
159 PUSH_META( URL
, "url" );
160 PUSH_META( Language
, "language" );
161 PUSH_META( NowPlaying
, "now_playing" );
162 PUSH_META( Publisher
, "publisher" );
163 PUSH_META( EncodedBy
, "encoded_by" );
164 PUSH_META( ArtworkURL
, "artwork_url" );
165 PUSH_META( TrackID
, "track_id" );
166 PUSH_META( TrackTotal
, "track_total" );
167 PUSH_META( Director
, "director" );
168 PUSH_META( Season
, "season" );
169 PUSH_META( Episode
, "episode" );
170 PUSH_META( ShowName
, "show_name" );
171 PUSH_META( Actors
, "actors" );
175 char **names
= vlc_meta_CopyExtraNames(p_item
->p_meta
);
176 for(int i
= 0; names
[i
]; i
++)
178 const char *meta
= vlc_meta_GetExtra(p_item
->p_meta
, names
[i
]);
179 lua_pushstring( L
, meta
);
180 lua_setfield( L
, -2, names
[i
] );
185 vlc_mutex_unlock(&p_item
->lock
);
190 static int vlclua_input_item_stats( lua_State
*L
)
192 input_item_t
*p_item
= vlclua_input_item_get_internal( L
);
196 vlc_mutex_lock( &p_item
->p_stats
->lock
);
197 #define STATS_INT( n ) lua_pushinteger( L, p_item->p_stats->i_ ## n ); \
198 lua_setfield( L, -2, #n );
199 #define STATS_FLOAT( n ) lua_pushnumber( L, p_item->p_stats->f_ ## n ); \
200 lua_setfield( L, -2, #n );
201 STATS_INT( read_packets
)
202 STATS_INT( read_bytes
)
203 STATS_FLOAT( input_bitrate
)
204 STATS_FLOAT( average_input_bitrate
)
205 STATS_INT( demux_read_packets
)
206 STATS_INT( demux_read_bytes
)
207 STATS_FLOAT( demux_bitrate
)
208 STATS_FLOAT( average_demux_bitrate
)
209 STATS_INT( demux_corrupted
)
210 STATS_INT( demux_discontinuity
)
211 STATS_INT( decoded_audio
)
212 STATS_INT( decoded_video
)
213 STATS_INT( displayed_pictures
)
214 STATS_INT( lost_pictures
)
215 STATS_INT( sent_packets
)
216 STATS_INT( sent_bytes
)
217 STATS_FLOAT( send_bitrate
)
218 STATS_INT( played_abuffers
)
219 STATS_INT( lost_abuffers
)
222 vlc_mutex_unlock( &p_item
->p_stats
->lock
);
227 static int vlclua_input_add_subtitle( lua_State
*L
)
229 input_thread_t
*p_input
= vlclua_get_input_internal( L
);
231 return luaL_error( L
, "can't add subtitle: no current input" );
232 if( !lua_isstring( L
, 1 ) )
233 return luaL_error( L
, "vlc.input.add_subtitle() usage: (path)" );
234 const char *psz_path
= luaL_checkstring( L
, 1 );
235 char* psz_mrl
= vlc_path2uri( psz_path
, NULL
);
238 input_AddSlave( p_input
, SLAVE_TYPE_SPU
, psz_mrl
, false, false );
241 vlc_object_release( p_input
);
245 /*****************************************************************************
247 *****************************************************************************/
249 static input_item_t
* vlclua_input_item_get_internal( lua_State
*L
)
251 input_item_t
**pp_item
= luaL_checkudata( L
, 1, "input_item" );
252 input_item_t
*p_item
= *pp_item
;
255 luaL_error( L
, "script went completely foobar" );
260 /* Garbage collection of an input_item_t */
261 static int vlclua_input_item_delete( lua_State
*L
)
263 input_item_t
**pp_item
= luaL_checkudata( L
, 1, "input_item" );
264 input_item_t
*p_item
= *pp_item
;
267 return luaL_error( L
, "script went completely foobar" );
270 input_item_Release( p_item
);
275 static int vlclua_input_item_get( lua_State
*L
, input_item_t
*p_item
);
277 static int vlclua_input_item_get_current( lua_State
*L
)
279 input_thread_t
*p_input
= vlclua_get_input_internal( L
);
280 input_item_t
*p_item
= p_input
? input_GetItem( p_input
) : NULL
;
284 if( p_input
) vlc_object_release( p_input
);
288 vlclua_input_item_get( L
, p_item
);
290 if( p_input
) vlc_object_release( p_input
);
294 static int vlclua_input_item_metas( lua_State
*L
)
296 vlclua_input_metas_internal( L
, vlclua_input_item_get_internal( L
) );
300 static int vlclua_input_item_is_preparsed( lua_State
*L
)
302 lua_pushboolean( L
, input_item_IsPreparsed( vlclua_input_item_get_internal( L
) ) );
306 static int vlclua_input_item_uri( lua_State
*L
)
308 char *uri
= input_item_GetURI( vlclua_input_item_get_internal( L
) );
309 lua_pushstring( L
, uri
);
314 static int vlclua_input_item_name( lua_State
*L
)
316 char *name
= input_item_GetName( vlclua_input_item_get_internal( L
) );
317 lua_pushstring( L
, name
);
322 static int vlclua_input_item_duration( lua_State
*L
)
324 mtime_t duration
= input_item_GetDuration( vlclua_input_item_get_internal( L
) );
325 lua_pushnumber( L
, ((double)duration
)/1000000. );
329 static int vlclua_input_item_set_meta( lua_State
*L
)
331 input_item_t
*p_item
= vlclua_input_item_get_internal( L
);
332 lua_settop( L
, 1 + 2 ); // two arguments
333 const char *psz_name
= luaL_checkstring( L
, 2 ),
334 *psz_value
= luaL_checkstring( L
, 3 );
336 #define META_TYPE( n, s ) { s, vlc_meta_ ## n },
339 const char psz_name
[15];
341 } pp_meta_types
[] = {
342 META_TYPE( Title
, "title" )
343 META_TYPE( Artist
, "artist" )
344 META_TYPE( Genre
, "genre" )
345 META_TYPE( Copyright
, "copyright" )
346 META_TYPE( Album
, "album" )
347 META_TYPE( TrackNumber
, "track_number" )
348 META_TYPE( Description
, "description" )
349 META_TYPE( Rating
, "rating" )
350 META_TYPE( Date
, "date" )
351 META_TYPE( Setting
, "setting" )
352 META_TYPE( URL
, "url" )
353 META_TYPE( Language
, "language" )
354 META_TYPE( NowPlaying
, "now_playing" )
355 META_TYPE( ESNowPlaying
, "now_playing" )
356 META_TYPE( Publisher
, "publisher" )
357 META_TYPE( EncodedBy
, "encoded_by" )
358 META_TYPE( ArtworkURL
, "artwork_url" )
359 META_TYPE( TrackID
, "track_id" )
360 META_TYPE( TrackTotal
, "track_total" )
361 META_TYPE( Director
, "director" )
362 META_TYPE( Season
, "season" )
363 META_TYPE( Episode
, "episode" )
364 META_TYPE( ShowName
, "show_name" )
365 META_TYPE( Actors
, "actors" )
366 META_TYPE( AlbumArtist
, "album_artist" )
367 META_TYPE( DiscNumber
, "disc_number" )
368 META_TYPE( DiscTotal
, "disc_total" )
372 static_assert( sizeof(pp_meta_types
)
373 == VLC_META_TYPE_COUNT
* sizeof(pp_meta_types
[0]),
374 "Inconsistent meta data types" );
375 vlc_meta_type_t type
= vlc_meta_Title
;
376 for( unsigned i
= 0; i
< VLC_META_TYPE_COUNT
; i
++ )
378 if( !strcasecmp( pp_meta_types
[i
].psz_name
, psz_name
) )
380 type
= pp_meta_types
[i
].type
;
381 input_item_SetMeta( p_item
, type
, psz_value
);
386 vlc_meta_AddExtra( p_item
->p_meta
, psz_name
, psz_value
);
390 /*****************************************************************************
392 *****************************************************************************/
393 static const luaL_Reg vlclua_input_reg
[] = {
394 { "is_playing", vlclua_input_is_playing
},
395 { "item", vlclua_input_item_get_current
},
396 { "add_subtitle", vlclua_input_add_subtitle
},
400 void luaopen_input( lua_State
*L
)
403 luaL_register( L
, NULL
, vlclua_input_reg
);
404 lua_setfield( L
, -2, "input" );
407 static const luaL_Reg vlclua_input_item_reg
[] = {
408 { "is_preparsed", vlclua_input_item_is_preparsed
},
409 { "metas", vlclua_input_item_metas
},
410 { "set_meta", vlclua_input_item_set_meta
},
411 { "uri", vlclua_input_item_uri
},
412 { "name", vlclua_input_item_name
},
413 { "duration", vlclua_input_item_duration
},
414 { "stats", vlclua_input_item_stats
},
415 { "info", vlclua_input_item_info
},
419 static int vlclua_input_item_get( lua_State
*L
, input_item_t
*p_item
)
421 input_item_Hold( p_item
);
422 input_item_t
**pp
= lua_newuserdata( L
, sizeof( input_item_t
* ) );
425 if( luaL_newmetatable( L
, "input_item" ) )
428 luaL_register( L
, NULL
, vlclua_input_item_reg
);
429 lua_setfield( L
, -2, "__index" );
430 lua_pushcfunction( L
, vlclua_input_item_delete
);
431 lua_setfield( L
, -2, "__gc" );
434 lua_setmetatable(L
, -2);
440 void luaopen_input_item( lua_State
*L
, input_item_t
*item
)
443 vlclua_input_item_get( L
, item
);
444 lua_setfield( L
, -2, "item" );