You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
14 KiB
356 lines
14 KiB
/*****************************************************************************
|
|
* sd.c: Services discovery related functions
|
|
*****************************************************************************
|
|
* Copyright (C) 2007-2008 the VideoLAN team
|
|
* $Id$
|
|
*
|
|
* Authors: Antoine Cellerier <dionoea at videolan tod org>
|
|
* Fabio Ritrovato <sephiroth87 at videolan dot org>
|
|
*
|
|
* 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
|
|
*****************************************************************************/
|
|
#ifndef _GNU_SOURCE
|
|
# define _GNU_SOURCE
|
|
#endif
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include "config.h"
|
|
#endif
|
|
|
|
#include <vlc_common.h>
|
|
#include <vlc_services_discovery.h>
|
|
#include <vlc_playlist.h>
|
|
#include <vlc_charset.h>
|
|
|
|
#include <lua.h> /* Low level lua C API */
|
|
#include <lauxlib.h> /* Higher level C API */
|
|
#include <lualib.h> /* Lua libs */
|
|
|
|
#include "../vlc.h"
|
|
#include "../libs.h"
|
|
#include "playlist.h"
|
|
|
|
/*****************************************************************************
|
|
*
|
|
*****************************************************************************/
|
|
static int vlclua_node_add_subitem( lua_State * );
|
|
static int vlclua_node_add_node( lua_State * );
|
|
|
|
static const luaL_Reg vlclua_node_reg[] = {
|
|
{ "add_subitem", vlclua_node_add_subitem },
|
|
{ "add_node", vlclua_node_add_node },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static int vlclua_sd_get_services_names( lua_State *L )
|
|
{
|
|
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
|
|
char **ppsz_longnames;
|
|
char **ppsz_names = vlc_sd_GetNames( p_playlist, &ppsz_longnames, NULL );
|
|
if( !ppsz_names )
|
|
return 0;
|
|
|
|
char **ppsz_longname = ppsz_longnames;
|
|
char **ppsz_name = ppsz_names;
|
|
lua_settop( L, 0 );
|
|
lua_newtable( L );
|
|
for( ; *ppsz_name; ppsz_name++,ppsz_longname++ )
|
|
{
|
|
lua_pushstring( L, *ppsz_longname );
|
|
lua_setfield( L, -2, *ppsz_name );
|
|
free( *ppsz_name );
|
|
free( *ppsz_longname );
|
|
}
|
|
free( ppsz_names );
|
|
free( ppsz_longnames );
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_sd_add( lua_State *L )
|
|
{
|
|
const char *psz_sd = luaL_checkstring( L, 1 );
|
|
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
|
|
int i_ret = playlist_ServicesDiscoveryAdd( p_playlist, psz_sd );
|
|
return vlclua_push_ret( L, i_ret );
|
|
}
|
|
|
|
static int vlclua_sd_remove( lua_State *L )
|
|
{
|
|
const char *psz_sd = luaL_checkstring( L, 1 );
|
|
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
|
|
int i_ret = playlist_ServicesDiscoveryRemove( p_playlist, psz_sd );
|
|
return vlclua_push_ret( L, i_ret );
|
|
}
|
|
|
|
static int vlclua_sd_is_loaded( lua_State *L )
|
|
{
|
|
const char *psz_sd = luaL_checkstring( L, 1 );
|
|
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
|
|
lua_pushboolean( L, playlist_IsServicesDiscoveryLoaded( p_playlist, psz_sd ));
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_sd_add_node( lua_State *L )
|
|
{
|
|
services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
|
|
if( lua_istable( L, -1 ) )
|
|
{
|
|
lua_getfield( L, -1, "title" );
|
|
if( lua_isstring( L, -1 ) )
|
|
{
|
|
char *name = strdup( lua_tostring( L, -1 ) );
|
|
lua_pop( L, 1 );
|
|
input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
|
|
"vlc://nop",
|
|
name, 0, NULL, 0,
|
|
-1, ITEM_TYPE_NODE );
|
|
if( p_input )
|
|
{
|
|
lua_getfield( L, -1, "arturl" );
|
|
if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
|
|
{
|
|
char *psz_value = strdup( lua_tostring( L, -1 ) );
|
|
EnsureUTF8( psz_value );
|
|
msg_Dbg( p_sd, "ArtURL: %s", psz_value );
|
|
/** @todo Ask for art download if not local file */
|
|
input_item_SetArtURL( p_input, psz_value );
|
|
free( psz_value );
|
|
}
|
|
services_discovery_AddItem( p_sd, p_input, NULL );
|
|
input_item_t **udata = (input_item_t **)
|
|
lua_newuserdata( L, sizeof( input_item_t * ) );
|
|
*udata = p_input;
|
|
if( luaL_newmetatable( L, "node" ) )
|
|
{
|
|
lua_newtable( L );
|
|
luaL_register( L, NULL, vlclua_node_reg );
|
|
lua_setfield( L, -2, "__index" );
|
|
}
|
|
lua_setmetatable( L, -2 );
|
|
}
|
|
free( name );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "vlc.sd.add_node: the \"title\" parameter can't be empty" );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "Error parsing add_node arguments" );
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_sd_add_item( lua_State *L )
|
|
{
|
|
services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
|
|
if( lua_istable( L, -1 ) )
|
|
{
|
|
lua_getfield( L, -1, "path" );
|
|
if( lua_isstring( L, -1 ) )
|
|
{
|
|
char **ppsz_options = NULL;
|
|
int i_options = 0;
|
|
char *psz_path = strdup( lua_tostring( L, -1 ) );
|
|
lua_pop( L, 1 );
|
|
vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
|
|
input_item_t *p_input = input_item_NewExt( p_sd, psz_path, psz_path,
|
|
i_options,
|
|
(const char **)ppsz_options,
|
|
VLC_INPUT_OPTION_TRUSTED, -1 );
|
|
if( p_input )
|
|
{
|
|
vlclua_read_meta_data( p_sd, L, p_input );
|
|
/* This one is to be tested... */
|
|
vlclua_read_custom_meta_data( p_sd, L, p_input );
|
|
/* The duration is given in seconds, convert to microseconds */
|
|
lua_getfield( L, -1, "duration" );
|
|
if( lua_isnumber( L, -1 ) )
|
|
input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
|
|
else if( !lua_isnil( L, -1 ) )
|
|
msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
|
|
lua_pop( L, 1 );
|
|
services_discovery_AddItem( p_sd, p_input, NULL );
|
|
input_item_t **udata = (input_item_t **)
|
|
lua_newuserdata( L, sizeof( input_item_t * ) );
|
|
*udata = p_input;
|
|
if( luaL_newmetatable( L, "input_item_t" ) )
|
|
{
|
|
lua_pushliteral( L, "none of your business" );
|
|
lua_setfield( L, -2, "__metatable" );
|
|
}
|
|
lua_setmetatable( L, -2 );
|
|
vlc_gc_decref( p_input );
|
|
}
|
|
free( psz_path );
|
|
while( i_options > 0 )
|
|
free( ppsz_options[--i_options] );
|
|
free( ppsz_options );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "vlc.sd.add_item: the \"path\" parameter can't be empty" );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "Error parsing add_item arguments" );
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_sd_remove_item( lua_State *L )
|
|
{
|
|
services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
|
|
if( !lua_isnil( L, 1 ) )
|
|
{
|
|
input_item_t **pp_input = luaL_checkudata( L, 1, "input_item_t" );
|
|
if( *pp_input )
|
|
services_discovery_RemoveItem( p_sd, *pp_input );
|
|
/* Make sure we won't try to remove it again */
|
|
*pp_input = NULL;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_node_add_subitem( lua_State *L )
|
|
{
|
|
services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
|
|
input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
|
|
if( *pp_node )
|
|
{
|
|
if( lua_istable( L, -1 ) )
|
|
{
|
|
lua_getfield( L, -1, "path" );
|
|
if( lua_isstring( L, -1 ) )
|
|
{
|
|
char **ppsz_options = NULL;
|
|
int i_options = 0;
|
|
char *psz_path = strdup( lua_tostring( L, -1 ) );
|
|
lua_pop( L, 1 );
|
|
vlclua_read_options( p_sd, L, &i_options, &ppsz_options );
|
|
input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
|
|
input_item_t *p_input = input_item_NewExt( p_sd, psz_path,
|
|
psz_path, i_options,
|
|
(const char **)ppsz_options,
|
|
VLC_INPUT_OPTION_TRUSTED, -1 );
|
|
if( p_input )
|
|
{
|
|
vlclua_read_meta_data( p_sd, L, p_input );
|
|
/* This one is to be tested... */
|
|
vlclua_read_custom_meta_data( p_sd, L, p_input );
|
|
lua_getfield( L, -1, "duration" );
|
|
if( lua_isnumber( L, -1 ) )
|
|
input_item_SetDuration( p_input, (lua_tonumber( L, -1 )*1e6) );
|
|
else if( !lua_isnil( L, -1 ) )
|
|
msg_Warn( p_sd, "Item duration should be a number (in seconds)." );
|
|
lua_pop( L, 1 );
|
|
input_item_node_AppendItem( p_input_node, p_input );
|
|
input_item_node_PostAndDelete( p_input_node );
|
|
input_item_t **udata = (input_item_t **)
|
|
lua_newuserdata( L, sizeof( input_item_t * ) );
|
|
*udata = p_input;
|
|
if( luaL_newmetatable( L, "input_item_t" ) )
|
|
{
|
|
lua_pushliteral( L, "none of your business" );
|
|
lua_setfield( L, -2, "__metatable" );
|
|
}
|
|
lua_setmetatable( L, -2 );
|
|
vlc_gc_decref( p_input );
|
|
}
|
|
free( psz_path );
|
|
while( i_options > 0 )
|
|
free( ppsz_options[--i_options] );
|
|
free( ppsz_options );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "node:add_subitem: the \"path\" parameter can't be empty" );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "Error parsing add_subitem arguments" );
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int vlclua_node_add_node( lua_State *L )
|
|
{
|
|
services_discovery_t *p_sd = (services_discovery_t *)vlclua_get_this( L );
|
|
input_item_t **pp_node = (input_item_t **)luaL_checkudata( L, 1, "node" );
|
|
if( *pp_node )
|
|
{
|
|
if( lua_istable( L, -1 ) )
|
|
{
|
|
lua_getfield( L, -1, "title" );
|
|
if( lua_isstring( L, -1 ) )
|
|
{
|
|
char *name = strdup( lua_tostring( L, -1 ) );
|
|
lua_pop( L, 1 );
|
|
input_item_node_t *p_input_node = input_item_node_Create( *pp_node );
|
|
input_item_t *p_input = input_item_NewWithType( VLC_OBJECT( p_sd ),
|
|
"vlc://nop",
|
|
name, 0, NULL, 0,
|
|
-1, ITEM_TYPE_NODE );
|
|
if( p_input )
|
|
{
|
|
lua_getfield( L, -1, "arturl" );
|
|
if( lua_isstring( L, -1 ) && strcmp( lua_tostring( L, -1 ), "" ) )
|
|
{
|
|
char *psz_value = strdup( lua_tostring( L, -1 ) );
|
|
EnsureUTF8( psz_value );
|
|
msg_Dbg( p_sd, "ArtURL: %s", psz_value );
|
|
input_item_SetArtURL( p_input, psz_value );
|
|
free( psz_value );
|
|
}
|
|
input_item_node_AppendItem( p_input_node, p_input );
|
|
input_item_node_PostAndDelete( p_input_node );
|
|
input_item_t **udata = (input_item_t **)
|
|
lua_newuserdata( L, sizeof( input_item_t * ) );
|
|
*udata = p_input;
|
|
if( luaL_newmetatable( L, "node" ) )
|
|
{
|
|
lua_newtable( L );
|
|
luaL_register( L, NULL, vlclua_node_reg );
|
|
lua_setfield( L, -2, "__index" );
|
|
}
|
|
lua_setmetatable( L, -2 );
|
|
}
|
|
free( name );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "node:add_node: the \"title\" parameter can't be empty" );
|
|
}
|
|
else
|
|
msg_Err( p_sd, "Error parsing add_node arguments" );
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
*****************************************************************************/
|
|
static const luaL_Reg vlclua_sd_reg[] = {
|
|
{ "get_services_names", vlclua_sd_get_services_names },
|
|
{ "add", vlclua_sd_add },
|
|
{ "remove", vlclua_sd_remove },
|
|
{ "is_loaded", vlclua_sd_is_loaded },
|
|
{ "add_node", vlclua_sd_add_node },
|
|
{ "add_item", vlclua_sd_add_item },
|
|
{ "remove_item", vlclua_sd_remove_item },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
void luaopen_sd( lua_State *L )
|
|
{
|
|
lua_newtable( L );
|
|
luaL_register( L, NULL, vlclua_sd_reg );
|
|
lua_setfield( L, -2, "sd" );
|
|
}
|
|
|