Commit 25d2a663 authored by Gildas Bazin's avatar Gildas Bazin

* src/input/*, include/vlc_input.h: the MRL is now parsed for titles/chapters directly in the core.

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