]> git.sesse.net Git - vlc/blobdiff - modules/access/vdr.c
DTV: add dvbt shortcut, for old-BDA module compatibility
[vlc] / modules / access / vdr.c
index cd5427b6788a98517f579b9f99bef83af34336b6..79653bf7c3f3c922621be950c1c4c0e0917fea83 100644 (file)
@@ -31,8 +31,8 @@ VDR recordings have either of two directory layouts:
             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.
 ***/
@@ -45,15 +45,9 @@ 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 )
@@ -149,14 +143,12 @@ static int Control( access_t *, int, va_list );
 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 );
@@ -164,6 +156,7 @@ static void ImportMarks( 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
@@ -180,14 +173,17 @@ static int Open( vlc_object_t *p_this )
      * 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;
     }
 
@@ -204,7 +200,7 @@ static int Open( vlc_object_t *p_this )
     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 );
@@ -236,7 +232,7 @@ static void Close( vlc_object_t * 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;
 
@@ -249,15 +245,6 @@ static bool ScanDirectory( access_t *p_access, bool b_strict )
             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;
@@ -407,8 +394,8 @@ static int Seek( access_t *p_access, uint64_t i_pos )
 
     /* 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++;
@@ -607,27 +594,6 @@ static void UpdateFileSize( access_t *p_access )
     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.
  *****************************************************************************/
@@ -850,6 +816,8 @@ static void ImportMarks( access_t *p_access )
         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 *
@@ -974,3 +942,21 @@ static int64_t ParseFrameNumber( const char *psz_line, float fps )
     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;
+}