diff --git a/modules/lua/Makefile.am b/modules/lua/Makefile.am index a8bb596039113465bde39cbf40b35a2a178c91e3..39852e5116c25838d97183398493956dcdbcc1e7 100644 --- a/modules/lua/Makefile.am +++ b/modules/lua/Makefile.am @@ -31,7 +31,8 @@ liblua_plugin_la_SOURCES = \ lua/libs/xml.c \ lua/libs/io.c \ lua/libs/errno.c \ - lua/libs/rand.c + lua/libs/rand.c \ + lua/libs/renderers.c if HAVE_WIN32 liblua_plugin_la_SOURCES += lua/libs/win.c diff --git a/modules/lua/extension.c b/modules/lua/extension.c index 9850fa328571c3cad487bf6db1d09574db00b2cc..998ba5a0cd8d5c43e558a8f46c865a52f78012e7 100644 --- a/modules/lua/extension.c +++ b/modules/lua/extension.c @@ -834,6 +834,7 @@ static lua_State* GetLuaState( extensions_manager_t *p_mgr, luaopen_vlcio( L ); luaopen_errno( L ); luaopen_rand( L ); + luaopen_rd( L ); #if defined(_WIN32) && !VLC_WINSTORE_APP luaopen_win( L ); #endif diff --git a/modules/lua/intf.c b/modules/lua/intf.c index 58976d67feba6795688050002c9df75d54cd35a5..409432e8eccec943906976a608a2f81c2709b289 100644 --- a/modules/lua/intf.c +++ b/modules/lua/intf.c @@ -271,6 +271,7 @@ static int Start_LuaIntf( vlc_object_t *p_this, const char *name ) luaopen_vlcio( L ); luaopen_errno( L ); luaopen_rand( L ); + luaopen_rd( L ); #if defined(_WIN32) && !VLC_WINSTORE_APP luaopen_win( L ); #endif diff --git a/modules/lua/libs.h b/modules/lua/libs.h index c94854ded8316802a161370eb60474596002f786..ba8cbb24969fefbb4f00bd120e48a288f0088221 100644 --- a/modules/lua/libs.h +++ b/modules/lua/libs.h @@ -49,6 +49,7 @@ void luaopen_equalizer( lua_State *L ); void luaopen_vlcio( lua_State *L ); void luaopen_errno( lua_State *L ); void luaopen_rand( lua_State *L ); +void luaopen_rd( lua_State *L ); #ifdef _WIN32 void luaopen_win( lua_State *L ); #endif diff --git a/modules/lua/libs/renderers.c b/modules/lua/libs/renderers.c new file mode 100644 index 0000000000000000000000000000000000000000..822b7ad237f1ad8a25f8244366b6e065aac0635f --- /dev/null +++ b/modules/lua/libs/renderers.c @@ -0,0 +1,216 @@ +/***************************************************************************** + * renderers.c + ***************************************************************************** + * Copyright (C) 2020 the VideoLAN team + * + * 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. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_player.h> +#include <vlc_renderer_discovery.h> +#include <vlc_vector.h> + +#include "../vlc.h" +#include "../libs.h" + +#include "misc.h" + +typedef struct vlclua_renderer_item +{ + uint32_t id; + vlc_renderer_item_t* item; +} vlclua_renderer_item; + +struct rd_items_vec VLC_VECTOR(vlclua_renderer_item); + +typedef struct vlclua_rd_sys_t +{ + struct vlc_renderer_discovery_owner owner; + vlc_renderer_discovery_t* rd; + struct rd_items_vec items; + vlc_mutex_t mutex; + uint32_t last_renderer_id; +} vlclua_rd_sys_t; + +static bool vlclua_renderer_compare( vlc_renderer_item_t* rhs, + vlc_renderer_item_t* lhs ) +{ + return !strcmp( vlc_renderer_item_name( rhs ), vlc_renderer_item_name( lhs ) ) && + !strcmp( vlc_renderer_item_type( rhs ), vlc_renderer_item_type( lhs ) ); +} + +static int vlclua_rd_list( lua_State* L ) +{ + vlclua_rd_sys_t* sys = (vlclua_rd_sys_t*)luaL_checkudata( L, 1, "renderer_discoverer" ); + + vlc_renderer_item_t *activeRenderer; + vlc_player_t* player = vlclua_get_player_internal( L ); + vlc_player_Lock( player ); + activeRenderer = vlc_player_GetRenderer( player ); + if ( activeRenderer ) + vlc_renderer_item_hold( activeRenderer ); + vlc_player_Unlock( player ); + + lua_createtable( L, sys->items.size, 0 ); + vlc_mutex_lock( &sys->mutex ); + for ( size_t i = 0; i < sys->items.size; ++i ) + { + lua_newtable( L ); + + lua_pushinteger( L, sys->items.data[i].id ); + lua_setfield( L, -2, "id" ); + lua_pushstring( L, vlc_renderer_item_name( sys->items.data[i].item ) ); + lua_setfield( L, -2, "name" ); + lua_pushstring( L, vlc_renderer_item_type( sys->items.data[i].item ) ); + lua_setfield( L, -2, "type" ); + + bool selected = activeRenderer != NULL && + vlclua_renderer_compare( activeRenderer, sys->items.data[i].item ); + lua_pushboolean( L, selected ); + lua_setfield( L, -2, "selected" ); + + lua_rawseti( L, -2, i + 1 ); + } + vlc_mutex_unlock( &sys->mutex ); + + if ( activeRenderer ) + vlc_renderer_item_release( activeRenderer ); + + return 1; +} + +static int vlclua_rd_select( lua_State* L ) +{ + vlc_player_t* player = vlclua_get_player_internal( L ); + if ( !player ) + return 0; + vlclua_rd_sys_t* sys = (vlclua_rd_sys_t*)luaL_checkudata( L, 1, "renderer_discoverer" ); + lua_Integer id = luaL_checkinteger( L, 2 ); + if ( id < 0 ) + { + vlc_player_Lock( player ); + vlc_player_SetRenderer( player, NULL ); + vlc_player_Unlock( player ); + } + vlc_mutex_lock( &sys->mutex ); + for ( size_t i = 0; i < sys->items.size; ++i ) + { + if ( sys->items.data[i].id != id ) + continue; + vlc_player_Lock( player ); + vlc_player_SetRenderer( player, sys->items.data[i].item ); + vlc_player_Unlock( player ); + } + vlc_mutex_unlock( &sys->mutex ); + return 0; +} + +static const luaL_Reg vlclua_rd_obj_reg[] = { + { "list", vlclua_rd_list}, + { "select", vlclua_rd_select }, + { NULL, NULL } +}; + +static int vlclua_rd_obj_delete( lua_State *L ) +{ + vlclua_rd_sys_t* sys = (vlclua_rd_sys_t*)luaL_checkudata( L, 1, "renderer_discoverer" ); + vlc_rd_release( sys->rd ); + for ( size_t i = 0; i < sys->items.size; ++i ) + vlc_renderer_item_release( sys->items.data[i].item ); + vlc_vector_destroy( &sys->items ); + return 0; +} + +static void vlclua_rd_on_item_added( struct vlc_renderer_discovery_t* rd, + struct vlc_renderer_item_t* item ) +{ + vlclua_rd_sys_t* sys = rd->owner.sys; + vlc_mutex_lock( &sys->mutex ); + vlclua_renderer_item i = + { + sys->last_renderer_id++, + vlc_renderer_item_hold( item ), + }; + vlc_vector_push( &sys->items, i ); + vlc_mutex_unlock( &sys->mutex ); +} + +static void vlclua_rd_on_item_removed( struct vlc_renderer_discovery_t* rd, + struct vlc_renderer_item_t* item ) +{ + vlclua_rd_sys_t* sys = rd->owner.sys; + + vlc_mutex_lock( &sys->mutex ); + for ( size_t i = 0; i < sys->items.size; ++i ) + { + if ( !vlclua_renderer_compare( item, sys->items.data[i].item ) ) + continue; + vlc_vector_remove( &sys->items, i ); + break; + } + vlc_mutex_unlock( &sys->mutex ); +} + +static int vlclua_rd_create( lua_State* L ) +{ + vlclua_rd_sys_t* sys = lua_newuserdata( L, sizeof( *sys ) ); + if ( !sys ) + return 0; + sys->owner.sys = sys; + sys->owner.item_added = vlclua_rd_on_item_added; + sys->owner.item_removed = vlclua_rd_on_item_removed; + vlc_vector_init( &sys->items ); + vlc_mutex_init( &sys->mutex ); + sys->last_renderer_id = 0; + + vlc_object_t *this = vlclua_get_this( L ); + const char* name = luaL_checkstring( L, 1 ); + + sys->rd = vlc_rd_new( this, name, &sys->owner ); + if ( !sys->rd ) + { + vlc_vector_destroy( &sys->items ); + return 0; + } + + if ( luaL_newmetatable( L, "renderer_discoverer" ) ) + { + lua_newtable( L ); + luaL_register( L, NULL, vlclua_rd_obj_reg ); + lua_setfield( L, -2, "__index" ); + lua_pushcfunction( L, vlclua_rd_obj_delete ); + lua_setfield( L, -2, "__gc" ); + } + lua_setmetatable( L, -2 ); + + return 1; +} + +static const luaL_Reg vlclua_rd_reg[] = { + { "create", vlclua_rd_create }, + { NULL, NULL } +}; + +void luaopen_rd( lua_State *L ) +{ + lua_newtable( L ); + luaL_register( L, NULL, vlclua_rd_reg ); + lua_setfield( L, -2, "rd" ); +}