📄 vlm.c
字号:
/***************************************************************************** * vlm.c: VLM interface plugin ***************************************************************************** * Copyright (C) 2000-2005 the VideoLAN team * $Id: 4a92e60baa6b967ac9a94e2ca71fcda5db430226 $ * * 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>#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. *****************************************************************************/static void vlm_Destructor( vlm_t *p_vlm );static void* Manage( vlc_object_t * );static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list );/***************************************************************************** * vlm_New: *****************************************************************************/vlm_t *__vlm_New ( vlc_object_t *p_this ){ vlc_value_t lockval; vlm_t *p_vlm = NULL, **pp_vlm = &(libvlc_priv (p_this->p_libvlc)->p_vlm); char *psz_vlmconf; static const char vlm_object_name[] = "vlm daemon"; /* Avoid multiple creation */ if( var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX ) || var_Get( p_this->p_libvlc, "vlm_mutex", &lockval ) ) return NULL; vlc_mutex_lock( lockval.p_address ); p_vlm = *pp_vlm; if( p_vlm ) { /* VLM already exists */ vlc_object_yield( p_vlm ); vlc_mutex_unlock( lockval.p_address ); return p_vlm; } msg_Dbg( p_this, "creating VLM" ); p_vlm = vlc_custom_create( p_this, sizeof( *p_vlm ), VLC_OBJECT_GENERIC, vlm_object_name ); if( !p_vlm ) { vlc_mutex_unlock( lockval.p_address ); return NULL; } vlc_mutex_init( &p_vlm->lock ); p_vlm->i_id = 1; TAB_INIT( p_vlm->i_media, p_vlm->media ); TAB_INIT( p_vlm->i_schedule, p_vlm->schedule ); p_vlm->i_vod = 0; p_vlm->p_vod = NULL; vlc_object_attach( p_vlm, p_this->p_libvlc ); if( vlc_thread_create( p_vlm, "vlm thread", Manage, VLC_THREAD_PRIORITY_LOW, false ) ) { vlc_mutex_destroy( &p_vlm->lock ); vlc_object_release( p_vlm ); return NULL; } /* Load our configuration file */ psz_vlmconf = var_CreateGetString( 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" ); if( asprintf(&psz_buffer, "load %s", psz_vlmconf ) != -1 ) { msg_Dbg( p_this, "%s", 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 ); vlc_object_set_destructor( p_vlm, (vlc_destructor_t)vlm_Destructor ); *pp_vlm = p_vlm; /* for future reference */ vlc_mutex_unlock( lockval.p_address ); return p_vlm;}/***************************************************************************** * vlm_Delete: *****************************************************************************/void vlm_Delete( vlm_t *p_vlm ){ vlc_value_t lockval; /* vlm_Delete() is serialized against itself, and against vlm_New(). * This way, vlm_Destructor () (called from vlc_objet_release() above) * is serialized against setting libvlc_priv->p_vlm from vlm_New(). */ var_Get( p_vlm->p_libvlc, "vlm_mutex", &lockval ); vlc_mutex_lock( lockval.p_address ); /* Parental advisory: terrific humongous horrible follows... * This is so that vlc_object_destroy() (from vlc_object_release()) will * NOT join our thread. See also vlm_Destructor(). * -- Courmisch, 24/08/2008 */ vlc_internals( p_vlm )->b_thread = false; vlc_object_release( p_vlm ); vlc_mutex_unlock( lockval.p_address );}/***************************************************************************** * vlm_Destructor: *****************************************************************************/static void vlm_Destructor( vlm_t *p_vlm ){ libvlc_priv (p_vlm->p_libvlc)->p_vlm = NULL; vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); TAB_CLEAN( p_vlm->i_media, p_vlm->media ); vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES ); TAB_CLEAN( p_vlm->schedule, p_vlm->schedule ); vlc_object_kill( p_vlm ); /* Continuation of the vlm_Delete() hack. -- Courmisch */ vlc_internals( p_vlm )->b_thread = true; vlc_thread_join( p_vlm ); vlc_mutex_destroy( &p_vlm->lock );}/***************************************************************************** * 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;}int64_t vlm_Date(void){#ifdef WIN32 struct timeb tm; ftime( &tm ); return ((int64_t)tm.time) * 1000000 + ((int64_t)tm.millitm) * 1000;#else struct timeval tv_date; /* gettimeofday() cannot fail given &tv_date is a valid address */ (void)gettimeofday( &tv_date, NULL ); return (mtime_t) tv_date.tv_sec * 1000000 + (mtime_t) tv_date.tv_usec;#endif}/***************************************************************************** * *****************************************************************************/static int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media, const char *psz_id, int i_query, va_list args ){ vlm_t *vlm = (vlm_t *)p_private; int i, i_ret; const char *psz; int64_t id; if( !p_private || !p_vod_media ) return VLC_EGENERIC; vlc_mutex_lock( &vlm->lock ); /* Find media id */ for( i = 0, id = -1; i < vlm->i_media; i++ ) { if( p_vod_media == vlm->media[i]->vod.p_media ) { id = vlm->media[i]->cfg.id; break; } } if( id == -1 ) { vlc_mutex_unlock( &vlm->lock ); return VLC_EGENERIC; } switch( i_query ) { case VOD_MEDIA_PLAY: psz = (const char *)va_arg( args, const char * ); i_ret = vlm_ControlInternal( vlm, VLM_START_MEDIA_VOD_INSTANCE, id, psz_id, 0, psz ); break; case VOD_MEDIA_PAUSE: i_ret = vlm_ControlInternal( vlm, VLM_PAUSE_MEDIA_INSTANCE, id, psz_id ); break; case VOD_MEDIA_STOP: i_ret = vlm_ControlInternal( vlm, VLM_STOP_MEDIA_INSTANCE, id, psz_id ); break; case VOD_MEDIA_SEEK: { double d_position = (double)va_arg( args, double ); i_ret = vlm_ControlInternal( vlm, VLM_SET_MEDIA_INSTANCE_POSITION, id, psz_id, d_position/100.0 ); break; } case VOD_MEDIA_REWIND: { double d_scale = (double)va_arg( args, double ); double d_position; vlm_ControlInternal( vlm, VLM_GET_MEDIA_INSTANCE_POSITION, id, psz_id, &d_position ); d_position -= (d_scale / 1000.0); if( d_position < 0.0 ) d_position = 0.0; i_ret = vlm_ControlInternal( vlm, VLM_SET_MEDIA_INSTANCE_POSITION, id, psz_id, d_position ); break; } case VOD_MEDIA_FORWARD: { double d_scale = (double)va_arg( args, double ); double d_position; vlm_ControlInternal( vlm, VLM_GET_MEDIA_INSTANCE_POSITION, id, psz_id, &d_position ); d_position += (d_scale / 1000.0); if( d_position > 1.0 ) d_position = 1.0; i_ret = vlm_ControlInternal( vlm, VLM_SET_MEDIA_INSTANCE_POSITION, id, psz_id, d_position ); break; } default: i_ret = VLC_EGENERIC; break; } vlc_mutex_unlock( &vlm->lock ); return i_ret;}/***************************************************************************** * Manage: *****************************************************************************/static void* Manage( vlc_object_t* p_object ){ vlm_t *vlm = (vlm_t*)p_object; int i, j; mtime_t i_lastcheck; mtime_t i_time; i_lastcheck = vlm_Date(); while( !vlm->b_die ) { char **ppsz_scheduled_commands = NULL; int i_scheduled_commands = 0; vlc_mutex_lock( &vlm->lock ); /* destroy the inputs that wants to die, and launch the next input */ for( i = 0; i < vlm->i_media; i++ ) { vlm_media_sys_t *p_media = vlm->media[i]; for( j = 0; j < p_media->i_instance; ) { vlm_media_instance_sys_t *p_instance = p_media->instance[j]; if( p_instance->p_input && ( p_instance->p_input->b_eof || p_instance->p_input->b_error ) ) { int i_new_input_index; /* */ i_new_input_index = p_instance->i_index + 1; if( !p_media->cfg.b_vod && p_media->cfg.broadcast.b_loop && i_new_input_index >= p_media->cfg.i_input ) i_new_input_index = 0; /* FIXME implement multiple input with VOD */ if( p_media->cfg.b_vod || i_new_input_index >= p_media->cfg.i_input ) vlm_ControlInternal( vlm, VLM_STOP_MEDIA_INSTANCE, p_media->cfg.id, p_instance->psz_name ); else vlm_ControlInternal( vlm, VLM_START_MEDIA_BROADCAST_INSTANCE, p_media->cfg.id, p_instance->psz_name, i_new_input_index ); j = 0; } else { j++; } } } /* scheduling */ i_time = vlm_Date(); for( i = 0; i < vlm->i_schedule; i++ ) { mtime_t i_real_date = vlm->schedule[i]->i_date; if( vlm->schedule[i]->b_enabled == true ) { if( vlm->schedule[i]->i_date == 0 ) // now ! { vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ; i_real_date = i_time; } else if( vlm->schedule[i]->i_period != 0 ) { int j = 0; while( vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period <= i_lastcheck && ( vlm->schedule[i]->i_repeat > j || vlm->schedule[i]->i_repeat == -1 ) ) { j++; } i_real_date = vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -