-/*******************************************************************************
+/*****************************************************************************
* intf_cmd.c: interface commands parsing and executions functions
- * (c)1998 VideoLAN
- *******************************************************************************
* This file implements the interface commands execution functions. It is used
* by command-line oriented interfaces and scripts. The commands themselves are
* implemented in intf_ctrl.
- *******************************************************************************/
-
-/*******************************************************************************
+ *****************************************************************************
+ * Copyright (C) 1998, 1999, 2000 VideoLAN
+ *
+ * Authors:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
* Preamble
- *******************************************************************************/
-#include <errno.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/soundcard.h>
-#include <sys/uio.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/XShm.h>
+ *****************************************************************************/
+#include <errno.h> /* errno */
+#include <stdio.h> /* FILE */
+#include <stdlib.h> /* strtod(), strtol() */
+#include <string.h> /* strerror() */
#include "config.h"
#include "common.h"
#include "mtime.h"
-#include "vlc_thread.h"
-
-#include "input.h"
-#include "input_vlan.h"
-
-#include "audio_output.h"
+#include "threads.h"
-#include "video.h"
-#include "video_output.h"
-
-#include "xconsole.h"
#include "interface.h"
#include "intf_msg.h"
#include "intf_cmd.h"
#include "intf_ctrl.h"
-
-#include "pgm_data.h"
+#include "main.h"
/*
* Local prototypes
*/
static int ParseCommandArguments ( char *psz_argv[INTF_MAX_ARGS], char *psz_cmd );
-static int CheckCommandArguments ( intf_arg_t argv[INTF_MAX_ARGS], int i_argc,
+static int CheckCommandArguments ( intf_arg_t argv[INTF_MAX_ARGS], int i_argc,
char *psz_argv[INTF_MAX_ARGS], char *psz_format );
static void ParseFormatString ( intf_arg_t format[INTF_MAX_ARGS], char *psz_format );
static int ConvertArgument ( intf_arg_t *p_arg, int i_flags, char *psz_str );
-/*******************************************************************************
- * intf_ExecCommand: parse and execute a command
- *******************************************************************************
+/*****************************************************************************
+ * intf_ExecCommand: parse and execute a command
+ *****************************************************************************
* This function is called when a command needs to be executed. It parse the
* command line, build an argument array, find the command in control commands
* array and run the command. It returns the return value of the command, or
- * EINVAL if no command could be executed. Command line is modified by this
+ * EINVAL if no command could be executed. Command line is modified by this
* function.
* Note that this function may terminate abruptly the program or signify it's
* end to the interface thread.
- *******************************************************************************/
+ *****************************************************************************/
int intf_ExecCommand( char *psz_cmd )
{
- char * psz_argv[INTF_MAX_ARGS]; /* arguments pointers */
- intf_arg_t argv[INTF_MAX_ARGS]; /* converted arguments */
- int i_argc; /* number of arguments */
- int i_index; /* multi-purposes index */
- int i_return; /* command return value */
+ char * psz_argv[INTF_MAX_ARGS]; /* arguments pointers */
+ intf_arg_t argv[INTF_MAX_ARGS]; /* converted arguments */
+ int i_argc; /* number of arguments */
+ int i_index; /* multi-purposes index */
+ int i_return; /* command return value */
- intf_DbgMsg("intf debug: command `%s'\n", psz_cmd);
+ intf_DbgMsg("command `%s'\n", psz_cmd);
- /* Parse command line (separate arguments). If nothing has been found,
+ /* Parse command line (separate arguments). If nothing has been found,
* the function returns without error */
i_argc = ParseCommandArguments( psz_argv, psz_cmd );
if( !i_argc )
}
/* Find command. Command is always the first token on the line */
- for( i_index = 0;
- control_command[i_index].psz_name && strcmp( psz_argv[0], control_command[i_index].psz_name );
+ for( i_index = 0;
+ control_command[i_index].psz_name && strcmp( psz_argv[0], control_command[i_index].psz_name );
i_index++ )
{
;
}
- if( !control_command[i_index].psz_name ) /* unknown command */
+ if( !control_command[i_index].psz_name ) /* unknown command */
{
/* Print error message */
intf_IntfMsg( "error: unknown command `%s'. Try `help'", psz_argv[0] );
/* Check arguments validity */
if( CheckCommandArguments( argv, i_argc, psz_argv, control_command[i_index].psz_format ) )
{
- /* The given arguments does not match the format string. An error message has
+ /* The given arguments does not match the format string. An error message has
* already been displayed, so only the usage string is printed */
intf_IntfMsg( "usage: %s", control_command[i_index].psz_usage );
return( INTF_USAGE_ERROR );
}
- /* Execute command */
+ /* Execute command */
i_return = control_command[i_index].function( i_argc, argv );
/* Manage special error codes */
switch( i_return )
{
- case INTF_FATAL_ERROR: /* fatal error */
+ case INTF_FATAL_ERROR: /* fatal error */
/* Print message and terminates the interface thread */
- intf_ErrMsg( "intf fatal: in command `%s'\n", psz_argv[0] );
- p_program_data->intf_thread.b_die = 1;
+ intf_ErrMsg( "fatal error in command `%s'\n", psz_argv[0] );
+ p_main->p_intf->b_die = 1;
break;
- case INTF_CRITICAL_ERROR: /* critical error */
+ case INTF_CRITICAL_ERROR: /* critical error */
/* Print message, flush messages queue and exit. Note that this
* error should be very rare since it does not even try to cancel other
* threads... */
- intf_ErrMsg("intf critical: in command `%s'. Please report this error !\n", psz_argv[0] );
+ intf_ErrMsg("critical error in command `%s'. Please report this error !\n", psz_argv[0] );
intf_FlushMsg();
exit( INTF_CRITICAL_ERROR );
break;
- case INTF_USAGE_ERROR: /* usage error */
+ case INTF_USAGE_ERROR: /* usage error */
/* Print error message and usage */
intf_IntfMsg( "usage: %s", control_command[i_index].psz_usage );
break;
return( i_return );
}
-/*******************************************************************************
+/*****************************************************************************
* intf_ExecScript: parse and execute a command script
- *******************************************************************************
+ *****************************************************************************
* This function, based on ExecCommand read a file and tries to execute each
* of its line as a command. It returns 0 if everything succeeded, a negative
* number if the script could not be executed and a positive one if an error
* occured during execution.
- *******************************************************************************/
+ *****************************************************************************/
int intf_ExecScript( char *psz_filename )
{
- FILE * p_file; /* file */
- char psz_line[INTF_MAX_CMD_SIZE]; /* line */
- char * psz_index; /* index in string */
- int i_err; /* error indicator */
-
+ FILE * p_file; /* file */
+ char psz_line[INTF_MAX_CMD_SIZE]; /* line */
+ char * psz_index; /* index in string */
+ int i_err; /* error indicator */
+
/* Open file */
- i_err = 0;
+ i_err = 0;
p_file = fopen( psz_filename, "r" );
if( p_file == NULL )
{
- intf_ErrMsg("intf error: %s: %s\n", psz_filename, strerror(errno));
- return( -1 );
+ intf_ErrMsg("warning: %s: %s\n", psz_filename, strerror(errno));
+ return( -1 );
}
-
- /* For each line: read and execute */
+
+ /* For each line: read and execute */
while( fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL )
{
/* If line begins with a '#', it is a comment and shoule be ignored,
* else, execute it */
if( psz_line[0] != '#' )
- {
+ {
/* The final '\n' needs to be removed before execution */
for( psz_index = psz_line; *psz_index && (*psz_index != '\n'); psz_index++ )
- {
- ;
+ {
+ ;
}
if( *psz_index == '\n' )
{
- *psz_index = '\0';
- }
+ *psz_index = '\0';
+ }
/* Execute command */
- i_err |= intf_ExecCommand( psz_line );
- }
+ i_err |= intf_ExecCommand( psz_line );
+ }
}
if( !feof( p_file ) )
{
- intf_ErrMsg("intf error: %s: %s\n", psz_filename, strerror(errno));
- return( -1 );
+ intf_ErrMsg("error: %s: %s\n", psz_filename, strerror(errno));
+ return( -1 );
}
-
+
/* Close file */
fclose( p_file );
return( i_err != 0 );
/* following functions are local */
-/*******************************************************************************
+/*****************************************************************************
* ParseCommandArguments: isolate arguments in a command line
- *******************************************************************************
+ *****************************************************************************
* This function modify the original command line, adding '\0' and completes
* an array of pointers to beginning of arguments. It return the number of
* arguments.
- *******************************************************************************/
+ *****************************************************************************/
static int ParseCommandArguments( char *psz_argv[INTF_MAX_ARGS], char *psz_cmd )
{
- int i_argc; /* number of arguments */
- char * psz_index; /* index */
- boolean_t b_block; /* block (argument) indicator */
+ int i_argc; /* number of arguments */
+ char * psz_index; /* index */
+ boolean_t b_block; /* block (argument) indicator */
/* Initialize parser state */
- b_block = 0; /* we start outside a block to remove spaces at beginning */
+ b_block = 0; /* we start outside a block to remove spaces at beginning */
i_argc = 0;
/* Go through command until end has been reached or maximal number of
{
if( *psz_index == ' ' )
{
- *psz_index = '\0'; /* mark the end of argument */
- b_block = 0; /* exit the block */
+ *psz_index = '\0'; /* mark the end of argument */
+ b_block = 0; /* exit the block */
}
-
+
}
/* Outside a block, beginning of blocks are marked by any character
* different from space */
{
if( *psz_index != ' ' )
{
- psz_argv[i_argc++] = psz_index; /* store argument */
- b_block = 1; /* enter the block */
+ psz_argv[i_argc++] = psz_index; /* store argument */
+ b_block = 1; /* enter the block */
}
}
}
return( i_argc );
}
-/*******************************************************************************
+/*****************************************************************************
* CheckCommandArguments: check arguments agains format
- *******************************************************************************
+ *****************************************************************************
* This function parse each argument and tries to find a match in the format
* string. It fills the argv array.
* If all arguments have been sucessfuly identified and converted, it returns
* 0, else, an error message is issued and non 0 is returned.
* Note that no memory is allocated by this function, but that the arguments
* can be modified.
- *******************************************************************************/
-static int CheckCommandArguments( intf_arg_t argv[INTF_MAX_ARGS], int i_argc,
+ *****************************************************************************/
+static int CheckCommandArguments( intf_arg_t argv[INTF_MAX_ARGS], int i_argc,
char *psz_argv[INTF_MAX_ARGS], char *psz_format )
{
- intf_arg_t format[INTF_MAX_ARGS]; /* parsed format indicators */
- int i_arg; /* argument index */
- int i_format; /* format index */
- char * psz_index; /* string index */
- char * psz_cmp_index; /* string comparaison index */
- int i_index; /* generic index */
- boolean_t b_found; /* `argument found' flag */
+ intf_arg_t format[INTF_MAX_ARGS]; /* parsed format indicators */
+ int i_arg; /* argument index */
+ int i_format; /* format index */
+ char * psz_index; /* string index */
+ char * psz_cmp_index; /* string comparaison index */
+ int i_index; /* generic index */
+ boolean_t b_found; /* `argument found' flag */
/* Build format array */
ParseFormatString( format, psz_format );
/* Initialize parser: i_format must be the first non named formatter */
- for( i_format = 0; ( i_format < INTF_MAX_ARGS )
+ for( i_format = 0; ( i_format < INTF_MAX_ARGS )
&& (format[i_format].i_flags & INTF_NAMED_ARG);
i_format++ )
{
/* Test if argument can be taken as a named argument: try to find a
* '=' in the string */
- for( psz_index = psz_argv[i_arg]; *psz_index && ( *psz_index != '=' ); psz_index++ )
+ for( psz_index = psz_argv[i_arg]; *psz_index && ( *psz_index != '=' ); psz_index++ )
{
;
}
- if( *psz_index == '=' ) /* '=' found */
+ if( *psz_index == '=' ) /* '=' found */
{
/* Browse all named arguments to check if there is one matching */
- for( i_index = 0; (i_index < INTF_MAX_ARGS)
+ for( i_index = 0; (i_index < INTF_MAX_ARGS)
&& ( format[i_index].i_flags & INTF_NAMED_ARG )
&& !b_found;
i_index++ )
{
- /* Current format string is named... compare start of two
+ /* Current format string is named... compare start of two
* names. A local inline ntation of a strcmp is used since
* string isn't ended by '\0' but by '=' */
- for( psz_index = psz_argv[i_arg], psz_cmp_index = format[i_index].ps_name;
+ for( psz_index = psz_argv[i_arg], psz_cmp_index = format[i_index].ps_name;
(*psz_index == *psz_cmp_index) && (*psz_index != '=') && (*psz_cmp_index != '=');
psz_index++, psz_cmp_index++ )
{
;
}
- if( *psz_index == *psz_cmp_index ) /* the names match */
+ if( *psz_index == *psz_cmp_index ) /* the names match */
{
/* The argument is a named argument which name match the
* named argument i_index. To be valid, the argument should
- * not have been already encountered and the type must
+ * not have been already encountered and the type must
* match. Before going further, the '=' is replaced by
* a '\0'. */
*psz_index = '\0';
format[i_index].i_flags |= INTF_PRESENT_ARG;
argv[i_arg].i_flags = INTF_NAMED_ARG;
argv[i_arg].i_index = i_index;
- argv[i_arg].ps_name = psz_argv[i_arg];
+ argv[i_arg].ps_name = psz_argv[i_arg];
/* Check type and store value */
psz_index++;
}
}
}
- }
+ }
/* If argument is not a named argument, the format string will
* be browsed starting from last position until the argument is
/* If argument is not a named argument, the format string will
* be browsed starting from last position until the argument is
- * found, an error occurs or the last format argument is
+ * found, an error occurs or the last format argument is
* reached */
while( !b_found && (i_format < INTF_MAX_ARGS) && format[i_format].i_flags )
{
/* Try to convert argument */
- if( !ConvertArgument( &argv[i_arg], format[i_format].i_flags, psz_argv[i_arg] ) )
+ if( !ConvertArgument( &argv[i_arg], format[i_format].i_flags, psz_argv[i_arg] ) )
{
/* Matching format has been found */
b_found = 1;
else
{
/* Argument does not match format. This can be an error, or
- * just a missing optionnal parameter, or the end of a
- * repeated argument */
- if( (format[i_format].i_flags & INTF_OPT_ARG)
+ * just a missing optionnal parameter, or the end of a
+ * repeated argument */
+ if( (format[i_format].i_flags & INTF_OPT_ARG)
|| (format[i_format].i_flags & INTF_PRESENT_ARG) )
{
/* This is not an error */
return( 1 );
}
- intf_DbgMsg("intf debug: argument flags=0x%x (index=%d) name=%s str=%s int=%d float=%f\n",
+ intf_DbgMsg("argument flags=0x%x (index=%d) name=%s str=%s int=%d float=%f\n",
argv[i_arg].i_flags,
argv[i_arg].i_index,
(argv[i_arg].i_flags & INTF_NAMED_ARG) ? argv[i_arg].ps_name : "NA",
return( 1 );
}
}
-
+
/* If an error occured, the function already exited, so if this point is
* reached, everything is fine */
return( 0 );
}
-/*******************************************************************************
+/*****************************************************************************
* ConvertArgument: try to convert an argument to a given type
- *******************************************************************************
+ *****************************************************************************
* This function tries to convert the string argument given in psz_str to
* a type specified in i_flags. It updates p_arg and returns O on success,
* or 1 on error. No error message is issued.
- *******************************************************************************/
+ *****************************************************************************/
static int ConvertArgument( intf_arg_t *p_arg, int i_flags, char *psz_str )
{
- char *psz_end; /* end pointer for conversion functions */
+ char *psz_end; /* end pointer for conversion functions */
- if( i_flags & INTF_STR_ARG ) /* string */
+ if( i_flags & INTF_STR_ARG ) /* string */
{
/* A conversion from a string to a string will always succeed... */
p_arg->psz_str = psz_str;
p_arg->i_flags |= INTF_STR_ARG;
}
- else if( i_flags & INTF_INT_ARG ) /* integer */
- {
- p_arg->i_num = strtol( psz_str, &psz_end, 0 ); /* convert string */
+ else if( i_flags & INTF_INT_ARG ) /* integer */
+ {
+ p_arg->i_num = strtol( psz_str, &psz_end, 0 ); /* convert string */
/* If the conversion failed, return 1 and do not modify argument
* flags. Else, add 'int' flag and continue. */
if( !*psz_str || *psz_end )
}
p_arg->i_flags |= INTF_INT_ARG;
}
- else if( i_flags & INTF_FLOAT_ARG ) /* float */
+ else if( i_flags & INTF_FLOAT_ARG ) /* float */
{
- p_arg->f_num = strtod( psz_str, &psz_end ); /* convert string */
+ p_arg->f_num = strtod( psz_str, &psz_end ); /* convert string */
/* If the conversion failed, return 1 and do not modify argument
* flags. Else, add 'float' flag and continue. */
if( !*psz_str || *psz_end )
p_arg->i_flags |= INTF_FLOAT_ARG;
}
#ifdef DEBUG
- else /* error: missing type specifier */
+ else /* error: missing type specifier */
{
- intf_ErrMsg("intf error: missing type specifier for `%s' (0x%x)\n", psz_str, i_flags);
+ intf_ErrMsg("error: missing type specifier for `%s' (0x%x)\n", psz_str, i_flags);
return( 1 );
}
#endif
return( 0 );
}
-/*******************************************************************************
+/*****************************************************************************
* ParseFormatString: parse a format string (ok ?)
- *******************************************************************************
+ *****************************************************************************
* This function read a format string, as specified in the control_command
* array, and fill a format array, to allow easier argument identification.
* Note that no memory is allocated by this function, but that, in a named
* Note that this function is designed to be efficient, not to check everything
* in a format string, which should be entered by a developper and therefore
* should be correct (TRUST !).
- *******************************************************************************/
+ *****************************************************************************/
static void ParseFormatString( intf_arg_t format[INTF_MAX_ARGS], char *psz_format )
{
- char * psz_index; /* format string index */
- char * psz_start; /* argument format start */
- char * psz_item; /* item index */
- int i_index; /* format index */
+ char * psz_index; /* format string index */
+ char * psz_start; /* argument format start */
+ char * psz_item; /* item index */
+ int i_index; /* format index */
/* Initialize parser */
i_index = 0;
- psz_start = psz_format;
+ psz_start = psz_format;
/* Reset first format indicator */
format[ 0 ].i_flags = 0;
{
/* A space is always an item terminator */
if( *psz_index == ' ' )
- {
+ {
/* Parse format item. Items are parsed from end to beginning or to
* first '=' */
- for( psz_item = psz_index - 1;
- (psz_item >= psz_start) && !( format[i_index].i_flags & INTF_NAMED_ARG);
+ for( psz_item = psz_index - 1;
+ (psz_item >= psz_start) && !( format[i_index].i_flags & INTF_NAMED_ARG);
psz_item-- )
{
switch( *psz_item )
{
- case 's': /* string */
+ case 's': /* string */
format[i_index].i_flags |= INTF_STR_ARG;
break;
- case 'i': /* integer */
+ case 'i': /* integer */
format[i_index].i_flags |= INTF_INT_ARG;
break;
- case 'f': /* float */
+ case 'f': /* float */
format[i_index].i_flags |= INTF_FLOAT_ARG;
break;
- case '*': /* can be repeated */
+ case '*': /* can be repeated */
format[i_index].i_flags |= INTF_REP_ARG;
break;
- case '?': /* optionnal argument */
+ case '?': /* optionnal argument */
format[i_index].i_flags |= INTF_OPT_ARG;
break;
- case '=': /* name argument */
+ case '=': /* name argument */
format[i_index].i_flags |= INTF_NAMED_ARG;
- format[i_index].ps_name = psz_start;
+ format[i_index].ps_name = psz_start;
break;
#ifdef DEBUG
- default: /* error which should never happen: incorrect format */
- intf_DbgMsg("intf error: incorrect format string `%s'\n", psz_format);
+ default:/* error which should never happen: incorrect format */
+ intf_DbgMsg("error: incorrect format string `%s'\n", psz_format);
break;
#endif
}
}
- /* Mark next item start, increase items counter and reset next
+ /* Mark next item start, increase items counter and reset next
* format indicator, if it wasn't the last one. */
i_index++;
- psz_start = psz_index + 1;
- if( i_index != INTF_MAX_ARGS ) /* end of array not reached */
+ psz_start = psz_index + 1;
+ if( i_index != INTF_MAX_ARGS ) /* end of array not reached */
{
format[ i_index ].i_flags = 0;
}