* src/input/*, include/vlc_input.h: the MRL is now parsed for titles/chapters directl...
authorGildas Bazin <gbazin@videolan.org>
Fri, 20 Aug 2004 23:37:40 +0000 (23:37 +0000)
committerGildas Bazin <gbazin@videolan.org>
Fri, 20 Aug 2004 23:37:40 +0000 (23:37 +0000)
  - syntax is: [url][@[title-start][,chapter-start][-[title-end][,chapter-end]]]
  - core also handles start/end boundaries itself (simplifies the access plugins).
* modules/access/dvdread.c,dvdnav.c,cdda.c: removed MRL parsing code.

include/vlc_input.h
modules/access/cdda.c
modules/access/dvdnav.c
modules/access/dvdread.c
src/input/input.c
src/input/var.c

index 8ae8ce1..48db4b6 100644 (file)
@@ -201,6 +201,14 @@ typedef struct
     int          i_title;
     input_title_t **title;
 
+    int i_title_offset;
+    int i_seekpoint_offset;
+
+    int i_title_start;
+    int i_title_end;
+    int i_seekpoint_start;
+    int i_seekpoint_end;
+
     /* Properties */
     vlc_bool_t b_can_pace_control;
     vlc_bool_t b_can_pause;
@@ -253,6 +261,9 @@ struct input_thread_t
     int          i_title;
     input_title_t **title;
 
+    int i_title_offset;
+    int i_seekpoint_offset;
+
     /* User bookmarks FIXME won't be easy with multiples input */
     int         i_bookmark;
     seekpoint_t **bookmark;
index a6e6cd9..72ac171 100644 (file)
@@ -72,9 +72,6 @@ struct access_sys_t
     int           i_titles;
     input_title_t *title[99];         /* No more that 99 track in a cd-audio */
 
-    int i_title_start;
-    int i_title_end;
-
     /* Current position */
     int         i_sector;                                  /* Current Sector */
     int *       p_sectors;                                  /* Track sectors */
@@ -90,54 +87,38 @@ static int      Control( access_t *, int, va_list );
 
 /*****************************************************************************
  * Open: open cdda
- * MRL syntax: [dev_path][@[title-start][-[title-end]]]
  *****************************************************************************/
 static int Open( vlc_object_t *p_this )
 {
     access_t     *p_access = (access_t*)p_this;
     access_sys_t *p_sys;
 
-    char *psz_dup, *psz;
-    int  i, i_title_start = -1, i_title_end = -1;
     vcddev_t *vcddev;
+    char *psz_name;
+    int  i;
 
-    /* Command line: [dev_path][@[title-start][-[title-end]]] */
-    psz_dup = p_access->psz_path? strdup( p_access->psz_path ) : 0;
-    if( psz_dup && ( psz = strchr( psz_dup, '@' ) ) )
-    {
-        *psz++ = 0;
-        i_title_start = i_title_end = strtol( psz, NULL, 0 );
-
-        if( ( psz = strchr( psz, '-' ) ) )
-        {
-            *psz++;
-            i_title_end = strtol( psz, NULL, 0 );
-        }
-    }
-
-    if( !psz_dup || !*psz_dup )
+    if( !p_access->psz_path || !*p_access->psz_path )
     {
-        if( psz_dup ) free( psz_dup );
-
         /* Only when selected */
-        if( !p_access->b_force ) return VLC_EGENERIC;
+        if( !p_this->b_force ) return VLC_EGENERIC;
 
-        psz_dup = var_CreateGetString( p_access, "cd-audio" );
-        if( !psz_dup || !*psz_dup )
+        psz_name = var_CreateGetString( p_this, "cd-audio" );
+        if( !psz_name || !*psz_name )
         {
-            if( psz_dup ) free( psz_dup );
+            if( psz_name ) free( psz_name );
             return VLC_EGENERIC;
         }
     }
+    else psz_name = strdup( p_access->psz_path );
 
     /* Open CDDA */
-    if( (vcddev = ioctl_Open( VLC_OBJECT(p_access), psz_dup )) == NULL )
+    if( (vcddev = ioctl_Open( VLC_OBJECT(p_access), psz_name )) == NULL )
     {
-        msg_Warn( p_access, "could not open %s", psz_dup );
-        free( psz_dup );
+        msg_Warn( p_access, "could not open %s", psz_name );
+        free( psz_name );
         return VLC_EGENERIC;
     }
-    free( psz_dup );
+    free( psz_name );
 
     /* Set up p_access */
     p_access->pf_read = NULL;
@@ -184,17 +165,8 @@ static int Open( vlc_object_t *p_this )
         t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
     }
 
-    /* Starting title and sector */
-    if( i_title_start < 1 || i_title_start > p_sys->i_titles )
-        p_sys->i_title_start = 1;
-    else p_sys->i_title_start = i_title_start;
-    if( i_title_end < 1 || i_title_end > p_sys->i_titles )
-        p_sys->i_title_end = -1;
-    else p_sys->i_title_end = i_title_end;
-
-    p_sys->i_sector = p_sys->p_sectors[p_sys->i_title_start-1];
-    p_access->info.i_title = p_sys->i_title_start-1;
-    p_access->info.i_size = p_sys->title[p_sys->i_title_start-1]->i_size;
+    p_sys->i_sector = p_sys->p_sectors[0];
+    p_access->info.i_size = p_sys->title[0]->i_size;
 
     /* Build a WAV header for the output data */
     memset( &p_sys->waveheader, 0, sizeof(WAVEHEADER) );
