[vlc-devel] [PATCH 3/3] lua: Add basic support for renderer discovery

Hugo Beauzée-Luyssen hugo at beauzee.fr
Wed May 27 11:22:57 CEST 2020


---
 modules/lua/Makefile.am      |   3 +-
 modules/lua/extension.c      |   1 +
 modules/lua/intf.c           |   1 +
 modules/lua/libs.h           |   1 +
 modules/lua/libs/renderers.c | 216 +++++++++++++++++++++++++++++++++++
 5 files changed, 221 insertions(+), 1 deletion(-)
 create mode 100644 modules/lua/libs/renderers.c

diff --git a/modules/lua/Makefile.am b/modules/lua/Makefile.am
index a8bb596039..39852e5116 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 9850fa3285..998ba5a0cd 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 58976d67fe..409432e8ec 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 c94854ded8..ba8cbb2496 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 0000000000..822b7ad237
--- /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" );
+}
-- 
2.20.1



More information about the vlc-devel mailing list