001.vdr, 002.vdr, 003.vdr, ...
index.vdr, info.vdr, marks.vdr, ...
2) TS format:
- /path/to/0000-00-00.00.00.0.0.rec/
- 001.ts, 002.ts, 003.ts, ...
+ /path/to/0000-00-00.00.00.0-0.rec/
+ 00001.ts, 00002.ts, 00003.ts, ...
index, info, marks, ...
See http://www.vdr-wiki.de/ and http://www.tvdr.de/ for more information.
***/
# include "config.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#elif defined( WIN32 ) && !defined( UNDER_CE )
static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len );
static int Seek( access_t *p_access, uint64_t i_pos);
static void FindSeekpoint( access_t *p_access );
-static bool ScanDirectory( access_t *p_access, bool b_strict );
+static bool ScanDirectory( access_t *p_access );
static char *GetFilePath( access_t *p_access, unsigned i_file );
static bool ImportNextFile( access_t *p_access );
static bool SwitchFile( access_t *p_access, unsigned i_file );
static void OptimizeForRead( int fd );
static void UpdateFileSize( access_t *p_access );
-static int StatRelativeFile( access_t *p_access, const char *psz_file,
- struct stat *p_stat );
static FILE *OpenRelativeFile( access_t *p_access, const char *psz_file );
static bool ReadLine( char **ppsz_line, size_t *pi_size, FILE *p_file );
static void ImportMeta( access_t *p_access );
static bool ReadIndexRecord( FILE *p_file, bool b_ts, int64_t i_frame,
uint64_t *pi_offset, uint16_t *pi_file_num );
static int64_t ParseFrameNumber( const char *psz_line, float fps );
+static const char *BaseName( const char *psz_path );
/*****************************************************************************
* Open a directory
* and we can avoid false positives in the general case. */
bool b_strict = strcmp( p_access->psz_access, "vdr" );
- /* Do a quick test based on the directory extension to see if this
+ /* Do a quick test based on the directory name to see if this
* directory might contain a VDR recording. We can be reasonably
* sure if ScanDirectory() actually finds files. */
if( b_strict )
{
- const char *psz_ext = strrchr( p_access->psz_filepath, '.' );
- if( !psz_ext || ( strcasecmp( psz_ext, ".rec" )
- && strcasecmp( psz_ext, ".rec" DIR_SEP ) ) )
+ char psz_extension[4];
+ int i_length = 0;
+ const char *psz_name = BaseName( p_access->psz_filepath );
+ if( sscanf( psz_name, "%*u-%*u-%*u.%*u.%*u.%*u%*[-.]%*u.%3s%n",
+ psz_extension, &i_length ) != 1 || strcasecmp( psz_extension, "rec" ) ||
+ ( psz_name[i_length] != DIR_SEP_CHAR && psz_name[i_length] != '\0' ) )
return VLC_EGENERIC;
}
ARRAY_INIT( p_sys->file_sizes );
/* Import all files and prepare playback. */
- if( !ScanDirectory( p_access, b_strict ) ||
+ if( !ScanDirectory( p_access ) ||
!SwitchFile( p_access, 0 ) )
{
Close( p_this );
/*****************************************************************************
* Determine format and import files
*****************************************************************************/
-static bool ScanDirectory( access_t *p_access, bool b_strict )
+static bool ScanDirectory( access_t *p_access )
{
access_sys_t *p_sys = p_access->p_sys;
return false;
}
- /* meta data and index should exist */
- if( b_strict )
- {
- struct stat st;
- if( StatRelativeFile( p_access, "info", &st ) ||
- StatRelativeFile( p_access, "index", &st ) )
- return false;
- }
-
/* get all remaining parts */
while( ImportNextFile( p_access ) )
continue;
/* find correct file */
unsigned i_file = 0;
- while( i_pos >= FILE_SIZE( i_file ) &&
- i_file < FILE_COUNT - 1 )
+ while( i_file < FILE_COUNT - 1 &&
+ i_pos >= FILE_SIZE( i_file ) )
{
i_pos -= FILE_SIZE( i_file );
i_file++;
p_access->info.i_update |= INPUT_UPDATE_SIZE;
}
-/*****************************************************************************
- * Stat file relative to base directory
- *****************************************************************************/
-static int StatRelativeFile( access_t *p_access, const char *psz_file,
- struct stat *p_stat )
-{
- /* build path and add extension */
- char *psz_path;
- if( asprintf( &psz_path, "%s" DIR_SEP "%s%s",
- p_access->psz_filepath, psz_file,
- p_access->p_sys->b_ts_format ? "" : ".vdr" ) == -1 )
- return -1;
-
- int ret = vlc_stat( psz_path, p_stat );
- if( ret )
- msg_Dbg( p_access, "could not stat %s: %m", psz_path );
- free( psz_path );
-
- return ret;
-}
-
/*****************************************************************************
* Open file relative to base directory for reading.
*****************************************************************************/
return;
}
p_marks->psz_name = strdup( _("VDR Cut Marks") );
+ p_marks->i_length = i_frame_count * (int64_t)( CLOCK_FREQ / p_sys->fps );
+ p_marks->i_size = p_access->info.i_size;
/* offset for chapter positions */
int i_chapter_offset = p_sys->fps / 1000 *
int64_t i_frame = strtoll( psz_line, NULL, 10 );
return __MAX(1, i_frame) - 1;
}
+
+/*****************************************************************************
+ * Return the last path component (including trailing separators)
+ *****************************************************************************/
+static const char *BaseName( const char *psz_path )
+{
+ const char *psz_name = psz_path + strlen( psz_path );
+
+ /* skip superfluous separators at the end */
+ while( psz_name > psz_path && psz_name[-1] == DIR_SEP_CHAR )
+ --psz_name;
+
+ /* skip last component */
+ while( psz_name > psz_path && psz_name[-1] != DIR_SEP_CHAR )
+ --psz_name;
+
+ return psz_name;
+}