@@ -266,9 +238,7 @@ static block_t *Block( access_t *p_access )
     /* Check end of title */
     while( p_sys->i_sector >= p_sys->p_sectors[p_access->info.i_title + 1] )
     {
-        if( p_access->info.i_title + 1 >= p_sys->i_titles ||
-            ( p_sys->i_title_end > 0 &&
-              p_access->info.i_title + 1 >= p_sys->i_title_end ) )
+        if( p_access->info.i_title + 1 >= p_sys->i_titles )
         {
             p_access->info.b_eof = VLC_TRUE;
             return NULL;
@@ -371,6 +341,7 @@ static int Control( access_t *p_access, int i_query, va_list args )
         case ACCESS_GET_TITLE_INFO:
             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
             pi_int    = (int*)va_arg( args, int* );
+           *((int*)va_arg( args, int* )) = 1; /* Title offset */
 
             /* Duplicate title infos */
             *pi_int = p_sys->i_titles;
@@ -394,10 +365,6 @@ static int Control( access_t *p_access, int i_query, va_list args )
 
                 /* Next sector to read */
                 p_sys->i_sector = p_sys->p_sectors[i];
-
-                /* User tries to access another title so better reset
-                 * the end title */
-                p_sys->i_title_end = -1;
             }
             break;
 
index 2ff28cb..1ce2cf0 100644 (file)
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
+#define ANGLE_TEXT N_("DVD angle")
+#define ANGLE_LONGTEXT N_( \
+    "Allows you to select the default DVD angle." )
+
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Allows you to modify the default caching value for DVDnav streams. This "\
@@ -66,6 +70,8 @@ static void Close( vlc_object_t * );
 
 vlc_module_begin();
     set_description( _("DVDnav Input") );
