intf.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * intf.c: Generic lua interface functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2007-2008 the VideoLAN team
  5.  * $Id: 9ee4b1b1a4380892df0fe3808cb98a77fcb18748 $
  6.  *
  7.  * Authors: Antoine Cellerier <dionoea at videolan tod org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifndef  _GNU_SOURCE
  27. #   define  _GNU_SOURCE
  28. #endif
  29. #ifdef HAVE_CONFIG_H
  30. # include "config.h"
  31. #endif
  32. #include <vlc_common.h>
  33. #include <vlc_meta.h>
  34. #include <vlc_charset.h>
  35. #include <vlc_interface.h>
  36. #include <vlc_playlist.h>
  37. #include <vlc_aout.h>
  38. #include <lua.h>        /* Low level lua C API */
  39. #include <lauxlib.h>    /* Higher level C API */
  40. #include <lualib.h>     /* Lua libs */
  41. #include "vlc.h"
  42. #include "libs.h"
  43. /*****************************************************************************
  44.  * Prototypes
  45.  *****************************************************************************/
  46. static void *Run( void * );
  47. static const char * const ppsz_intf_options[] = { "intf", "config", NULL };
  48. /*****************************************************************************
  49.  *
  50.  *****************************************************************************/
  51. static char *FindFile( const char *psz_name )
  52. {
  53.     char  *ppsz_dir_list[] = { NULL, NULL, NULL, NULL };
  54.     char **ppsz_dir;
  55.     vlclua_dir_list( "intf", ppsz_dir_list );
  56.     for( ppsz_dir = ppsz_dir_list; *ppsz_dir; ppsz_dir++ )
  57.     {
  58.         char *psz_filename;
  59.         FILE *fp;
  60.         if( asprintf( &psz_filename, "%s"DIR_SEP"%s.lua", *ppsz_dir,
  61.                       psz_name ) < 0 )
  62.         {
  63.             vlclua_dir_list_free( ppsz_dir_list );
  64.             return NULL;
  65.         }
  66.         fp = fopen( psz_filename, "r" );
  67.         if( fp )
  68.         {
  69.             fclose( fp );
  70.             vlclua_dir_list_free( ppsz_dir_list );
  71.             return psz_filename;
  72.         }
  73.         free( psz_filename );
  74.     }
  75.     vlclua_dir_list_free( ppsz_dir_list );
  76.     return NULL;
  77. }
  78. static inline void luaL_register_submodule( lua_State *L, const char *psz_name,
  79.                                             const luaL_Reg *l )
  80. {
  81.     lua_newtable( L );
  82.     luaL_register( L, NULL, l );
  83.     lua_setfield( L, -2, psz_name );
  84. }
  85. static const struct
  86. {
  87.     const char *psz_shortcut;
  88.     const char *psz_name;
  89. } pp_shortcuts[] = {
  90.     { "luarc", "rc" },
  91.     /* { "rc", "rc" }, */
  92.     { "luahotkeys", "hotkeys" },
  93.     /* { "hotkeys", "hotkeys" }, */
  94.     { "luatelnet", "telnet" },
  95.     /* { "telnet", "telnet" }, */
  96.     { "luahttp", "http" },
  97.     /* { "http", "http" }, */
  98.     { NULL, NULL } };
  99. static bool WordInList( const char *psz_list, const char *psz_word )
  100. {
  101.     const char *psz_str = strstr( psz_list, psz_word );
  102.     int i_len = strlen( psz_word );
  103.     while( psz_str )
  104.     {
  105.         if( (psz_str == psz_list || *(psz_str-1) == ',' )
  106.          /* it doesn't start in middle of a word */
  107.          /* it doest end in middle of a word */
  108.          && ( psz_str[i_len] == '' || psz_str[i_len] == ',' ) )
  109.             return true;
  110.         psz_str = strstr( psz_str, psz_word );
  111.     }
  112.     return false;
  113. }
  114. static char *GetModuleName( intf_thread_t *p_intf )
  115. {
  116.     int i;
  117.     const char *psz_intf;
  118.     /*if( *p_intf->psz_intf == '$' )
  119.         psz_intf = var_GetString( p_intf, p_intf->psz_intf+1 );
  120.     else*/
  121.         psz_intf = p_intf->psz_intf;
  122.     for( i = 0; pp_shortcuts[i].psz_name; i++ )
  123.     {
  124.         if( WordInList( psz_intf, pp_shortcuts[i].psz_shortcut ) )
  125.             return strdup( pp_shortcuts[i].psz_name );
  126.     }
  127.     return var_CreateGetString( p_intf, "lua-intf" );
  128. }
  129. static const luaL_Reg p_reg[] = { { NULL, NULL } };
  130. int Open_LuaIntf( vlc_object_t *p_this )
  131. {
  132.     intf_thread_t *p_intf = (intf_thread_t*)p_this;
  133.     intf_sys_t *p_sys;
  134.     lua_State *L;
  135.     config_ChainParse( p_intf, "lua-", ppsz_intf_options, p_intf->p_cfg );
  136.     char *psz_name = GetModuleName( p_intf );
  137.     char *psz_config;
  138.     bool b_config_set = false;
  139.     if( !psz_name ) psz_name = strdup( "dummy" );
  140.     p_intf->p_sys = (intf_sys_t*)malloc( sizeof(intf_sys_t) );
  141.     if( !p_intf->p_sys )
  142.     {
  143.         free( psz_name );
  144.         return VLC_ENOMEM;
  145.     }
  146.     p_sys = p_intf->p_sys;
  147.     p_sys->psz_filename = FindFile( psz_name );
  148.     if( !p_sys->psz_filename )
  149.     {
  150.         msg_Err( p_intf, "Couldn't find lua interface script "%s".",
  151.                  psz_name );
  152.         free( psz_name );
  153.         free( p_sys );
  154.         return VLC_EGENERIC;
  155.     }
  156.     msg_Dbg( p_intf, "Found lua interface script: %s", p_sys->psz_filename );
  157.     L = luaL_newstate();
  158.     if( !L )
  159.     {
  160.         msg_Err( p_intf, "Could not create new Lua State" );
  161.         free( psz_name );
  162.         free( p_sys );
  163.         return VLC_EGENERIC;
  164.     }
  165.     luaL_openlibs( L );
  166.     /* register our functions */
  167.     luaL_register( L, "vlc", p_reg );
  168.     /* store a pointer to p_intf (FIXME: user could overwrite this) */
  169.     lua_pushlightuserdata( L, p_intf );
  170.     lua_setfield( L, -2, "private" );
  171.     /* register submodules */
  172.     luaopen_acl( L );
  173.     luaopen_config( L );
  174.     luaopen_volume( L );
  175.     luaopen_httpd( L );
  176.     luaopen_input( L );
  177.     luaopen_msg( L );
  178.     luaopen_misc( L );
  179.     luaopen_net( L );
  180.     luaopen_object( L );
  181.     luaopen_osd( L );
  182.     luaopen_playlist( L );
  183.     luaopen_sd( L );
  184.     luaopen_stream( L );
  185.     luaopen_strings( L );
  186.     luaopen_variables( L );
  187.     luaopen_video( L );
  188.     luaopen_vlm( L );
  189.     luaopen_volume( L );
  190.     /* clean up */
  191.     lua_pop( L, 1 );
  192.     /* <gruik> */
  193.     /* Setup the module search path */
  194.     {
  195.     char *psz_command;
  196.     char *psz_char = strrchr(p_sys->psz_filename,DIR_SEP_CHAR);
  197.     *psz_char = '';
  198.     /* FIXME: don't use luaL_dostring */
  199.     if( asprintf( &psz_command,
  200.                   "package.path = "%s"DIR_SEP"modules"DIR_SEP"?.lua;"..package.path",
  201.                   p_sys->psz_filename ) < 0 )
  202.         return VLC_EGENERIC;
  203.     *psz_char = DIR_SEP_CHAR;
  204.     if( luaL_dostring( L, psz_command ) )
  205.         return VLC_EGENERIC;
  206.     }
  207.     /* </gruik> */
  208.     psz_config = var_CreateGetString( p_intf, "lua-config" );
  209.     if( psz_config && *psz_config )
  210.     {
  211.         char *psz_buffer;
  212.         if( asprintf( &psz_buffer, "config={%s}", psz_config ) != -1 )
  213.         {
  214.             printf("%sn", psz_buffer);
  215.             if( luaL_dostring( L, psz_buffer ) == 1 )
  216.                 msg_Err( p_intf, "Error while parsing "lua-config"." );
  217.             free( psz_buffer );
  218.             lua_getglobal( L, "config" );
  219.             if( lua_istable( L, -1 ) )
  220.             {
  221.                 lua_getfield( L, -1, psz_name );
  222.                 if( lua_istable( L, -1 ) )
  223.                 {
  224.                     lua_setglobal( L, "config" );
  225.                     b_config_set = true;
  226.                 }
  227.             }
  228.         }
  229.     }
  230.     free( psz_config );
  231.     if( b_config_set == false )
  232.     {
  233.         lua_newtable( L );
  234.         lua_setglobal( L, "config" );
  235.     }
  236.     p_sys->L = L;
  237.     p_intf->psz_header = psz_name;
  238.     /* ^^ Do I need to clean that up myself in Close_LuaIntf? */
  239.     vlc_mutex_init( &p_sys->lock );
  240.     vlc_cond_init( &p_sys->wait );
  241.     p_sys->exiting = false;
  242.     if( vlc_clone( &p_sys->thread, Run, p_intf, VLC_THREAD_PRIORITY_LOW ) )
  243.     {
  244.         p_sys->exiting = true;
  245.         Close_LuaIntf( p_this );
  246.         return VLC_ENOMEM;
  247.     }
  248.     return VLC_SUCCESS;
  249. }
  250. void Close_LuaIntf( vlc_object_t *p_this )
  251. {
  252.     intf_thread_t *p_intf = (intf_thread_t*)p_this;
  253.     intf_sys_t *p_sys = p_intf->p_sys;
  254.     if( !p_sys->exiting ) /* <- Read-only here and in thread: no locking */
  255.     {
  256.         vlc_mutex_lock( &p_sys->lock );
  257.         p_sys->exiting = true;
  258.         vlc_cond_signal( &p_sys->wait );
  259.         vlc_mutex_unlock( &p_sys->lock );
  260.         vlc_join( p_sys->thread, NULL );
  261.     }
  262.     vlc_cond_destroy( &p_sys->wait );
  263.     vlc_mutex_destroy( &p_sys->lock );
  264.     lua_close( p_sys->L );
  265.     free( p_sys );
  266. }
  267. static void *Run( void *data )
  268. {
  269.     intf_thread_t *p_intf = data;
  270.     intf_sys_t *p_sys = p_intf->p_sys;
  271.     lua_State *L = p_sys->L;
  272.     if( luaL_dofile( L, p_sys->psz_filename ) )
  273.     {
  274.         msg_Err( p_intf, "Error loading script %s: %s", p_sys->psz_filename,
  275.                  lua_tostring( L, lua_gettop( L ) ) );
  276.         lua_pop( L, 1 );
  277.     }
  278.     return NULL;
  279. }