📄 vlmshell.c
字号:
/***************************************************************************** * vlm.c: VLM interface plugin ***************************************************************************** * Copyright (C) 2000-2005 the VideoLAN team * $Id: 0d8bc10e61e9a0d6301e3871ddb264adb31b8d5f $ * * Authors: Simon Latapie <garf@videolan.org> * Laurent Aimar <fenrir@videolan.org> * Gildas Bazin <gbazin@videolan.org> * * 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. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <stdio.h>#include <ctype.h> /* tolower() */#include <assert.h>#include <vlc_vlm.h>#ifdef ENABLE_VLM#ifndef WIN32# include <sys/time.h> /* gettimeofday() */#endif#ifdef HAVE_TIME_H# include <time.h> /* ctime() */# include <sys/timeb.h> /* ftime() */#endif#include <vlc_input.h>#include "input_internal.h"#include <vlc_stream.h>#include "vlm_internal.h"#include <vlc_vod.h>#include <vlc_charset.h>#include <vlc_sout.h>#include "../stream_output/stream_output.h"#include "../libvlc.h"/***************************************************************************** * Local prototypes. *****************************************************************************//* ugly kludge to avoid "null format string" warnings, * even if we handle NULL format string in vlm_MessageNew() */static const char *vlm_NULL = NULL;/* */static vlm_message_t *vlm_Show( vlm_t *, vlm_media_sys_t *, vlm_schedule_sys_t *, const char * );static vlm_schedule_sys_t *vlm_ScheduleSearch( vlm_t *, const char * );static char *Save( vlm_t * );static int Load( vlm_t *, char * );static vlm_schedule_sys_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name );static int vlm_ScheduleSetup( vlm_schedule_sys_t *schedule, const char *psz_cmd, const char *psz_value );/* */static vlm_media_sys_t *vlm_MediaSearch( vlm_t *, const char *);static const char quotes[] = "\"'";/** * FindCommandEnd: look for the end of a possibly quoted string * @return NULL on mal-formatted string, * pointer past the last character otherwise. */static const char *FindCommandEnd( const char *psz_sent ){ char c, quote = 0; while( (c = *psz_sent) != '\0' ) { if( !quote ) { if( strchr(quotes,c) ) // opening quote quote = c; else if( isspace(c) ) // non-escaped space return psz_sent; else if( c == '\\' ) { psz_sent++; // skip escaped character if( *psz_sent == '\0' ) return psz_sent; } } else { if( c == quote ) // non-escaped matching quote quote = 0; else if( (quote == '"') && (c == '\\') ) { psz_sent++; // skip escaped character if (*psz_sent == '\0') return NULL; // error, closing quote missing } } psz_sent++; } // error (NULL) if we could not find a matching quote return quote ? NULL : psz_sent;}/** * Unescape a nul-terminated string. * Note that in and out can be identical. * * @param out output buffer (at least <strlen (in) + 1> characters long) * @param in nul-terminated string to be unescaped * * @return 0 on success, -1 on error. */static int Unescape( char *out, const char *in ){ char c, quote = 0; while( (c = *in++) != '\0' ) { if( !quote ) { if (strchr(quotes,c)) // opening quote { quote = c; continue; } else if( c == '\\' ) { switch (c = *in++) { case '"': case '\'': case '\\': *out++ = c; continue; case '\0': *out = '\0'; return 0; } if( isspace(c) ) { *out++ = c; continue; } /* None of the special cases - copy the backslash */ *out++ = '\\'; } } else { if( c == quote ) // non-escaped matching quote { quote = 0; continue; } if( (quote == '"') && (c == '\\') ) { switch( c = *in++ ) { case '"': case '\\': *out++ = c; continue; case '\0': // should never happen *out = '\0'; return -1; } /* None of the special cases - copy the backslash */ *out++ = '\\'; } } *out++ = c; } *out = '\0'; return 0;}/***************************************************************************** * ExecuteCommand: The main state machine ***************************************************************************** * Execute a command which ends with '\0' (string) *****************************************************************************/static int ExecuteSyntaxError( const char *psz_cmd, vlm_message_t **pp_status ){ *pp_status = vlm_MessageNew( psz_cmd, "Wrong command syntax" ); return VLC_EGENERIC;}static bool ExecuteIsMedia( vlm_t *p_vlm, const char *psz_name ){ int64_t id; if( !psz_name || vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ) return false; return true;}static bool ExecuteIsSchedule( vlm_t *p_vlm, const char *psz_name ){ if( !psz_name || !vlm_ScheduleSearch( p_vlm, psz_name ) ) return false; return true;}static int ExecuteDel( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status ){ vlm_media_sys_t *p_media; vlm_schedule_sys_t *p_schedule; p_media = vlm_MediaSearch( p_vlm, psz_name ); p_schedule = vlm_ScheduleSearch( p_vlm, psz_name ); if( p_schedule != NULL ) { vlm_ScheduleDelete( p_vlm, p_schedule ); } else if( p_media != NULL ) { vlm_ControlInternal( p_vlm, VLM_DEL_MEDIA, p_media->cfg.id ); } else if( !strcmp(psz_name, "media") ) { vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); } else if( !strcmp(psz_name, "schedule") ) { vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES ); } else if( !strcmp(psz_name, "all") ) { vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES ); } else { *pp_status = vlm_MessageNew( "del", "%s: media unknown", psz_name ); return VLC_EGENERIC; } *pp_status = vlm_MessageNew( "del", vlm_NULL ); return VLC_SUCCESS;}static int ExecuteShow( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status ){ vlm_media_sys_t *p_media; vlm_schedule_sys_t *p_schedule; if( !psz_name ) { *pp_status = vlm_Show( p_vlm, NULL, NULL, NULL ); return VLC_SUCCESS; } p_media = vlm_MediaSearch( p_vlm, psz_name ); p_schedule = vlm_ScheduleSearch( p_vlm, psz_name ); if( p_schedule != NULL ) *pp_status = vlm_Show( p_vlm, NULL, p_schedule, NULL ); else if( p_media != NULL ) *pp_status = vlm_Show( p_vlm, p_media, NULL, NULL ); else *pp_status = vlm_Show( p_vlm, NULL, NULL, psz_name ); return VLC_SUCCESS;}static int ExecuteHelp( vlm_message_t **pp_status ){ vlm_message_t *message_child;#define MessageAdd( a ) \ vlm_MessageAdd( *pp_status, vlm_MessageNew( a, vlm_NULL ) );#define MessageAddChild( a ) \ vlm_MessageAdd( message_child, vlm_MessageNew( a, vlm_NULL ) ); *pp_status = vlm_MessageNew( "help", vlm_NULL ); message_child = MessageAdd( "Commands Syntax:" ); MessageAddChild( "new (name) vod|broadcast|schedule [properties]" ); MessageAddChild( "setup (name) (properties)" ); MessageAddChild( "show [(name)|media|schedule]" ); MessageAddChild( "del (name)|all|media|schedule" ); MessageAddChild( "control (name) [instance_name] (command)" ); MessageAddChild( "save (config_file)" ); MessageAddChild( "export" ); MessageAddChild( "load (config_file)" ); message_child = MessageAdd( "Media Proprieties Syntax:" ); MessageAddChild( "input (input_name)" ); MessageAddChild( "inputdel (input_name)|all" ); MessageAddChild( "inputdeln input_number" ); MessageAddChild( "output (output_name)" ); MessageAddChild( "option (option_name)[=value]" ); MessageAddChild( "enabled|disabled" ); MessageAddChild( "loop|unloop (broadcast only)" ); MessageAddChild( "mux (mux_name)" ); message_child = MessageAdd( "Schedule Proprieties Syntax:" ); MessageAddChild( "enabled|disabled" ); MessageAddChild( "append (command_until_rest_of_the_line)" ); MessageAddChild( "date (year)/(month)/(day)-(hour):(minutes):" "(seconds)|now" ); MessageAddChild( "period (years_aka_12_months)/(months_aka_30_days)/" "(days)-(hours):(minutes):(seconds)" ); MessageAddChild( "repeat (number_of_repetitions)" ); message_child = MessageAdd( "Control Commands Syntax:" ); MessageAddChild( "play [input_number]" ); MessageAddChild( "pause" ); MessageAddChild( "stop" ); MessageAddChild( "seek [+-](percentage) | [+-](seconds)s | [+-](miliseconds)ms" ); return VLC_SUCCESS;}static int ExecuteControl( vlm_t *p_vlm, const char *psz_name, const int i_arg, char ** ppsz_arg, vlm_message_t **pp_status ){ vlm_media_sys_t *p_media; const char *psz_control = NULL; const char *psz_instance = NULL; const char *psz_argument = NULL; int i_index; int i_result; if( !ExecuteIsMedia( p_vlm, psz_name ) ) { *pp_status = vlm_MessageNew( "control", "%s: media unknown", psz_name ); return VLC_EGENERIC; } assert( i_arg > 0 );#define IS(txt) ( !strcmp( ppsz_arg[i_index], (txt) ) ) i_index = 0; if( !IS("play") && !IS("stop") && !IS("pause") && !IS("seek") ) { i_index = 1; psz_instance = ppsz_arg[0]; if( i_index >= i_arg || ( !IS("play") && !IS("stop") && !IS("pause") && !IS("seek") ) ) return ExecuteSyntaxError( "control", pp_status ); }#undef IS psz_control = ppsz_arg[i_index]; if( i_index+1 < i_arg ) psz_argument = ppsz_arg[i_index+1]; p_media = vlm_MediaSearch( p_vlm, psz_name ); assert( p_media ); if( !strcmp( psz_control, "play" ) ) { int i_input_index = 0; int i; if( ( psz_argument && sscanf(psz_argument, "%d", &i) == 1 ) && i > 0 && i-1 < p_media->cfg.i_input ) { i_input_index = i-1; } else if( psz_argument ) { int j; vlm_media_t *p_cfg = &p_media->cfg; for ( j=0; j < p_cfg->i_input; j++) { if( !strcmp( p_cfg->ppsz_input[j], psz_argument ) ) { i_input_index = j; break; } } } if( p_media->cfg.b_vod ) i_result = vlm_ControlInternal( p_vlm, VLM_START_MEDIA_VOD_INSTANCE, p_media->cfg.id, psz_instance, i_input_index, NULL ); // we should get here now else i_result = vlm_ControlInternal( p_vlm, VLM_START_MEDIA_BROADCAST_INSTANCE, p_media->cfg.id, psz_instance, i_input_index ); } else if( !strcmp( psz_control, "seek" ) ) { if( psz_argument ) { bool b_relative; if( psz_argument[0] == '+' || psz_argument[0] == '-' ) b_relative = true; else b_relative = false; if( strstr( psz_argument, "ms" ) || strstr( psz_argument, "s" ) ) { /* Time (ms or s) */ int64_t i_new_time; if( strstr( psz_argument, "ms" ) ) i_new_time = 1000 * (int64_t)atoi( psz_argument ); else i_new_time = 1000000 * (int64_t)atoi( psz_argument ); if( b_relative ) { int64_t i_time = 0; vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_TIME, p_media->cfg.id, psz_instance, &i_time ); i_new_time += i_time; } if( i_new_time < 0 ) i_new_time = 0; i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_TIME, p_media->cfg.id, psz_instance, i_new_time ); } else { /* Percent */ double d_new_position = us_atof( psz_argument ) / 100.0; if( b_relative ) { double d_position = 0.0; vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, &d_position ); d_new_position += d_position; } if( d_new_position < 0.0 ) d_new_position = 0.0; else if( d_new_position > 1.0 ) d_new_position = 1.0; i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, d_new_position );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -