Commit 144bd771 authored by Gildas Bazin's avatar Gildas Bazin

* modules/access/file.c:

   + implemented a --file-cat config option that accepts a coma separated list of file names.
     This option allows opening splitted files as a single (concatenated) input.
parent f50eee0d
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* file.c: file input (file: access plug-in) * file.c: file input (file: access plug-in)
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: file.c,v 1.23 2004/03/01 12:50:39 gbazin Exp $ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -53,10 +53,14 @@ ...@@ -53,10 +53,14 @@
/* stat() support for large files on win32 */ /* stat() support for large files on win32 */
#if defined( WIN32 ) && !defined( UNDER_CE ) #if defined( WIN32 ) && !defined( UNDER_CE )
#define stat(a,b) _stati64(a,b) #define stat _stati64
#define fstat(a,b) _fstati64(a,b) #define fstat(a,b) _fstati64(a,b)
#endif #endif
#ifdef UNDER_CE
# define close(a) CloseHandle((HANDLE)a)
#endif
/***************************************************************************** /*****************************************************************************
* Exported prototypes * Exported prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -66,6 +70,8 @@ static void Close ( vlc_object_t * ); ...@@ -66,6 +70,8 @@ static void Close ( vlc_object_t * );
static void Seek ( input_thread_t *, off_t ); static void Seek ( input_thread_t *, off_t );
static ssize_t Read ( input_thread_t *, byte_t *, size_t ); static ssize_t Read ( input_thread_t *, byte_t *, size_t );
static int _OpenFile( input_thread_t *, char * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
...@@ -73,10 +79,15 @@ static ssize_t Read ( input_thread_t *, byte_t *, size_t ); ...@@ -73,10 +79,15 @@ static ssize_t Read ( input_thread_t *, byte_t *, size_t );
#define CACHING_LONGTEXT N_( \ #define CACHING_LONGTEXT N_( \
"Allows you to modify the default caching value for file streams. This " \ "Allows you to modify the default caching value for file streams. This " \
"value should be set in miliseconds units." ) "value should be set in miliseconds units." )
#define CAT_TEXT N_("Concatenate with additional files")
#define CAT_LONGTEXT N_( \
"Allows you to play splitted files as they were part of a unique file. " \
"Specify a coma (',') separated list of files." )
vlc_module_begin(); vlc_module_begin();
set_description( _("Standard filesystem file input") ); set_description( _("Standard filesystem file input") );
add_integer( "file-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); add_integer( "file-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
add_string( "file-cat", NULL, NULL, CAT_TEXT, CAT_LONGTEXT, VLC_TRUE );
set_capability( "access", 50 ); set_capability( "access", 50 );
add_shortcut( "file" ); add_shortcut( "file" );
add_shortcut( "stream" ); add_shortcut( "stream" );
...@@ -88,12 +99,27 @@ vlc_module_end(); ...@@ -88,12 +99,27 @@ vlc_module_end();
* _input_socket_t: private access plug-in data, modified to add private * _input_socket_t: private access plug-in data, modified to add private
* fields * fields
*****************************************************************************/ *****************************************************************************/
typedef struct file_entry_s
{
char *psz_name;
int64_t i_size;
} file_entry_t;
typedef struct _input_socket_s typedef struct _input_socket_s
{ {
input_socket_t _socket; input_socket_t _socket;
unsigned int i_nb_reads; unsigned int i_nb_reads;
vlc_bool_t b_kfir; vlc_bool_t b_kfir;
/* Files list */
file_entry_t **p_files;
int i_files;
/* Current file */
int i_index;
} _input_socket_t; } _input_socket_t;
/***************************************************************************** /*****************************************************************************
...@@ -105,16 +131,14 @@ static int Open( vlc_object_t *p_this ) ...@@ -105,16 +131,14 @@ static int Open( vlc_object_t *p_this )
char * psz_name = p_input->psz_name; char * psz_name = p_input->psz_name;
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
int i_stat; int i_stat;
#if defined( WIN32 ) && !defined( UNDER_CE )
struct _stati64 stat_info;
#else
struct stat stat_info; struct stat stat_info;
#endif
#endif #endif
_input_socket_t * p_access_data; _input_socket_t * p_access_data;
vlc_bool_t b_stdin, b_kfir = 0; vlc_bool_t b_stdin, b_kfir = 0;
vlc_value_t val; vlc_value_t val;
file_entry_t * p_file;
p_input->i_mtu = 0; p_input->i_mtu = 0;
b_stdin = psz_name[0] == '-' && psz_name[1] == '\0'; b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
...@@ -217,37 +241,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -217,37 +241,11 @@ static int Open( vlc_object_t *p_this )
} }
else else
{ {
#ifdef UNDER_CE if( _OpenFile( p_input, psz_name ) != VLC_SUCCESS )
wchar_t psz_filename[MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, psz_name, -1, psz_filename, MAX_PATH );
p_access_data->_socket.i_handle = (int)CreateFile( psz_filename,
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
if( (HANDLE)p_access_data->_socket.i_handle == INVALID_HANDLE_VALUE )
{ {
msg_Err( p_input, "cannot open file %s", psz_name );
free( p_access_data ); free( p_access_data );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_input->stream.p_selected_area->i_size =
GetFileSize( (HANDLE)p_access_data->_socket.i_handle, NULL );
#else
p_access_data->_socket.i_handle = open( psz_name,
O_NONBLOCK /*| O_LARGEFILE*/ );
if( p_access_data->_socket.i_handle == -1 )
{
# ifdef HAVE_ERRNO_H
msg_Err( p_input, "cannot open file %s (%s)", psz_name,
strerror(errno) );
# else
msg_Err( p_input, "cannot open file %s", psz_name );
# endif
free( p_access_data );
return VLC_EGENERIC;
}
#endif
} }
if ( p_input->stream.b_seekable if ( p_input->stream.b_seekable
...@@ -263,6 +261,63 @@ static int Open( vlc_object_t *p_this ) ...@@ -263,6 +261,63 @@ static int Open( vlc_object_t *p_this )
var_Get( p_input, "file-caching", &val ); var_Get( p_input, "file-caching", &val );
p_input->i_pts_delay = val.i_int * 1000; p_input->i_pts_delay = val.i_int * 1000;
/*
* Get the additional list of files
*/
p_access_data->p_files = NULL;
p_access_data->i_files = p_access_data->i_index = 0;
p_file = (file_entry_t *)malloc( sizeof(file_entry_t) );
p_file->i_size = p_input->stream.p_selected_area->i_size;
p_file->psz_name = strdup( psz_name );
TAB_APPEND( p_access_data->i_files, p_access_data->p_files, p_file );
var_Create( p_input, "file-cat", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
var_Get( p_input, "file-cat", &val );
if( val.psz_string && *val.psz_string )
{
char *psz_parser = psz_name = val.psz_string;
int64_t i_size;
while( psz_name && *psz_name )
{
psz_parser = strchr( psz_name, ',' );
if( psz_parser ) *psz_parser = 0;
psz_name = strdup( psz_name );
if( psz_name )
{
msg_Dbg( p_input, "adding file `%s'", psz_name );
#ifdef HAVE_SYS_STAT_H
if( !stat( psz_name, &stat_info ) )
{
p_input->stream.p_selected_area->i_size +=
stat_info.st_size;
i_size = stat_info.st_size;
}
else
{
msg_Dbg( p_input, "cannot stat() file `%s'", psz_name );
i_size = 0;
}
#endif
p_file = (file_entry_t *)malloc( sizeof(file_entry_t) );
p_file->i_size = i_size;
p_file->psz_name = psz_name;
TAB_APPEND( p_access_data->i_files, p_access_data->p_files,
p_file );
}
psz_name = psz_parser;
if( psz_name ) psz_name++;
}
}
if( val.psz_string ) free( val.psz_string );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -271,17 +326,21 @@ static int Open( vlc_object_t *p_this ) ...@@ -271,17 +326,21 @@ static int Open( vlc_object_t *p_this )
*****************************************************************************/ *****************************************************************************/
static void Close( vlc_object_t * p_this ) static void Close( vlc_object_t * p_this )
{ {
input_thread_t * p_input = (input_thread_t *)p_this; input_thread_t *p_input = (input_thread_t *)p_this;
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data; _input_socket_t *p_access_data = (_input_socket_t *)p_input->p_access_data;
int i;
msg_Info( p_input, "closing `%s/%s://%s'", msg_Info( p_input, "closing `%s/%s://%s'",
p_input->psz_access, p_input->psz_demux, p_input->psz_name ); p_input->psz_access, p_input->psz_demux, p_input->psz_name );
#ifdef UNDER_CE close( p_access_data->_socket.i_handle );
CloseHandle( (HANDLE)p_access_data->i_handle );
#else for( i = 0; i < p_access_data->i_files; i++ )
close( p_access_data->i_handle ); {
#endif free( p_access_data->p_files[i]->psz_name );
free( p_access_data->p_files[i] );
}
if( p_access_data->p_files ) free( p_access_data->p_files );
free( p_access_data ); free( p_access_data );
} }
...@@ -291,7 +350,7 @@ static void Close( vlc_object_t * p_this ) ...@@ -291,7 +350,7 @@ static void Close( vlc_object_t * p_this )
*****************************************************************************/ *****************************************************************************/
static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len ) static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
{ {
_input_socket_t * p_access_data = (_input_socket_t *)p_input->p_access_data; _input_socket_t *p_access_data = (_input_socket_t *)p_input->p_access_data;
ssize_t i_ret; ssize_t i_ret;
#ifdef UNDER_CE #ifdef UNDER_CE
...@@ -380,11 +439,9 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len ) ...@@ -380,11 +439,9 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
if ( p_input->stream.p_selected_area->i_size != 0 if ( p_input->stream.p_selected_area->i_size != 0
&& (p_access_data->i_nb_reads % INPUT_FSTAT_NB_READS) == 0 ) && (p_access_data->i_nb_reads % INPUT_FSTAT_NB_READS) == 0 )
{ {
#if defined( WIN32 ) && !defined( UNDER_CE )
struct _stati64 stat_info;
#else
struct stat stat_info; struct stat stat_info;
#endif int i_file = p_access_data->i_index;
if ( fstat( p_access_data->_socket.i_handle, &stat_info ) == -1 ) if ( fstat( p_access_data->_socket.i_handle, &stat_info ) == -1 )
{ {
# ifdef HAVE_ERRNO_H # ifdef HAVE_ERRNO_H
...@@ -394,14 +451,32 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len ) ...@@ -394,14 +451,32 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
msg_Warn( p_input, "couldn't stat again the file" ); msg_Warn( p_input, "couldn't stat again the file" );
# endif # endif
} }
else if ( p_input->stream.p_selected_area->i_size != stat_info.st_size ) else if ( p_access_data->p_files[i_file]->i_size != stat_info.st_size )
{ {
p_input->stream.p_selected_area->i_size = stat_info.st_size; p_input->stream.p_selected_area->i_size +=
(stat_info.st_size - p_access_data->p_files[i_file]->i_size);
p_input->stream.b_changed = 1; p_input->stream.b_changed = 1;
} }
} }
#endif #endif
/* If we reached an EOF then switch to the next file in the list */
if ( i_ret == 0 && ++p_access_data->i_index < p_access_data->i_files )
{
int i_handle = p_access_data->_socket.i_handle;
char *psz_name =
p_access_data->p_files[p_access_data->i_index]->psz_name;
msg_Dbg( p_input, "opening file `%s'", psz_name );
if ( _OpenFile( p_input, psz_name ) != VLC_SUCCESS ) return i_ret;
close( i_handle );
/* We have to read some data */
return Read( p_input, p_buffer, i_len );
}
return i_ret; return i_ret;
} }
...@@ -411,12 +486,40 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len ) ...@@ -411,12 +486,40 @@ static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
static void Seek( input_thread_t * p_input, off_t i_pos ) static void Seek( input_thread_t * p_input, off_t i_pos )
{ {
#define S p_input->stream #define S p_input->stream
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data; _input_socket_t *p_access_data = (_input_socket_t *)p_input->p_access_data;
int64_t i_size = 0;
/* Check which file we need to access */
if ( p_access_data->i_files > 1 )
{
int i, i_handle = p_access_data->_socket.i_handle;
char * psz_name;
for ( i = 0; i < p_access_data->i_files - 1; i++ )
{
if( i_pos < p_access_data->p_files[i+1]->i_size + i_size ) break;
i_size += p_access_data->p_files[i+1]->i_size;
}
psz_name = p_access_data->p_files[i]->psz_name;
p_access_data->i_index = i;
msg_Dbg( p_input, "opening file `%s'", psz_name );
if ( _OpenFile( p_input, psz_name ) == VLC_SUCCESS )
{
/* Close old file */
close( i_handle );
}
else
{
p_access_data->_socket.i_handle = i_handle;
}
}
#if defined( WIN32 ) && !defined( UNDER_CE ) #if defined( WIN32 ) && !defined( UNDER_CE )
_lseeki64( p_access_data->i_handle, i_pos, SEEK_SET ); _lseeki64( p_access_data->_socket.i_handle, i_pos - i_size, SEEK_SET );
#else #else
lseek( p_access_data->i_handle, i_pos, SEEK_SET ); lseek( p_access_data->_socket.i_handle, i_pos - i_size, SEEK_SET );
#endif #endif
vlc_mutex_lock( &S.stream_lock ); vlc_mutex_lock( &S.stream_lock );
...@@ -435,3 +538,42 @@ static void Seek( input_thread_t * p_input, off_t i_pos ) ...@@ -435,3 +538,42 @@ static void Seek( input_thread_t * p_input, off_t i_pos )
#undef S #undef S
} }
/*****************************************************************************
* OpenFile: Opens a specific file
*****************************************************************************/
static int _OpenFile( input_thread_t * p_input, char * psz_name )
{
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
#ifdef UNDER_CE
wchar_t psz_filename[MAX_PATH];
MultiByteToWideChar( CP_ACP, 0, psz_name, -1, psz_filename, MAX_PATH );
p_access_data->i_handle =
(int)CreateFile( psz_filename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( (HANDLE)p_access_data->i_handle == INVALID_HANDLE_VALUE )
{
msg_Err( p_input, "cannot open file %s", psz_name );
return VLC_EGENERIC;
}
p_input->stream.p_selected_area->i_size =
GetFileSize( (HANDLE)p_access_data->i_handle, NULL );
#else
p_access_data->i_handle = open( psz_name, O_NONBLOCK /*| O_LARGEFILE*/ );
if ( p_access_data->i_handle == -1 )
{
# ifdef HAVE_ERRNO_H
msg_Err( p_input, "cannot open file %s (%s)", psz_name,
strerror(errno) );
# else
msg_Err( p_input, "cannot open file %s", psz_name );
# endif
return VLC_EGENERIC;
}
#endif
return VLC_SUCCESS;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment