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.
 
 
 
 
 
 

216 lines
6.5 KiB

/*****************************************************************************
* 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" );
}