Commit f64fd9ac authored by Laurent Aimar's avatar Laurent Aimar

Start cleaning up VLM + fixed vlm_New() race condition.

parent 894e084c
......@@ -36,77 +36,6 @@ extern "C" {
#include <vlc_input.h>
/* VLM specific - structures and functions */
enum
{
VOD_TYPE = 0,
BROADCAST_TYPE,
SCHEDULE_TYPE,
};
typedef struct
{
/* instance name */
char *psz_name;
/* "playlist" index */
int i_index;
input_item_t item;
input_thread_t *p_input;
} vlm_media_instance_t;
struct vlm_media_t
{
vlc_bool_t b_enabled;
int i_type;
/* name "media" is reserved */
char *psz_name;
input_item_t item;
/* "playlist" */
int i_input;
char **input;
int i_option;
char **option;
char *psz_output;
/* only for broadcast */
vlc_bool_t b_loop;
/* only for vod */
vod_media_t *vod_media;
char *psz_vod_output;
char *psz_mux;
/* actual input instances */
int i_instance;
vlm_media_instance_t **instance;
};
struct vlm_schedule_t
{
/* names "schedule" is reserved */
char *psz_name;
vlc_bool_t b_enabled;
/* list of commands to execute on date */
int i_command;
char **command;
/* the date of 1st execution */
mtime_t i_date;
/* if != 0 repeat schedule every (period) */
mtime_t i_period;
/* number of times you have to repeat
i_repeat < 0 : endless repeat */
int i_repeat;
};
/* ok, here is the structure of a vlm_message:
The parent node is ( name_of_the_command , NULL ), or
......@@ -122,42 +51,14 @@ struct vlm_message_t
};
struct vlm_t
{
VLC_COMMON_MEMBERS
vlc_mutex_t lock;
int i_media;
vlm_media_t **media;
int i_vod;
vod_t *vod;
int i_schedule;
vlm_schedule_t **schedule;
};
#define vlm_New( a ) __vlm_New( VLC_OBJECT(a) )
VLC_EXPORT( vlm_t *, __vlm_New, ( vlc_object_t * ) );
VLC_EXPORT( void, vlm_Delete, ( vlm_t * ) );
VLC_EXPORT( int, vlm_ExecuteCommand, ( vlm_t *, const char *, vlm_message_t ** ) );
VLC_EXPORT( void, vlm_MessageDelete, ( vlm_message_t * ) );
VLC_EXPORT( vlm_media_t *, vlm_MediaNew, ( vlm_t *, const char *, int ) );
VLC_EXPORT( void, vlm_MediaDelete, ( vlm_t *, vlm_media_t *, const char * ) );
VLC_EXPORT( int, vlm_MediaSetup, ( vlm_t *, vlm_media_t *, const char *, const char * ) );
VLC_EXPORT( int, vlm_MediaControl, ( vlm_t *, vlm_media_t *, const char *, const char *, const char * ) );
VLC_EXPORT( vlm_media_t* , vlm_MediaSearch,( vlm_t *, const char *) );
VLC_EXPORT( vlm_schedule_t *, vlm_ScheduleNew, ( vlm_t *, const char * ) );
VLC_EXPORT( void, vlm_ScheduleDelete, ( vlm_t *, vlm_schedule_t *, const char * ) );
VLC_EXPORT( int, vlm_ScheduleSetup, ( vlm_schedule_t *, const char *, const char * ) );
VLC_EXPORT( int, vlm_MediaVodControl, ( void *, vod_media_t *, const char *, int, va_list ) );
VLC_EXPORT( int, vlm_Save, ( vlm_t *, const char * ) );
VLC_EXPORT( int, vlm_Load, ( vlm_t *, const char * ) );
VLC_EXPORT( void, vlm_Delete, ( vlm_t * ) );
VLC_EXPORT( int, vlm_ExecuteCommand, ( vlm_t *, const char *, vlm_message_t ** ) );
VLC_EXPORT( vlm_message_t *, vlm_MessageNew, ( const char *, const char *, ... ) );
VLC_EXPORT( vlm_message_t *, vlm_MessageAdd, ( vlm_message_t *, vlm_message_t * ) );
VLC_EXPORT( void, vlm_MessageDelete, ( vlm_message_t * ) );
#ifdef __cpluplus
}
......
......@@ -25,7 +25,7 @@
#include <vlc/libvlc.h>
#include <vlc_es.h>
#include <vlc_input.h>
#include <vlc_vlm.h>
#include "../input/vlm_internal.h"
static void InitVLM( libvlc_instance_t *p_instance )
{
......
......@@ -45,6 +45,7 @@
#include "input_internal.h"
#include <vlc_stream.h>
#include <vlc_vlm.h>
#include "vlm_internal.h"
#include <vlc_vod.h>
#include <vlc_charset.h>
......@@ -63,6 +64,18 @@ static int Load( vlm_t *, char * );
static int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** );
static int Manage( vlc_object_t * );
static int vlm_Save( vlm_t *p_vlm, const char *psz_file );
static int vlm_Load( vlm_t *p_vlm, const char *psz_file );
static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name );
static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched, const char *psz_name );
static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
const char *psz_value );
static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list );
/*****************************************************************************
* vlm_New:
*****************************************************************************/
......@@ -72,30 +85,37 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
vlm_t *p_vlm = NULL;
char *psz_vlmconf;
/* to be sure to avoid multiple creation */
var_Create( p_this->p_libvlc_global, "vlm_mutex", VLC_VAR_MUTEX );
var_Get( p_this->p_libvlc_global, "vlm_mutex", &lockval );
/* Avoid multiple creation */
if( var_Create( p_this->p_libvlc_global, "vlm_mutex", VLC_VAR_MUTEX ) ||
var_Get( p_this->p_libvlc_global, "vlm_mutex", &lockval ) )
return NULL;
vlc_mutex_lock( lockval.p_address );
if( !(p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE );
if( p_vlm )
{
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_object_yield( p_vlm );
vlc_mutex_unlock( lockval.p_address );
return p_vlm;
}
vlc_mutex_init( p_this->p_libvlc, &p_vlm->lock );
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->vod = NULL;
msg_Dbg( p_this, "creating VLM" );
vlc_object_yield( p_vlm );
vlc_object_attach( p_vlm, p_this->p_libvlc );
p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM );
if( !p_vlm )
{
vlc_mutex_unlock( lockval.p_address );
return NULL;
}
vlc_mutex_unlock( lockval.p_address );
vlc_mutex_init( p_this->p_libvlc, &p_vlm->lock );
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->vod = NULL;
vlc_object_yield( p_vlm );
vlc_object_attach( p_vlm, p_this->p_libvlc );
if( vlc_thread_create( p_vlm, "vlm thread",
Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
......@@ -105,9 +125,8 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
return NULL;
}
/* Try loading the vlm conf file given by --vlm-conf */
psz_vlmconf = config_GetPsz( p_vlm, "vlm-conf" );
/* Load our configuration file */
psz_vlmconf = var_CreateGetString( p_vlm, "vlm-conf" );
if( psz_vlmconf && *psz_vlmconf )
{
vlm_message_t *p_message = NULL;
......@@ -117,17 +136,19 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
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_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);
}
free(psz_vlmconf);
return p_vlm;
vlc_mutex_unlock( lockval.p_address );
return p_vlm;
}
/*****************************************************************************
......@@ -137,6 +158,7 @@ void vlm_Delete( vlm_t *p_vlm )
{
vlc_value_t lockval;
msg_Err( p_vlm, "vlm_Delete called" );
var_Get( p_vlm->p_libvlc_global, "vlm_mutex", &lockval );
vlc_mutex_lock( lockval.p_address );
......@@ -151,16 +173,18 @@ void vlm_Delete( vlm_t *p_vlm )
p_vlm->b_die = VLC_TRUE;
vlc_thread_join( p_vlm );
vlc_object_detach( p_vlm );
vlc_mutex_destroy( &p_vlm->lock );
while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
FREENULL( p_vlm->media );
while( p_vlm->i_media )
vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
TAB_CLEAN( p_vlm->i_media, p_vlm->media );
while( p_vlm->i_schedule ) vlm_ScheduleDelete( p_vlm,
p_vlm->schedule[0], NULL );
FREENULL( p_vlm->schedule );
while( p_vlm->i_schedule )
vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
TAB_CLEAN( p_vlm->schedule, p_vlm->schedule );
vlc_object_detach( p_vlm );
vlc_object_destroy( p_vlm );
vlc_mutex_unlock( lockval.p_address );
}
......@@ -180,77 +204,6 @@ int vlm_ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
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[] = "\"'";
/**
......@@ -891,6 +844,80 @@ vlm_media_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name )
return NULL;
}
/*****************************************************************************
* vlm_Save:
*****************************************************************************/
static 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:
*****************************************************************************/
static 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;
}
/*****************************************************************************
* Media handling
*****************************************************************************/
......@@ -1400,7 +1427,7 @@ static int64_t vlm_Date(void)
#endif
}
vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
{
vlm_schedule_t *p_sched = malloc( sizeof( vlm_schedule_t ) );
......@@ -1428,7 +1455,7 @@ vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
}
/* for now, simple delete. After, del with options (last arg) */
void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
const char *psz_name )
{
if( sched == NULL ) return;
......@@ -1462,7 +1489,7 @@ static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, const char *psz_name )
}
/* Ok, setup schedule command will be able to support only one (argument value) at a time */
int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
const char *psz_value )
{
if( !strcmp( psz_cmd, "enabled" ) )
......@@ -2380,8 +2407,8 @@ static char *Save( vlm_t *vlm )
/*****************************************************************************
* Manage:
*****************************************************************************/
int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
const char *psz_id, int i_query, va_list args )
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 = VLC_EGENERIC;
......@@ -2590,23 +2617,39 @@ static int Manage( vlc_object_t* p_object )
vlm_t *__vlm_New( vlc_object_t *a )
{
msg_Err( a, "VideoLAN manager support is disabled" );
return 0;
return NULL;
}
void vlm_Delete( vlm_t *a )
{
;
}
int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c )
{
return -1;
}
void vlm_MessageDelete( vlm_message_t *a )
{
;
}
vlm_media_t *vlm_MediaNew( vlm_t *a, char *b, int c )
{
return NULL;
}
vlm_media_t *vlm_MediaSearch (vlm_t *a, const char *b )
{
return NULL;
}
void vlm_MediaDelete( vlm_t *a, vlm_media_t *b, char *c )
{
;
}
int vlm_MediaSetup( vlm_t *a, vlm_media_t *b, char *c, char *d )
{
return -1;
}
void vlm_Delete( vlm_t *a ){}
int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c ){ return -1; }
void vlm_MessageDelete( vlm_message_t *a ){}
vlm_media_t *vlm_MediaNew( vlm_t *a, char *b, int c ){ return NULL; }
vlm_media_t *vlm_MediaSearch (vlm_t *a, const char *b ) { return NULL; }
void vlm_MediaDelete( vlm_t *a, vlm_media_t *b, char *c ){}
int vlm_MediaSetup( vlm_t *a, vlm_media_t *b, char *c, char *d ){ return -1; }
int vlm_MediaControl( vlm_t *a, vlm_media_t *b, char *c, char *d, char *e )
{ return -1; }
vlm_schedule_t * vlm_ScheduleNew( vlm_t *a, char *b ){ return NULL; }
void vlm_ScheduleDelete( vlm_t *a, vlm_schedule_t *b, char *c ){}
int vlm_ScheduleSetup( vlm_schedule_t *a, char *b, char *c ){ return -1; }
int vlm_MediaVodControl( void *a, vod_media_t *b, char *c, int d, va_list e )
{ return -1; }
int vlm_Save( vlm_t *a, char *b ){ return -1; }
int vlm_Load( vlm_t *a, char *b ){ return -1; }
{
return -1;
}
#endif /* ENABLE_VLM */
/*****************************************************************************
* vlm_internal.h: Internal vlm structures
*****************************************************************************
* Copyright (C) 1998-2006 the VideoLAN team
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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.
*****************************************************************************/
#ifndef _VLM_INTERNAL_H
#define _VLM_INTERNAL_H 1
#include <vlc_vlm.h>
enum
{
VOD_TYPE = 0,
BROADCAST_TYPE,
SCHEDULE_TYPE,
};
typedef struct
{
/* instance name */
char *psz_name;
/* "playlist" index */
int i_index;
input_item_t item;
input_thread_t *p_input;
} vlm_media_instance_t;
struct vlm_media_t
{
vlc_bool_t b_enabled;
int i_type;
/* name "media" is reserved */
char *psz_name;
input_item_t item;
/* "playlist" */
int i_input;
char **input;
int i_option;
char **option;
char *psz_output;
/* only for broadcast */
vlc_bool_t b_loop;
/* only for vod */
vod_media_t *vod_media;
char *psz_vod_output;
char *psz_mux;
/* actual input instances */
int i_instance;
vlm_media_instance_t **instance;
};
struct vlm_schedule_t
{
/* names "schedule" is reserved */
char *psz_name;
vlc_bool_t b_enabled;
/* list of commands to execute on date */
int i_command;
char **command;
/* the date of 1st execution */
mtime_t i_date;
/* if != 0 repeat schedule every (period) */
mtime_t i_period;
/* number of times you have to repeat
i_repeat < 0 : endless repeat */
int i_repeat;
};
struct vlm_t
{
VLC_COMMON_MEMBERS
vlc_mutex_t lock;
int i_media;
vlm_media_t **media;
int i_vod;
vod_t *vod;
int i_schedule;
vlm_schedule_t **schedule;
};
vlm_media_t *vlm_MediaNew( vlm_t *, const char *, int );
void vlm_MediaDelete( vlm_t *, vlm_media_t *, const char * );
int vlm_MediaSetup( vlm_t *, vlm_media_t *, const char *, const char * );
int vlm_MediaControl( vlm_t *, vlm_media_t *, const char *, const char *, const char * );
vlm_media_t *vlm_MediaSearch( vlm_t *, const char *);