-SOURCES_lua = playlist.c meta.c intf.c vlc.c vlc.h callbacks.c objects.c variables.c configuration.c net.c vlm.c httpd.c acl.c
+SOURCES_lua = playlist.c meta.c intf.c vlc.c vlc.h callbacks.c objects.c variables.c configuration.c net.c vlm.c httpd.c acl.c sd.c
/*****************************************************************************
* Internal lua<->vlc utils
*****************************************************************************/
-static inline playlist_t *vlclua_get_playlist_internal( lua_State *L )
+playlist_t *vlclua_get_playlist_internal( lua_State *L )
{
vlc_object_t *p_this = vlclua_get_this( L );
return pl_Yield( p_this );
return 0;
}
+static int vlclua_playlist_skip( lua_State * L )
+{
+ int i_skip = luaL_checkint( L, 1 );
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ playlist_Skip( p_playlist, i_skip );
+ vlc_object_release( p_playlist );
+ return 0;
+}
+
static int vlclua_playlist_play( lua_State * L )
{
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
return 0;
}
+static int vlclua_playlist_pause( lua_State * L )
+{
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ playlist_Pause( p_playlist );
+ vlc_object_release( p_playlist );
+ return 0;
+}
+
static int vlclua_playlist_stop( lua_State * L )
{
playlist_t *p_playlist = vlclua_get_playlist_internal( L );
static int vlclua_playlist_goto( lua_State * L )
{
- /* XXX: logic copied from rc.c ... i'm not sure that it's ok as it
- * implies knowledge of the playlist internals. */
- playlist_t *p_playlist;
- int i_size;
- playlist_item_t *p_item, *p_parent;
-
- int i_pos;
- if( lua_gettop( L ) != 1 ) return vlclua_error( L );
- i_pos = luaL_checkint( L, -1 );
- lua_pop( L, 1 );
- if( i_pos <= 0 ) return 0;
-
- p_playlist = vlclua_get_playlist_internal( L );
- /* The playlist stores 2 times the same item: onelevel & category */
- i_size = p_playlist->items.i_size / 2;
-
- if( i_pos > i_size )
- {
- vlc_object_release( p_playlist );
- return 0;
- }
-
- p_item = p_parent = p_playlist->items.p_elems[i_pos*2-1];
- while( p_parent->p_parent )
- p_parent = p_parent->p_parent;
- playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VLC_TRUE,
- p_parent, p_item );
-
+ int i_id = luaL_checkint( L, 1 );
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ int i_ret = playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+ VLC_TRUE, NULL,
+ playlist_ItemGetById( p_playlist, i_id,
+ VLC_TRUE ) );
vlc_object_release( p_playlist );
- lua_pushboolean( L, 1 );
- return 1;
+ return vlclua_push_ret( L, i_ret );
}
static int vlclua_playlist_add( lua_State *L )
return 1;
}
-static int vlclua_playlist_get( lua_State *L )
+static void push_playlist_item( lua_State *L, playlist_item_t *p_item );
+static void push_playlist_item( lua_State *L, playlist_item_t *p_item )
{
- /* TODO: make it possible to get the tree playlist */
- playlist_t *p_playlist = vlclua_get_playlist_internal( L );
- playlist_item_t *p_root;
- int i;
- if( lua_isboolean( L, 1 ) && lua_toboolean( L, 1 ) )
- p_root = p_playlist->p_ml_onelevel; /* media library */
- else
- p_root = p_playlist->p_local_onelevel; /* local/normal playlist */
- lua_createtable( L, p_root->i_children, 0 );
- for( i = 0; i < p_root->i_children; i++ )
+ input_item_t *p_input = p_item->p_input;
+ int i_flags = p_item->i_flags;
+ lua_newtable( L );
+ lua_pushinteger( L, p_item->i_id );
+ lua_setfield( L, -2, "id" );
+ lua_newtable( L );
+#define CHECK_AND_SET_FLAG( name, label ) \
+ if( i_flags & PLAYLIST_ ## name ## _FLAG ) \
+ { \
+ lua_pushboolean( L, 1 ); \
+ lua_setfield( L, -2, #label ); \
+ }
+ CHECK_AND_SET_FLAG( SAVE, save )
+ CHECK_AND_SET_FLAG( SKIP, skip )
+ CHECK_AND_SET_FLAG( DBL, disabled )
+ CHECK_AND_SET_FLAG( RO, ro )
+ CHECK_AND_SET_FLAG( REMOVE, remove )
+ CHECK_AND_SET_FLAG( EXPANDED, expanded )
+#undef CHECK_AND_SET_FLAG
+ lua_setfield( L, -2, "flags" );
+ if( p_input )
{
- playlist_item_t *p_item = p_root->pp_children[i];
- input_item_t *p_input = p_item->p_input;
- lua_pushinteger( L, i+1 );
- lua_newtable( L );
lua_pushstring( L, p_input->psz_name );
lua_setfield( L, -2, "name" );
lua_pushstring( L, p_input->psz_uri );
lua_pushinteger( L, p_input->i_nb_played );
lua_setfield( L, -2, "nb_played" );
/* TODO: add (optional) info categories, meta, options, es */
+ }
+ if( p_item->i_children >= 0 )
+ {
+ int i;
+ lua_createtable( L, p_item->i_children, 0 );
+ for( i = 0; i < p_item->i_children; i++ )
+ {
+ push_playlist_item( L, p_item->pp_children[i] );
+ lua_rawseti( L, -2, i+1 );
+ }
+ lua_setfield( L, -2, "children" );
+ }
+}
+
+static int vlclua_playlist_get( lua_State *L )
+{
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ int b_category = luaL_optboolean( L, 2, 1 ); /* Default to tree playlist (discared when 1st argument is a playlist_item's id) */
+ playlist_item_t *p_item = NULL;
+
+ if( lua_isnumber( L, 1 ) )
+ {
+ int i_id = lua_tointeger( L, 1 );
+ p_item = playlist_ItemGetById( p_playlist, i_id, VLC_TRUE );
+ if( !p_item )
+ {
+ vlc_object_release( p_playlist );
+ return 0; /* Should we return an error instead? */
+ }
+ }
+ else if( lua_isstring( L, 1 ) )
+ {
+ const char *psz_what = lua_tostring( L, 1 );
+ if( !strcasecmp( psz_what, "normal" )
+ || !strcasecmp( psz_what, "playlist" ) )
+ p_item = b_category ? p_playlist->p_local_category
+ : p_playlist->p_local_onelevel;
+ else if( !strcasecmp( psz_what, "ml" )
+ || !strcasecmp( psz_what, "media library" ) )
+ p_item = b_category ? p_playlist->p_ml_category
+ : p_playlist->p_ml_onelevel;
+ else if( !strcasecmp( psz_what, "root" ) )
+ p_item = b_category ? p_playlist->p_root_category
+ : p_playlist->p_root_onelevel;
+ else
+ {
+ int i;
+ for( i = 0; i < p_playlist->i_sds; i++ )
+ {
+ if( !strcasecmp( psz_what,
+ p_playlist->pp_sds[i]->p_sd->psz_module ) )
+ {
+ p_item = b_category ? p_playlist->pp_sds[i]->p_cat
+ : p_playlist->pp_sds[i]->p_one;
+ break;
+ }
+ }
+ if( !p_item )
+ {
+ vlc_object_release( p_playlist );
+ return 0; /* Should we return an error instead? */
+ }
+ }
+ }
+ else
+ {
+ p_item = b_category ? p_playlist->p_root_category
+ : p_playlist->p_root_onelevel;
+ }
+ push_playlist_item( L, p_item );
+ vlc_object_release( p_playlist );
+ return 1;
+}
+#if 0
+ int s;
+ lua_createtable( L, 0, 2 + p_playlist->i_sds );
+ for( s = -2; s < p_playlist->i_sds; s++ )
+ {
+ playlist_item_t *p_root;
+ switch( s )
+ {
+ case -2:
+ /* local/normal playlist */
+ lua_pushstring( L, "local" );
+ p_root = p_playlist->p_local_onelevel;
+ break;
+ case -1:
+ /* media library */
+ lua_pushstring( L, "ml" );
+ p_root = p_playlist->p_ml_onelevel;
+ break;
+ default:
+ lua_pushstring( L, p_playlist->pp_sds[s]->p_sd->psz_module );
+ printf("%s\n", p_playlist->pp_sds[s]->p_sd->psz_module );
+ p_root = p_playlist->pp_sds[s]->p_one;
+ break;
+ }
+ printf("s = %d\n", s);
+ printf("children = %d\n", p_root->i_children );
+ push_playlist_item( L, p_root );
lua_settable( L, -3 );
}
+ printf("done\n");
+#endif
+
+static int vlclua_playlist_search( lua_State *L )
+{
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ const char *psz_string = luaL_optstring( L, 1, "" );
+ int b_category = luaL_optboolean( L, 2, 1 ); /* default to category */
+ playlist_LiveSearchUpdate( p_playlist,
+ b_category ? p_playlist->p_root_category
+ : p_playlist->p_root_onelevel,
+ psz_string );
+ push_playlist_item( L, p_playlist->p_root_category );
vlc_object_release( p_playlist );
return 1;
}
+static int vlc_sort_key_from_string( const char *psz_name )
+{
+ static const struct
+ {
+ const char *psz_name;
+ int i_key;
+ } pp_keys[] =
+ { { "id", SORT_ID },
+ { "title", SORT_TITLE },
+ { "title nodes first", SORT_TITLE_NODES_FIRST },
+ { "artist", SORT_ARTIST },
+ { "genre", SORT_GENRE },
+ { "random", SORT_RANDOM },
+ { "duration", SORT_DURATION },
+ { "title numeric", SORT_TITLE_NUMERIC },
+ { "album", SORT_ALBUM },
+ { NULL, -1 } };
+ int i;
+ for( i = 0; pp_keys[i].psz_name; i++ )
+ {
+ if( !strcmp( psz_name, pp_keys[i].psz_name ) )
+ return pp_keys[i].i_key;
+ }
+ return -1;
+}
+
static int vlclua_playlist_sort( lua_State *L )
{
/* allow setting the different sort keys */
- return 0;
+ int i_mode = vlc_sort_key_from_string( luaL_checkstring( L, 1 ) );
+ if( i_mode == -1 )
+ return luaL_error( L, "Invalid search key." );
+ int i_type = luaL_optboolean( L, 2, 0 ) ? ORDER_REVERSE : ORDER_NORMAL;
+ int b_category = luaL_optboolean( L, 3, 1 ); /* default to category */
+ playlist_t *p_playlist = vlclua_get_playlist_internal( L );
+ playlist_item_t *p_root = b_category ? p_playlist->p_local_category
+ : p_playlist->p_local_onelevel;
+ int i_ret = playlist_RecursiveNodeSort( p_playlist, p_root, i_mode,
+ i_type );
+ vlc_object_release( p_playlist );
+ return vlclua_push_ret( L, i_ret );
}
/* FIXME: split this in 3 different functions? */
{
{ "prev", vlclua_playlist_prev },
{ "next", vlclua_playlist_next },
+ { "skip", vlclua_playlist_skip },
{ "play", vlclua_playlist_play },
+ { "pause", vlclua_playlist_pause },
{ "stop", vlclua_playlist_stop },
{ "clear", vlclua_playlist_clear },
{ "repeat_", vlclua_playlist_repeat },
{ "add", vlclua_playlist_add },
{ "enqueue", vlclua_playlist_enqueue },
{ "get", vlclua_playlist_get },
+ { "search", vlclua_playlist_search },
+ { "sort", vlclua_playlist_sort },
+
{ "stats", vlclua_input_stats },
{ NULL, NULL }
};
+static luaL_Reg p_reg_sd[] =
+{
+ { "get_services_names", vlclua_sd_get_services_names },
+ { "add", vlclua_sd_add },
+ { "remove", vlclua_sd_remove },
+ { "is_loaded", vlclua_sd_is_loaded },
+
+ { NULL, NULL }
+};
+
static luaL_Reg p_reg_volume[] =
{
{ "get", vlclua_volume_get },
luaL_register_submodule( L, "config", p_reg_config );
luaL_register_submodule( L, "msg", p_reg_msg );
luaL_register_submodule( L, "playlist", p_reg_playlist );
+ luaL_register_submodule( L, "sd", p_reg_sd );
luaL_register_submodule( L, "volume", p_reg_volume );
luaL_register_submodule( L, "osd", p_reg_osd );
luaL_register_submodule( L, "net", p_reg_net );
--- /dev/null
+/*****************************************************************************
+ * sd.c: Services discovery related functions
+ *****************************************************************************
+ * Copyright (C) 2007 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Antoine Cellerier <dionoea at videolan tod 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
+
+#include <vlc/vlc.h>
+#include <vlc_services_discovery.h>
+#include <vlc_playlist.h>
+
+#include <lua.h> /* Low level lua C API */
+#include <lauxlib.h> /* Higher level C API */
+#include <lualib.h> /* Lua libs */
+
+#include "vlc.h"
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+int vlclua_sd_get_services_names( lua_State *L )
+{
+ vlc_object_t *p_this = vlclua_get_this( L );
+ char **ppsz_longnames;
+ char **ppsz_names = services_discovery_GetServicesNames( p_this, &ppsz_longnames );
+ 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;
+}
+
+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 );
+ vlc_object_release( p_playlist );
+ return vlclua_push_ret( L, i_ret );
+}
+
+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 );
+ vlc_object_release( p_playlist );
+ return vlclua_push_ret( L, i_ret );
+}
+
+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 ));
+ vlc_object_release( p_playlist );
+ return 1;
+}
return lua_toboolean( L, narg );
}
+static inline int luaL_optboolean( lua_State *L, int narg, int def )
+{
+ return luaL_opt( L, luaL_checkboolean, narg, def );
+}
+
static inline const void *luaL_checklightuserdata( lua_State *L, int narg )
{
luaL_checktype( L, narg, LUA_TLIGHTUSERDATA ); /* can raise an error */
int vlclua_object_find( lua_State *L );
int vlclua_object_find_name( lua_State *L );
+vlc_object_t * vlclua_get_this( lua_State * );
+playlist_t *vlclua_get_playlist_internal( lua_State * );
+
int vlclua_add_callback( lua_State * );
int vlclua_del_callback( lua_State * );
int vlclua_acl_add_net( lua_State * );
int vlclua_acl_load_file( lua_State * );
+int vlclua_sd_get_services_names( lua_State * );
+int vlclua_sd_add( lua_State * );
+int vlclua_sd_remove( lua_State * );
+int vlclua_sd_is_loaded( lua_State * );
+
/*****************************************************************************
* Lua function bridge
*****************************************************************************/
-vlc_object_t * vlclua_get_this( lua_State * );
#define vlclua_error( L ) luaL_error( L, "VLC lua error in file %s line %d (function %s)", __FILE__, __LINE__, __func__ )
int vlclua_push_ret( lua_State *, int i_error );
<span class="btn_text">Sort</span>
</button>
<div id="menu_sort" class="menu" >
- <button class="menuout" onclick="pl_sort(1,0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Name ascending" >Name</button><br/>
- <button class="menuout" onclick="pl_sort(1,1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Name descending" >Name reverse</button><br/>
- <button class="menuout" onclick="pl_sort(3,0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Author ascending" >Author</button><br/>
- <button class="menuout" onclick="pl_sort(3,1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Author ascending" >Author reverse</button><br/>
- <button class="menuout" onclick="pl_sort(5,0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Randomize" >Random</button><br/>
- <button class="menuout" onclick="pl_sort(7,0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Track number" >Track number</button><br/>
- <button class="menuout" onclick="pl_sort(0,0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Id ascending" >Id</button><br/>
- <button class="menuout" onclick="pl_sort(0,1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Id descending" >Id reverse</button><br/>
+ <button class="menuout" onclick="pl_sort('title',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Title ascending" >Title</button><br/>
+ <button class="menuout" onclick="pl_sort('title',1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Title descending" >Title reverse</button><br/>
+ <button class="menuout" onclick="pl_sort('artist',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Artist ascending" >Artist</button><br/>
+ <button class="menuout" onclick="pl_sort('artist',1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Artist ascending" >Artist reverse</button><br/>
+ <button class="menuout" onclick="pl_sort('album',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Album ascending" >Album</button><br/>
+ <button class="menuout" onclick="pl_sort('album',1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Album ascending" >Album reverse</button><br/>
+ <button class="menuout" onclick="pl_sort('genre',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Genre ascending" >Genre</button><br/>
+ <button class="menuout" onclick="pl_sort('genre',1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Genre ascending" >Genre reverse</button><br/>
+ <button class="menuout" onclick="pl_sort('random',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Randomize" >Random</button><br/>
+ <button class="menuout" onclick="pl_sort('id',0);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Id ascending" >Id</button><br/>
+ <button class="menuout" onclick="pl_sort('id',1);hide_menu('menu_sort');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" title="Sort by Id descending" >Id reverse</button><br/>
</div>
</td>
<td onmouseover="show_menu('menu_sd');" onmouseout="hide_menu('menu_sd');">
<span class="btn_text">Services Discovery</span>
</button>
<div id="menu_sd" class="menu" >
- <?vlc --[[ FIXME
- <vlc id="rpn" param1="services_discovery" />
- <vlc id="foreach" param1="sd" param2="object" />
- <button onclick="pl_sd('<vlc id="value" param1="sd" />');hide_menu('menu_sd');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" class="menuout" title="Toggle <vlc id="value" param1="sd.name" />" ><vlc id="value" param1="sd.name" /></button><br/>
- <vlc id="end" />
- ]] ?>
+ <?vlc
+ local sd = vlc.sd.get_services_names()
+ for n,ln in pairs(sd) do
+ print([[<button onclick="pl_sd(']]..n..[[');hide_menu('menu_sd');" onmouseover="setclass(this,'menuover');" onmouseout="setclass(this,'menuout');" class="menuout" title="Toggle ]]..ln..[[" >]]..ln..[[</button><br/>]])
+ end
+ ?>
</div>
</td>
</tr>
< - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
]] ?>
-<node id="0" name="Undefined" ro="ro">
<?vlc
-local playlist = vlc.playlist.get()
-for i,item in ipairs(playlist) do
- local name, path = vlc.convert_xml_special_chars(item.name,item.path)
- print("<leaf id='"..tostring(i).."' uri='"..path.."' name='"..name.."' ro='ro' duration='"..tostring(item.duration).."'/>")
+--[[<node id="0" name="Undefined" ro="ro">]]
+function print_playlist(item)
+ if item.children then
+ local name = vlc.convert_xml_special_chars(item.name)
+ print("<node id=\""..tostring(item.id).."\" name=\""..name.."\" ro=\""..(item.flags.ro and "ro" or "rw").."\">")
+ for _, c in ipairs(item.children) do
+ print_playlist(c)
+ end
+ print("</node>")
+ else
+ local name, path = vlc.convert_xml_special_chars(item.name,item.path or "")
+ print("<leaf id='"..tostring(item.id).."' uri='"..path.."' name='"..name.."' ro='"..(item.flags.ro and "ro" or "rw").."' duration='"..tostring(item.duration).."'/>")
+ end
end
+function a(t,pre)
+ local pre = pre or ""
+ for k,v in pairs(t) do
+ vlc.msg.err(pre..tostring(k).." : "..tostring(v))
+ if type(v) == "table" then
+ a(v,pre.." ")
+ end
+ end
+end
+--[[
+for cat,pl in pairs(p) do
+ print("<node id=\"-1\" name=\""..cat.."\" ro=\"ro\">")
+ print_playlist(pl)
+ print("</node>")
+end
+--]]
+local p = vlc.playlist.get()
+-- a(p) Uncomment to debug
+print_playlist(p)
?>
-</node>
<?vlc --[[
+</node>
<node id="9" name="Nevermind" ro="rw">
<leaf id="10" current="current" uri="file:///mnt/stuff/media/Nirvana/Nevermind/01 - Smells Like Teen Spirit.mp3" name="Smells Like Teen Spirit" ro="rw" duration="-1"/>
]]?>
elseif command == "pl_empty" then
vlc.playlist.clear()
elseif command == "pl_sort" then
- vlc.msg.err("FIXME: pl_sort unimplemented")
+ vlc.playlist.sort( val, id > 0 )
elseif command == "pl_random" then
vlc.playlist.random()
elseif command == "pl_loop" then
elseif command == "pl_repeat" then
vlc.playlist.repeat_()
elseif command == "pl_sd" then
- vlc.msg.err("FIXME: pl_sd unimplemented")
- --[[
- <vlc id="if" param1="val value services_discovery_is_loaded" />
- <vlc id="rpn" param1="val value services_discovery_remove" />
- <vlc id="else" />
- <vlc id="rpn" param1="val value services_discovery_add" />
- <vlc id="end" />
- ]]
+ if vlc.sd.is_loaded(val) then
+ vlc.sd.remove(val)
+ else
+ vlc.sd.add(val)
+ end
elseif command == "fullscreen" then
vlc.fullscreen()
elseif command == "snapshot" then
end
function playlist(name,client,arg)
- -- TODO: add possibility to filter playlist items using a mask
+ function playlist0(item,prefix)
+ local prefix = prefix or ""
+ if not item.flags.disabled then
+ local str = "| "..prefix..tostring(item.id).." - "..item.name
+ if item.duration > 0 then
+ str = str.." ("..common.durationtostring(item.duration)..")"
+ end
+ if item.nb_played > 0 then
+ str = str.." [played "..tostring(item.nb_played).." time"
+ if item.nb_played > 1 then
+ str = str .. "s"
+ end
+ str = str .. "]"
+ end
+ client:append(str)
+ end
+ if item.children then
+ for _, c in ipairs(item.children) do
+ playlist0(c,prefix.." ")
+ end
+ end
+ end
local playlist
- if arg == "ml" then
- playlist = vlc.playlist.get(true)
- client:append("+----[ Playlist - Media Library ]")
+ if name == "search" then
+ playlist = vlc.playlist.search(arg or "")
+ else
+ if tonumber(arg) then
+ print "number"
+ playlist = vlc.playlist.get(tonumber(arg))
+ elseif arg then
+ print "string"
+ playlist = vlc.playlist.get(arg)
+ else
+ playlist = vlc.playlist.get()
+ end
+ end
+ if name == "search" then
+ client:append("+----[ Search - "..(arg or "`reset'").." ]")
+ else
+ client:append("+----[ Playlist - "..playlist.name.." ]")
+ end
+ if playlist.children then
+ for _, item in ipairs(playlist.children) do
+ playlist0(item)
+ end
+ else
+ playlist0(playlist)
+ end
+ if name == "search" then
+ client:append("+----[ End of search - Use `search' to reset ]")
else
- playlist = vlc.playlist.get()
- client:append("+----[ Playlist ]")
+ client:append("+----[ End of playlist ]")
end
- for i, item in pairs(playlist) do
- local str = "| "..tostring(i).." - "..item.name
- if item.duration > 0 then
- str = str.." ("..common.durationtostring(item.duration)..")"
+end
+
+function playlist_sort(name,client,arg)
+ if not arg then
+ client:append("Valid sort keys are: id, title, artist, genre, random, duration, album.")
+ else
+ vlc.playlist.sort(arg)
+ end
+end
+
+function services_discovery(name,client,arg)
+ if arg then
+ if vlc.sd.is_loaded(arg) then
+ vlc.sd.remove(arg)
+ client:append(arg.." disabled.")
+ else
+ vlc.sd.add(arg)
+ client:append(arg.." enabled.")
end
- if item.nb_played > 0 then
- str = str.." played "..tostring(item.nb_played).." time"
- if item.nb_played > 1 then
- str = str .. "s"
+ else
+ local sd = vlc.sd.get_services_names()
+ client:append("+----[ Services discovery ]")
+ for n,ln in pairs(sd) do
+ local status
+ if vlc.sd.is_loaded(n) then
+ status = "enabled"
+ else
+ status = "disabled"
end
+ client:append("| "..n..": " .. ln .. " (" .. status .. ")")
end
- client:append(str)
+ client:append("+----[ End of services discovery ]")
end
- client:append("+----[ End of playlist ]")
end
function print_text(label,text)
{ "add"; { func = add; args = "XYZ"; help = "add XYZ to playlist" } };
{ "enqueue"; { func = add; args = "XYZ"; help = "queue XYZ to playlist" } };
{ "playlist"; { func = playlist; help = "show items currently in playlist" } };
+ { "search"; { func = playlist; args = "[string]"; help = "search for items in playlist (or reset search)" } };
+ { "sort"; { func = playlist_sort; args = "key"; help = "sort the playlist" } };
+ { "sd"; { func = services_discovery; args = "[sd]"; help = "show services discovery or toggle" } };
{ "play"; { func = skip2(vlc.playlist.play); help = "play stream" } };
{ "stop"; { func = skip2(vlc.playlist.stop); help = "stop stream" } };
{ "next"; { func = skip2(vlc.playlist.next); help = "next playlist item" } };