+    add_integer( "dvdnav-angle", 1, NULL, ANGLE_TEXT,
+        ANGLE_LONGTEXT, VLC_FALSE );
     add_integer( "dvdnav-caching", DEFAULT_PTS_DELAY / 1000, NULL,
         CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
     add_bool( "dvdnav-menu", VLC_TRUE, NULL,
@@ -82,8 +88,6 @@ vlc_module_end();
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static char *ParseCL( vlc_object_t *, char *, vlc_bool_t, int *, int *, int *);
-
 typedef struct
 {
     VLC_COMMON_MEMBERS
@@ -146,16 +150,28 @@ static int Open( vlc_object_t *p_this )
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys;
     dvdnav_t    *p_dvdnav;
-    int         i_title, i_chapter, i_angle;
+    int         i_angle;
     char        *psz_name;
     vlc_value_t val;
 
-    psz_name = ParseCL( VLC_OBJECT(p_demux), p_demux->psz_path, VLC_TRUE,
-                        &i_title, &i_chapter, &i_angle );
-    if( !psz_name )
+    if( !p_demux->psz_path || !*p_demux->psz_path )
     {
-        return VLC_EGENERIC;
+        /* Only when selected */
+        if( !p_this->b_force ) return VLC_EGENERIC;
+
+        psz_name = var_CreateGetString( p_this, "dvd" );
+        if( !psz_name || !*psz_name )
+        {
+            if( psz_name ) free( psz_name );
+            return VLC_EGENERIC;
+        }
     }
+    else psz_name = strdup( p_demux->psz_path );
+
+#ifdef WIN32
+    if( psz_name[0] && psz_name[1] == ':' &&
+        psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
+#endif
 
     /* Try some simple probing to avoid going through dvdnav_open too often */
     if( ProbeDVD( p_demux, psz_name ) != VLC_SUCCESS )
@@ -164,9 +180,6 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    msg_Dbg( p_this, "dvdroot=%s title=%d chapter=%d angle=%d",
-             psz_name, i_title, i_chapter, i_angle );
-
     /* Open dvdnav */
     if( dvdnav_open( &p_dvdnav, psz_name ) != DVDNAV_STATUS_OK )
     {
@@ -227,39 +240,9 @@ static int Open( vlc_object_t *p_this )
 
     DemuxTitles( p_demux );
 
-    /* Set forced title/chapter */
-    if( i_title > 0 )
-    {
-        if( dvdnav_title_play( p_sys->dvdnav, i_title ) != DVDNAV_STATUS_OK )
-        {
-            msg_Warn( p_demux, "cannot set title" );
-            i_title = 0;
-        }
-        else
-        {
-            p_demux->info.i_update |= INPUT_UPDATE_TITLE;
-            p_demux->info.i_title = i_title;
-        }
-    }
-
-    if( i_chapter > 1 && i_title > 0 )
-    {
-        if( dvdnav_part_play( p_sys->dvdnav, i_title, i_chapter ) !=
-            DVDNAV_STATUS_OK )
-        {
-            msg_Warn( p_demux, "cannot set chapter" );
-            i_chapter = 1;
-        }
-        else
-        {
-            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
-            p_demux->info.i_seekpoint = i_chapter;
-        }
-    }
-
     var_Create( p_demux, "dvdnav-menu", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
     var_Get( p_demux, "dvdnav-menu", &val );
-    if( (i_title < 0 && val.b_bool) || i_title == 0 )
+    if( val.b_bool )
     {
         msg_Dbg( p_demux, "trying to go to dvd menu" );
 
@@ -273,15 +256,12 @@ static int Open( vlc_object_t *p_this )
         {
             msg_Warn( p_demux, "cannot go to dvd menu" );
         }
-        else
-        {
-            p_demux->info.i_update |=
-                INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
-            p_demux->info.i_title = 0;
-            p_demux->info.i_seekpoint = 0;
-        }
     }
 
+    var_Create( p_demux, "dvdnav-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+    var_Get( p_demux, "dvdnav-angle", &val );
+    i_angle = val.i_int > 0 ? val.i_int : 1;
+
     /* Update default_pts to a suitable value for dvdnav access */
     var_Create( p_demux, "dvdnav-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
 
@@ -426,6 +406,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_GET_TITLE_INFO:
             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
             pi_int    = (int*)va_arg( args, int* );
+           *((int*)va_arg( args, int* )) = 0; /* Title offset */
+           *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
 
             /* Duplicate title infos */
             *pi_int = p_sys->i_title;
@@ -732,73 +714,6 @@ static int Demux( demux_t *p_demux )
     return 1;
 }
 
-/*****************************************************************************
- * ParseCL: parse command line.
- * Titles start from 0 (menu), chapters and angles start from 1.
- *****************************************************************************/
-static char *ParseCL( vlc_object_t *p_this, char *psz_name, vlc_bool_t b_force,
-                      int *i_title, int *i_chapter, int *i_angle )
-{
-    char *psz_parser, *psz_source, *psz_next;
-
-    psz_source = strdup( psz_name );
-    if( psz_source == NULL ) return NULL;
-
-    *i_title = -1;
-    *i_chapter = 1;
-    *i_angle = 1;
-
-    /* Start with the end, because you could have :
-     * dvdnav:/Volumes/my@toto/VIDEO_TS@1,1
-     * (yes, this is kludgy). */
-    for( psz_parser = psz_source + strlen(psz_source) - 1;
-         psz_parser >= psz_source && *psz_parser != '@';
-         psz_parser-- );
-
-    if( psz_parser >= psz_source && *psz_parser == '@' )
-    {
-        /* Found options */
-        *psz_parser = '\0';
-        ++psz_parser;
-
-        *i_title = (int)strtol( psz_parser, &psz_next, 10 );
-        if( *psz_next )
-        {
-            psz_parser = psz_next + 1;
-            *i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
-            if( *psz_next )
-            {
-                *i_angle = (int)strtol( psz_next + 1, NULL, 10 );
-            }
-        }
-    }
-
-    *i_title   = *i_title >= 0 ? *i_title : -1;
-    *i_chapter = *i_chapter > 0 ? *i_chapter : 1;
-    *i_angle   = *i_angle > 0 ? *i_angle : 1;
-
-    if( !*psz_source )
-    {
-        free( psz_source );
-        if( !b_force )
-        {
-            return NULL;
-        }
-        psz_source = config_GetPsz( p_this, "dvd" );
-        if( !psz_source ) return NULL;
-    }
-
-#ifdef WIN32
-    if( psz_source[0] && psz_source[1] == ':' &&
-        psz_source[2] == '\\' && psz_source[3] == '\0' )
-    {
-        psz_source[2] = '\0';
-    }
-#endif
-
-    return psz_source;
-}
-
 static void DemuxTitles( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
@@ -855,8 +770,6 @@ static void DemuxTitles( demux_t *p_demux )
         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
         {
             s = vlc_seekpoint_New();
-            s->psz_name = malloc( strlen( _("Chapter %i") ) + 20 );
-            sprintf( s->psz_name, _("Chapter %i"), j + 1 );
             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
         }
 
index 43a5511..a72f32d 100644 (file)
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
+#define ANGLE_TEXT N_("DVD angle")
+#define ANGLE_LONGTEXT N_( \
+    "Allows you to select the default DVD angle." )
+
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Allows you to modify the default caching value for DVDread streams. " \
@@ -84,13 +88,15 @@ static void Close( vlc_object_t * );
 
 vlc_module_begin();
     set_description( _("DVDRead Input") );
+    add_integer( "dvdread-angle", 1, NULL, ANGLE_TEXT,
+        ANGLE_LONGTEXT, VLC_FALSE );
     add_integer( "dvdread-caching", DEFAULT_PTS_DELAY / 1000, NULL,
         CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
     add_string( "dvdread-css-method", NULL, NULL, CSSMETHOD_TEXT,
                 CSSMETHOD_LONGTEXT, VLC_TRUE );
         change_string_list( psz_css_list, psz_css_list_text, 0 );
     set_capability( "access_demux", 0 );
-    //add_shortcut( "dvd" );
+    add_shortcut( "dvd" );
     add_shortcut( "dvdread" );
     add_shortcut( "dvdsimple" );
     set_callbacks( Open, Close );
@@ -150,13 +156,11 @@ struct demux_sys_t
     uint32_t clut[16];
 };
 
-static char *ParseCL( vlc_object_t *, char *, vlc_bool_t, int *, int *, int *);
-
 static int Control   ( demux_t *, int, va_list );
 static int Demux     ( demux_t * );
 static int DemuxBlock( demux_t *, uint8_t *, int );
 
-static void DemuxTitles( demux_t *, int *, int *, int * );
+static void DemuxTitles( demux_t *, int * );
 static void ESNew( demux_t *, int, int );
 
 static int  DvdReadSetArea  ( demux_t *, int, int, int );
@@ -171,18 +175,30 @@ static int Open( vlc_object_t *p_this )
 {
     demux_t      *p_demux = (demux_t*)p_this;
     demux_sys_t  *p_sys;
-    int          i_title, i_chapter, i_angle;
     char         *psz_name;
     char         *psz_dvdcss_env;
     dvd_reader_t *p_dvdread;
     ifo_handle_t *p_vmg_file;
+    vlc_value_t  val;
 
-    psz_name = ParseCL( VLC_OBJECT(p_demux), p_demux->psz_path, VLC_TRUE,
-                        &i_title, &i_chapter, &i_angle );
-    if( !psz_name )
+    if( !p_demux->psz_path || !*p_demux->psz_path )
     {
-        return VLC_EGENERIC;
+        /* Only when selected */
+        if( !p_this->b_force ) return VLC_EGENERIC;
+
+        psz_name = var_CreateGetString( p_this, "dvd" );
+        if( !psz_name || !*psz_name )
+        {
+            if( psz_name ) free( psz_name );
+            return VLC_EGENERIC;
+        }
     }
+    else psz_name = strdup( p_demux->psz_path );
+
+#ifdef WIN32
+    if( psz_name[0] && psz_name[1] == ':' &&
+        psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
+#endif
 
     /* Override environment variable DVDCSS_METHOD with config option
      * (FIXME: this creates a small memory leak) */
@@ -193,7 +209,6 @@ static int Open( vlc_object_t *p_this )
 
         psz_env = malloc( strlen("DVDCSS_METHOD=") +
                           strlen( psz_dvdcss_env ) + 1 );
-
         if( !psz_env )
         {
             free( psz_dvdcss_env );
@@ -239,11 +254,13 @@ static int Open( vlc_object_t *p_this )
     p_sys->p_vts_file = NULL;
 
     p_sys->i_title = p_sys->i_chapter = -1;
-    p_sys->i_angle = i_angle;
 
-    DemuxTitles( p_demux, &i_title, &i_chapter, &i_angle );
+    var_Create( p_demux, "dvdread-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+    var_Get( p_demux, "dvdread-angle", &val );
+    p_sys->i_angle = val.i_int > 0 ? val.i_int : 1;
 
-    DvdReadSetArea( p_demux, i_title, i_chapter, i_angle );
+    DemuxTitles( p_demux, &p_sys->i_angle );
+    DvdReadSetArea( p_demux, 0, 0, p_sys->i_angle );
 
     /* Update default_pts to a suitable value for dvdread access */
     var_Create( p_demux, "dvdread-caching",
@@ -350,6 +367,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_GET_TITLE_INFO:
             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
             pi_int    = (int*)va_arg( args, int* );
+            *((int*)va_arg( args, int* )) = 1; /* Title offset */
+            *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
 
             /* Duplicate title infos */
             *pi_int = p_sys->i_titles;
@@ -433,14 +452,18 @@ static int Demux( demux_t *p_demux )
         /* End of title */
         if( p_sys->i_next_vobu > p_sys->i_title_end_block )
         {
-            if( p_sys->i_title + 1 >= p_sys->i_titles ) return 0; /* EOF */
+            if( p_sys->i_title + 1 >= p_sys->i_titles )
+            {
+                return 0; /* EOF */
+            }
 
             DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
         }
 
         if( p_sys->i_pack_len >= 1024 )
         {
-            msg_Err( p_demux, "i_pack_len >= 1024. This shouldn't happen!" );
+            msg_Err( p_demux, "i_pack_len >= 1024 (%i). "
+                     "This shouldn't happen!", p_sys->i_pack_len );
             return 0; /* EOF */
         }
 
@@ -454,7 +477,10 @@ static int Demux( demux_t *p_demux )
 
     if( p_sys->i_cur_block > p_sys->i_title_end_block )
     {
-        if( p_sys->i_title + 1 >= p_sys->i_titles ) return 0; /* EOF */
+        if( p_sys->i_title + 1 >= p_sys->i_titles )
+        {
+            return 0; /* EOF */
+        }
 
         DvdReadSetArea( p_demux, p_sys->i_title + 1, 0, -1 );
     }
@@ -901,7 +927,7 @@ static int DvdReadSetArea( demux_t *p_demux, int i_title, int i_chapter,
      * Chapter selection
      */
 
-    if( i_chapter >= 0 && i_chapter <= p_sys->i_chapters )
+    if( i_chapter >= 0 && i_chapter < p_sys->i_chapters )
     {
         pgc_id = p_vts->vts_ptt_srpt->title[
                      p_sys->i_ttn - 1].ptt[i_chapter].pgcn;
@@ -1052,6 +1078,7 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
      * care about.
      */
     p_sys->i_cur_block = p_sys->dsi_pack.dsi_gi.nv_pck_lbn;
+    p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
 
     /*
      * If we're not at the end of this cell, we can determine the next
@@ -1060,7 +1087,12 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
      * avoiding the doubled scenes in The Matrix, and makes our life
      * really happy.
      */
-    if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL )
+
+    p_sys->i_next_vobu = p_sys->i_cur_block +
+        ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
+
+    if( p_sys->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL
+        && p_sys->i_angle > 1 )
     {
         switch( ( p_sys->dsi_pack.sml_pbi.category & 0xf000 ) >> 12 )
         {
@@ -1076,7 +1108,6 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
             {
                 p_sys->i_next_vobu = p_sys->i_cur_block +
                     p_sys->dsi_pack.dsi_gi.vobu_ea + 1;
-                p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
             }
             break;
         case 0x5:
@@ -1100,16 +1131,14 @@ static void DvdReadHandleDSI( demux_t *p_demux, uint8_t *p_data )
         default:
             p_sys->i_next_vobu = p_sys->i_cur_block +
                 ( p_sys->dsi_pack.vobu_sri.next_vobu & 0x7fffffff );
-            p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
             break;
         }
     }
-    else
+    else if( p_sys->dsi_pack.vobu_sri.next_vobu == SRI_END_OF_CELL )
     {
         p_sys->i_cur_cell = p_sys->i_next_cell;
         DvdReadFindCell( p_demux );
 
-        p_sys->i_pack_len = p_sys->dsi_pack.dsi_gi.vobu_ea;
         p_sys->i_next_vobu =
             p_sys->p_cur_pgc->cell_playback[p_sys->i_cur_cell].first_sector;
     }
@@ -1187,8 +1216,7 @@ static void DvdReadFindCell( demux_t *p_demux )
 /*****************************************************************************
  * DemuxTitles: get the titles/chapters structure
  *****************************************************************************/
-static void DemuxTitles( demux_t *p_demux,
-                         int *pi_title, int *pi_chapter, int *pi_angle )
+static void DemuxTitles( demux_t *p_demux, int *pi_angle )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
     input_title_t *t;
@@ -1211,97 +1239,15 @@ static void DemuxTitles( demux_t *p_demux,
         msg_Dbg( p_demux, "title %d has %d chapters", i, i_chapters );
 
         t = vlc_input_title_New();
-        t->psz_name = malloc( strlen( _("Title %i") ) + 20 );
-        sprintf( t->psz_name, _("Title %i"), i + 1 );
 
         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
         {
             s = vlc_seekpoint_New();
-            s->psz_name = malloc( strlen( _("Chapter %i") ) + 20 );
-            sprintf( s->psz_name, _("Chapter %i"), j + 1 );
             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
         }
 
         TAB_APPEND( p_sys->i_titles, p_sys->titles, t );
     }
 
-    /* Set forced title/chapter/angle */
-    *pi_title = (*pi_title >= 0 && *pi_title < i_titles) ? *pi_title : 0;
-    *pi_chapter = (*pi_chapter >= 0 && *pi_chapter <
-        tt_srpt->title[*pi_title].nr_of_ptts) ? *pi_chapter : 0;
-
 #undef tt_srpt
 }
-
-/*****************************************************************************
- * ParseCL: parse command line. Titles, chapters and angles start from 1.
- *****************************************************************************/
-static char *ParseCL( vlc_object_t *p_this, char *psz_name, vlc_bool_t b_force,
-                      int *i_title, int *i_chapter, int *i_angle )
-{
-    char *psz_parser, *psz_source, *psz_next;
-
-    psz_source = strdup( psz_name );
-    if( psz_source == NULL ) return NULL;
-
-    *i_title = 1;
-    *i_chapter = 1;
-    *i_angle = 1;
-
-    /* Start with the end, because you could have :
-     * dvdnav:/Volumes/my@toto/VIDEO_TS@1,1
-     * (yes, this is kludgy). */
-    for( psz_parser = psz_source + strlen(psz_source) - 1;
-         psz_parser >= psz_source && *psz_parser != '@';
-         psz_parser-- );
-
-    if( psz_parser >= psz_source && *psz_parser == '@' )
-    {
-        /* Found options */
-        *psz_parser = '\0';
-        ++psz_parser;
-
-        *i_title = (int)strtol( psz_parser, &psz_next, 10 );
-        if( *psz_next )
-        {
-            psz_parser = psz_next + 1;
-            *i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
-            if( *psz_next )
-            {
-                *i_angle = (int)strtol( psz_next + 1, NULL, 10 );
-            }
-        }
-    }
-
-    *i_title   = *i_title > 0 ? *i_title : 1;
-    *i_chapter = *i_chapter > 0 ? *i_chapter : 1;
-    *i_angle   = *i_angle > 0 ? *i_angle : 1;
-
-    if( !*psz_source )
-    {
-        free( psz_source );
-        if( !b_force )
-        {
-            return NULL;
-        }
-        psz_source = config_GetPsz( p_this, "dvd" );
-        if( !psz_source ) return NULL;
-    }
-
-#ifdef WIN32
-    if( psz_source[0] && psz_source[1] == ':' &&
-        psz_source[2] == '\\' && psz_source[3] == '\0' )
-    {
-        psz_source[2] = '\0';
-    }
-#endif
-
-    msg_Dbg( p_this, "dvdroot=%s title=%d chapter=%d angle=%d",
-             psz_source, *i_title, *i_chapter, *i_angle );
-
-    /* Get back to a 0-based offset */
-    (*i_title)--;
-    (*i_chapter)--;
-
-    return psz_source;
-}
index e0a95e9..4af7554 100644 (file)
@@ -53,8 +53,8 @@ static void       ControlReduce( input_thread_t * );
 static vlc_bool_t Control( input_thread_t *, int, vlc_value_t );
 
 
-static void UpdateFromAccess( input_thread_t * );
-static void UpdateFromDemux( input_thread_t * );
+static int  UpdateFromAccess( input_thread_t * );
+static int  UpdateFromDemux( input_thread_t * );
 
 static void UpdateItemLength( input_thread_t *, int64_t i_length );
 
@@ -62,6 +62,7 @@ static void ParseOption( input_thread_t *p_input, const char *psz_option );
 
 static void DecodeUrl  ( char * );
 static void MRLSplit( input_thread_t *, char *, char **, char **, char ** );
+static void MRLSections( input_thread_t *, char *, int *, int *, int *, int *);
 
 static input_source_t *InputSourceNew( input_thread_t *);
 static int  InputSourceInit( input_thread_t *, input_source_t *,
@@ -123,6 +124,7 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     p_input->i_stop  = 0;
     p_input->i_title = 0;
     p_input->title   = NULL;
+    p_input->i_title_offset = p_input->i_seekpoint_offset = 0;
     p_input->i_state = INIT_S;
     p_input->i_rate  = INPUT_RATE_DEFAULT;
     p_input->i_bookmark = 0;
@@ -132,7 +134,6 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     p_input->b_out_pace_control = VLC_FALSE;
     p_input->i_pts_delay = 0;
 
-
     /* Init Input fields */
     p_input->input.p_item = p_item;
     p_input->input.p_access = NULL;
@@ -141,6 +142,7 @@ input_thread_t *__input_CreateThread( vlc_object_t *p_parent,
     p_input->input.b_title_demux = VLC_FALSE;
     p_input->input.i_title  = 0;
     p_input->input.title    = NULL;
+    p_input->input.i_title_offset = p_input->input.i_seekpoint_offset = 0;
     p_input->input.b_can_pace_control = VLC_TRUE;
     p_input->input.b_eof = VLC_FALSE;
     p_input->input.i_cr_average = 0;
@@ -344,18 +346,19 @@ static int Run( input_thread_t *p_input )
                 if( p_input->input.b_title_demux &&
                     p_input->input.p_demux->info.i_update )
                 {
-                    UpdateFromDemux( p_input );
+                    i_ret = UpdateFromDemux( p_input );
                     b_force_update = VLC_TRUE;
                 }
                 else if( !p_input->input.b_title_demux &&
                           p_input->input.p_access &&
                           p_input->input.p_access->info.i_update )
                 {
-                    UpdateFromAccess( p_input );
+                    i_ret = UpdateFromAccess( p_input );
                     b_force_update = VLC_TRUE;
                 }
             }
-            else if( i_ret == 0 )    /* EOF */
+
+            if( i_ret == 0 )    /* EOF */
             {
                 vlc_value_t repeat;
 
@@ -377,9 +380,21 @@ static int Run( input_thread_t *p_input )
                         var_Set( p_input, "input-repeat", repeat );
                     }
 
-                    /* Seek to title 0 position 0(start) */
-                    val.i_int = 0;
-                    input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
+                    /* Seek to start title/seekpoint */
+                    val.i_int = p_input->input.i_title_start -
+                        p_input->input.i_title_offset;
+                    if( val.i_int < 0 || val.i_int >= p_input->input.i_title )
+                        val.i_int = 0;
+                    input_ControlPush( p_input,
+                                       INPUT_CONTROL_SET_TITLE, &val );
+
+                    val.i_int = p_input->input.i_seekpoint_start -
+                        p_input->input.i_seekpoint_offset;
+                    if( val.i_int > 0 /* TODO: check upper boundary */ )
+                        input_ControlPush( p_input,
+                                           INPUT_CONTROL_SET_SEEKPOINT, &val );
+
+                    /* Seek to start position */
                     if( p_input->i_start > 0 )
                     {
                         val.i_time = p_input->i_start;
@@ -421,8 +436,7 @@ static int Run( input_thread_t *p_input )
         }
         vlc_mutex_unlock( &p_input->lock_control );
 
-        if( b_force_update ||
-            i_intf_update < mdate() )
+        if( b_force_update || i_intf_update < mdate() )
         {
             vlc_value_t val;
             double f_pos;
@@ -529,6 +543,8 @@ static int Init( input_thread_t * p_input )
     /* Create global title (from master) */
     p_input->i_title = p_input->input.i_title;
     p_input->title   = p_input->input.title;
+    p_input->i_title_offset = p_input->input.i_title_offset;
+    p_input->i_seekpoint_offset = p_input->input.i_seekpoint_offset;
     if( p_input->i_title > 0 )
     {
         /* Setup variables */
@@ -547,8 +563,7 @@ static int Init( input_thread_t * p_input )
     /* If the desynchronisation requested by the user is < 0, we need to
      * cache more data. */
     var_Get( p_input, "audio-desync", &val );
-    if( val.i_int < 0 )
-        p_input->i_pts_delay -= (val.i_int * 1000);
+    if( val.i_int < 0 ) p_input->i_pts_delay -= (val.i_int * 1000);
 
     /* Load master infos */
     /* Init length */
@@ -559,6 +574,17 @@ static int Init( input_thread_t * p_input )
 
         UpdateItemLength( p_input, val.i_time );
     }
+
+    /* Start title/chapter */
+    val.i_int = p_input->input.i_title_start -
+        p_input->input.i_title_offset;
+    if( val.i_int > 0 && val.i_int < p_input->input.i_title )
+        input_ControlPush( p_input, INPUT_CONTROL_SET_TITLE, &val );
+    val.i_int = p_input->input.i_seekpoint_start -
+        p_input->input.i_seekpoint_offset;
+    if( val.i_int > 0 /* TODO: check upper boundary */ )
+        input_ControlPush( p_input, INPUT_CONTROL_SET_SEEKPOINT, &val );
+
     /* Start time*/
     /* Set start time */
     p_input->i_start = (int64_t)var_GetInteger( p_input, "start-time" ) *
@@ -1344,7 +1370,7 @@ static vlc_bool_t Control( input_thread_t *p_input, int i_type,
 /*****************************************************************************
  * UpdateFromDemux:
  *****************************************************************************/
-static void UpdateFromDemux( input_thread_t *p_input )
+static int UpdateFromDemux( input_thread_t *p_input )
 {
     demux_t *p_demux = p_input->input.p_demux;
     vlc_value_t v;
@@ -1366,12 +1392,38 @@ static void UpdateFromDemux( input_thread_t *p_input )
         p_demux->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
     }
     p_demux->info.i_update &= ~INPUT_UPDATE_SIZE;
+
+    /* Hmmm only works with master input */
+    if( p_input->input.p_demux == p_demux )
+    {
+        int i_title_end = p_input->input.i_title_end -
+            p_input->input.i_title_offset;
+        int i_seekpoint_end = p_input->input.i_seekpoint_end -
+            p_input->input.i_seekpoint_offset;
+
+        if( i_title_end >= 0 && i_seekpoint_end >=0 )
+        {
+            if( p_demux->info.i_title > i_title_end ||
+                ( p_demux->info.i_title == i_title_end &&
+                  p_demux->info.i_seekpoint > i_seekpoint_end ) ) return 0;
+        }
+        else if( i_seekpoint_end >=0 )
+        {
+            if( p_demux->info.i_seekpoint > i_seekpoint_end ) return 0;
+        }
+        else if( i_title_end >= 0 )
+        {
+            if( p_demux->info.i_title > i_title_end ) return 0;
+        }
+    }
+
+    return 1;
 }
 
 /*****************************************************************************
  * UpdateFromAccess:
  *****************************************************************************/
-static void UpdateFromAccess( input_thread_t *p_input )
+static int UpdateFromAccess( input_thread_t *p_input )
 {
     access_t *p_access = p_input->input.p_access;
     vlc_value_t v;
@@ -1395,6 +1447,32 @@ static void UpdateFromAccess( input_thread_t *p_input )
         p_access->info.i_update &= ~INPUT_UPDATE_SEEKPOINT;
     }
     p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
+
+    /* Hmmm only works with master input */
+    if( p_input->input.p_access == p_access )
+    {
+        int i_title_end = p_input->input.i_title_end -
+            p_input->input.i_title_offset;
+        int i_seekpoint_end = p_input->input.i_seekpoint_end -
+            p_input->input.i_seekpoint_offset;
+
+        if( i_title_end >= 0 && i_seekpoint_end >=0 )
+        {
+            if( p_access->info.i_title > i_title_end ||
+                ( p_access->info.i_title == i_title_end &&
+                  p_access->info.i_seekpoint > i_seekpoint_end ) ) return 0;
+        }
+        else if( i_seekpoint_end >=0 )
+        {
+            if( p_access->info.i_seekpoint > i_seekpoint_end ) return 0;
+        }
+        else if( i_title_end >= 0 )
+        {
+            if( p_access->info.i_title > i_title_end ) return 0;
+        }
+    }
+
+    return 1;
 }
 
 /*****************************************************************************
@@ -1452,6 +1530,10 @@ static int InputSourceInit( input_thread_t *p_input,
     msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'",
              psz_mrl, psz_access, psz_demux, psz_path );
 
+    /* Find optional titles and seekpoints */
+    MRLSections( p_input, psz_path, &in->i_title_start, &in->i_title_end,
+                 &in->i_seekpoint_start, &in->i_seekpoint_end );
+
     if( psz_forced_demux && *psz_forced_demux )
         psz_demux = psz_forced_demux;
 
@@ -1472,9 +1554,9 @@ static int InputSourceInit( input_thread_t *p_input,
         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
 
         in->b_title_demux = VLC_TRUE;
-        if( demux2_Control( in->p_demux,
-                            DEMUX_GET_TITLE_INFO,
-                            &in->title, &in->i_title ) )
+        if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
+                            &in->title, &in->i_title,
+                            &in->i_title_offset, &in->i_seekpoint_offset ) )
         {
             in->i_title = 0;
             in->title   = NULL;
@@ -1537,9 +1619,10 @@ static int InputSourceInit( input_thread_t *p_input,
         p_input->i_pts_delay = __MAX( p_input->i_pts_delay, i_pts_delay );
 
         in->b_title_demux = VLC_FALSE;
-        if( access2_Control( in->p_access,
-                             ACCESS_GET_TITLE_INFO,
-                             &in->title, &in->i_title ) )
+        if( access2_Control( in->p_access, ACCESS_GET_TITLE_INFO,
+                             &in->title, &in->i_title,
+                             &in->i_title_offset, &in->i_seekpoint_offset ) )
+
         {
             in->i_title = 0;
             in->title   = NULL;
@@ -1578,7 +1661,8 @@ static int InputSourceInit( input_thread_t *p_input,
         if( in->i_title <= 0 )
         {
             if( demux2_Control( in->p_demux, DEMUX_GET_TITLE_INFO,
-                                &in->title, &in->i_title ) )
+                                &in->title, &in->i_title,
+                                &in->i_title_offset, &in->i_seekpoint_offset ))
             {
                 in->i_title = 0;
                 in->title   = NULL;
@@ -1871,6 +1955,10 @@ static void ParseOption( input_thread_t *p_input, const char *psz_option )
     return;
 }
 
+/*****************************************************************************
+ * MRLSplit: parse the access, demux and url part of the
+ *           Media Resource Locator.
+ *****************************************************************************/
 static void MRLSplit( input_thread_t *p_input, char *psz_dup,
                       char **ppsz_access, char **ppsz_demux, char **ppsz_path )
 {
@@ -1928,3 +2016,56 @@ static void MRLSplit( input_thread_t *p_input, char *psz_dup,
     else
         *ppsz_path = psz_path;
 }
+
+/*****************************************************************************
+ * MRLSections: parse title and seekpoint info from the Media Resource Locator.
+ *
+ * Syntax:
+ * [url][@[title-start][,chapter-start][-[title-end][,chapter-end]]]
+ *****************************************************************************/
+static void MRLSections( input_thread_t *p_input, char *psz_source,
+                         int *pi_title_start, int *pi_title_end,
+                         int *pi_chapter_start, int *pi_chapter_end )
+{
+    char *psz, *psz_end, *psz_next;
+
+    *pi_title_start = *pi_title_end = -1;
+    *pi_chapter_start = *pi_chapter_end = -1;
+
+    /* Start by parsing titles and chapters */
+    if( !psz_source || !( psz = strrchr( psz_source, '@' ) ) ) return;
+
+    *psz++ = 0;
+
+    /* Separate start and end */
+    if( ( psz_end = strchr( psz, '-' ) ) ) *psz_end++ = 0;
+
+    /* Look for the start title */
+    *pi_title_start = strtol( psz, &psz_next, 0 );
+    if( !*pi_title_start && psz == psz_next ) *pi_title_start = -1;
+    *pi_title_end = *pi_title_start;
+    psz = psz_next;
+
+    /* Look for the start chapter */
+    if( *psz ) psz++;
+    *pi_chapter_start = strtol( psz, &psz_next, 0 );
+    if( !*pi_chapter_start && psz == psz_next ) *pi_chapter_start = -1;
+    *pi_chapter_end = *pi_chapter_start;
+
+    if( psz_end )
+    {
+        /* Look for the end title */
+        *pi_title_end = strtol( psz_end, &psz_next, 0 );
+        if( !*pi_title_end && psz_end == psz_next ) *pi_title_end = -1;
+        psz_end = psz_next;
+
+        /* Look for the end chapter */
+        if( *psz_end ) psz_end++;
+        *pi_chapter_end = strtol( psz_end, &psz_next, 0 );
+        if( !*pi_chapter_end && psz_end == psz_next ) *pi_chapter_end = -1;
+    }
+
+    msg_Dbg( p_input, "source=`%s' title=%d/%d seekpoint=%d/%d",
+             psz_source, *pi_title_start, *pi_chapter_start,
+             *pi_title_end, *pi_chapter_end );
+}
index e406a82..c75933b 100644 (file)
@@ -281,8 +281,8 @@ void input_ControlVarNavigation( input_thread_t *p_input )
         if( p_input->title[i]->psz_name == NULL ||
             *p_input->title[i]->psz_name == '\0' )
         {
-            text.psz_string = malloc( strlen( _("Title %i") ) + 20 );
-            sprintf( text.psz_string, _("Title %i"), i );
+            asprintf( &text.psz_string, _("Title %i"),
+                      i + p_input->i_title_offset );
         }
         else
         {
@@ -304,8 +304,8 @@ void input_ControlVarNavigation( input_thread_t *p_input )
                 *p_input->title[i]->seekpoint[j]->psz_name == '\0' )
             {
                 /* Default value */
-                text2.psz_string = malloc( strlen( _("Chapter %i") ) + 20 );
-                sprintf( text2.psz_string, _("Chapter %i"), j );
+                asprintf( &text2.psz_string, _("Chapter %i"),
+                          j + p_input->i_seekpoint_offset );
             }
             else
             {
@@ -364,8 +364,8 @@ void input_ControlVarTitle( input_thread_t *p_input, int i_title )
             *t->seekpoint[i]->psz_name == '\0' )
         {
             /* Default value */
-            text.psz_string = malloc( strlen( _("Chapter %i") ) + 20 );
-            sprintf( text.psz_string, _("Chapter %i"), i );
+            asprintf( &text.psz_string, _("Chapter %i"),
+                      i + p_input->i_seekpoint_offset );
         }
         else
         {