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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * simple.c - The OSD Menu simple parser code.
  3.  *****************************************************************************
  4.  * Copyright (C) 2005-2008 M2X
  5.  * $Id: 992efe90fb94b534a7019567fd713cd105d7a1a8 $
  6.  *
  7.  * Authors: Jean-Paul Saman
  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. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_osd.h>
  31. #include <vlc_charset.h>
  32. #include <limits.h>
  33. #include "osd_menu.h"
  34. int osd_parser_simpleOpen( vlc_object_t *p_this );
  35. /*****************************************************************************
  36.  * Simple parser open function
  37.  *****************************************************************************/
  38. int osd_parser_simpleOpen( vlc_object_t *p_this )
  39. {
  40.     osd_menu_t     *p_menu = (osd_menu_t *) p_this;
  41.     osd_button_t   *p_current = NULL; /* button currently processed */
  42.     osd_button_t   *p_prev = NULL;    /* previous processed button */
  43.     FILE       *fd = NULL;
  44.     int        result = 0;
  45.     if( !p_menu ) return VLC_ENOOBJ;
  46.     msg_Dbg( p_this, "opening osdmenu definition file %s", p_menu->psz_file );
  47.     fd = utf8_fopen( p_menu->psz_file, "r" );
  48.     if( !fd )
  49.     {
  50.         msg_Err( p_this, "failed to open osdmenu definition file %s",
  51.                 p_menu->psz_file );
  52.         return VLC_EGENERIC;
  53.     }
  54.     /* Read first line */
  55.     if( !feof( fd ) )
  56.     {
  57.         char action[25] = "";
  58.         char cmd[25] = "";
  59.         char path[PATH_MAX] = "";
  60.         char *psz_path = NULL;
  61.         size_t i_len = 0;
  62.         long pos = 0;
  63.         result = fscanf(fd, "%24s %255s", action, path );
  64.         /* override images path ? */
  65.         psz_path = config_GetPsz( p_this, "osdmenu-file-path" );
  66.         if( psz_path )
  67.         {
  68.             /* psz_path is not null and therefor path cannot be NULL
  69.              * it might be null terminated.
  70.              */
  71.             strncpy( path, psz_path, PATH_MAX );
  72.             free( psz_path );
  73.             psz_path = NULL;
  74.         }
  75.         /* NULL terminate before asking the length of path[] */
  76.         path[PATH_MAX-1] = '';
  77.         i_len = strlen(path);
  78.         /* Protect against buffer overflow:
  79.          * max index is PATH_MAX-1 and we increment by 1 after
  80.          * so PATH_MAX-2 is the bigest we can have */
  81.         if( i_len > PATH_MAX - 2 )
  82.             i_len = PATH_MAX - 2;
  83. #if defined(WIN32) || defined(UNDER_CE)
  84.         if( (i_len > 0) && path[i_len] != '\' )
  85.             path[i_len] = '\';
  86. #else
  87.         if( (i_len > 0) && path[i_len] != '/' )
  88.             path[i_len] = '/';
  89. #endif
  90.         path[i_len+1] = '';
  91.         if( result == 0 || result == EOF )
  92.             goto error;
  93.         msg_Dbg( p_this, "osdmenu dir %s", path );
  94.         if( i_len == 0 )
  95.             p_menu = osd_MenuNew( p_menu, NULL, 0, 0 );
  96.         else
  97.             p_menu = osd_MenuNew( p_menu, path, 0, 0 );
  98.         /* Peek for 'style' argument */
  99.         pos = ftell( fd );
  100.         if( pos < 0 )
  101.             goto error;
  102.         result = fscanf(fd, "%24s %24s", cmd, action );
  103.         if( result == 0 || result == EOF )
  104.             goto error;
  105.         msg_Dbg( p_this, "osdmenu %s %s", cmd, action );
  106.         if( strncmp( cmd, "style", 5 ) == 0 )
  107.         {
  108.             if( strncmp( action, "default", 7) == 0 )
  109.             {
  110.                 p_menu->i_style = OSD_MENU_STYLE_SIMPLE;
  111.             }
  112.             else if( strncmp( action, "concat", 6) == 0 )
  113.             {
  114.                 p_menu->i_style = OSD_MENU_STYLE_CONCAT;
  115.             }
  116.         }
  117.         else
  118.         {
  119.             result = fseek( fd, pos, SEEK_SET );
  120.             if( result < 0 )
  121.                 goto error;
  122.         }
  123.     }
  124.     if( !p_menu )
  125.         goto error;
  126.     /* read successive lines */
  127.     while( !feof( fd ) )
  128.     {
  129.         osd_state_t   *p_state_current = NULL; /* button state currently processed */
  130.         osd_state_t   *p_state_prev = NULL;    /* previous state processed button */
  131.         char cmd[25] = "";
  132.         char action[25] = "";
  133.         char state[25]  = "";
  134.         char file[256]  = "";
  135.         char path[PATH_MAX]  = "";
  136.         int  i_x = 0;
  137.         int  i_y = 0;
  138.         result = fscanf( fd, "%24s %24s (%d,%d)", cmd, action, &i_x, &i_y );
  139.         if( result == 0 )
  140.             goto error;
  141.         if( strncmp( &cmd[0], "action", 6 ) != 0 )
  142.             break;
  143.         msg_Dbg( p_this, " + %s hotkey=%s (%d,%d)", cmd, action, i_x, i_y );
  144.         p_prev = p_current;
  145.         p_current = osd_ButtonNew( action, i_x, i_y );
  146.         if( !p_current )
  147.             goto error;
  148.         if( p_prev )
  149.             p_prev->p_next = p_current;
  150.         else
  151.             p_menu->p_button = p_current;
  152.         p_current->p_prev = p_prev;
  153.         /* parse all states */
  154.         while( !feof( fd ) )
  155.         {
  156.             char type[25] = "";
  157.             result = fscanf( fd, "t%24s", state );
  158.             if( result == 0 )
  159.                 goto error;
  160.             /* FIXME: We only parse one level deep now */
  161.             if( strncmp( state, "action", 6 ) == 0 )
  162.             {
  163.                 osd_button_t   *p_up = NULL;
  164.                 result = fscanf( fd, "%24s (%d,%d)", action, &i_x, &i_y );
  165.                 if( result == 0 )
  166.                     goto error;
  167.                 /* create new button */
  168.                 p_up = osd_ButtonNew( action, i_x, i_y );
  169.                 if( !p_up )
  170.                     goto error;
  171.                 /* Link to list */
  172.                 p_up->p_down = p_current;
  173.                 p_current->p_up = p_up;
  174.                 msg_Dbg( p_this, " + (menu up) hotkey=%s (%d,%d)", action, i_x, i_y );
  175.                 /* Parse type state */
  176.                 result = fscanf( fd, "t%24s %24s", cmd, type );
  177.                 if( result == 0 )
  178.                     goto error;
  179.                 if( strncmp( cmd, "type", 4 ) == 0 )
  180.                 {
  181.                     if( strncmp( type, "volume", 6 ) == 0 )
  182.                     {
  183.                         p_menu->p_state->p_volume = p_up;
  184.                         msg_Dbg( p_this, " + type=%s", type );
  185.                     }
  186.                 }
  187.                 /* Parse range state */
  188.                 result = fscanf( fd, "t%24s", state );
  189.                 if( result == 0 )
  190.                     goto error;
  191.                 /* Parse the range state */
  192.                 if( strncmp( state, "range", 5 ) == 0 )
  193.                 {
  194.                     osd_state_t   *p_range_current = NULL; /* range state currently processed */
  195.                     osd_state_t   *p_range_prev = NULL;    /* previous state processed range */
  196.                     int i_index = 0;
  197.                     p_up->b_range = true;
  198.                     result = fscanf( fd, "t%24s", action );
  199.                     if( result == 0 )
  200.                         goto error;
  201.                     result = fscanf( fd, "t%d", &i_index );
  202.                     if( result == 0 )
  203.                         goto error;
  204.                     msg_Dbg( p_this, " + (menu up) hotkey down %s, file=%s%s",
  205.                              action, p_menu->psz_path, file );
  206.                     free( p_up->psz_action_down );
  207.                     p_up->psz_action_down = strdup( action );
  208.                     /* Parse range contstruction :
  209.                      * range <hotkey>
  210.                      *      <state1> <file1>
  211.                      *
  212.                      *      <stateN> <fileN>
  213.                      * end
  214.                      */
  215.                     while( !feof( fd ) )
  216.                     {
  217.                         result = fscanf( fd, "t%255s", file );
  218.                         if( result == 0 )
  219.                             goto error;
  220.                         if( strncmp( file, "end", 3 ) == 0 )
  221.                             break;
  222.                         p_range_prev = p_range_current;
  223.                         if( p_menu->psz_path )
  224.                         {
  225.                             size_t i_path_size = strlen( p_menu->psz_path );
  226.                             size_t i_file_size = strlen( file );
  227.                             if( (i_path_size + i_file_size >= PATH_MAX) ||
  228.                                 (i_path_size >= PATH_MAX) )
  229.                                 goto error;
  230.                             strncpy( path, p_menu->psz_path, i_path_size );
  231.                             strncpy( &path[i_path_size], file,
  232.                                      PATH_MAX - (i_path_size + i_file_size) );
  233.                             path[ i_path_size + i_file_size ] = '';
  234.                             p_range_current = osd_StateNew( p_menu, path, "pressed" );
  235.                         }
  236.                         else /* absolute paths are used. */
  237.                             p_range_current = osd_StateNew( p_menu, file, "pressed" );
  238.                         if( !p_range_current )
  239.                             goto error;
  240.                         if( !p_range_current->p_pic )
  241.                         {
  242.                             osd_StatesFree( p_menu, p_range_current );
  243.                             goto error;
  244.                         }
  245.                         p_range_current->i_x = i_x;
  246.                         p_range_current->i_y = i_y;
  247.                         /* increment the number of ranges for this button */
  248.                         p_up->i_ranges++;
  249.                         if( p_range_prev )
  250.                             p_range_prev->p_next = p_range_current;
  251.                         else
  252.                             p_up->p_states = p_range_current;
  253.                         p_range_current->p_prev = p_range_prev;
  254.                         msg_Dbg( p_this, "  |- range=%d, file=%s%s",
  255.                                  p_up->i_ranges,
  256.                                  p_menu->psz_path, file );
  257.                     }
  258.                     if( i_index > 0 )
  259.                     {
  260.                         osd_state_t *p_range = NULL;
  261.                         /* Find the default index for state range */
  262.                         p_range = p_up->p_states;
  263.                         while( (--i_index > 0) && p_range->p_next )
  264.                         {
  265.                             osd_state_t *p_temp = NULL;
  266.                             p_temp = p_range->p_next;
  267.                             p_range = p_temp;
  268.                         }
  269.                         p_up->p_current_state = p_range;
  270.                     }
  271.                     else p_up->p_current_state = p_up->p_states;
  272.                 }
  273.                 result = fscanf( fd, "t%24s", state );
  274.                 if( result == 0 )
  275.                     goto error;
  276.                 if( strncmp( state, "end", 3 ) != 0 )
  277.                     goto error;
  278.                 /* Continue at the beginning of the while() */
  279.                 continue;
  280.             }
  281.             /* Parse the range state */
  282.             if( strncmp( state, "range", 5 ) == 0 )
  283.             {
  284.                 osd_state_t   *p_range_current = NULL; /* range state currently processed */
  285.                 osd_state_t   *p_range_prev = NULL;    /* previous state processed range */
  286.                 int i_index = 0;
  287.                 p_current->b_range = true;
  288.                 result = fscanf( fd, "t%24s", action );
  289.                 if( result == 0 )
  290.                     goto error;
  291.                 result = fscanf( fd, "t%d", &i_index );
  292.                 if( result == 0 )
  293.                     goto error;
  294.                 msg_Dbg( p_this, " + hotkey down %s, file=%s%s", 
  295.                          action, p_menu->psz_path, file );
  296.                 free( p_current->psz_action_down );
  297.                 p_current->psz_action_down = strdup( action );
  298.                 /* Parse range contstruction :
  299.                  * range <hotkey>
  300.                  *      <state1> <file1>
  301.                  *
  302.                  *      <stateN> <fileN>
  303.                  * end
  304.                  */
  305.                 while( !feof( fd ) )
  306.                 {
  307.                     result = fscanf( fd, "t%255s", file );
  308.                     if( result == 0 )
  309.                         goto error;
  310.                     if( strncmp( file, "end", 3 ) == 0 )
  311.                         break;
  312.                     p_range_prev = p_range_current;
  313.                     if( p_menu->psz_path )
  314.                     {
  315.                         size_t i_path_size = strlen( p_menu->psz_path );
  316.                         size_t i_file_size = strlen( file );
  317.                         if( (i_path_size + i_file_size >= PATH_MAX) ||
  318.                             (i_path_size >= PATH_MAX) )
  319.                             goto error;
  320.                         strncpy( path, p_menu->psz_path, i_path_size );
  321.                         strncpy( &path[i_path_size], file,
  322.                                  PATH_MAX - (i_path_size + i_file_size) );
  323.                         path[ i_path_size + i_file_size ] = '';
  324.                         p_range_current = osd_StateNew( p_menu, path, "pressed" );
  325.                     }
  326.                     else /* absolute paths are used. */
  327.                         p_range_current = osd_StateNew( p_menu, file, "pressed" );
  328.                     if( !p_range_current )
  329.                         goto error;
  330.                     if( !p_range_current->p_pic )
  331.                     {
  332.                         osd_StatesFree( p_menu, p_range_current );
  333.                         goto error;
  334.                     }
  335.                     p_range_current->i_x = i_x;
  336.                     p_range_current->i_y = i_y;
  337.                     /* increment the number of ranges for this button */
  338.                     p_current->i_ranges++;
  339.                     if( p_range_prev )
  340.                         p_range_prev->p_next = p_range_current;
  341.                     else
  342.                         p_current->p_states = p_range_current;
  343.                     p_range_current->p_prev = p_range_prev;
  344.                     msg_Dbg( p_this, "  |- range=%d, file=%s%s",
  345.                              p_current->i_ranges,
  346.                              p_menu->psz_path, file );
  347.                 }
  348.                 if( i_index > 0 )
  349.                 {
  350.                     osd_state_t *p_range = NULL;
  351.                     /* Find the default index for state range */
  352.                     p_range = p_current->p_states;
  353.                     while( (--i_index > 0) && p_range->p_next )
  354.                     {
  355.                         osd_state_t *p_temp = NULL;
  356.                         p_temp = p_range->p_next;
  357.                         p_range = p_temp;
  358.                     }
  359.                     p_current->p_current_state = p_range;
  360.                 }
  361.                 else p_current->p_current_state = p_current->p_states;
  362.                 /* Continue at the beginning of the while() */
  363.                 continue;
  364.             }
  365.             if( strncmp( state, "end", 3 ) == 0 )
  366.                 break;
  367.             result = fscanf( fd, "t%255s", file );
  368.             if( result == 0 )
  369.                 goto error;
  370.             p_state_prev = p_state_current;
  371.             if( ( strncmp( ppsz_button_states[0], state, strlen(ppsz_button_states[0]) ) != 0 ) &&
  372.                 ( strncmp( ppsz_button_states[1], state, strlen(ppsz_button_states[1]) ) != 0 ) &&
  373.                 ( strncmp( ppsz_button_states[2], state, strlen(ppsz_button_states[2]) ) != 0 ) )
  374.             {
  375.                 msg_Err( p_this, "invalid button state %s for button %s "
  376.                          "expected %u: unselect, select or pressed)",
  377.                          state, action, (unsigned)strlen(state));
  378.                 goto error;
  379.             }
  380.             if( p_menu->psz_path )
  381.             {
  382.                 size_t i_path_size = strlen( p_menu->psz_path );
  383.                 size_t i_file_size = strlen( file );
  384.                 if( (i_path_size + i_file_size >= PATH_MAX) ||
  385.                     (i_path_size >= PATH_MAX) )
  386.                     goto error;
  387.                 strncpy( path, p_menu->psz_path, i_path_size );
  388.                 strncpy( &path[i_path_size], file,
  389.                          PATH_MAX - (i_path_size + i_file_size) );
  390.                 path[ i_path_size + i_file_size ] = '';
  391.                 p_state_current = osd_StateNew( p_menu, path, state );
  392.             }
  393.             else /* absolute paths are used. */
  394.                 p_state_current = osd_StateNew( p_menu, file, state );
  395.             if( !p_state_current )
  396.                 goto error;
  397.             if( !p_state_current->p_pic )
  398.             {
  399.                 osd_StatesFree( p_menu, p_state_current );
  400.                 goto error;
  401.             }
  402.             p_state_current->i_x = i_x;
  403.             p_state_current->i_y = i_y;
  404.             if( p_state_prev )
  405.                 p_state_prev->p_next = p_state_current;
  406.             else
  407.                 p_current->p_states = p_state_current;
  408.             p_state_current->p_prev = p_state_prev;
  409.             msg_Dbg( p_this, " |- state=%s, file=%s%s", state,
  410.                      p_menu->psz_path, file );
  411.         }
  412.         p_current->p_current_state = p_current->p_states;
  413.     }
  414.     /* Find the last button and store its pointer.
  415.      * The OSD menu behaves like a roundrobin list.
  416.      */
  417.     p_current = p_menu->p_button;
  418.     while( p_current && p_current->p_next )
  419.     {
  420.         osd_button_t *p_temp = NULL;
  421.         p_temp = p_current->p_next;
  422.         p_current = p_temp;
  423.     }
  424.     p_menu->p_last_button = p_current;
  425.     fclose( fd );
  426.     return VLC_SUCCESS;
  427. error:
  428.     msg_Err( p_menu, "parsing file failed (returned %d)", result );
  429.     if( p_menu )
  430.         osd_MenuFree( p_menu );
  431.     fclose( fd );
  432.     return VLC_EGENERIC;
  433. }