📄 vlm.c
字号:
/***************************************************************************** * vlm.c: VLM interface plugin ***************************************************************************** * Copyright (C) 2000-2005 the VideoLAN team * $Id: vlm.c 18284 2006-12-06 09:59:39Z md $ * * 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 *****************************************************************************/#include <stdlib.h> /* malloc(), free() */#include <ctype.h> /* tolower() */#include <vlc/vlc.h>#ifdef ENABLE_VLM#include <vlc/intf.h>#include <vlc/input.h>#ifdef HAVE_TIME_H# include <time.h> /* ctime() */# include <sys/timeb.h> /* ftime() */#endif#include <vlc_vlm.h>#include <vlc_vod.h>#include <charset.h>#define FREE( p ) \ if( p ) { free( p ); (p) = NULL; }/***************************************************************************** * Local prototypes. *****************************************************************************/static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, const char * );static vlm_message_t *vlm_Help( vlm_t *, char * );static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, const char * );static vlm_message_t *vlm_MessageNew( const char *, const char *, ... );static vlm_message_t *vlm_MessageAdd( vlm_message_t *, vlm_message_t * );static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, const char * );static char *Save( vlm_t * );static int Load( vlm_t *, char * );static int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** );static int Manage( vlc_object_t * );/***************************************************************************** * vlm_New: *****************************************************************************/vlm_t *__vlm_New ( vlc_object_t *p_this ){ vlc_value_t lockval; vlm_t *p_vlm = NULL; char *psz_vlmconf; /* to be sure to avoid multiple creation */ var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX ); var_Get( p_this->p_libvlc, "vlm_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); if( !(p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) ) { msg_Info( p_this, "creating VLM" ); if( ( p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL ) { vlc_mutex_unlock( lockval.p_address ); return NULL; } vlc_mutex_init( p_this->p_vlc, &p_vlm->lock ); p_vlm->i_media = 0; p_vlm->media = NULL; p_vlm->i_vod = 0; p_vlm->i_schedule = 0; p_vlm->schedule = NULL; vlc_object_yield( p_vlm ); vlc_object_attach( p_vlm, p_this->p_vlc ); } vlc_mutex_unlock( lockval.p_address ); if( vlc_thread_create( p_vlm, "vlm thread", Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { vlc_mutex_destroy( &p_vlm->lock ); vlc_object_destroy( p_vlm ); return NULL; } /* Try loading the vlm conf file given by --vlm-conf */ psz_vlmconf = config_GetPsz( p_vlm, "vlm-conf" ); if( psz_vlmconf && *psz_vlmconf ) { vlm_message_t *p_message = NULL; char *psz_buffer = NULL; msg_Dbg( p_this, "loading VLM configuration" ); asprintf(&psz_buffer, "load %s", psz_vlmconf ); if( psz_buffer ) { msg_Dbg( p_this, psz_buffer); if( vlm_ExecuteCommand( p_vlm, psz_buffer, &p_message ) ){ msg_Warn( p_this, "error while loading the configuration file" ); } vlm_MessageDelete(p_message); free(psz_buffer); } } free(psz_vlmconf); return p_vlm;}/***************************************************************************** * vlm_Delete: *****************************************************************************/void vlm_Delete( vlm_t *p_vlm ){ vlc_value_t lockval; var_Get( p_vlm->p_libvlc, "vlm_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); vlc_object_release( p_vlm ); if( p_vlm->i_refcount > 0 ) { vlc_mutex_unlock( lockval.p_address ); return; } p_vlm->b_die = VLC_TRUE; vlc_thread_join( p_vlm ); vlc_mutex_destroy( &p_vlm->lock ); while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL ); FREE( p_vlm->media ); while( p_vlm->i_schedule ) vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL ); FREE( p_vlm->schedule ); vlc_object_detach( p_vlm ); vlc_object_destroy( p_vlm ); vlc_mutex_unlock( lockval.p_address );}/***************************************************************************** * vlm_ExecuteCommand: *****************************************************************************/int vlm_ExecuteCommand( vlm_t *p_vlm, const char *psz_command, vlm_message_t **pp_message){ int i_result; vlc_mutex_lock( &p_vlm->lock ); i_result = ExecuteCommand( p_vlm, psz_command, pp_message ); vlc_mutex_unlock( &p_vlm->lock ); return i_result;}/***************************************************************************** * vlm_Save: *****************************************************************************/int vlm_Save( vlm_t *p_vlm, const char *psz_file ){ FILE *file; char *psz_save; if( !p_vlm || !psz_file ) return 1; file = utf8_fopen( psz_file, "wt" ); if( file == NULL ) return 1; psz_save = Save( p_vlm ); if( psz_save == NULL ) { fclose( file ); return 1; } fwrite( psz_save, strlen( psz_save ), 1, file ); fclose( file ); free( psz_save ); return 0;}/***************************************************************************** * vlm_Load: *****************************************************************************/int vlm_Load( vlm_t *p_vlm, const char *psz_file ){ stream_t *p_stream; int64_t i_size; char *psz_buffer; if( !p_vlm || !psz_file ) return 1; p_stream = stream_UrlNew( p_vlm, psz_file ); if( p_stream == NULL ) return 1; if( stream_Seek( p_stream, 0 ) != 0 ) { stream_Delete( p_stream ); return 2; } i_size = stream_Size( p_stream ); psz_buffer = malloc( i_size + 1 ); if( !psz_buffer ) { stream_Delete( p_stream ); return 2; } stream_Read( p_stream, psz_buffer, i_size ); psz_buffer[ i_size ] = '\0'; stream_Delete( p_stream ); if( Load( p_vlm, psz_buffer ) ) { free( psz_buffer ); return 3; } free( psz_buffer ); return 0;}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 ExecuteCommand( vlm_t *p_vlm, const char *psz_command, vlm_message_t **pp_message ){ int i_command = 0; char **ppsz_command = NULL; const char *psz_cmd = psz_command; vlm_message_t *p_message = NULL; int i, j; /* First, parse the line and cut it */ while( *psz_cmd != '\0' ) { if( isspace(*psz_cmd) ) { psz_cmd++; } else { const char *psz_temp; /* support for comments */ if( i_command == 0 && *psz_cmd == '#') { p_message = vlm_MessageNew( "", NULL ); goto success; } psz_temp = FindCommandEnd( psz_cmd ); if( psz_temp == NULL ) { p_message = vlm_MessageNew( "Incomplete command", psz_cmd ); goto error; } ppsz_command = realloc( ppsz_command, (i_command + 1) * sizeof(char*) ); ppsz_command[i_command] = strndup (psz_cmd, psz_temp - psz_cmd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -