Commit f6c80a75 authored by Stéphane Borel's avatar Stéphane Borel

-Various bug fixes in dvd_netlist. Some bugs seem to remain though.

-New function input_ToggleES for interaction with interface.
-Changes in gnome interface : navigation menus are now splited, there
are radio item in menus and the code should be better.
-First step for dvd_ifo rewritting. Now allocation/disallocation is
being done as it has to be.
-Fixed a bug in title management that make dvd like Seven work.
parent e38b7772
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* control the pace of reading. * control the pace of reading.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.28 2001/03/07 10:31:10 stef Exp $ * $Id: input_ext-intf.h,v 1.29 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -353,3 +353,6 @@ void input_Seek ( struct input_thread_s *, off_t ); ...@@ -353,3 +353,6 @@ void input_Seek ( struct input_thread_s *, off_t );
void input_DumpStream( struct input_thread_s * ); void input_DumpStream( struct input_thread_s * );
char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t ); char * input_OffsetToTime( struct input_thread_s *, char * psz_buffer, off_t );
int input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, int ); int input_ChangeES ( struct input_thread_s *, struct es_descriptor_s *, int );
int input_ToggleES ( struct input_thread_s *,
struct es_descriptor_s *,
boolean_t );
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.c: Functions for ifo parsing * dvd_ifo.c: Functions for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.c,v 1.15 2001/03/06 10:21:59 massiot Exp $ * $Id: dvd_ifo.c,v 1.16 2001/04/01 07:31:38 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -49,95 +49,18 @@ ...@@ -49,95 +49,18 @@
/* /*
* Local prototypes * Local prototypes
*/ */
static vmg_t ReadVMG ( ifo_t* ); void CommandRead ( command_desc_t );
void CommandRead( ifo_command_t ); static int ReadTitle ( ifo_t * , title_t * );
static int FreeTitle ( title_t * );
/* static int ReadUnitInf ( ifo_t * , unit_inf_t * );
* IFO Management. static int FreeUnitInf ( unit_inf_t * );
*/ static int ReadTitleUnit ( ifo_t * , title_unit_t * );
static int FreeTitleUnit ( title_unit_t * );
/***************************************************************************** static int ReadVobuMap ( ifo_t * , vobu_map_t * );
* IfoInit : Creates an ifo structure and prepares for parsing directly static int FreeVobuMap ( vobu_map_t * );
* on DVD device. static int ReadCellInf ( ifo_t * , cell_inf_t * );
*****************************************************************************/ static int FreeCellInf ( cell_inf_t * );
ifo_t IfoInit( int i_fd ) static int FreeTitleSet ( vts_t * );
{
ifo_t ifo;
u32 i_lba;
/* If we are here the dvd device has already been opened */
ifo.i_fd = i_fd;
i_lba = UDFFindFile( i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
ifo.i_off = (off_t)(i_lba) * DVD_LB_SIZE;
ifo.i_pos = lseek( ifo.i_fd, ifo.i_off, SEEK_SET );
/* Video Manager Initialization */
intf_WarnMsg( 2, "ifo: initializing VMG" );
ifo.vmg = ReadVMG( &ifo );
return ifo;
}
/*****************************************************************************
* IfoEnd : Frees all the memory allocated to ifo structures
*****************************************************************************/
void IfoEnd( ifo_t* p_ifo )
{
#if 0
int i,j;
/* Free structures from video title sets */
for( j=0 ; j<p_ifo->vmg.mat.i_tts_nb ; j++ )
{
free( p_ifo->p_vts[j].vobu_admap.pi_vobu_ssector );
free( p_ifo->p_vts[j].c_adt.p_cell_inf );
free( p_ifo->p_vts[j].m_vobu_admap.pi_vobu_ssector );
free( p_ifo->p_vts[j].m_c_adt.p_cell_inf );
for( i=0 ; i<p_ifo->p_vts[j].tmap_ti.i_nb ; i++ )
{
free( p_ifo->p_vts[j].tmap_ti.p_tmap[i].pi_sector );
}
free( p_ifo->p_vts[j].tmap_ti.pi_sbyte );
free( p_ifo->p_vts[j].tmap_ti.p_tmap );
free( p_ifo->p_vts[j].pgci_ti.p_srp );
for( i=0 ; i<p_ifo->p_vts[j].pgci_ut.i_lu_nb ; i++ )
{
free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf[i].p_srp );
}
free( p_ifo->p_vts[j].pgci_ut.p_pgci_inf );
free( p_ifo->p_vts[j].pgci_ut.p_lu );
}
free( p_ifo->p_vts );
/* Free structures from video manager */
free( p_ifo->vmg.vobu_admap.pi_vobu_ssector );
free( p_ifo->vmg.c_adt.p_cell_inf );
for( i=0 ; i<p_ifo->vmg.pgci_ut.i_lu_nb ; i++ )
{
free( p_ifo->vmg.pgci_ut.p_pgci_inf[i].p_srp );
}
free( p_ifo->vmg.pgci_ut.p_pgci_inf );
free( p_ifo->vmg.pgci_ut.p_lu );
for( i=1 ; i<=8 ; i++ )
{
free( p_ifo->vmg.ptl_mait.p_ptl_mask->ppi_ptl_mask[i] );
}
free( p_ifo->vmg.ptl_mait.p_ptl_desc );
free( p_ifo->vmg.ptl_mait.p_ptl_mask );
free( p_ifo->vmg.vts_atrt.pi_vts_atrt_sbyte );
free( p_ifo->vmg.vts_atrt.p_vts_atrt );
free( p_ifo->vmg.pgc.p_cell_pos_inf );
free( p_ifo->vmg.pgc.p_cell_play_inf );
free( p_ifo->vmg.pgc.prg_map.pi_entry_cell );
free( p_ifo->vmg.pgc.com_tab.p_cell_com );
free( p_ifo->vmg.pgc.com_tab.p_post_com );
free( p_ifo->vmg.pgc.com_tab.p_pre_com );
#endif
return;
}
/* /*
* Macros to process ifo files * Macros to process ifo files
...@@ -198,960 +121,1252 @@ void IfoEnd( ifo_t* p_ifo ) ...@@ -198,960 +121,1252 @@ void IfoEnd( ifo_t* p_ifo )
p_ifo->i_pos + (i_len), SEEK_SET ); \ p_ifo->i_pos + (i_len), SEEK_SET ); \
} }
/* /*
* Function common to Video Manager and Video Title set Processing * IFO Management.
*/ */
/***************************************************************************** /*****************************************************************************
* ReadPGC : Fills the Program Chain structure. * IfoInit : Creates an ifo structure and prepares for parsing directly
* on DVD device. Then reads information from the management table.
*****************************************************************************/ *****************************************************************************/
#define GETCOMMAND( p_com ) \ int IfoInit( ifo_t ** pp_ifo, int i_fd )
{ \ {
read( p_ifo->i_fd , (p_com) , 8 ); \ ifo_t * p_ifo;
/*fprintf(stderr, "Pos : %lld Type : %d direct : %d cmd : %d dircmp : %d cmp : %d subcmd : %d v0 : %d v2 : %d v4 : %d\n", \ u64 i_temp;
(long long)(p_ifo->i_pos - i_start), \ u32 i_lba;
(int)((p_com)->i_type), \ int i, j, k;
(int)((p_com)->i_direct), \ off_t i_start;
(int)((p_com)->i_cmd), \
(int)((p_com)->i_dir_cmp), \
(int)((p_com)->i_cmp), \ p_ifo = malloc( sizeof(ifo_t) );
(int)((p_com)->i_sub_cmd), \ if( p_ifo == NULL )
(int)((p_com)->data.pi_16[0]), \ {
(int)((p_com)->data.pi_16[1]), \ intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
(int)((p_com)->data.pi_16[2]));*/ \ return -1;
/* CommandRead( *(p_com) );*/ \
p_ifo->i_pos += 8; \
} }
static pgc_t ReadPGC( ifo_t* p_ifo ) *pp_ifo = p_ifo;
{
pgc_t pgc;
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "PGC\n" ); /* if we are here the dvd device has already been opened */
p_ifo->i_fd = i_fd;
/* find the start sector of video information on the dvd */
i_lba = UDFFindFile( i_fd, "/VIDEO_TS/VIDEO_TS.IFO");
p_ifo->i_off = (off_t)(i_lba) * DVD_LB_SIZE;
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off, SEEK_SET );
/*
* read the video manager information table
*/
#define manager_inf p_ifo->vmg.manager_inf
//fprintf( stderr, "VMGI\n" );
GET( manager_inf.psz_id , 12 );
manager_inf.psz_id[12] = '\0';
GETL( &manager_inf.i_vmg_end_sector );
FLUSH( 12 );
GETL( &manager_inf.i_vmg_inf_end_sector );
FLUSH( 1 );
GETC( &manager_inf.i_spec_ver );
GETL( &manager_inf.i_cat );
GETS( &manager_inf.i_volume_nb );
GETS( &manager_inf.i_volume );
GETC( &manager_inf.i_disc_side );
FLUSH( 19 );
GETS( &manager_inf.i_title_set_nb );
GET( manager_inf.ps_provider_id, 32 );
GETLL( &manager_inf.i_pos_code );
FLUSH( 24 );
GETL( &manager_inf.i_vmg_inf_end_byte );
GETL( &manager_inf.i_first_play_title_start_byte );
FLUSH( 56 );
GETL( &manager_inf.i_vob_start_sector );
GETL( &manager_inf.i_title_inf_start_sector );
GETL( &manager_inf.i_title_unit_start_sector );
GETL( &manager_inf.i_parental_inf_start_sector );
GETL( &manager_inf.i_vts_inf_start_sector );
GETL( &manager_inf.i_text_data_start_sector );
GETL( &manager_inf.i_cell_inf_start_sector );
GETL( &manager_inf.i_vobu_map_start_sector );
FLUSH( 32 );
// GETS( &manager_inf.video_atrt );
FLUSH(2); FLUSH(2);
GETC( &pgc.i_prg_nb ); FLUSH( 1 );
GETC( &pgc.i_cell_nb ); GETC( &manager_inf.i_audio_nb );
//fprintf( stderr, "PGC: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb ); //fprintf( stderr, "vmgi audio nb : %d\n", manager_inf.i_audio_nb );
GETL( &pgc.i_play_time ); for( i=0 ; i < 8 ; i++ )
GETL( &pgc.i_prohibited_user_op );
for( i=0 ; i<8 ; i++ )
{ {
GETS( &pgc.pi_audio_status[i] ); GETLL( &i_temp );
} }
for( i=0 ; i<32 ; i++ ) FLUSH( 17 );
GETC( &manager_inf.i_spu_nb );
//fprintf( stderr, "vmgi subpic nb : %d\n", manager_inf.i_subpic_nb );
for( i=0 ; i < manager_inf.i_spu_nb ; i++ )
{ {
GETL( &pgc.pi_subpic_status[i] ); GET( &i_temp, 6 );
/* FIXME : take care of endianness */
} }
GETS( &pgc.i_next_pgc_nb );
GETS( &pgc.i_prev_pgc_nb ); /*
GETS( &pgc.i_goup_pgc_nb ); * read first play title.
//fprintf( stderr, "PGC: Prev: %d Next: %d Up: %d\n",pgc.i_prev_pgc_nb ,pgc.i_next_pgc_nb, pgc.i_goup_pgc_nb ); */
GETC( &pgc.i_still_time ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
GETC( &pgc.i_play_mode ); manager_inf.i_first_play_title_start_byte,
for( i=0 ; i<16 ; i++ ) SEEK_SET );
if( ReadTitle( p_ifo, &p_ifo->vmg.title ) < 0)
{ {
GETL( &pgc.pi_yuv_color[i] ); return -1;
/* FIXME : We have to erase the extra bit */
} }
GETS( &pgc.i_com_tab_sbyte );
GETS( &pgc.i_prg_map_sbyte );
GETS( &pgc.i_cell_play_inf_sbyte );
GETS( &pgc.i_cell_pos_inf_sbyte );
/* Parsing of pgc_com_tab_t */ /*
if( pgc.i_com_tab_sbyte ) * fills the title information structure.
*/
#define title_inf p_ifo->vmg.title_inf
if( manager_inf.i_title_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ pgc.i_com_tab_sbyte, SEEK_SET ); manager_inf.i_title_inf_start_sector *DVD_LB_SIZE,
GETS( &pgc.com_tab.i_pre_com_nb ); SEEK_SET );
GETS( &pgc.com_tab.i_post_com_nb ); //fprintf( stderr, "title inf\n" );
GETS( &pgc.com_tab.i_cell_com_nb );
GETS( &title_inf.i_title_nb );
//fprintf( stderr, "title_inf: TTU nb %d\n", title_inf.i_title_nb );
FLUSH( 2 ); FLUSH( 2 );
if( pgc.com_tab.i_pre_com_nb ) GETL( &title_inf.i_end_byte );
{
pgc.com_tab.p_pre_com = /* parsing of title attributes */
malloc(pgc.com_tab.i_pre_com_nb *sizeof(ifo_command_t)); title_inf.p_attr = malloc( title_inf.i_title_nb *sizeof(title_attr_t) );
if( pgc.com_tab.p_pre_com == NULL ) if( title_inf.p_attr == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
for( i=0 ; i<pgc.com_tab.i_pre_com_nb ; i++ )
{
GETCOMMAND( &pgc.com_tab.p_pre_com[i] );
}
}
if( pgc.com_tab.i_post_com_nb )
{ {
pgc.com_tab.p_post_com = intf_ErrMsg( "ifo error: out of memory in IfoInit" );
malloc(pgc.com_tab.i_post_com_nb *sizeof(ifo_command_t)); return -1;
if( pgc.com_tab.p_post_com == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
for( i=0 ; i<pgc.com_tab.i_post_com_nb ; i++ )
{
GETCOMMAND( &pgc.com_tab.p_post_com[i] );
}
} }
if( pgc.com_tab.i_cell_com_nb )
for( i = 0 ; i < title_inf.i_title_nb ; i++ )
{ {
pgc.com_tab.p_cell_com = GETC( &title_inf.p_attr[i].i_play_type );
malloc(pgc.com_tab.i_cell_com_nb *sizeof(ifo_command_t)); GETC( &title_inf.p_attr[i].i_angle_nb );
if( pgc.com_tab.p_cell_com == NULL ) GETS( &title_inf.p_attr[i].i_chapter_nb );
{ GETS( &title_inf.p_attr[i].i_parental_id );
intf_ErrMsg( "Out of memory" ); GETC( &title_inf.p_attr[i].i_title_set_num );
p_ifo->b_error = 1; GETC( &title_inf.p_attr[i].i_title_num );
return pgc; GETL( &title_inf.p_attr[i].i_start_sector );
} //fprintf( stderr, "title_inf: %d %d %d\n", ptr.p_tts[i].i_ptt_nb, ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn );
for( i=0 ; i<pgc.com_tab.i_cell_com_nb ; i++ )
{
GETCOMMAND( &pgc.com_tab.p_cell_com[i] );
}
} }
} }
/* Parsing of pgc_prg_map_t */ else
if( pgc.i_prg_map_sbyte )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start title_inf.p_attr = NULL;
+ pgc.i_prg_map_sbyte, SEEK_SET );
pgc.prg_map.pi_entry_cell = malloc( pgc.i_prg_nb *sizeof(u8) );
if( pgc.prg_map.pi_entry_cell == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
GET( pgc.prg_map.pi_entry_cell, pgc.i_prg_nb );
/* FIXME : check endianness here */
} }
/* Parsing of cell_play_inf_t */ #undef title_inf
if( pgc.i_cell_play_inf_sbyte )
/*
* fills the title unit structure.
*/
if( manager_inf.i_title_unit_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ pgc.i_cell_play_inf_sbyte, SEEK_SET ); manager_inf.i_title_unit_start_sector *DVD_LB_SIZE,
pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) ); SEEK_SET );
if( pgc.p_cell_play_inf == NULL ) if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit ) < 0 )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
for( i=0 ; i<pgc.i_cell_nb ; i++ )
{ {
GETS( &pgc.p_cell_play_inf[i].i_cat ); return -1;
GETC( &pgc.p_cell_play_inf[i].i_still_time );
GETC( &pgc.p_cell_play_inf[i].i_com_nb );
GETL( &pgc.p_cell_play_inf[i].i_play_time );
GETL( &pgc.p_cell_play_inf[i].i_entry_sector );
GETL( &pgc.p_cell_play_inf[i].i_first_ilvu_vobu_esector );
GETL( &pgc.p_cell_play_inf[i].i_lvobu_ssector );
GETL( &pgc.p_cell_play_inf[i].i_lsector );
} }
} }
/* Parsing of cell_pos_inf_map */
if( pgc.i_cell_pos_inf_sbyte ) /*
* fills the structure about parental information.
*/
#define parental p_ifo->vmg.parental_inf
if( manager_inf.i_parental_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
+ pgc.i_cell_pos_inf_sbyte, SEEK_SET ); manager_inf.i_parental_inf_start_sector *DVD_LB_SIZE,
pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) ); SEEK_SET );
if( pgc.p_cell_pos_inf == NULL ) i_start = p_ifo->i_pos;
//fprintf( stderr, "PTL\n" );
GETS( &parental.i_country_nb );
GETS( &parental.i_vts_nb );
GETL( &parental.i_end_byte );
parental.p_parental_desc = malloc( parental.i_country_nb *
sizeof(parental_desc_t) );
if( parental.p_parental_desc == NULL )
{ {
intf_ErrMsg( "Out of memory" ); intf_ErrMsg( "ifo error: out of memory in IfoInit" );
p_ifo->b_error = 1; return -1;
return pgc;
} }
for( i=0 ; i<pgc.i_cell_nb ; i++ )
for( i = 0 ; i < parental.i_country_nb ; i++ )
{ {
GETS( &pgc.p_cell_pos_inf[i].i_vob_id ); GET( parental.p_parental_desc[i].ps_country_code, 2 );
FLUSH( 1 ); FLUSH( 2 );
GETC( &pgc.p_cell_pos_inf[i].i_cell_id ); GETS( &parental.p_parental_desc[i].i_parental_mask_start_byte );
FLUSH( 2 );
} }
}
return pgc;
}
/***************************************************************************** parental.p_parental_mask = malloc( parental.i_country_nb *
* ReadUnit : Fills Menu Language Unit Table/ PGC Info Table sizeof(parental_mask_t) );
*****************************************************************************/ if( parental.p_parental_mask == NULL )
static pgci_inf_t ReadUnit( ifo_t* p_ifo ) {
{ intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
pgci_inf_t inf; return -1;
int i; }
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit\n" );
GETS( &inf.i_srp_nb ); for( i = 0 ; i < parental.i_country_nb ; i++ )
FLUSH( 2 ); {
GETL( &inf.i_lu_ebyte ); p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) ); parental.p_parental_desc[i].i_parental_mask_start_byte,
if( inf.p_srp == NULL ) SEEK_SET );
{ for( j = 0 ; j < 8 ; j++ )
intf_ErrMsg( "Out of memory" ); {
p_ifo->b_error = 1; parental.p_parental_mask[i].ppi_mask[j] =
return inf; malloc( ( parental.i_vts_nb + 1 ) *sizeof(u16) );
} if( parental.p_parental_mask[i].ppi_mask[j] == NULL )
for( i=0 ; i<inf.i_srp_nb ; i++ ) {
{ intf_ErrMsg( "ifo error: out of memory in IfoInit" );
GETC( &inf.p_srp[i].i_pgc_cat_mask ); return -1;
GETC( &inf.p_srp[i].i_pgc_cat ); }
GETS( &inf.p_srp[i].i_par_mask ); for( k = 0 ; k < parental.i_vts_nb + 1 ; k++ )
GETL( &inf.p_srp[i].i_pgci_sbyte ); {
GETS( &parental.p_parental_mask[i].ppi_mask[j][k] );
}
}
}
} }
for( i=0 ; i<inf.i_srp_nb ; i++ ) #undef parental
/*
* information and attributes about for each vts.
*/
#define vts_inf p_ifo->vmg.vts_inf
if( manager_inf.i_vts_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, u64 i_temp;
i_start + inf.p_srp[i].i_pgci_sbyte,
SEEK_SET );
//fprintf( stderr, "Unit: PGC %d\n", i );
inf.p_srp[i].pgc = ReadPGC( p_ifo );
}
return inf; p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
} manager_inf.i_vts_inf_start_sector *DVD_LB_SIZE,
SEEK_SET );
i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS ATTR\n" );
GETS( &vts_inf.i_vts_nb );
//fprintf( stderr, "VTS ATTR Nb: %d\n", vts_inf.i_vts_nb );
FLUSH( 2 );
GETL( &vts_inf.i_end_byte );
vts_inf.pi_vts_attr_start_byte =
malloc( vts_inf.i_vts_nb *sizeof(u32) );
if( vts_inf.pi_vts_attr_start_byte == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoInit" );
return -1;
}
/***************************************************************************** for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
* ReadUnitTable : Fills the PGCI Unit structure. {
*****************************************************************************/ GETL( &vts_inf.pi_vts_attr_start_byte[i] );
static pgci_ut_t ReadUnitTable( ifo_t* p_ifo ) }
{
pgci_ut_t pgci;
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit Table\n" ); vts_inf.p_vts_attr = malloc( vts_inf.i_vts_nb *sizeof(vts_attr_t) );
if( vts_inf.p_vts_attr == NULL )
{
intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
return -1;
}
GETS( &pgci.i_lu_nb ); for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
FLUSH( 2 ); {
GETL( &pgci.i_ebyte ); p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) ); vts_inf.pi_vts_attr_start_byte[i],
if( pgci.p_lu == NULL ) SEEK_SET );
{ GETL( &vts_inf.p_vts_attr[i].i_end_byte );
intf_ErrMsg( "Out of memory" ); GETL( &vts_inf.p_vts_attr[i].i_cat_app_type );
p_ifo->b_error = 1; // GETS( &vts_inf.p_vts_attr[i].vts_menu_video_attr );
return pgci; FLUSH(2);
} FLUSH( 1 );
for( i=0 ; i<pgci.i_lu_nb ; i++ ) GETC( &vts_inf.p_vts_attr[i].i_vts_menu_audio_nb );
{ //fprintf( stderr, "m audio nb : %d\n", vts_inf.p_vts_vts_inf[i].i_vtsm_audio_nb );
GET( pgci.p_lu[i].ps_lang_code, 2 ); for( j = 0 ; j < 8 ; j++ )
FLUSH( 1 ); {
GETC( &pgci.p_lu[i].i_existence_mask ); GETLL( &i_temp );
GETL( &pgci.p_lu[i].i_lu_sbyte ); }
FLUSH( 17 );
GETC( &vts_inf.p_vts_attr[i].i_vts_menu_spu_nb );
//fprintf( stderr, "m subp nb : %d\n", vts_inf.p_vts_vts_inf[i].i_vtsm_subpic_nb );
for( j = 0 ; j < 28 ; j++ )
{
GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
}
FLUSH( 2 );
// GETS( &vts_inf.p_vts_attr[i].vtstt_video_vts_inf );
FLUSH(2);
FLUSH( 1 );
GETL( &vts_inf.p_vts_attr[i].i_vts_title_audio_nb );
//fprintf( stderr, "tt audio nb : %d\n", vts_inf.p_vts_vts_inf[i].i_vtstt_audio_nb );
for( j = 0 ; j < 8 ; j++ )
{
GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &vts_inf.p_vts_attr[i].i_vts_title_spu_nb );
//fprintf( stderr, "tt subp nb : %d\n", vts_inf.p_vts_vts_inf[i].i_vtstt_subpic_nb );
for( j=0 ; j<28/*vts_inf.p_vts_vts_inf[i].i_vtstt_subpic_nb*/ ; j++ )
{
GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
}
}
} }
pgci.p_pgci_inf = malloc( pgci.i_lu_nb *sizeof(pgci_inf_t) ); #undef vts_inf
if( pgci.p_pgci_inf == NULL )
/*
* global cell map.
*/
if( manager_inf.i_cell_inf_start_sector )
{ {
intf_ErrMsg( "Out of memory" ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
p_ifo->b_error = 1; manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE,
return pgci; SEEK_SET );
if( ReadCellInf( p_ifo, &p_ifo->vmg.cell_inf ) < 0 )
{
return -1;
}
} }
for( i=0 ; i<pgci.i_lu_nb ; i++ )
/*
* global vob unit map.
*/
if( manager_inf.i_vobu_map_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
pgci.p_lu[i].i_lu_sbyte, manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE,
SEEK_SET ); SEEK_SET );
pgci.p_pgci_inf[i] = ReadUnit( p_ifo ); if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map ) < 0 )
{
return -1;
}
} }
#undef manager_inf
return pgci; p_ifo->vts.b_initialized = 0;
}
/*****************************************************************************
* ReadCellInf : Fills the Cell Information structure.
*****************************************************************************/
static c_adt_t ReadCellInf( ifo_t* p_ifo )
{
c_adt_t c_adt;
off_t i_start = p_ifo->i_pos;
int i;
//fprintf( stderr, "CELL ADD\n" ); intf_WarnMsg( 1, "ifo info: vmg initialized" );
GETS( &c_adt.i_vob_nb ); return 0;
FLUSH( 2 );
GETL( &c_adt.i_ebyte );
c_adt.i_cell_nb =
( i_start + c_adt.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(cell_inf_t);
c_adt.p_cell_inf = malloc( c_adt.i_cell_nb *sizeof(cell_inf_t) );
if( c_adt.p_cell_inf == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return c_adt;
}
for( i = 0 ; i < c_adt.i_cell_nb ; i++ )
{
GETS( &c_adt.p_cell_inf[i].i_vob_id );
GETC( &c_adt.p_cell_inf[i].i_cell_id );
FLUSH( 1 );
GETL( &c_adt.p_cell_inf[i].i_ssector );
GETL( &c_adt.p_cell_inf[i].i_esector );
}
return c_adt;
} }
/***************************************************************************** /*****************************************************************************
* ReadMap : Fills the VOBU Map structure. * IfoTitleSet: Parse vts*.ifo files to fill the Video Title Set structure.
*****************************************************************************/ *****************************************************************************/
static vobu_admap_t ReadMap( ifo_t* p_ifo ) int IfoTitleSet( ifo_t * p_ifo )
{ {
vobu_admap_t map; off_t i_off;
int i, i_max; off_t i_start;
off_t i_start = p_ifo->i_pos; u64 i_temp;
int i, j;
//fprintf( stderr, "VOBU ADMAP\n" );
GETL( &map.i_ebyte ); if( p_ifo->vts.b_initialized )
i_max = ( i_start + map.i_ebyte + 1 - p_ifo->i_pos ) / sizeof(u32);
map.pi_vobu_ssector = malloc( i_max *sizeof(u32) );
for( i=0 ; i<i_max ; i++ )
{ {
GETL( &map.pi_vobu_ssector[i] ); FreeTitleSet( &p_ifo->vts );
} }
return map; i_off =
} (off_t)( p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_start_sector )
* DVD_LB_SIZE
/* + p_ifo->i_off;
* Video Manager Information Processing.
* This is what is contained in video_ts.ifo.
*/
/***************************************************************************** p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
* ReadVMGInfMat : Fills the Management Information structure.
*****************************************************************************/
static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo )
{
vmgi_mat_t mat;
u64 i_temp;
int i;
// off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VMGI\n" ); p_ifo->vts.i_pos = p_ifo->i_pos;
#define manager_inf p_ifo->vts.manager_inf
/*
* reads manager information
*/
//fprintf( stderr, "VTSI\n" );
GET( mat.psz_id , 12 ); GET( manager_inf.psz_id , 12 );
mat.psz_id[12] = '\0'; manager_inf.psz_id[12] = '\0';
GETL( &mat.i_lsector ); GETL( &manager_inf.i_end_sector );
FLUSH( 12 ); FLUSH( 12 );
GETL( &mat.i_i_lsector ); GETL( &manager_inf.i_inf_end_sector );
FLUSH( 1 ); FLUSH( 1 );
GETC( &mat.i_spec_ver ); GETC( &manager_inf.i_spec_ver );
GETL( &mat.i_cat ); GETL( &manager_inf.i_cat );
GETS( &mat.i_vol_nb ); FLUSH( 90 );
GETS( &mat.i_vol ); GETL( &manager_inf.i_inf_end_byte );
GETC( &mat.i_disc_side ); FLUSH( 60 );
FLUSH( 19 ); GETL( &manager_inf.i_menu_vob_start_sector );
GETS( &mat.i_tts_nb ); GETL( &manager_inf.i_title_vob_start_sector );
GET( mat.ps_provider_id, 32 ); GETL( &manager_inf.i_title_inf_start_sector );
GETLL( &mat.i_pos_code ); GETL( &manager_inf.i_title_unit_start_sector );
GETL( &manager_inf.i_menu_unit_start_sector );
GETL( &manager_inf.i_time_inf_start_sector );
GETL( &manager_inf.i_menu_cell_inf_start_sector );
GETL( &manager_inf.i_menu_vobu_map_start_sector );
GETL( &manager_inf.i_cell_inf_start_sector );
GETL( &manager_inf.i_vobu_map_start_sector );
FLUSH( 24 ); FLUSH( 24 );
GETL( &mat.i_i_mat_ebyte ); // GETS( &manager_inf.m_video_atrt );
GETL( &mat.i_fp_pgc_sbyte );
FLUSH( 56 );
GETL( &mat.i_vobs_ssector );
GETL( &mat.i_ptt_srpt_ssector );
GETL( &mat.i_pgci_ut_ssector );
GETL( &mat.i_ptl_mait_ssector );
GETL( &mat.i_vts_atrt_ssector );
GETL( &mat.i_txtdt_mg_ssector );
GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector );
FLUSH( 32 );
// GETS( &mat.video_atrt );
FLUSH(2); FLUSH(2);
FLUSH( 1 ); FLUSH( 1 );
GETC( &mat.i_audio_nb ); GETC( &manager_inf.i_menu_audio_nb );
//fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb ); for( i=0 ; i<8 ; i++ )
for( i=0 ; i < 8 ; i++ )
{ {
GETLL( &i_temp ); GETLL( &i_temp );
} }
FLUSH( 17 ); FLUSH( 17 );
GETC( &mat.i_subpic_nb ); GETC( &manager_inf.i_menu_spu_nb );
//fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb ); for( i=0 ; i<28 ; i++ )
for( i=0 ; i < mat.i_subpic_nb ; i++ )
{ {
GET( &i_temp, 6 ); GET( &i_temp, 6 );
/* FIXME : take care of endianness */ /* FIXME : take care of endianness */
} }
FLUSH( 2 );
// GETS( &manager_inf.video_atrt );
FLUSH(2);
FLUSH( 1 );
GETC( &manager_inf.i_audio_nb );
//fprintf( stderr, "vtsi audio nb : %d\n", manager_inf.i_audio_nb );
for( i=0 ; i<8 ; i++ )
{
GETLL( &i_temp );
//fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
i_temp >>= 32;
manager_inf.p_audio_attr[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
manager_inf.p_audio_attr[i].i_num_channels = i_temp & 0x7;
i_temp >>= 4;
manager_inf.p_audio_attr[i].i_sample_freq = i_temp & 0x3;
i_temp >>= 2;
manager_inf.p_audio_attr[i].i_quantization = i_temp & 0x3;
i_temp >>= 2;
manager_inf.p_audio_attr[i].i_appl_mode = i_temp & 0x3;
i_temp >>= 2;
manager_inf.p_audio_attr[i].i_type = i_temp & 0x3;
i_temp >>= 2;
manager_inf.p_audio_attr[i].i_multichannel_extension = i_temp & 0x1;
i_temp >>= 1;
manager_inf.p_audio_attr[i].i_coding_mode = i_temp & 0x7;
}
FLUSH( 17 );
GETC( &manager_inf.i_spu_nb );
//fprintf( stderr, "vtsi subpic nb : %d\n", manager_inf.i_subpic_nb );
for( i=0 ; i<manager_inf.i_spu_nb ; i++ )
{
GET( &i_temp, 6 );
i_temp = hton64( i_temp ) >> 16;
//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
manager_inf.p_spu_attr[i].i_caption = i_temp & 0xff;
i_temp >>= 16;
manager_inf.p_spu_attr[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
manager_inf.p_spu_attr[i].i_prefix = i_temp & 0xffff;
}
return mat; /*
} * reads title information: set of pointers to title
*/
#define title_inf p_ifo->vts.title_inf
if( manager_inf.i_title_inf_start_sector )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_title_inf_start_sector *DVD_LB_SIZE,
SEEK_SET );
/***************************************************************************** i_start = p_ifo->i_pos;
* ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
*****************************************************************************/ //fprintf( stderr, "VTS PTR\n" );
static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
{ GETS( &title_inf.i_title_nb );
vmg_ptt_srpt_t ptr; //fprintf( stderr, "VTS title_inf nb: %d\n", title_inf.i_title_nb );
int i; FLUSH( 2 );
// off_t i_start = p_ifo->i_pos; GETL( &title_inf.i_end_byte );
//fprintf( stderr, "PTR\n" ); title_inf.pi_start_byte = malloc( title_inf.i_title_nb *sizeof(u32) );
if( title_inf.pi_start_byte == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
return -1;
}
GETS( &ptr.i_ttu_nb ); for( i = 0 ; i < title_inf.i_title_nb ; i++ )
//fprintf( stderr, "PTR: TTU nb %d\n", ptr.i_ttu_nb ); {
FLUSH( 2 ); GETL( &title_inf.pi_start_byte[i] );
GETL( &ptr.i_ebyte ); }
/* Parsing of tts */
ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) ); /* Parsing of tts */
if( ptr.p_tts == NULL ) title_inf.p_title_start = malloc( title_inf.i_title_nb
*sizeof(title_start_t) );
if( title_inf.p_title_start == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
return -1;
}
for( i = 0 ; i < title_inf.i_title_nb ; i++ )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
title_inf.pi_start_byte[i], SEEK_SET );
GETS( &title_inf.p_title_start[i].i_program_chain_num );
GETS( &title_inf.p_title_start[i].i_program_num );
//fprintf( stderr, "VTS %d title_inf Pgc: %d Prg: %d\n", i,title_inf.p_title_start[i].i_program_chain_num, title_inf.p_title_start[i].i_program_num );
}
}
#undef title_inf
/*
* menu unit information
*/
if( manager_inf.i_menu_unit_start_sector )
{ {
intf_ErrMsg( "Out of memory" ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
p_ifo->b_error = 1; manager_inf.i_menu_unit_start_sector *DVD_LB_SIZE,
return ptr; SEEK_SET );
if( ReadTitleUnit( p_ifo, &p_ifo->vts.menu_unit ) < 0 )
{
return -1;
}
} }
for( i=0 ; i<ptr.i_ttu_nb ; i++ )
/*
* title unit information
*/
if( manager_inf.i_title_unit_start_sector )
{ {
GETC( &ptr.p_tts[i].i_play_type ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
GETC( &ptr.p_tts[i].i_angle_nb ); manager_inf.i_title_unit_start_sector *DVD_LB_SIZE,
GETS( &ptr.p_tts[i].i_ptt_nb ); SEEK_SET );
GETS( &ptr.p_tts[i].i_parental_id ); if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit ) < 0 )
GETC( &ptr.p_tts[i].i_tts_nb ); {
GETC( &ptr.p_tts[i].i_vts_ttn ); return -1;
GETL( &ptr.p_tts[i].i_ssector ); }
//fprintf( stderr, "PTR: %d %d %d\n", ptr.p_tts[i].i_ptt_nb, ptr.p_tts[i].i_tts_nb,ptr.p_tts[i].i_vts_ttn );
} }
return ptr; /*
} * time map inforamtion
*/
#define time_inf p_ifo->vts.time_inf
if( manager_inf.i_time_inf_start_sector )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_time_inf_start_sector *DVD_LB_SIZE,
SEEK_SET );
/***************************************************************************** //fprintf( stderr, "TMAP\n" );
* ReadParentalInf : Fills the Parental Management structure.
*****************************************************************************/
static vmg_ptl_mait_t ReadParentalInf( ifo_t* p_ifo )
{
vmg_ptl_mait_t par;
int i, j, k;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "PTL\n" ); GETS( &time_inf.i_nb );
FLUSH( 2 );
GETL( &time_inf.i_end_byte );
time_inf.pi_start_byte = malloc( time_inf.i_nb *sizeof(u32) );
if( time_inf.pi_start_byte == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
return -1;
}
for( i = 0 ; i < time_inf.i_nb ; i++ )
{
GETL( &time_inf.pi_start_byte[i] );
}
time_inf.p_time_map = malloc( time_inf.i_nb *sizeof(time_map_t) );
if( time_inf.p_time_map == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
return -1;
}
GETS( &par.i_country_nb ); for( i = 0 ; i < time_inf.i_nb ; i++ )
GETS( &par.i_vts_nb ); {
GETL( &par.i_ebyte ); GETC( &time_inf.p_time_map[i].i_time_unit );
par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) ); FLUSH( 1 );
if( par.p_ptl_desc == NULL ) GETS( &time_inf.p_time_map[i].i_entry_nb );
time_inf.p_time_map[i].pi_sector =
malloc( time_inf.p_time_map[i].i_entry_nb *sizeof(u32) );
if( time_inf.p_time_map[i].pi_sector == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoTitleSet" );
return -1;
}
for( j = 0 ; j < time_inf.p_time_map[i].i_entry_nb ; j++ )
{
GETL( &time_inf.p_time_map[i].pi_sector[j] );
}
}
}
#undef time_inf
if( manager_inf.i_menu_cell_inf_start_sector )
{ {
intf_ErrMsg( "Out of memory" ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
p_ifo->b_error = 1; manager_inf.i_menu_cell_inf_start_sector *DVD_LB_SIZE,
return par; SEEK_SET );
if( ReadCellInf( p_ifo, &p_ifo->vts.menu_cell_inf ) < 0 )
{
return -1;
}
} }
for( i=0 ; i<par.i_country_nb ; i++ )
if( manager_inf.i_menu_vobu_map_start_sector )
{ {
GET( par.p_ptl_desc[i].ps_country_code, 2 ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
FLUSH( 2 ); manager_inf.i_menu_vobu_map_start_sector *DVD_LB_SIZE,
GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte ); SEEK_SET );
FLUSH( 2 ); if( ReadVobuMap( p_ifo, &p_ifo->vts.menu_vobu_map ) < 0 )
{
return -1;
}
} }
par.p_ptl_mask = malloc( par.i_country_nb *sizeof(vmg_ptl_mask_t) );
if( par.p_ptl_mask == NULL ) if( manager_inf.i_cell_inf_start_sector )
{ {
intf_ErrMsg( "Out of memory" ); p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
p_ifo->b_error = 1; manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE,
return par; SEEK_SET );
if( ReadCellInf( p_ifo, &p_ifo->vts.cell_inf ) )
{
return -1;
}
} }
for( i=0 ; i<par.i_country_nb ; i++ )
if( manager_inf.i_vobu_map_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET ); manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE,
for( j=1 ; j<=8 ; j++ ) SEEK_SET );
if( ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map ) )
{ {
par.p_ptl_mask[i].ppi_ptl_mask[j] = return -1;
malloc( par.i_vts_nb *sizeof(u16) );
if( par.p_ptl_mask[i].ppi_ptl_mask[j] == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return par;
}
for( k=0 ; k<par.i_vts_nb ; k++ )
{
GETS( &par.p_ptl_mask[i].ppi_ptl_mask[j][k] );
}
} }
} }
return par; intf_WarnMsg( 2, "ifo info: VTS %d initialized",
p_ifo->vmg.title_inf.p_attr[p_ifo->i_title-1].i_title_set_num );
#undef manager_inf
p_ifo->vts.b_initialized = 1;
return 0;
} }
/***************************************************************************** /*****************************************************************************
* ReadVTSAttr : Fills the structure about VTS attributes. * FreeTitleSet : free all structures allocated by IfoTitleSet
*****************************************************************************/ *****************************************************************************/
static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) static int FreeTitleSet( vts_t * p_vts )
{ {
vmg_vts_atrt_t atrt; int i;
int i, j;
u64 i_temp;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS ATTR\n" ); if( p_vts->manager_inf.i_vobu_map_start_sector )
{
FreeVobuMap( &p_vts->vobu_map );
}
GETS( &atrt.i_vts_nb ); if( p_vts->manager_inf.i_cell_inf_start_sector )
//fprintf( stderr, "VTS ATTR Nb: %d\n", atrt.i_vts_nb );
FLUSH( 2 );
GETL( &atrt.i_ebyte );
atrt.pi_vts_atrt_sbyte = malloc( atrt.i_vts_nb *sizeof(u32) );
if( atrt.pi_vts_atrt_sbyte == NULL )
{ {
intf_ErrMsg( "Out of memory" ); FreeCellInf( &p_vts->cell_inf );
p_ifo->b_error = 1;
return atrt;
} }
for( i=0 ; i<atrt.i_vts_nb ; i++ )
if( p_vts->manager_inf.i_menu_vobu_map_start_sector )
{ {
GETL( &atrt.pi_vts_atrt_sbyte[i] ); FreeVobuMap( &p_vts->menu_vobu_map );
} }
atrt.p_vts_atrt = malloc( atrt.i_vts_nb *sizeof(vts_atrt_t) );
if( atrt.p_vts_atrt == NULL ) if( p_vts->manager_inf.i_menu_cell_inf_start_sector )
{ {
intf_ErrMsg( "Out of memory" ); FreeCellInf( &p_vts->menu_cell_inf );
p_ifo->b_error = 1;
return atrt;
} }
for( i=0 ; i<atrt.i_vts_nb ; i++ )
if( p_vts->manager_inf.i_time_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
atrt.pi_vts_atrt_sbyte[i],
SEEK_SET );
GETL( &atrt.p_vts_atrt[i].i_ebyte );
GETL( &atrt.p_vts_atrt[i].i_cat_app_type );
// GETS( &atrt.p_vts_atrt[i].vtsm_video_atrt );
FLUSH(2);
FLUSH( 1 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_audio_nb );
//fprintf( stderr, "m audio nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_audio_nb );
for( j=0 ; j<8 ; j++ )
{
GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
//fprintf( stderr, "m subp nb : %d\n", atrt.p_vts_atrt[i].i_vtsm_subpic_nb );
for( j=0 ; j<28 ; j++ )
{
GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
}
FLUSH( 2 );
// GETS( &atrt.p_vts_atrt[i].vtstt_video_atrt );
FLUSH(2);
FLUSH( 1 );
GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb );
//fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb );
for( j=0 ; j<8 ; j++ )
{ {
GETLL( &i_temp ); free( p_vts->time_inf.p_time_map[i].pi_sector );
}
FLUSH( 17 );
GETC( &atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
//fprintf( stderr, "tt subp nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_subpic_nb );
for( j=0 ; j<28/*atrt.p_vts_atrt[i].i_vtstt_subpic_nb*/ ; j++ )
{
GET( &i_temp, 6 );
/* FIXME : Fix endianness issue here */
} }
free( p_vts->time_inf.p_time_map );
free( p_vts->time_inf.pi_start_byte );
} }
return atrt; if( p_vts->manager_inf.i_title_unit_start_sector )
{
FreeUnitInf( &p_vts->title_unit );
}
if( p_vts->manager_inf.i_menu_unit_start_sector )
{
FreeTitleUnit( &p_vts->menu_unit );
}
if( p_vts->manager_inf.i_title_inf_start_sector )
{
free( p_vts->title_inf.pi_start_byte );
free( p_vts->title_inf.p_title_start );
}
p_vts->b_initialized = 0;
return 0;
} }
/***************************************************************************** /*****************************************************************************
* ReadVMG : Parse video_ts.ifo file to fill the Video Manager structure. * IfoEnd : Frees all the memory allocated to ifo structures
*****************************************************************************/ *****************************************************************************/
static vmg_t ReadVMG( ifo_t* p_ifo ) void IfoEnd( ifo_t * p_ifo )
{ {
vmg_t vmg; int i, j;
FreeTitleSet( &p_ifo->vts );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off, SEEK_SET); if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
vmg.mat = ReadVMGInfMat( p_ifo );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
vmg.mat.i_fp_pgc_sbyte, SEEK_SET );
vmg.pgc = ReadPGC( p_ifo );
if( vmg.mat.i_ptt_srpt_ssector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + FreeVobuMap( &p_ifo->vmg.vobu_map );
vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
} }
if( vmg.mat.i_pgci_ut_ssector )
if( p_ifo->vmg.manager_inf.i_cell_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + FreeCellInf( &p_ifo->vmg.cell_inf );
vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.pgci_ut = ReadUnitTable( p_ifo );
} }
if( vmg.mat.i_ptl_mait_ssector )
if( p_ifo->vmg.manager_inf.i_vts_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + free( p_ifo->vmg.vts_inf.p_vts_attr );
vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE, free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
SEEK_SET );
vmg.ptl_mait = ReadParentalInf( p_ifo );
} }
if( vmg.mat.i_vts_atrt_ssector )
/* free parental information structures */
if( p_ifo->vmg.manager_inf.i_parental_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE, {
SEEK_SET ); for( j = 0 ; j < 8 ; j++ )
vmg.vts_atrt = ReadVTSAttr( p_ifo ); {
free( p_ifo->vmg.parental_inf.p_parental_mask[i].ppi_mask[j] );
}
}
free( p_ifo->vmg.parental_inf.p_parental_mask );
free( p_ifo->vmg.parental_inf.p_parental_desc );
} }
if( vmg.mat.i_c_adt_ssector )
if( p_ifo->vmg.manager_inf.i_title_unit_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + FreeTitleUnit( &p_ifo->vmg.title_unit );
vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.c_adt = ReadCellInf( p_ifo );
} }
if( vmg.mat.i_vobu_admap_ssector )
if( p_ifo->vmg.manager_inf.i_title_inf_start_sector )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off + free( p_ifo->vmg.title_inf.p_attr );
vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.vobu_admap = ReadMap( p_ifo );
} }
return vmg;
}
FreeTitle( &p_ifo->vmg.title );
free( p_ifo );
return;
}
/* /*
* Video Title Set Information Processing. * Function common to Video Manager and Video Title set Processing
* This is what is contained in vts_*.ifo.
*/ */
/***************************************************************************** /*****************************************************************************
* ReadVTSInfMat : Fills the Title Set Information structure. * ReadTitle : Fills the title structure.
*****************************************************************************
* Titles are logical stream units that correspond to a whole inside the dvd.
* Several title can point to the same part of the physical DVD, and give
* map to different anglesfor instance.
*****************************************************************************/ *****************************************************************************/
static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) #define GETCOMMAND( p_com ) \
{ \
read( p_ifo->i_fd , (p_com) , 8 ); \
/*fprintf(stderr, "Pos : %lld Type : %d direct : %d cmd : %d dircmp : %d cmp : %d subcmd : %d v0 : %d v2 : %d v4 : %d\n", \
(long long)(p_ifo->i_pos - i_start), \
(int)((p_com)->i_type), \
(int)((p_com)->i_direct), \
(int)((p_com)->i_cmd), \
(int)((p_com)->i_dir_cmp), \
(int)((p_com)->i_cmp), \
(int)((p_com)->i_sub_cmd), \
(int)((p_com)->data.pi_16[0]), \
(int)((p_com)->data.pi_16[1]), \
(int)((p_com)->data.pi_16[2]));*/ \
/* CommandRead( *(p_com) );*/ \
p_ifo->i_pos += 8; \
}
static int ReadTitle( ifo_t * p_ifo, title_t * p_title )
{ {
vtsi_mat_t mat; off_t i_start;
int i; int i;
u64 i_temp;
// off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTSI\n" ); i_start = p_ifo->i_pos;
GET( mat.psz_id , 12 ); //fprintf( stderr, "PGC\n" );
mat.psz_id[12] = '\0';
GETL( &mat.i_lsector ); FLUSH(2);
FLUSH( 12 ); GETC( &p_title->i_chapter_nb );
GETL( &mat.i_i_lsector ); GETC( &p_title->i_cell_nb );
FLUSH( 1 ); //fprintf( stderr, "title: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb );
GETC( &mat.i_spec_ver ); GETL( &p_title->i_play_time );
GETL( &mat.i_cat ); GETL( &p_title->i_prohibited_user_op );
FLUSH( 90 );
GETL( &mat.i_mat_ebyte );
FLUSH( 60 );
GETL( &mat.i_m_vobs_ssector );
GETL( &mat.i_tt_vobs_ssector );
GETL( &mat.i_ptt_srpt_ssector );
GETL( &mat.i_pgcit_ssector );
GETL( &mat.i_m_pgci_ut_ssector );
GETL( &mat.i_tmap_ti_ssector );
GETL( &mat.i_m_c_adt_ssector );
GETL( &mat.i_m_vobu_admap_ssector );
GETL( &mat.i_c_adt_ssector );
GETL( &mat.i_vobu_admap_ssector );
FLUSH( 24 );
// GETS( &mat.m_video_atrt );
FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_m_audio_nb );
for( i=0 ; i<8 ; i++ ) for( i=0 ; i<8 ; i++ )
{ {
GETLL( &i_temp ); GETS( &p_title->pi_audio_status[i] );
} }
FLUSH( 17 ); for( i=0 ; i<32 ; i++ )
GETC( &mat.i_m_subpic_nb );
for( i=0 ; i<28 ; i++ )
{ {
GET( &i_temp, 6 ); GETL( &p_title->pi_subpic_status[i] );
/* FIXME : take care of endianness */
} }
FLUSH( 2 ); GETS( &p_title->i_next_title_num );
// GETS( &mat.video_atrt ); GETS( &p_title->i_prev_title_num );
FLUSH(2); GETS( &p_title->i_go_up_title_num );
FLUSH( 1 ); //fprintf( stderr, "title: Prev: %d Next: %d Up: %d\n",pgc.i_prev_pgc_nb ,pgc.i_next_pgc_nb, pgc.i_goup_pgc_nb );
GETC( &mat.i_audio_nb ); GETC( &p_title->i_still_time );
//fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb ); GETC( &p_title->i_play_mode );
for( i=0 ; i<8 ; i++ ) for( i=0 ; i<16 ; i++ )
{ {
GETLL( &i_temp ); GETL( &p_title->pi_yuv_color[i] );
//fprintf( stderr, "Audio %d: %llx\n", i, i_temp ); /* FIXME : We have to erase the extra bit */
i_temp >>= 32;
mat.p_audio_atrt[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
mat.p_audio_atrt[i].i_num_channels = i_temp & 0x7;
i_temp >>= 4;
mat.p_audio_atrt[i].i_sample_freq = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_quantization = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_appl_mode = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_type = i_temp & 0x3;
i_temp >>= 2;
mat.p_audio_atrt[i].i_multichannel_extension = i_temp & 0x1;
i_temp >>= 1;
mat.p_audio_atrt[i].i_coding_mode = i_temp & 0x7;
} }
FLUSH( 17 ); GETS( &p_title->i_command_start_byte );
GETC( &mat.i_subpic_nb ); GETS( &p_title->i_chapter_map_start_byte );
//fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb ); GETS( &p_title->i_cell_play_start_byte );
for( i=0 ; i<mat.i_subpic_nb ; i++ ) GETS( &p_title->i_cell_pos_start_byte );
/* parsing of command_t */
if( p_title->i_command_start_byte )
{ {
GET( &i_temp, 6 ); p_ifo->i_pos = lseek( p_ifo->i_fd,
i_temp = hton64( i_temp ) >> 16; i_start + p_title->i_command_start_byte,
//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp ); SEEK_SET );
mat.p_subpic_atrt[i].i_caption = i_temp & 0xff;
i_temp >>= 16;
mat.p_subpic_atrt[i].i_lang_code = i_temp & 0xffff;
i_temp >>= 16;
mat.p_subpic_atrt[i].i_prefix = i_temp & 0xffff;
}
return mat; /* header */
} GETS( &p_title->command.i_pre_command_nb );
GETS( &p_title->command.i_post_command_nb );
GETS( &p_title->command.i_cell_command_nb );
FLUSH( 2 );
/***************************************************************************** /* pre-title commands */
* ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure. if( p_title->command.i_pre_command_nb )
*****************************************************************************/ {
static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo ) p_title->command.p_pre_command =
{ malloc( p_title->command.i_pre_command_nb
vts_ptt_srpt_t ptr; *sizeof(command_desc_t) );
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS PTR\n" ); if( p_title->command.p_pre_command == NULL )
{
intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
return -1;
}
GETS( &ptr.i_ttu_nb ); for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
//fprintf( stderr, "VTS PTR nb: %d\n", ptr.i_ttu_nb ); {
FLUSH( 2 ); GETCOMMAND( &p_title->command.p_pre_command[i] );
GETL( &ptr.i_ebyte ); }
ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) ); }
if( ptr.pi_ttu_sbyte == NULL ) else
{ {
intf_ErrMsg( "Out of memory" ); p_title->command.p_pre_command = NULL;
p_ifo->b_error = 1; }
return ptr;
/* post-title commands */
if( p_title->command.i_post_command_nb )
{
p_title->command.p_post_command =
malloc( p_title->command.i_post_command_nb
*sizeof(command_desc_t) );
if( p_title->command.p_post_command == NULL )
{
intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
return -1;
}
for( i=0 ; i<p_title->command.i_post_command_nb ; i++ )
{
GETCOMMAND( &p_title->command.p_post_command[i] );
}
}
else
{
p_title->command.p_post_command = NULL;
}
/* cell commands */
if( p_title->command.i_cell_command_nb )
{
p_title->command.p_cell_command =
malloc( p_title->command.i_cell_command_nb
*sizeof(command_desc_t) );
if( p_title->command.p_cell_command == NULL )
{
intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
return -1;
}
for( i=0 ; i<p_title->command.i_cell_command_nb ; i++ )
{
GETCOMMAND( &p_title->command.p_cell_command[i] );
}
}
else
{
p_title->command.p_cell_command = NULL;
}
} }
for( i=0 ; i<ptr.i_ttu_nb ; i++ )
/* parsing of chapter_map_t: it gives the entry cell for each chapter */
if( p_title->i_chapter_map_start_byte )
{ {
GETL( &ptr.pi_ttu_sbyte[i] ); p_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + p_title->i_chapter_map_start_byte,
SEEK_SET );
p_title->chapter_map.pi_start_cell =
malloc( p_title->i_chapter_nb *sizeof(chapter_map_t) );
if( p_title->chapter_map.pi_start_cell == NULL )
{
intf_ErrMsg( "ifo error: out of memory in Read Title" );
return -1;
}
GET( p_title->chapter_map.pi_start_cell, p_title->i_chapter_nb );
} }
/* Parsing of tts */ else
ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
if( ptr.p_ttu == NULL )
{ {
intf_ErrMsg( "Out of memory" ); p_title->chapter_map.pi_start_cell = NULL;
p_ifo->b_error = 1;
return ptr;
} }
for( i=0 ; i<ptr.i_ttu_nb ; i++ )
/* parsing of cell_play_t */
if( p_title->i_cell_play_start_byte )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start + p_ifo->i_pos = lseek( p_ifo->i_fd,
ptr.pi_ttu_sbyte[i], SEEK_SET ); i_start + p_title->i_cell_play_start_byte,
GETS( &ptr.p_ttu[i].i_pgc_nb ); SEEK_SET );
GETS( &ptr.p_ttu[i].i_prg_nb );
//fprintf( stderr, "VTS %d PTR Pgc: %d Prg: %d\n", i,ptr.p_ttu[i].i_pgc_nb, ptr.p_ttu[i].i_prg_nb ); p_title->p_cell_play = malloc( p_title->i_cell_nb
*sizeof(cell_play_t) );
if( p_title->p_cell_play == NULL )
{
intf_ErrMsg( "ifo error: out of memory in ReadTitle" );
return -1;
}
for( i = 0 ; i < p_title->i_cell_nb ; i++ )
{
GETS( &p_title->p_cell_play[i].i_category );
GETC( &p_title->p_cell_play[i].i_still_time );
GETC( &p_title->p_cell_play[i].i_command_nb );
GETL( &p_title->p_cell_play[i].i_play_time );
GETL( &p_title->p_cell_play[i].i_start_sector );
GETL( &p_title->p_cell_play[i].i_first_ilvu_vobu_esector );
GETL( &p_title->p_cell_play[i].i_last_vobu_start_sector );
GETL( &p_title->p_cell_play[i].i_end_sector );
}
} }
return ptr; /* Parsing of cell_pos_t */
if( p_title->i_cell_pos_start_byte )
{
p_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + p_title->i_cell_pos_start_byte,
SEEK_SET );
p_title->p_cell_pos = malloc( p_title->i_cell_nb
*sizeof(cell_pos_t) );
if( p_title->p_cell_pos == NULL )
{
intf_ErrMsg( "ifo error: out of memory" );
return -1;
}
for( i = 0 ; i < p_title->i_cell_nb ; i++ )
{
GETS( &p_title->p_cell_pos[i].i_vob_id );
FLUSH( 1 );
GETC( &p_title->p_cell_pos[i].i_cell_id );
}
}
return 0;
} }
/***************************************************************************** /*****************************************************************************
* ReadVTSTimeMap : Fills the time map table * FreeTitle: frees alla structure allocated by a call to ReadTitle
*****************************************************************************/ *****************************************************************************/
static vts_tmap_ti_t ReadVTSTimeMap( ifo_t* p_ifo ) static int FreeTitle( title_t * p_title )
{ {
vts_tmap_ti_t tmap; if( p_title->i_command_start_byte )
int i,j; {
// off_t i_start = p_ifo->i_pos; if( p_title->command.i_pre_command_nb )
{
free( p_title->command.p_pre_command );
}
//fprintf( stderr, "TMAP\n" ); if( p_title->command.i_post_command_nb )
{
free( p_title->command.p_post_command );
}
GETS( &tmap.i_nb ); if( p_title->command.i_cell_command_nb )
FLUSH( 2 ); {
GETL( &tmap.i_ebyte ); free( p_title->command.p_cell_command );
tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) ); }
if( tmap.pi_sbyte == NULL )
{ if( p_title->i_chapter_map_start_byte )
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return tmap;
}
for( i=0 ; i<tmap.i_nb ; i++ )
{
GETL( &tmap.pi_sbyte[i] );
}
tmap.p_tmap = malloc( tmap.i_nb *sizeof(tmap_t) );
if( tmap.p_tmap == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return tmap;
}
for( i=0 ; i<tmap.i_nb ; i++ )
{
GETC( &tmap.p_tmap[i].i_time_unit );
FLUSH( 1 );
GETS( &tmap.p_tmap[i].i_entry_nb );
tmap.p_tmap[i].pi_sector =
malloc( tmap.p_tmap[i].i_entry_nb *sizeof(u32) );
if( tmap.p_tmap[i].pi_sector == NULL )
{ {
intf_ErrMsg( "Out of memory" ); free( p_title->chapter_map.pi_start_cell );
p_ifo->b_error = 1;
return tmap;
} }
for( j=0 ; j<tmap.p_tmap[i].i_entry_nb ; j++ )
if( p_title->i_cell_play_start_byte )
{ {
GETL( &tmap.p_tmap[i].pi_sector[j] ); free( p_title->p_cell_play );
}
if( p_title->i_cell_pos_start_byte )
{
free( p_title->p_cell_pos );
} }
} }
return tmap; return 0;
} }
/***************************************************************************** /*****************************************************************************
* IfoReadVTS : Parse vts*.ifo files to fill the Video Title Set structure. * ReadUnitInf : Fills Menu Language Unit Table/ PGC Info Table
*****************************************************************************/ *****************************************************************************/
int IfoReadVTS( ifo_t* p_ifo ) static int ReadUnitInf( ifo_t * p_ifo, unit_inf_t * p_unit_inf )
{ {
vts_t vts; off_t i_start;
off_t i_off; int i;
int i_title;
intf_WarnMsg( 2, "ifo: initializing VTS %d", p_ifo->i_title );
i_title = p_ifo->i_title;
i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title-1].i_ssector )
* DVD_LB_SIZE
+ p_ifo->i_off;
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET ); i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit\n" );
vts.i_pos = p_ifo->i_pos; GETS( &p_unit_inf->i_title_nb );
FLUSH( 2 );
GETL( &p_unit_inf->i_end_byte );
vts.mat = ReadVTSInfMat( p_ifo ); p_unit_inf->p_title =
if( vts.mat.i_ptt_srpt_ssector ) malloc( p_unit_inf->i_title_nb *sizeof(unit_title_t) );
if( p_unit_inf->p_title == NULL )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + intf_ErrMsg( "ifo error: out of memory in ReadUnit" );
vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE, return -1;
SEEK_SET );
vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
} }
if( vts.mat.i_m_pgci_ut_ssector )
for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + GETC( &p_unit_inf->p_title[i].i_category_mask );
vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE, GETC( &p_unit_inf->p_title[i].i_category );
SEEK_SET ); GETS( &p_unit_inf->p_title[i].i_parental_mask );
vts.pgci_ut = ReadUnitTable( p_ifo ); GETL( &p_unit_inf->p_title[i].i_title_start_byte );
} }
if( vts.mat.i_pgcit_ssector )
for( i = 0 ; i < p_unit_inf->i_title_nb ; i++ )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
vts.mat.i_pgcit_ssector *DVD_LB_SIZE, p_unit_inf->p_title[i].i_title_start_byte,
SEEK_SET ); SEEK_SET );
vts.pgci_ti = ReadUnit( p_ifo ); //fprintf( stderr, "Unit: PGC %d\n", i );
ReadTitle( p_ifo, &p_unit_inf->p_title[i].title );
} }
if( vts.mat.i_tmap_ti_ssector )
return 0;
}
/*****************************************************************************
* FreeUnitInf : frees a structure allocated by ReadUnit
*****************************************************************************/
static int FreeUnitInf( unit_inf_t * p_unit_inf )
{
if( p_unit_inf->p_title != NULL )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + free( p_unit_inf->p_title );
vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.tmap_ti = ReadVTSTimeMap( p_ifo );
} }
if( vts.mat.i_m_c_adt_ssector )
return 0;
}
/*****************************************************************************
* ReadTitleUnit: Fills the Title Unit structure.
*****************************************************************************/
static int ReadTitleUnit( ifo_t * p_ifo, title_unit_t * p_title_unit )
{
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit Table\n" );
GETS( &p_title_unit->i_unit_nb );
FLUSH( 2 );
GETL( &p_title_unit->i_end_byte );
p_title_unit->p_unit = malloc( p_title_unit->i_unit_nb *sizeof(unit_t) );
if( p_title_unit->p_unit == NULL )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE, return -1;
SEEK_SET );
vts.m_c_adt = ReadCellInf( p_ifo );
} }
if( vts.mat.i_m_vobu_admap_ssector )
for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + GET( p_title_unit->p_unit[i].ps_lang_code, 2 );
vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE, FLUSH( 1 );
SEEK_SET ); GETC( &p_title_unit->p_unit[i].i_existence_mask );
vts.m_vobu_admap = ReadMap( p_ifo ); GETL( &p_title_unit->p_unit[i].i_unit_inf_start_byte );
} }
if( vts.mat.i_c_adt_ssector )
p_title_unit->p_unit_inf =
malloc( p_title_unit->i_unit_nb *sizeof(unit_inf_t) );
if( p_title_unit->p_unit_inf == NULL )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
vts.mat.i_c_adt_ssector *DVD_LB_SIZE, return -1;
SEEK_SET );
vts.c_adt = ReadCellInf( p_ifo );
} }
if( vts.mat.i_vobu_admap_ssector )
for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
{ {
p_ifo->i_pos = lseek( p_ifo->i_fd, vts.i_pos + p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE, p_title_unit->p_unit[i].i_unit_inf_start_byte,
SEEK_SET ); SEEK_SET );
vts.vobu_admap = ReadMap( p_ifo ); ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i] );
} }
p_ifo->vts = vts;
return 0; return 0;
} }
/*
* DVD Information Management
*/
#if 0
/***************************************************************************** /*****************************************************************************
* IfoRead : Function that fills structure and calls specified functions * FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
* to do it.
*****************************************************************************/ *****************************************************************************/
void IfoRead( ifo_t* p_ifo ) static int FreeTitleUnit( title_unit_t * p_title_unit )
{ {
int i; int i;
off_t i_off;
/* Video Title Sets initialization */ if( p_title_unit->p_unit_inf != NULL )
p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
if( p_ifo->p_vts == NULL )
{ {
intf_ErrMsg( "Out of memory" ); for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
p_ifo->b_error = 1; {
return; FreeUnitInf( &p_title_unit->p_unit_inf[i] );
}
free( p_title_unit->p_unit_inf );
} }
for( i=0 ; i<p_ifo->vmg.mat.i_tts_nb ; i++ ) return 0;
}
/*****************************************************************************
* ReadCellInf : Fills the Cell Information structure.
*****************************************************************************/
static int ReadCellInf( ifo_t * p_ifo, cell_inf_t * p_cell_inf )
{
off_t i_start;
int i;
i_start = p_ifo->i_pos;
//fprintf( stderr, "CELL ADD\n" );
GETS( &p_cell_inf->i_vob_nb );
FLUSH( 2 );
GETL( &p_cell_inf->i_end_byte );
p_cell_inf->i_cell_nb =
( i_start + p_cell_inf->i_end_byte + 1 - p_ifo->i_pos )
/ sizeof(cell_map_t);
p_cell_inf->p_cell_map =
malloc( p_cell_inf->i_cell_nb *sizeof(cell_map_t) );
if( p_cell_inf->p_cell_map == NULL )
{ {
intf_ErrMsg( "ifo error: out of memory in ReadCellInf" );
return -1;
}
intf_WarnMsg( 2, "ifo: initializing VTS %d", i+1 ); for( i = 0 ; i < p_cell_inf->i_cell_nb ; i++ )
{
GETS( &p_cell_inf->p_cell_map[i].i_vob_id );
GETC( &p_cell_inf->p_cell_map[i].i_cell_id );
FLUSH( 1 );
GETL( &p_cell_inf->p_cell_map[i].i_start_sector );
GETL( &p_cell_inf->p_cell_map[i].i_end_sector );
}
return 0;
}
i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i].i_ssector ) *DVD_LB_SIZE /*****************************************************************************
+ p_ifo->i_off; * FreeCellInf : frees structures allocated by ReadCellInf
*****************************************************************************/
static int FreeCellInf( cell_inf_t * p_cell_inf )
{
free( p_cell_inf->p_cell_map );
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET ); return 0;
}
/* FIXME : I really don't know why udf find file /*****************************************************************************
* does not give the exact beginning of file */ * ReadVobuMap : Fills the VOBU Map structure.
*****************************************************************************/
static int ReadVobuMap( ifo_t * p_ifo, vobu_map_t * p_vobu_map )
{
off_t i_start;
int i, i_max;
i_start = p_ifo->i_pos;
//fprintf( stderr, "VOBU ADMAP\n" );
p_ifo->p_vts[i] = ReadVTS( p_ifo ); GETL( &p_vobu_map->i_end_byte );
i_max = ( i_start + p_vobu_map->i_end_byte + 1 - p_ifo->i_pos )
/ sizeof(u32);
p_vobu_map->pi_vobu_start_sector = malloc( i_max *sizeof(u32) );
if( p_vobu_map->pi_vobu_start_sector == NULL )
{
intf_ErrMsg( "ifo error: out of memory in ReadVobuMap" );
return -1;
} }
return; for( i = 0 ; i < i_max ; i++ )
{
GETL( &p_vobu_map->pi_vobu_start_sector[i] );
}
return 0;
} }
#endif
/*****************************************************************************
* FreeVobuMap: frees structures allocated by ReadVobuMap
*****************************************************************************/
static int FreeVobuMap( vobu_map_t * p_vobu_map )
{
free( p_vobu_map->pi_vobu_start_sector );
return 0;
}
/* /*
* IFO virtual machine : a set of commands that give the * IFO virtual machine : a set of commands that give the
* interactive behaviour of the dvd * interactive behaviour of the dvd
*/ */
#if 1 #if 0
#define OP_VAL_16(i) (ntoh16( com.data.pi_16[i])) #define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
#define OP_VAL_8(i) ((com.data.pi_8[i])) #define OP_VAL_8(i) ((com.data.pi_8[i]))
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvd_ifo.h: Structures for ifo parsing * dvd_ifo.h: Structures for ifo parsing
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ifo.h,v 1.8 2001/02/22 08:44:45 stef Exp $ * $Id: dvd_ifo.h,v 1.9 2001/04/01 07:31:38 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -76,7 +76,7 @@ typedef struct ifo_spu_t ...@@ -76,7 +76,7 @@ typedef struct ifo_spu_t
/* Ifo vitual machine Commands */ /* Ifo vitual machine Commands */
typedef struct ifo_command_s typedef struct command_desc_s
{ {
u8 i_type :3; u8 i_type :3;
u8 i_direct :1; u8 i_direct :1;
...@@ -89,162 +89,162 @@ typedef struct ifo_command_s ...@@ -89,162 +89,162 @@ typedef struct ifo_command_s
u8 pi_8[6]; u8 pi_8[6];
u16 pi_16[3]; u16 pi_16[3];
} data; } data;
} ifo_command_t; } command_desc_t;
/* Program Chain Command Table /* Program Chain Command Table
- start at i_pgc_com_tab_sbyte */ - start at i_pgc_com_tab_sbyte */
typedef struct pgc_com_tab_s typedef struct command_s
{ {
u16 i_pre_com_nb; // 2 bytes u16 i_pre_command_nb; // 2 bytes
u16 i_post_com_nb; // 2 bytes u16 i_post_command_nb; // 2 bytes
u16 i_cell_com_nb; // 2 bytes u16 i_cell_command_nb; // 2 bytes
// char[2] ??? // char[2] ???
ifo_command_t* p_pre_com; // i_pre_com_nb * 8 bytes command_desc_t* p_pre_command; // i_pre_com_nb * 8 bytes
ifo_command_t* p_post_com; // i_post_com_nb * 8 bytes command_desc_t* p_post_command; // i_post_com_nb * 8 bytes
ifo_command_t* p_cell_com; // i_cell_com_nb * 8 bytes command_desc_t* p_cell_command; // i_cell_com_nb * 8 bytes
} pgc_com_tab_t; } command_t;
/* Program Chain Map Table /* Program Chain Map Table
* - start at "i_pgc_prg_map_sbyte" */ * - start at "i_pgc_prg_map_sbyte" */
typedef struct pgc_prg_map_s typedef struct chapter_map_s
{ {
u8* pi_entry_cell; // i_prg_nb * 1 byte u8* pi_start_cell; // i_prg_nb * 1 byte
} pgc_prg_map_t; } chapter_map_t;
/* Cell Playback Information Table /* Cell Playback Information Table
* we have a pointer to such a structure for each cell * we have a pointer to such a structure for each cell
* - first start at "i_cell_play_inf_sbyte" */ * - first start at "i_cell_play_inf_sbyte" */
typedef struct cell_play_inf_s typedef struct cell_play_s
{ {
/* This information concerns the currently selected cell */ /* This information concerns the currently selected cell */
u16 i_cat; // 2 bytes u16 i_category; // 2 bytes
u8 i_still_time; // 1 byte; in seconds; ff=inf u8 i_still_time; // 1 byte; in seconds; ff=inf
u8 i_com_nb; // 1 byte; 0 = no com u8 i_command_nb; // 1 byte; 0 = no com
u32 i_play_time; // 4 bytes u32 i_play_time; // 4 bytes
u32 i_entry_sector; // 4 bytes u32 i_start_sector; // 4 bytes
u32 i_first_ilvu_vobu_esector; // 4 bytes; ??? u32 i_first_ilvu_vobu_esector; // 4 bytes; ???
u32 i_lvobu_ssector; // 4 bytes u32 i_last_vobu_start_sector; // 4 bytes
u32 i_lsector; // 4 bytes u32 i_end_sector; // 4 bytes
} cell_play_inf_t; } cell_play_t;
/* Cell Position Information Table /* Cell Position Information Table
* we have a pointer to such a structure for each cell * we have a pointer to such a structure for each cell
* - first start at "i_cell_pos_inf_sbyte" */ * - first start at "i_cell_pos_inf_sbyte" */
typedef struct cell_pos_inf_s typedef struct cell_pos_s
{ {
/* This information concerns the currently selected cell */ /* This information concerns the currently selected cell */
u16 i_vob_id; // 2 bytes u16 i_vob_id; // 2 bytes
// char ??? // char ???
u8 i_cell_id; // 1 byte u8 i_cell_id; // 1 byte
} cell_pos_inf_t; } cell_pos_t;
/* Main structure for Program Chain /* Main structure for Program Chain
* - start at i_fp_pgc_sbyte * - start at i_fp_pgc_sbyte
* - or at i_vmgm_pgci_sbyte in vmgm_pgci_srp_t */ * - or at i_vmgm_pgci_sbyte in vmgm_pgci_srp_t */
typedef struct pgc_s typedef struct title_s
{ {
/* Global features of program chain */ /* Global features of program chain */
// char[2] ??? // char[2] ???
u8 i_prg_nb; // 1 byte u8 i_chapter_nb; // 1 byte
u8 i_cell_nb; // 1 byte u8 i_cell_nb; // 1 byte
u32 i_play_time; // 4 bytes u32 i_play_time; // 4 bytes
u32 i_prohibited_user_op; // 4 bytes u32 i_prohibited_user_op; // 4 bytes
u16 pi_audio_status[8]; // 8*2 bytes u16 pi_audio_status[8]; // 8*2 bytes
u32 pi_subpic_status[32]; // 32*4 bytes u32 pi_subpic_status[32]; // 32*4 bytes
u16 i_next_pgc_nb; // 2 bytes u16 i_next_title_num; // 2 bytes
u16 i_prev_pgc_nb; // 2 bytes u16 i_prev_title_num; // 2 bytes
u16 i_goup_pgc_nb; // 2 bytes u16 i_go_up_title_num; // 2 bytes
u8 i_still_time; // 1 byte ; in seconds u8 i_still_time; // 1 byte ; in seconds
u8 i_play_mode; // 1 byte u8 i_play_mode; // 1 byte
/* In video_ts.ifo, the 3 significant bytes of each color are /* In video_ts.ifo, the 3 significant bytes of each color are
* preceded by 1 unsignificant byte */ * preceded by 1 unsignificant byte */
u32 pi_yuv_color[16]; // 16*3 bytes u32 pi_yuv_color[16]; // 16*3 bytes
/* Here come the start bytes of the following structures */ /* Here come the start bytes of the following structures */
u16 i_com_tab_sbyte; // 2 bytes u16 i_command_start_byte; // 2 bytes
u16 i_prg_map_sbyte; // 2 bytes u16 i_chapter_map_start_byte; // 2 bytes
u16 i_cell_play_inf_sbyte; // 2 bytes u16 i_cell_play_start_byte; // 2 bytes
u16 i_cell_pos_inf_sbyte; // 2 bytes u16 i_cell_pos_start_byte; // 2 bytes
/* Predefined structures */ /* Predefined structures */
pgc_com_tab_t com_tab; command_t command;
pgc_prg_map_t prg_map; chapter_map_t chapter_map;
cell_play_inf_t* p_cell_play_inf; // i_cell_nb * 24 bytes cell_play_t* p_cell_play; // i_cell_nb * 24 bytes
cell_pos_inf_t* p_cell_pos_inf; // i_cell_nb * 4 bytes cell_pos_t* p_cell_pos; // i_cell_nb * 4 bytes
} pgc_t; } title_t;
/* /*
* Menu PGCI Unit Table * Menu PGCI Unit Table
*/ */
/* Menu PGCI Language unit Descriptor */ /* Menu PGCI Language unit Descriptor */
typedef struct pgci_lu_s typedef struct unit_s
{ {
char ps_lang_code[2]; // 2 bytes (ISO-xx) char ps_lang_code[2]; // 2 bytes (ISO-xx)
// char ??? // char ???
u8 i_existence_mask; // 1 byte u8 i_existence_mask; // 1 byte
u32 i_lu_sbyte; // 4 bytes u32 i_unit_inf_start_byte; // 4 bytes
} pgci_lu_t; } unit_t;
typedef struct pgci_srp_s typedef struct unit_title_s
{ {
u8 i_pgc_cat_mask; // 1 byte u8 i_category_mask; // 1 byte
u8 i_pgc_cat; // 1 byte u8 i_category; // 1 byte
u16 i_par_mask; // 2 bytes u16 i_parental_mask; // 2 bytes
u32 i_pgci_sbyte; // 4 bytes u32 i_title_start_byte; // 4 bytes
pgc_t pgc; title_t title;
} pgci_srp_t; } unit_title_t;
/* Menu PGCI Language Unit Table /* Menu PGCI Language Unit Table
* - start at i_lu_sbyte */ * - start at i_lu_sbyte */
typedef struct pgci_inf_s typedef struct unit_inf_s
{ {
u16 i_srp_nb; // 2 bytes u16 i_title_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_lu_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
pgci_srp_t* p_srp; // i_srp_nb * 8 bytes unit_title_t * p_title; // i_srp_nb * 8 bytes
} pgci_inf_t; } unit_inf_t;
/* Main Struct for Menu PGCI /* Main Struct for Menu PGCI
* - start at i_*_pgci_ut_ssector */ * - start at i_*_pgci_ut_ssector */
typedef struct pgci_ut_s typedef struct title_unit_s
{ {
u16 i_lu_nb; // 2 bytes; ??? u16 i_unit_nb; // 2 bytes; ???
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
pgci_lu_t* p_lu; // i_lu_nb * 8 bytes unit_t* p_unit; // i_lu_nb * 8 bytes
pgci_inf_t* p_pgci_inf; // i_lu_nb * 8 bytes unit_inf_t* p_unit_inf; // i_lu_nb * 8 bytes
} pgci_ut_t; } title_unit_t;
/* /*
* Cell Adress Table Information * Cell Adress Table Information
*/ */
typedef struct cell_inf_s typedef struct cell_map_s
{ {
u16 i_vob_id; // 2 bytes u16 i_vob_id; // 2 bytes
u8 i_cell_id; // 1 byte u8 i_cell_id; // 1 byte
// char ??? // char ???
u32 i_ssector; // 4 bytes u32 i_start_sector; // 4 bytes
u32 i_esector; // 4 bytes u32 i_end_sector; // 4 bytes
} cell_inf_t; } cell_map_t;
typedef struct c_adt_s typedef struct cell_inf_s
{ {
u16 i_vob_nb; // 2 bytes u16 i_vob_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u16 i_cell_nb; // not in ifo; computed u16 i_cell_nb; // not in ifo; computed
// with e_byte // with e_byte
cell_inf_t* p_cell_inf; cell_map_t* p_cell_map;
} c_adt_t; } cell_inf_t;
/* /*
* VOBU Adress Map Table * VOBU Adress Map Table
*/ */
typedef struct vobu_admap_s typedef struct vobu_map_s
{ {
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u32* pi_vobu_ssector; // (nb of vobu) * 4 bytes u32* pi_vobu_start_sector; // (nb of vobu) * 4 bytes
} vobu_admap_t; } vobu_map_t;
/***************************************************************************** /*****************************************************************************
* Structures for Video Management (cf video_ts.ifo) * Structures for Video Management (cf video_ts.ifo)
...@@ -253,43 +253,43 @@ typedef struct vobu_admap_s ...@@ -253,43 +253,43 @@ typedef struct vobu_admap_s
/* /*
* Video Manager Information Management Table * Video Manager Information Management Table
*/ */
typedef struct vmgi_mat_s typedef struct manager_inf_s
{ {
char psz_id[13]; // 12 bytes (DVDVIDEO-VMG) char psz_id[13]; // 12 bytes (DVDVIDEO-VMG)
u32 i_lsector; // 4 bytes u32 i_vmg_end_sector; // 4 bytes
// char[12] ??? // char[12] ???
u32 i_i_lsector; // 4 bytes u32 i_vmg_inf_end_sector; // 4 bytes
// char ??? // char ???
u8 i_spec_ver; // 1 byte u8 i_spec_ver; // 1 byte
u32 i_cat; // 4 bytes u32 i_cat; // 4 bytes
u16 i_vol_nb; // 2 bytes u16 i_volume_nb; // 2 bytes
u16 i_vol; // 2 bytes u16 i_volume; // 2 bytes
u8 i_disc_side; // 1 bytes u8 i_disc_side; // 1 bytes
// char[20] ??? // char[20] ???
u16 i_tts_nb; // 2 bytes u16 i_title_set_nb; // 2 bytes
char ps_provider_id[32]; // 32 bytes char ps_provider_id[32]; // 32 bytes
u64 i_pos_code; // 8 bytes u64 i_pos_code; // 8 bytes
// char[24] ??? // char[24] ???
u32 i_i_mat_ebyte; // 4 bytes u32 i_vmg_inf_end_byte; // 4 bytes
u32 i_fp_pgc_sbyte; // 4 bytes u32 i_first_play_title_start_byte; // 4 bytes
// char[56] ??? // char[56] ???
u32 i_vobs_ssector; // 4 bytes u32 i_vob_start_sector; // 4 bytes
u32 i_ptt_srpt_ssector; // 4 bytes u32 i_title_inf_start_sector; // 4 bytes
u32 i_pgci_ut_ssector; // 4 bytes u32 i_title_unit_start_sector; // 4 bytes
u32 i_ptl_mait_ssector; // 4 bytes u32 i_parental_inf_start_sector; // 4 bytes
u32 i_vts_atrt_ssector; // 4 bytes u32 i_vts_inf_start_sector; // 4 bytes
u32 i_txtdt_mg_ssector; // 4 bytes u32 i_text_data_start_sector; // 4 bytes
u32 i_c_adt_ssector; // 4 bytes u32 i_cell_inf_start_sector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes u32 i_vobu_map_start_sector; // 4 bytes
// char[2] ??? // char[2] ???
ifo_video_t video_atrt; // 2 bytes ifo_video_t video_attr; // 2 bytes
// char ??? // char ???
u8 i_audio_nb; // 1 byte u8 i_audio_nb; // 1 byte
ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_subpic_nb; // 1 byte u8 i_spu_nb; // 1 byte
ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
} vmgi_mat_t; } manager_inf_t;
/* /*
...@@ -298,53 +298,53 @@ typedef struct vmgi_mat_s ...@@ -298,53 +298,53 @@ typedef struct vmgi_mat_s
/* Title sets structure /* Title sets structure
* we have a pointer to this structure for each tts */ * we have a pointer to this structure for each tts */
typedef struct tts_s typedef struct title_attr_s
{ {
u8 i_play_type; // 1 byte u8 i_play_type; // 1 byte
u8 i_angle_nb; // 1 byte u8 i_angle_nb; // 1 byte
u16 i_ptt_nb; // 2 bytes; Chapters/PGs u16 i_chapter_nb; // 2 bytes; Chapters/PGs
u16 i_parental_id; // 2 bytes u16 i_parental_id; // 2 bytes
u8 i_tts_nb; // 1 byte (VTS#) u8 i_title_set_num; // 1 byte (VTS#)
u8 i_vts_ttn; // 1 byte ??? u8 i_title_num; // 1 byte ???
u32 i_ssector; // 4 bytes u32 i_start_sector; // 4 bytes
} tts_t; } title_attr_t;
/* Main struct for tts /* Main struct for tts
* - start at "i_vmg_ptt_srpt_ssector" */ * - start at "i_vmg_ptt_srpt_ssector" */
typedef struct vmg_ptt_srpt_s typedef struct title_inf_s
{ {
u16 i_ttu_nb; // 2 bytes u16 i_title_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
tts_t* p_tts; // i_ttu_nb * 12 bytes title_attr_t * p_attr; // i_ttu_nb * 12 bytes
} vmg_ptt_srpt_t; } title_inf_t;
/* /*
* Parental Management Information Table * Parental Management Information Table
*/ */
typedef struct vmg_ptl_mai_desc_s typedef struct parental_desc_s
{ {
char ps_country_code[2]; // 2 bytes char ps_country_code[2]; // 2 bytes
// char[2] ??? // char[2] ???
u16 i_ptl_mai_sbyte; // 2 bytes u16 i_parental_mask_start_byte; // 2 bytes
// char[2] ??? // char[2] ???
} vmg_ptl_mai_desc_t; } parental_desc_t;
typedef struct vmg_ptl_mask_s typedef struct parental_mask_s
{ {
u16* ppi_ptl_mask[8]; // (i_vts_nb +1) * 8 * 2 bytes u16* ppi_mask[8]; // (i_vts_nb +1) * 8 * 2 bytes
} vmg_ptl_mask_t; } parental_mask_t;
/* Main struct for parental management /* Main struct for parental management
* - start at i_vmg_ptl_mait_ssector */ * - start at i_vmg_ptl_mait_ssector */
typedef struct vmg_ptl_mait_s typedef struct parental_inf_s
{ {
u16 i_country_nb; // 2 bytes u16 i_country_nb; // 2 bytes
u16 i_vts_nb; // 2 bytes u16 i_vts_nb; // 2 bytes
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
vmg_ptl_mai_desc_t* p_ptl_desc; // i_country_nb * 8 bytes parental_desc_t* p_parental_desc; // i_country_nb * 8 bytes
vmg_ptl_mask_t* p_ptl_mask; // i_country_nb * sizeof(vmg_ptl_mask_t) parental_mask_t* p_parental_mask; // i_country_nb * sizeof(vmg_ptl_mask_t)
} vmg_ptl_mait_t; } parental_inf_t;
/* /*
* Video Title Set Attribute Table * Video Title Set Attribute Table
...@@ -352,51 +352,51 @@ typedef struct vmg_ptl_mait_s ...@@ -352,51 +352,51 @@ typedef struct vmg_ptl_mait_s
/* Attribute structure : one for each vts /* Attribute structure : one for each vts
* - start at pi_atrt_sbyte */ * - start at pi_atrt_sbyte */
typedef struct vts_atrt_s typedef struct vts_attr_s
{ {
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u32 i_cat_app_type; // 4 bytes u32 i_cat_app_type; // 4 bytes
ifo_video_t vtsm_video_atrt; // 2 bytes ifo_video_t vts_menu_video_attr; // 2 bytes
// char ??? // char ???
u8 i_vtsm_audio_nb; // 1 byte u8 i_vts_menu_audio_nb; // 1 byte
ifo_audio_t p_vtsm_audio_atrt[8]; // 8 * 8 bytes ifo_audio_t p_vts_menu_audio_attr[8]; // 8 * 8 bytes
// char[17] ??? // char[17] ???
u8 i_vtsm_subpic_nb; // 1 byte u8 i_vts_menu_spu_nb; // 1 byte
ifo_spu_t p_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes ifo_spu_t p_vts_menu_spu_attr[28]; // i_vtsm_subpic_nb * 6 bytes
// char[2] ??? // char[2] ???
ifo_video_t vtstt_video_atrt; // 2 bytes ifo_video_t vts_title_video_attr; // 2 bytes
// char ??? // char ???
u8 i_vtstt_audio_nb; // 1 byte u8 i_vts_title_audio_nb; // 1 byte
ifo_audio_t p_vtstt_audio_atrt[8]; // 8 * 8 bytes ifo_audio_t p_vts_title_audio_attr[8]; // 8 * 8 bytes
// char[17] ??? // char[17] ???
u8 i_vtstt_subpic_nb; // 1 byte u8 i_vts_title_spu_nb; // 1 byte
ifo_spu_t p_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes ifo_spu_t p_vts_title_spu_attr[28]; // i_vtstt_subpic_nb * 6 bytes
} vts_atrt_t; } vts_attr_t;
/* Main struct for vts attributes /* Main struct for vts attributes
* - start at i_vmg_vts_atrt_ssector */ * - start at i_vmg_vts_atrt_ssector */
typedef struct vmg_vts_atrt_s typedef struct vts_inf_s
{ {
u16 i_vts_nb; // 2 bytes u16 i_vts_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u32* pi_vts_atrt_sbyte; // i_vts_nb * 4 bytes u32* pi_vts_attr_start_byte; // i_vts_nb * 4 bytes
vts_atrt_t* p_vts_atrt; vts_attr_t* p_vts_attr;
} vmg_vts_atrt_t; } vts_inf_t;
/* /*
* Global Structure for Video Manager * Global Structure for Video Manager
*/ */
typedef struct vmg_s typedef struct vmg_s
{ {
vmgi_mat_t mat; manager_inf_t manager_inf;
pgc_t pgc; title_t title;
vmg_ptt_srpt_t ptt_srpt; title_inf_t title_inf;
pgci_ut_t pgci_ut; title_unit_t title_unit;
vmg_ptl_mait_t ptl_mait; parental_inf_t parental_inf;
vmg_vts_atrt_t vts_atrt; vts_inf_t vts_inf;
c_adt_t c_adt; cell_inf_t cell_inf;
vobu_admap_t vobu_admap; vobu_map_t vobu_map;
} vmg_t; } vmg_t;
/***************************************************************************** /*****************************************************************************
...@@ -406,46 +406,46 @@ typedef struct vmg_s ...@@ -406,46 +406,46 @@ typedef struct vmg_s
/* /*
* Video Title Sets Information Management Table * Video Title Sets Information Management Table
*/ */
typedef struct vtsi_mat_s typedef struct vts_manager_s
{ {
char psz_id[13]; // 12 bytes (DVDVIDEO-VTS) char psz_id[13]; // 12 bytes (DVDVIDEO-VTS)
u32 i_lsector; // 4 bytes u32 i_end_sector; // 4 bytes
// char[12] ??? // char[12] ???
u32 i_i_lsector; // 4 bytes u32 i_inf_end_sector; // 4 bytes
// char ??? // char ???
u8 i_spec_ver; // 1 byte u8 i_spec_ver; // 1 byte
u32 i_cat; // 4 bytes u32 i_cat; // 4 bytes
// char[90] ??? // char[90] ???
u32 i_mat_ebyte; // 4 bytes u32 i_inf_end_byte; // 4 bytes
// char[60] ??? // char[60] ???
u32 i_m_vobs_ssector; // 4 bytes u32 i_menu_vob_start_sector; // 4 bytes
u32 i_tt_vobs_ssector; // 4 bytes u32 i_title_vob_start_sector; // 4 bytes
u32 i_ptt_srpt_ssector; // 4 bytes u32 i_title_inf_start_sector; // 4 bytes
u32 i_pgcit_ssector; // 4 bytes u32 i_title_unit_start_sector; // 4 bytes
u32 i_m_pgci_ut_ssector; // 4 bytes u32 i_menu_unit_start_sector; // 4 bytes
u32 i_tmap_ti_ssector; // 4 bytes u32 i_time_inf_start_sector; // 4 bytes
u32 i_m_c_adt_ssector; // 4 bytes u32 i_menu_cell_inf_start_sector; // 4 bytes
u32 i_m_vobu_admap_ssector; // 4 bytes u32 i_menu_vobu_map_start_sector; // 4 bytes
u32 i_c_adt_ssector; // 4 bytes u32 i_cell_inf_start_sector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes u32 i_vobu_map_start_sector; // 4 bytes
// char[24] ??? // char[24] ???
ifo_video_t m_video_atrt; // 2 bytes ifo_video_t menu_video_attr; // 2 bytes
// char ??? // char ???
u8 i_m_audio_nb; // 1 byte u8 i_menu_audio_nb; // 1 byte
ifo_audio_t p_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_menu_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_m_subpic_nb; // 1 byte u8 i_menu_spu_nb; // 1 byte
ifo_spu_t p_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_menu_spu_attr[32]; // i_subpic_nb * 6 bytes
// !!! only 28 subpics ??? // !!! only 28 subpics ???
// char[2] ??? // char[2] ???
ifo_video_t video_atrt; // 2 bytes ifo_video_t video_attr; // 2 bytes
// char ??? // char ???
u8 i_audio_nb; // 1 byte u8 i_audio_nb; // 1 byte
ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes ifo_audio_t p_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ??? // char[16] ???
u8 i_subpic_nb; // 1 byte u8 i_spu_nb; // 1 byte
ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
} vtsi_mat_t; } vts_manager_t;
/* /*
* Part Of Title Search Pointer Table Information * Part Of Title Search Pointer Table Information
...@@ -453,70 +453,63 @@ typedef struct vtsi_mat_s ...@@ -453,70 +453,63 @@ typedef struct vtsi_mat_s
/* Title sets structure /* Title sets structure
* we have a pointer to this structure for each tts */ * we have a pointer to this structure for each tts */
typedef struct ttu_s typedef struct title_start_s
{ {
u16 i_pgc_nb; // 2 bytes; Chapters/PGs u16 i_program_chain_num; // 2 bytes; Chapters/PGs
u16 i_prg_nb; // 2 bytes u16 i_program_num; // 2 bytes
} ttu_t; } title_start_t;
/* Main struct for tts /* Main struct for tts
* - start at "i_vts_ptt_srpt_ssector" */ * - start at "i_vts_ptt_srpt_ssector" */
typedef struct vts_ptt_srpt_s typedef struct vts_title_s
{ {
u16 i_ttu_nb; // 2 bytes u16 i_title_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u32* pi_ttu_sbyte; u32* pi_start_byte;
ttu_t* p_ttu; // i_ttu_nb * 4 bytes title_start_t * p_title_start; // i_ttu_nb * 4 bytes
} vts_ptt_srpt_t; } vts_title_t;
/* /*
* Time Map table information * Time Map table information
*/ */
/* Time Map structure */ /* Time Map structure */
typedef struct tmap_s typedef struct time_map_s
{ {
u8 i_time_unit; // 1 byte u8 i_time_unit; // 1 byte
// char ??? // char ???
u16 i_entry_nb; // 2 bytes u16 i_entry_nb; // 2 bytes
u32* pi_sector; // i_entry_nb * 4 bytes u32* pi_sector; // i_entry_nb * 4 bytes
} tmap_t; } time_map_t;
/* Main structure for tmap_ti /* Main structure for tmap_ti
* - start at "i_tmap_ti_ssector" */ * - start at "i_tmap_ti_ssector" */
typedef struct vts_tmap_ti_s typedef struct time_inf_s
{ {
u16 i_nb; // 2 bytes u16 i_nb; // 2 bytes
// char[2] ??? // char[2] ???
u32 i_ebyte; // 4 bytes u32 i_end_byte; // 4 bytes
u32* pi_sbyte; // i_tmap_nb * 4 bytes u32* pi_start_byte; // i_tmap_nb * 4 bytes
tmap_t* p_tmap; time_map_t* p_time_map;
} vts_tmap_ti_t; } time_inf_t;
/* /*
* Video Title Set * Video Title Set
*/ */
typedef struct vts_s typedef struct vts_s
{ {
boolean_t b_initialized;
off_t i_pos; off_t i_pos;
vtsi_mat_t mat; vts_manager_t manager_inf;
/* Part Of Title Search Pointer Table Info */ vts_title_t title_inf;
vts_ptt_srpt_t ptt_srpt; title_unit_t menu_unit;
/* Video Title Set Menu PGCI Unit Table */ unit_inf_t title_unit;
pgci_ut_t pgci_ut; time_inf_t time_inf;
/* Video Title Set Program Chain Info Table */ cell_inf_t menu_cell_inf;
pgci_inf_t pgci_ti; vobu_map_t menu_vobu_map;
/* Video Title Set Time Map Table */ cell_inf_t cell_inf;
vts_tmap_ti_t tmap_ti; vobu_map_t vobu_map;
/* VTSM Cell Adress Table Information */
c_adt_t m_c_adt;
/* VTSM VOBU Adress Map Table */
vobu_admap_t m_vobu_admap;
/* VTS Cell Adress Table Information */
c_adt_t c_adt;
/* VTS VOBU Adress Map Table */
vobu_admap_t vobu_admap;
} vts_t; } vts_t;
/* /*
...@@ -524,19 +517,12 @@ typedef struct vts_s ...@@ -524,19 +517,12 @@ typedef struct vts_s
*/ */
typedef struct ifo_s typedef struct ifo_s
{ {
/* File descriptor for the device */ int i_fd; /* File descriptor for the device */
int i_fd; off_t i_off; /* Offset to video_ts.ifo on the device */
/* Offset to video_ts.ifo on the device */ off_t i_pos; /* Position of stream pointer */
off_t i_off; boolean_t b_error; /* Error Management */
/* Position of stream pointer */ vmg_t vmg; /* Structure described in video_ts */
off_t i_pos; int i_title; /* Current title number */
/* Error Management */ vts_t vts; /* Vts ifo for current title set */
boolean_t b_error;
/* Current title set number */
int i_title;
/* Structure described in video_ts */
vmg_t vmg;
/* Vts ifo for current title set */
vts_t vts;
} ifo_t; } ifo_t;
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* will only be given back to netlist when refcount is zero. * will only be given back to netlist when refcount is zero.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: dvd_netlist.c,v 1.3 2001/03/22 01:23:03 stef Exp $ * $Id: dvd_netlist.c,v 1.4 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Henri Fallon <henri@videolan.org> * Authors: Henri Fallon <henri@videolan.org>
* Stphane Borel <stef@videolan.org> * Stphane Borel <stef@videolan.org>
...@@ -357,7 +357,7 @@ struct data_packet_s * DVDNewPacket( void * p_method_data, ...@@ -357,7 +357,7 @@ struct data_packet_s * DVDNewPacket( void * p_method_data,
{ {
dvd_netlist_t * p_netlist; dvd_netlist_t * p_netlist;
struct data_packet_s * p_packet; struct data_packet_s * p_packet;
//intf_ErrMsg( "netlist: New packet" );
/* cast */ /* cast */
p_netlist = (dvd_netlist_t *)p_method_data; p_netlist = (dvd_netlist_t *)p_method_data;
...@@ -382,14 +382,18 @@ struct data_packet_s * DVDNewPacket( void * p_method_data, ...@@ -382,14 +382,18 @@ struct data_packet_s * DVDNewPacket( void * p_method_data,
p_packet = p_netlist->pp_free_data[p_netlist->i_data_start]; p_packet = p_netlist->pp_free_data[p_netlist->i_data_start];
p_packet->p_buffer = p_packet->p_buffer =
p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base; p_netlist->p_free_iovec[p_netlist->i_iovec_start].iov_base;
p_packet->p_payload_start = p_packet->p_buffer; p_packet->p_payload_start = p_packet->p_buffer;
p_packet->p_payload_end = p_packet->p_payload_end =
p_packet->p_buffer + i_buffer_size; p_packet->p_buffer + i_buffer_size;
p_packet->p_next = NULL;
p_packet->b_discard_payload = 0;
p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start; p_packet->pi_refcount = p_netlist->pi_refcount + p_netlist->i_iovec_start;
(*p_packet->pi_refcount)++;
p_netlist->i_iovec_start ++; p_netlist->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec; p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
...@@ -411,6 +415,7 @@ struct pes_packet_s * DVDNewPES( void * p_method_data ) ...@@ -411,6 +415,7 @@ struct pes_packet_s * DVDNewPES( void * p_method_data )
dvd_netlist_t * p_netlist; dvd_netlist_t * p_netlist;
pes_packet_t * p_return; pes_packet_t * p_return;
//intf_ErrMsg( "netlist: New pes" );
/* cast */ /* cast */
p_netlist = (dvd_netlist_t *)p_method_data; p_netlist = (dvd_netlist_t *)p_method_data;
...@@ -433,9 +438,10 @@ struct pes_packet_s * DVDNewPES( void * p_method_data ) ...@@ -433,9 +438,10 @@ struct pes_packet_s * DVDNewPES( void * p_method_data )
vlc_mutex_unlock (&p_netlist->lock); vlc_mutex_unlock (&p_netlist->lock);
/* initialize PES */ /* initialize PES */
p_return->b_data_alignment = p_return->b_data_alignment = 0;
p_return->b_discontinuity = p_return->b_discontinuity = 0;
p_return->i_pts = p_return->i_dts = 0; p_return->i_pts = 0;
p_return->i_dts = 0;
p_return->i_pes_size = 0; p_return->i_pes_size = 0;
p_return->p_first = NULL; p_return->p_first = NULL;
...@@ -462,6 +468,9 @@ void DVDDeletePacket( void * p_method_data, data_packet_t * p_data ) ...@@ -462,6 +468,9 @@ void DVDDeletePacket( void * p_method_data, data_packet_t * p_data )
p_netlist->pp_free_data[p_netlist->i_data_end] = p_data; p_netlist->pp_free_data[p_netlist->i_data_end] = p_data;
p_data->p_next = NULL;
p_data->b_discard_payload = 0;
/* Update reference counter */ /* Update reference counter */
(*p_data->pi_refcount)--; (*p_data->pi_refcount)--;
...@@ -510,7 +519,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes ) ...@@ -510,7 +519,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
/* Update reference counter */ /* Update reference counter */
(*p_current_packet->pi_refcount)--; (*p_current_packet->pi_refcount)--;
if( (*p_current_packet->pi_refcount) == 0 ) if( (*p_current_packet->pi_refcount) <= 0 )
{ {
p_netlist->i_iovec_end++; p_netlist->i_iovec_end++;
p_netlist->i_iovec_end &= p_netlist->i_nb_iovec; p_netlist->i_iovec_end &= p_netlist->i_nb_iovec;
...@@ -520,6 +529,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes ) ...@@ -520,6 +529,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
p_next_packet = p_current_packet->p_next; p_next_packet = p_current_packet->p_next;
p_current_packet->p_next = NULL; p_current_packet->p_next = NULL;
p_current_packet->b_discard_payload = 0;
p_current_packet = p_next_packet; p_current_packet = p_next_packet;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* -dvd_udf to find files * -dvd_udf to find files
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.34 2001/03/22 01:23:03 stef Exp $ * $Id: input_dvd.c,v 1.35 2001/04/01 07:31:38 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -354,25 +354,26 @@ static int DVDCheckCSS( input_thread_t * p_input ) ...@@ -354,25 +354,26 @@ static int DVDCheckCSS( input_thread_t * p_input )
*****************************************************************************/ *****************************************************************************/
static int DVDFindCell( thread_dvd_data_t * p_dvd ) static int DVDFindCell( thread_dvd_data_t * p_dvd )
{ {
pgc_t * p_pgc;
int i_cell; int i_cell;
int i_index; int i_index;
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc; #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_program_chain-1].title
#define cell p_dvd->p_ifo->vts.cell_inf
i_cell = p_dvd->i_cell; i_cell = p_dvd->i_cell;
i_index = p_dvd->i_prg_cell; i_index = p_dvd->i_prg_cell;
while( ( ( p_pgc->p_cell_pos_inf[i_index].i_vob_id != while( ( ( title.p_cell_pos[i_index].i_vob_id !=
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id ) || cell.p_cell_map[i_cell].i_vob_id ) ||
( p_pgc->p_cell_pos_inf[i_index].i_cell_id != ( title.p_cell_pos[i_index].i_cell_id !=
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id ) ) && cell.p_cell_map[i_cell].i_cell_id ) ) &&
( i_cell < p_dvd->ifo.vts.c_adt.i_cell_nb ) ) ( i_cell < cell.i_cell_nb ) )
{ {
i_cell++; i_cell++;
} }
if( i_cell == p_dvd->ifo.vts.c_adt.i_cell_nb ) if( i_cell == cell.i_cell_nb )
{ {
return -1; return -1;
} }
...@@ -381,6 +382,8 @@ static int DVDFindCell( thread_dvd_data_t * p_dvd ) ...@@ -381,6 +382,8 @@ static int DVDFindCell( thread_dvd_data_t * p_dvd )
p_dvd->i_cell = i_cell; p_dvd->i_cell = i_cell;
return 0; return 0;
} }
#undef title
#undef cell
} }
/***************************************************************************** /*****************************************************************************
...@@ -389,11 +392,10 @@ static int DVDFindCell( thread_dvd_data_t * p_dvd ) ...@@ -389,11 +392,10 @@ static int DVDFindCell( thread_dvd_data_t * p_dvd )
*****************************************************************************/ *****************************************************************************/
static int DVDFindSector( thread_dvd_data_t * p_dvd ) static int DVDFindSector( thread_dvd_data_t * p_dvd )
{ {
pgc_t * p_pgc; #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_program_chain-1].title
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc; if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector )
if( p_dvd->i_sector > p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector )
{ {
p_dvd->i_prg_cell++; p_dvd->i_prg_cell++;
} }
...@@ -405,13 +407,14 @@ static int DVDFindSector( thread_dvd_data_t * p_dvd ) ...@@ -405,13 +407,14 @@ static int DVDFindSector( thread_dvd_data_t * p_dvd )
/* Find start and end sectors of new cell */ /* Find start and end sectors of new cell */
p_dvd->i_sector = MAX( p_dvd->i_sector = MAX(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_ssector, p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_entry_sector ); title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
p_dvd->i_end_sector = MIN( p_dvd->i_end_sector = MIN(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector, p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector ); title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
intf_WarnMsg( 3, "cell: %d sector1: 0x%x end1: 0x%x\nindex: %d sector2: 0x%x end2: 0x%x", p_dvd->i_cell, p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_ssector, p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector, p_dvd->i_prg_cell, p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_entry_sector, p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector ); //intf_WarnMsg( 3, "cell: %d sector1: 0x%x end1: 0x%x\nindex: %d sector2: 0x%x end2: 0x%x", p_dvd->i_cell, p_dvd->p_ifo->p_vts->c_adt.p_cell_inf[p_dvd->i_cell].i_ssector, p_dvd->p_ifo->p_vts->c_adt.p_cell_inf[p_dvd->i_cell].i_esector, p_dvd->i_prg_cell, p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_entry_sector, p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector );
#undef title
return 0; return 0;
} }
...@@ -422,12 +425,11 @@ intf_WarnMsg( 3, "cell: %d sector1: 0x%x end1: 0x%x\nindex: %d sector2: 0x%x end ...@@ -422,12 +425,11 @@ intf_WarnMsg( 3, "cell: %d sector1: 0x%x end1: 0x%x\nindex: %d sector2: 0x%x end
*****************************************************************************/ *****************************************************************************/
static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter ) static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
{ {
pgc_t * p_pgc; #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_program_chain-1].title
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc;
/* Find cell index in Program chain for current chapter */ /* Find cell index in Program chain for current chapter */
p_dvd->i_prg_cell = p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1; p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
p_dvd->i_cell = 0; p_dvd->i_cell = 0;
/* Search for cell_index in cell adress_table and initialize start sector */ /* Search for cell_index in cell adress_table and initialize start sector */
...@@ -441,7 +443,7 @@ static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter ) ...@@ -441,7 +443,7 @@ static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter )
p_dvd->i_start = lseek( p_dvd->i_fd, p_dvd->i_start, SEEK_SET ); p_dvd->i_start = lseek( p_dvd->i_fd, p_dvd->i_start, SEEK_SET );
p_dvd->i_chapter = i_chapter; p_dvd->i_chapter = i_chapter;
#undef title
return 0; return 0;
} }
...@@ -458,7 +460,8 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -458,7 +460,8 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
es_descriptor_t * p_es; es_descriptor_t * p_es;
int i_nb; int i_audio;
int i_spu;
u16 i_id; u16 i_id;
u8 i_ac3; u8 i_ac3;
u8 i_mpeg; u8 i_mpeg;
...@@ -482,26 +485,28 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -482,26 +485,28 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
/* title number: it is not vts nb! */ /* title number: it is not vts nb! */
p_dvd->i_title = p_area->i_id; p_dvd->i_title = p_area->i_id;
p_dvd->p_ifo->i_title = p_dvd->i_title;
/* ifo vts */
IfoTitleSet( p_dvd->p_ifo );
intf_WarnMsg( 2, "ifo info: vts initialized" );
#define vmg p_dvd->p_ifo->vmg
#define vts p_dvd->p_ifo->vts
/* title position inside the selected vts */ /* title position inside the selected vts */
p_dvd->i_vts_title = p_dvd->i_vts_title =
p_dvd->ifo.vmg.ptt_srpt.p_tts[p_dvd->i_title-1].i_vts_ttn; vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
p_dvd->i_program_chain =
/* vts number */ vts.title_inf.p_title_start[p_dvd->i_vts_title-1].i_program_chain_num;
p_dvd->ifo.i_title = p_dvd->i_title;
/* ifo vts */
IfoReadVTS( &(p_dvd->ifo) );
intf_WarnMsg( 2, "ifo info: vts initialized" );
/* css title key for current vts */ /* css title key for current vts */
if( p_dvd->b_encrypted ) if( p_dvd->b_encrypted )
{ {
p_dvd->p_css->i_title = p_dvd->p_css->i_title =
p_dvd->ifo.vmg.ptt_srpt.p_tts[p_dvd->i_title-1].i_tts_nb; vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_set_num;
p_dvd->p_css->i_title_pos = p_dvd->p_css->i_title_pos =
p_dvd->ifo.vts.i_pos + vts.i_pos +
p_dvd->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE; vts.manager_inf.i_title_vob_start_sector * DVD_LB_SIZE;
CSSGetKey( p_dvd->p_css ); CSSGetKey( p_dvd->p_css );
intf_WarnMsg( 2, "css info: vts key initialized" ); intf_WarnMsg( 2, "css info: vts key initialized" );
} }
...@@ -511,24 +516,24 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -511,24 +516,24 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
*/ */
/* title set offset */ /* title set offset */
p_dvd->i_title_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE * p_dvd->i_title_start = vts.i_pos + DVD_LB_SIZE *
(off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector ); (off_t)( vts.manager_inf.i_title_vob_start_sector );
/* last video cell */ /* last video cell */
p_dvd->i_cell = 0; p_dvd->i_cell = 0;
p_dvd->i_prg_cell = -1 + p_dvd->i_prg_cell = -1 +
p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc.i_cell_nb; vts.title_unit.p_title[p_dvd->i_program_chain-1].title.i_cell_nb;
DVDFindCell( p_dvd ); DVDFindCell( p_dvd );
/* temporary hack to fix size in some dvds */ /* temporary hack to fix size in some dvds */
if( p_dvd->i_cell >= p_dvd->ifo.vts.c_adt.i_cell_nb ) if( p_dvd->i_cell >= vts.cell_inf.i_cell_nb )
{ {
p_dvd->i_cell = p_dvd->ifo.vts.c_adt.i_cell_nb - 1; p_dvd->i_cell = vts.cell_inf.i_cell_nb - 1;
} }
p_dvd->i_sector = 0; p_dvd->i_sector = 0;
p_dvd->i_size = DVD_LB_SIZE * p_dvd->i_size = DVD_LB_SIZE *
(off_t)( p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector ); (off_t)( vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector );
DVDChapterSelect( p_dvd, 1 ); DVDChapterSelect( p_dvd, 1 );
...@@ -538,7 +543,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -538,7 +543,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
intf_WarnMsg( 2, "dvd info: vobstart at: %lld", p_dvd->i_start ); intf_WarnMsg( 2, "dvd info: vobstart at: %lld", p_dvd->i_start );
intf_WarnMsg( 2, "dvd info: stream size: %lld", p_dvd->i_size ); intf_WarnMsg( 2, "dvd info: stream size: %lld", p_dvd->i_size );
intf_WarnMsg( 2, "dvd info: number of chapters: %d", intf_WarnMsg( 2, "dvd info: number of chapters: %d",
p_dvd->ifo.vmg.ptt_srpt.p_tts[p_dvd->i_title-1].i_ptt_nb ); vmg.title_inf.p_attr[p_dvd->i_title-1].i_chapter_nb );
/* Area definition */ /* Area definition */
p_input->stream.p_selected_area->i_start = p_dvd->i_start; p_input->stream.p_selected_area->i_start = p_dvd->i_start;
...@@ -560,7 +565,6 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -560,7 +565,6 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
input_DelProgram( p_input, p_input->stream.pp_programs[0] ); input_DelProgram( p_input, p_input->stream.pp_programs[0] );
free( p_input->stream.pp_selected_es );
p_input->stream.pp_selected_es = NULL; p_input->stream.pp_selected_es = NULL;
p_input->stream.i_selected_es_number = 0; p_input->stream.i_selected_es_number = 0;
} }
...@@ -576,33 +580,31 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -576,33 +580,31 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
intf_WarnMsg( 1, "dvd info: video MPEG2 stream" ); intf_WarnMsg( 1, "dvd info: video MPEG2 stream" );
/* Audio ES, in the order they appear in .ifo */ /* Audio ES, in the order they appear in .ifo */
i_nb = p_dvd->ifo.vts.mat.i_audio_nb;
i_ac3 = 0x7f; i_ac3 = 0x7f;
i_mpeg = 0xc0; i_mpeg = 0xc0;
for( i = 1 ; i <= i_nb ; i++ ) for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
{ {
#ifdef DEBUG #ifdef DEBUG
intf_DbgMsg( "Audio %d: %x %x %x %x %x %x %x %x %x %x %x %x\n", i, intf_DbgMsg( "Audio %d: %x %x %x %x %x %x %x %x %x %x %x %x\n", i,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_num_channels, vts.manager_inf.p_audio_attr[i-1].i_num_channels,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode, vts.manager_inf.p_audio_attr[i-1].i_coding_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_multichannel_extension, vts.manager_inf.p_audio_attr[i-1].i_multichannel_extension,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_type, vts.manager_inf.p_audio_attr[i-1].i_type,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode, vts.manager_inf.p_audio_attr[i-1].i_appl_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_foo, vts.manager_inf.p_audio_attr[i-1].i_foo,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_bar, vts.manager_inf.p_audio_attr[i-1].i_bar,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode, vts.manager_inf.p_audio_attr[i-1].i_appl_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_quantization, vts.manager_inf.p_audio_attr[i-1].i_quantization,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_sample_freq, vts.manager_inf.p_audio_attr[i-1].i_sample_freq,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code, vts.manager_inf.p_audio_attr[i-1].i_lang_code,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_caption ); vts.manager_inf.p_audio_attr[i-1].i_caption );
#endif #endif
switch( p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode ) switch( vts.manager_inf.p_audio_attr[i-1].i_coding_mode )
{ {
case 0x00: /* AC3 */ case 0x00: /* AC3 */
i_id = ( ( i_ac3 + i ) << 8 ) | 0xbd; i_id = ( ( i_ac3 + i ) << 8 ) | 0xbd;
...@@ -612,7 +614,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -612,7 +614,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
p_es->i_type = AC3_AUDIO_ES; p_es->i_type = AC3_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
strcpy( p_es->psz_desc, Language( hton16( strcpy( p_es->psz_desc, Language( hton16(
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) ); vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)", intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)",
i, p_es->psz_desc, i_id ); i, p_es->psz_desc, i_id );
...@@ -627,7 +629,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -627,7 +629,7 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
p_es->i_type = MPEG2_AUDIO_ES; p_es->i_type = MPEG2_AUDIO_ES;
p_es->b_audio = 1; p_es->b_audio = 1;
strcpy( p_es->psz_desc, Language( hton16( strcpy( p_es->psz_desc, Language( hton16(
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) ); vts.manager_inf.p_audio_attr[i-1].i_lang_code ) ) );
intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)", intf_WarnMsg( 1, "dvd info: audio stream %d %s\t(0x%x)",
i, p_es->psz_desc, i_id ); i, p_es->psz_desc, i_id );
...@@ -645,17 +647,16 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -645,17 +647,16 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
default: default:
i_id = 0; i_id = 0;
intf_ErrMsg( "dvd warning: unknown audio type %.2x", intf_ErrMsg( "dvd warning: unknown audio type %.2x",
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode ); vts.manager_inf.p_audio_attr[i-1].i_coding_mode );
} }
} }
/* Sub Picture ES */ /* Sub Picture ES */
i_nb = p_dvd->ifo.vts.mat.i_subpic_nb;
b_last = 0; b_last = 0;
i_sub_pic = 0x20; i_sub_pic = 0x20;
for( i = 1 ; i <= i_nb ; i++ ) for( i = 1 ; i <= vts.manager_inf.i_spu_nb; i++ )
{ {
if( !b_last ) if( !b_last )
{ {
...@@ -666,16 +667,40 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -666,16 +667,40 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
p_es->i_type = DVD_SPU_ES; p_es->i_type = DVD_SPU_ES;
p_es->b_spu = 1; p_es->b_spu = 1;
strcpy( p_es->psz_desc, Language( hton16( strcpy( p_es->psz_desc, Language( hton16(
p_dvd->ifo.vts.mat.p_subpic_atrt[i-1].i_lang_code ) ) ); vts.manager_inf.p_spu_attr[i-1].i_lang_code ) ) );
intf_WarnMsg( 1, "dvd info: spu stream %d %s\t(0x%x)", intf_WarnMsg( 1, "dvd info: spu stream %d %s\t(0x%x)",
i, p_es->psz_desc, i_id ); i, p_es->psz_desc, i_id );
/* The before the last spu has a 0x0 prefix */ /* The before the last spu has a 0x0 prefix */
b_last = b_last =
( p_dvd->ifo.vts.mat.p_subpic_atrt[i].i_prefix == 0 ); ( vts.manager_inf.p_spu_attr[i].i_prefix == 0 );
} }
} }
/* For audio: first one if none or a not existing one specified */
i_audio = main_GetIntVariable( INPUT_CHANNEL_VAR, 1 );
if( i_audio < 0 || i_audio > vts.manager_inf.i_audio_nb )
{
main_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_audio = 1;
}
if( i_audio > 0 )
{
input_SelectES( p_input, p_input->stream.pp_es[i_audio] );
}
/* for spu, default is none */
i_spu = main_GetIntVariable( INPUT_SUBTITLE_VAR, 0 );
if( i_spu < 0 || i_spu > vts.manager_inf.i_spu_nb )
{
main_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_spu = 0;
}
if( i_spu > 0 )
{
i_spu += vts.manager_inf.i_audio_nb;
input_SelectES( p_input, p_input->stream.pp_es[i_spu] );
}
} // i_title >= 0 } // i_title >= 0
else else
{ {
...@@ -699,14 +724,13 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area ) ...@@ -699,14 +724,13 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
p_area->i_part, p_area->i_tell ); p_area->i_part, p_area->i_tell );
} }
/* By default first audio stream and no spu */
input_SelectES( p_input, p_input->stream.pp_es[1] );
/* No PSM to read in DVD mode, we already have all information */ /* No PSM to read in DVD mode, we already have all information */
p_input->stream.pp_programs[0]->b_is_ok = 1; p_input->stream.pp_programs[0]->b_is_ok = 1;
p_input->stream.pp_programs[0]->i_synchro_state = SYNCHRO_START;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
#undef vts
#undef vmg
return 0; return 0;
} }
...@@ -718,8 +742,6 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -718,8 +742,6 @@ static void DVDInit( input_thread_t * p_input )
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
int i_title; int i_title;
int i_chapter; int i_chapter;
int i_audio;
int i_spu;
int i; int i;
if( (p_dvd = malloc( sizeof(thread_dvd_data_t) )) == NULL ) if( (p_dvd = malloc( sizeof(thread_dvd_data_t) )) == NULL )
...@@ -747,8 +769,13 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -747,8 +769,13 @@ static void DVDInit( input_thread_t * p_input )
intf_WarnMsg( 2, "dvd info: netlist initialized" ); intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo initialisation */ /* Ifo initialisation */
p_dvd->ifo = IfoInit( p_input->i_handle ); if( IfoInit( &p_dvd->p_ifo, p_input->i_handle ) < 0 )
intf_WarnMsg( 2, "ifo info: vmg initialized" ); {
intf_ErrMsg( "ifo error: fatal failure" );
free( p_dvd );
p_input->b_error = 1;
return;
}
/* CSS initialisation */ /* CSS initialisation */
if( p_dvd->b_encrypted ) if( p_dvd->b_encrypted )
...@@ -758,6 +785,7 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -758,6 +785,7 @@ static void DVDInit( input_thread_t * p_input )
if( p_dvd->p_css == NULL ) if( p_dvd->p_css == NULL )
{ {
intf_ErrMsg( "css error: fatal failure" ); intf_ErrMsg( "css error: fatal failure" );
free( p_dvd );
p_input->b_error = 1; p_input->b_error = 1;
return; return;
} }
...@@ -771,12 +799,12 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -771,12 +799,12 @@ static void DVDInit( input_thread_t * p_input )
/* Set stream and area data */ /* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
#define srpt p_dvd->ifo.vmg.ptt_srpt #define title_inf p_dvd->p_ifo->vmg.title_inf
intf_WarnMsg( 2, "dvd info: number of titles: %d", srpt.i_ttu_nb ); intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf.i_title_nb );
#define area p_input->stream.pp_areas #define area p_input->stream.pp_areas
/* We start from 1 here since area 0 is reserved for video_ts.vob */ /* We start from 1 here since area 0 is reserved for video_ts.vob */
for( i = 1 ; i <= srpt.i_ttu_nb ; i++ ) for( i = 1 ; i <= title_inf.i_title_nb ; i++ )
{ {
input_AddArea( p_input ); input_AddArea( p_input );
...@@ -790,12 +818,12 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -790,12 +818,12 @@ static void DVDInit( input_thread_t * p_input )
area[i]->i_size = 0; area[i]->i_size = 0;
/* Number of chapters */ /* Number of chapters */
area[i]->i_part_nb = srpt.p_tts[i-1].i_ptt_nb; area[i]->i_part_nb = title_inf.p_attr[i-1].i_chapter_nb;
area[i]->i_part = 1; area[i]->i_part = 1;
/* Offset to vts_i_0.ifo */ /* Offset to vts_i_0.ifo */
area[i]->i_plugin_data = p_dvd->ifo.i_off + area[i]->i_plugin_data = p_dvd->p_ifo->i_off +
( srpt.p_tts[i-1].i_ssector * DVD_LB_SIZE ); ( title_inf.p_attr[i-1].i_start_sector * DVD_LB_SIZE );
} }
#undef area #undef area
...@@ -803,11 +831,11 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -803,11 +831,11 @@ static void DVDInit( input_thread_t * p_input )
/* Get requested title - if none try the first title */ /* Get requested title - if none try the first title */
i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 ); i_title = main_GetIntVariable( INPUT_TITLE_VAR, 1 );
if( i_title <= 0 || i_title > srpt.i_ttu_nb ) if( i_title <= 0 || i_title > title_inf.i_title_nb )
{ {
i_title = 1; i_title = 1;
} }
#undef srpt #undef title_inf
/* Get requested chapter - if none defaults to first one */ /* Get requested chapter - if none defaults to first one */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 ); i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
if( i_chapter <= 0 ) if( i_chapter <= 0 )
...@@ -816,28 +844,9 @@ static void DVDInit( input_thread_t * p_input ) ...@@ -816,28 +844,9 @@ static void DVDInit( input_thread_t * p_input )
} }
p_input->stream.pp_areas[i_title]->i_part = i_chapter; p_input->stream.pp_areas[i_title]->i_part = i_chapter;
DVDSetArea( p_input, p_input->stream.pp_areas[i_title] );
/* For audio: first one if none or a not existing one specified */ /* set title, chapter, audio and subpic */
i_audio = main_GetIntVariable( INPUT_CHANNEL_VAR, 1 ); DVDSetArea( p_input, p_input->stream.pp_areas[i_title] );
if( i_audio <= 0 )
{
main_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_audio = 1;
}
input_ChangeES( p_input, p_input->stream.pp_es[i_audio], 1 );
i_spu = main_GetIntVariable( INPUT_SUBTITLE_VAR, 0 );
if( i_spu < 0 )
{
main_PutIntVariable( INPUT_CHANNEL_VAR, 1 );
i_spu = 0;
}
/* We don't select spu here since we don't know the index :
* i_spu + i_audio_nb */
// input_ChangeES( p_input, p_input->stream.pp_es[i_spu], 1 );
return; return;
} }
...@@ -853,8 +862,12 @@ static void DVDEnd( input_thread_t * p_input ) ...@@ -853,8 +862,12 @@ static void DVDEnd( input_thread_t * p_input )
p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data;
p_netlist = (dvd_netlist_t *)p_input->p_method_data; p_netlist = (dvd_netlist_t *)p_input->p_method_data;
CSSEnd( p_dvd->p_css ); if( p_dvd->b_encrypted )
// IfoEnd( p_dvd->p_ifo ) ); {
CSSEnd( p_dvd->p_css );
}
IfoEnd( p_dvd->p_ifo );
free( p_dvd ); free( p_dvd );
DVDNetlistEnd( p_netlist ); DVDNetlistEnd( p_netlist );
} }
...@@ -870,7 +883,6 @@ static int DVDRead( input_thread_t * p_input, ...@@ -870,7 +883,6 @@ static int DVDRead( input_thread_t * p_input,
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
dvd_netlist_t * p_netlist; dvd_netlist_t * p_netlist;
pgc_t * p_pgc;
struct iovec * p_vec; struct iovec * p_vec;
struct data_packet_s * pp_data[p_input->i_read_once]; struct data_packet_s * pp_data[p_input->i_read_once];
u8 * pi_cur; u8 * pi_cur;
...@@ -886,7 +898,8 @@ static int DVDRead( input_thread_t * p_input, ...@@ -886,7 +898,8 @@ static int DVDRead( input_thread_t * p_input,
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data; p_dvd = (thread_dvd_data_t *)p_input->p_plugin_data;
p_netlist = (dvd_netlist_t *)p_input->p_method_data; p_netlist = (dvd_netlist_t *)p_input->p_method_data;
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc; #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_program_chain-1].title
/* Get an iovec pointer */ /* Get an iovec pointer */
if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL ) if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL )
...@@ -917,7 +930,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -917,7 +930,7 @@ static int DVDRead( input_thread_t * p_input,
/* update chapter : it will be easier when we have navigation /* update chapter : it will be easier when we have navigation
* ES support */ * ES support */
if( p_pgc->prg_map.pi_entry_cell[p_dvd->i_chapter-1] <= if( title.chapter_map.pi_start_cell[p_dvd->i_chapter-1] <=
p_dvd->i_prg_cell ) p_dvd->i_prg_cell )
{ {
p_dvd->i_chapter++; p_dvd->i_chapter++;
...@@ -1042,6 +1055,7 @@ static int DVDRead( input_thread_t * p_input, ...@@ -1042,6 +1055,7 @@ static int DVDRead( input_thread_t * p_input,
{ {
return 1; return 1;
} }
#undef title
} }
...@@ -1063,14 +1077,14 @@ static int DVDRewind( input_thread_t * p_input ) ...@@ -1063,14 +1077,14 @@ static int DVDRewind( input_thread_t * p_input )
static void DVDSeek( input_thread_t * p_input, off_t i_off ) static void DVDSeek( input_thread_t * p_input, off_t i_off )
{ {
thread_dvd_data_t * p_dvd; thread_dvd_data_t * p_dvd;
pgc_t * p_pgc;
off_t i_pos; off_t i_pos;
int i_prg_cell; int i_prg_cell;
int i_cell; int i_cell;
int i_chapter; int i_chapter;
p_dvd = ( thread_dvd_data_t * )p_input->p_plugin_data; p_dvd = ( thread_dvd_data_t * )p_input->p_plugin_data;
p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[p_dvd->i_vts_title-1].pgc; #define title \
p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_program_chain-1].title
/* we have to take care of offset of beginning of title */ /* we have to take care of offset of beginning of title */
i_pos = i_off + p_input->stream.p_selected_area->i_start i_pos = i_off + p_input->stream.p_selected_area->i_start
...@@ -1083,7 +1097,7 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -1083,7 +1097,7 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
i_chapter = 1; i_chapter = 1;
/* parse vobu address map to find program cell */ /* parse vobu address map to find program cell */
while( p_pgc->p_cell_play_inf[i_prg_cell].i_lsector < p_dvd->i_sector ) while( title.p_cell_play[i_prg_cell].i_end_sector < p_dvd->i_sector )
{ {
i_prg_cell++; i_prg_cell++;
} }
...@@ -1095,9 +1109,9 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -1095,9 +1109,9 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
DVDFindCell( p_dvd ); DVDFindCell( p_dvd );
i_cell = p_dvd->i_cell; i_cell = p_dvd->i_cell;
#define cell p_dvd->p_ifo->vts.cell_inf.p_cell_map[i_cell]
/* parse cell address map to find title cell containing sector */ /* parse cell address map to find title cell containing sector */
while( p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_esector < p_dvd->i_sector ) while( cell.i_end_sector < p_dvd->i_sector )
{ {
i_cell++; i_cell++;
} }
...@@ -1105,11 +1119,11 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off ) ...@@ -1105,11 +1119,11 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
p_dvd->i_cell = i_cell; p_dvd->i_cell = i_cell;
p_dvd->i_end_sector = MIN( p_dvd->i_end_sector = MIN(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector, cell.i_end_sector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector ); title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
/* update chapter */ /* update chapter */
while( p_pgc->prg_map.pi_entry_cell[i_chapter-1] <= p_dvd->i_prg_cell ) while( title.chapter_map.pi_start_cell[i_chapter-1] <= p_dvd->i_prg_cell )
{ {
i_chapter++; i_chapter++;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dvd.h: thread structure of the DVD plugin * input_dvd.h: thread structure of the DVD plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_dvd.h,v 1.13 2001/03/21 13:42:33 sam Exp $ * $Id: input_dvd.h,v 1.14 2001/04/01 07:31:38 stef Exp $
* *
* Author: Stéphane Borel <stef@via.ecp.fr> * Author: Stéphane Borel <stef@via.ecp.fr>
* *
...@@ -41,6 +41,7 @@ typedef struct thread_dvd_data_s ...@@ -41,6 +41,7 @@ typedef struct thread_dvd_data_s
/* Navigation information */ /* Navigation information */
int i_title; int i_title;
int i_vts_title; int i_vts_title;
int i_program_chain;
int i_chapter_nb; int i_chapter_nb;
int i_chapter; int i_chapter;
...@@ -59,17 +60,16 @@ typedef struct thread_dvd_data_s ...@@ -59,17 +60,16 @@ typedef struct thread_dvd_data_s
struct css_s * p_css; struct css_s * p_css;
/* Structure that contains all information of the DVD */ /* Structure that contains all information of the DVD */
struct ifo_s ifo; struct ifo_s * p_ifo;
} thread_dvd_data_t; } thread_dvd_data_t;
/***************************************************************************** /*****************************************************************************
* Prototypes in dvd_ifo.c * Prototypes in dvd_ifo.c
*****************************************************************************/ *****************************************************************************/
struct ifo_s IfoInit ( int ); int IfoInit ( struct ifo_s **, int );
int IfoReadVTS ( struct ifo_s * ); int IfoTitleSet ( struct ifo_s * );
void IfoRead ( struct ifo_s * ); void IfoEnd ( struct ifo_s * );
void IfoEnd ( ifo_t * );
/***************************************************************************** /*****************************************************************************
* Prototypes in dvd_css.c * Prototypes in dvd_css.c
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* gnome_callbacks.c : Callbacks for the Gnome plugin. * gnome_callbacks.c : Callbacks for the Gnome plugin.
***************************************************************************** *****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN * Copyright (C) 2000, 2001 VideoLAN
* $Id: gnome_callbacks.c,v 1.18 2001/03/21 13:42:34 sam Exp $ * $Id: gnome_callbacks.c,v 1.19 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -244,7 +245,10 @@ on_menubar_audio_toggle (GtkCheckMenuItem *menuitem, ...@@ -244,7 +245,10 @@ on_menubar_audio_toggle (GtkCheckMenuItem *menuitem,
p_es = (es_descriptor_t*)user_data; p_es = (es_descriptor_t*)user_data;
input_ChangeES( p_intf->p_input, p_es, 1 ); if( p_intf->p_sys->b_menus_ready )
{
input_ToggleES( p_intf->p_input, p_es, menuitem->active );
}
} }
...@@ -257,7 +261,10 @@ on_menubar_subtitle_toggle (GtkCheckMenuItem *menuitem, ...@@ -257,7 +261,10 @@ on_menubar_subtitle_toggle (GtkCheckMenuItem *menuitem,
p_es = (es_descriptor_t*)user_data; p_es = (es_descriptor_t*)user_data;
input_ChangeES( p_intf->p_input, p_es, 2 ); if( p_intf->p_sys->b_menus_ready )
{
input_ToggleES( p_intf->p_input, p_es, menuitem->active );
}
} }
...@@ -267,9 +274,13 @@ on_menubar_title_toggle (GtkCheckMenuItem *menuitem, ...@@ -267,9 +274,13 @@ on_menubar_title_toggle (GtkCheckMenuItem *menuitem,
{ {
intf_thread_t *p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" ); intf_thread_t *p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)user_data ); if( menuitem->active && p_intf->p_sys->b_menus_ready )
p_intf->p_sys->b_menus_update = 1; {
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY ); p_intf->p_input->pf_set_area( p_intf->p_input,
(input_area_t*)user_data );
p_intf->p_sys->b_menus_update = 1;
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
}
} }
...@@ -281,9 +292,12 @@ on_menubar_chapter_toggle (GtkCheckMenuItem *menuitem, ...@@ -281,9 +292,12 @@ on_menubar_chapter_toggle (GtkCheckMenuItem *menuitem,
input_area_t * p_area = p_intf->p_input->stream.p_selected_area; input_area_t * p_area = p_intf->p_input->stream.p_selected_area;
gint i_chapter = (gint)user_data; gint i_chapter = (gint)user_data;
p_area->i_part = i_chapter; if( menuitem->active && p_intf->p_sys->b_menus_ready )
{
p_area->i_part = i_chapter;
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
}
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY ); input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
} }
...@@ -558,7 +572,10 @@ on_popup_audio_toggle (GtkCheckMenuItem *menuitem, ...@@ -558,7 +572,10 @@ on_popup_audio_toggle (GtkCheckMenuItem *menuitem,
p_es = (es_descriptor_t*)user_data; p_es = (es_descriptor_t*)user_data;
input_ChangeES( p_intf->p_input, p_es, 1 ); if( p_intf->p_sys->b_menus_ready )
{
input_ToggleES( p_intf->p_input, p_es, menuitem->active );
}
} }
...@@ -571,7 +588,10 @@ on_popup_subtitle_toggle (GtkCheckMenuItem *menuitem, ...@@ -571,7 +588,10 @@ on_popup_subtitle_toggle (GtkCheckMenuItem *menuitem,
p_es = (es_descriptor_t*)user_data; p_es = (es_descriptor_t*)user_data;
input_ChangeES( p_intf->p_input, p_es, 2 ); if( p_intf->p_sys->b_menus_ready )
{
input_ToggleES( p_intf->p_input, p_es, menuitem->active );
}
} }
...@@ -579,14 +599,15 @@ void ...@@ -579,14 +599,15 @@ void
on_popup_navigation_toggle (GtkCheckMenuItem *menuitem, on_popup_navigation_toggle (GtkCheckMenuItem *menuitem,
gpointer user_data) gpointer user_data)
{ {
if( menuitem->active ) intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
if( menuitem->active && p_intf->p_sys->b_menus_ready )
{ {
intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
input_area_t * p_area; input_area_t * p_area;
gint i_title; gint i_title;
gint i_chapter; gint i_chapter;
i_title = (gint)(user_data) / 100 ; i_title = (gint)(user_data) / 100;
i_chapter = (gint)(user_data) - ( 100 * i_title ); i_chapter = (gint)(user_data) - ( 100 * i_title );
if( i_title != p_intf->p_input->stream.p_selected_area->i_id ) if( i_title != p_intf->p_input->stream.p_selected_area->i_id )
...@@ -598,7 +619,7 @@ on_popup_navigation_toggle (GtkCheckMenuItem *menuitem, ...@@ -598,7 +619,7 @@ on_popup_navigation_toggle (GtkCheckMenuItem *menuitem,
p_area->i_part = i_chapter; p_area->i_part = i_chapter;
p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area ); p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY ); input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
} }
} }
......
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* intf_gnome.c: Gnome interface * intf_gnome.c: Gnome interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: intf_gnome.c,v 1.23 2001/03/15 16:29:47 stef Exp $ * $Id: intf_gnome.c,v 1.24 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -144,6 +145,7 @@ static int intf_Open( intf_thread_t *p_intf ) ...@@ -144,6 +145,7 @@ static int intf_Open( intf_thread_t *p_intf )
p_intf->p_sys->b_window_changed = 0; p_intf->p_sys->b_window_changed = 0;
p_intf->p_sys->b_playlist_changed = 0; p_intf->p_sys->b_playlist_changed = 0;
p_intf->p_sys->b_menus_update = 1; p_intf->p_sys->b_menus_update = 1;
p_intf->p_sys->b_menus_ready = 0;
p_intf->p_sys->b_slider_free = 1; p_intf->p_sys->b_slider_free = 1;
...@@ -298,7 +300,9 @@ static gint GnomeManage( gpointer p_data ) ...@@ -298,7 +300,9 @@ static gint GnomeManage( gpointer p_data )
if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL && if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL &&
p_intf->p_sys->b_menus_update ) p_intf->p_sys->b_menus_update )
{ {
p_intf->p_sys->b_menus_ready = 0;
GnomeSetupMenu( p_intf ); GnomeSetupMenu( p_intf );
p_intf->p_sys->b_menus_ready = 1;
} }
/* Manage the slider */ /* Manage the slider */
...@@ -372,12 +376,12 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -372,12 +376,12 @@ static gint GnomeLanguageMenus( gpointer p_data,
GtkWidget * p_menu; GtkWidget * p_menu;
GtkWidget * p_separator; GtkWidget * p_separator;
GtkWidget * p_item; GtkWidget * p_item;
GtkWidget * p_item_off; GtkWidget * p_item_active;
GSList * p_group; GSList * p_group;
char * psz_name; char * psz_name;
gint b_active;
gint b_audio; gint b_audio;
gint b_spu; gint b_spu;
gint i_item;
gint i; gint i;
...@@ -385,32 +389,37 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -385,32 +389,37 @@ static gint GnomeLanguageMenus( gpointer p_data,
/* cast */ /* cast */
p_intf = (intf_thread_t *)p_data; p_intf = (intf_thread_t *)p_data;
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
/* removes previous menu */ /* removes previous menu */
gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) ); gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
gtk_widget_set_sensitive( p_root, FALSE );
b_audio = ( i_type == 1 );
p_group = NULL; p_group = NULL;
/* menu container */ /* menu container */
p_menu = gtk_menu_new(); p_menu = gtk_menu_new();
/* special case for "off" item */ /* special case for "off" item */
b_active = ( p_es == NULL ) ? TRUE : FALSE;
psz_name = "Off"; psz_name = "Off";
p_item_off = gtk_radio_menu_item_new_with_label( p_group, psz_name ); p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item_off ) ); p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
gtk_widget_show( p_item_off );
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_off ), gtk_widget_show( p_item );
b_active );
gtk_menu_append( GTK_MENU( p_menu ), p_item_off ); /* signal hanling for off */
gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
gtk_menu_append( GTK_MENU( p_menu ), p_item );
p_separator = gtk_menu_item_new(); p_separator = gtk_menu_item_new();
gtk_widget_set_sensitive( p_separator, FALSE );
gtk_widget_show( p_separator ); gtk_widget_show( p_separator );
gtk_menu_append( GTK_MENU( p_menu ), p_separator ); gtk_menu_append( GTK_MENU( p_menu ), p_separator );
gtk_widget_set_sensitive( p_separator, FALSE );
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
p_item_active = NULL;
i_item = 0;
/* create a set of language buttons and append them to the container */ /* create a set of language buttons and append them to the container */
for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ ) for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
...@@ -421,16 +430,24 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -421,16 +430,24 @@ static gint GnomeLanguageMenus( gpointer p_data,
if( b_audio || b_spu ) if( b_audio || b_spu )
{ {
b_active = ( p_es == p_intf->p_input->stream.pp_es[i] ) ? TRUE : i_item++;
FALSE;
psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc; psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
if( psz_name[0] == '\0' )
{
sprintf( psz_name, "Language %d", i_item );
}
p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name ); p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
p_group = p_group =
gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item ),
b_active ); if( p_es == p_intf->p_input->stream.pp_es[i] )
gtk_menu_append( GTK_MENU( p_menu ), p_item ); {
/* don't lose p_item when we append into menu */
p_item_active = p_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
gtk_widget_show( p_item ); gtk_widget_show( p_item );
/* setup signal hanling */ /* setup signal hanling */
...@@ -438,21 +455,29 @@ static gint GnomeLanguageMenus( gpointer p_data, ...@@ -438,21 +455,29 @@ static gint GnomeLanguageMenus( gpointer p_data,
GTK_SIGNAL_FUNC( pf_toggle ), GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)( p_intf->p_input->stream.pp_es[i] ) ); (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
gtk_menu_append( GTK_MENU( p_menu ), p_item );
} }
} }
/* signal hanling for off - dunno why this does not work vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
* if it is before the loop */
gtk_signal_connect( GTK_OBJECT( p_item_off ), "toggled",
GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
/* link the new menu to the menubar item */ /* link the new menu to the menubar item */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu ); gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
/* be sure that menu is sensitive */ /* acitvation will call signals so we can only do it
gtk_widget_set_sensitive( p_root, TRUE ); * when submenu is attached to menu - to get intf_window */
if( p_item_active != NULL )
{
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_active ) );
}
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); /* be sure that menu is sensitive if non empty */
if( i_item > 0 )
{
gtk_widget_set_sensitive( p_root, TRUE );
}
return TRUE; return TRUE;
} }
...@@ -466,54 +491,96 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter, ...@@ -466,54 +491,96 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
intf_thread_t * p_intf; intf_thread_t * p_intf;
char psz_name[10]; char psz_name[10];
GtkWidget * p_chapter_menu; GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu;
GtkWidget * p_menu_item;
GtkWidget * p_item; GtkWidget * p_item;
GtkWidget * p_item_selected;
GSList * p_chapter_group; GSList * p_chapter_group;
gint i_title; gint i_title;
gint i_chapter; gint i_chapter;
gint b_active; gint i_nb;
/* cast */ /* cast */
p_intf = (intf_thread_t*)p_data; p_intf = (intf_thread_t*)p_data;
/* removes previous menu */ /* removes previous menu */
gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_chapter ) ); gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_chapter ) );
gtk_widget_set_sensitive( p_chapter, FALSE );
p_chapter_submenu = NULL;
p_chapter_group = NULL; p_chapter_group = NULL;
p_item_selected = NULL;
p_menu_item = NULL;
i_title = p_intf->p_input->stream.p_selected_area->i_id; i_title = p_intf->p_input->stream.p_selected_area->i_id;
p_chapter_menu = gtk_menu_new(); p_chapter_menu = gtk_menu_new();
i_nb = p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
for( i_chapter = 0; for( i_chapter = 0 ; i_chapter < i_nb ; i_chapter++ )
i_chapter < p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ;
i_chapter++ )
{ {
b_active = ( p_intf->p_input->stream.pp_areas[i_title]->i_part /* we group chapters in packets of ten for small screens */
== i_chapter + 1 ) ? 1 : 0; if( ( i_chapter % 10 == 0 ) )// && ( i_nb > 20 ) )
{
if( i_chapter != 0 )
{
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_menu_item ),
p_chapter_submenu );
gtk_menu_append( GTK_MENU( p_chapter_menu ), p_menu_item );
}
sprintf( psz_name, "%d - %d", i_chapter + 1, i_chapter + 10);
p_menu_item = gtk_menu_item_new_with_label( psz_name );
gtk_widget_show( p_menu_item );
p_chapter_submenu = gtk_menu_new();
}
sprintf( psz_name, "Chapter %d", i_chapter + 1 ); sprintf( psz_name, "Chapter %d", i_chapter + 1 );
p_item = gtk_radio_menu_item_new_with_label( p_chapter_group, p_item = gtk_radio_menu_item_new_with_label( p_chapter_group,
psz_name ); psz_name );
p_chapter_group = p_chapter_group =
gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) ); gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
if( p_intf->p_input->stream.pp_areas[i_title]->i_part
== i_chapter + 1 )
{
p_item_selected = p_item;
gtk_object_ref( GTK_OBJECT( p_item_selected ) );
}
gtk_widget_show( p_item ); gtk_widget_show( p_item );
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item ),
b_active );
/* setup signal hanling */ /* setup signal hanling */
gtk_signal_connect( GTK_OBJECT( p_item ), gtk_signal_connect( GTK_OBJECT( p_item ),
"toggled", "toggled",
GTK_SIGNAL_FUNC( pf_toggle ), GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)(i_chapter + 1) ); (gpointer)(i_chapter + 1) );
gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
} }
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_menu_item ),
p_chapter_submenu );
gtk_menu_append( GTK_MENU( p_chapter_menu ), p_menu_item );
/* link the new menu to the title menu item */ /* link the new menu to the title menu item */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter ), gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter ),
p_chapter_menu ); p_chapter_menu );
/* be sure that chapter menu is sensitive */ /* toggle currently selected chapter */
gtk_widget_set_sensitive( p_chapter, TRUE ); if( p_item_selected != NULL )
{
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_selected ) );
}
/* be sure that chapter menu is sensitive, if there are several items */
if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
{
gtk_widget_set_sensitive( p_chapter, TRUE );
}
return TRUE; return TRUE;
} }
...@@ -532,53 +599,84 @@ static gint GnomeTitleMenu( gpointer p_data, ...@@ -532,53 +599,84 @@ static gint GnomeTitleMenu( gpointer p_data,
intf_thread_t * p_intf; intf_thread_t * p_intf;
char psz_name[10]; char psz_name[10];
GtkWidget * p_title_menu; GtkWidget * p_title_menu;
GtkWidget * p_title_submenu;
GtkWidget * p_title_item; GtkWidget * p_title_item;
GtkWidget * p_item_active;
GtkWidget * p_chapter_menu; GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu;
GtkWidget * p_title_menu_item;
GtkWidget * p_chapter_menu_item;
GtkWidget * p_item; GtkWidget * p_item;
GSList * p_title_group; GSList * p_title_group;
GSList * p_chapter_group; GSList * p_chapter_group;
gint i_title; gint i_title;
gint i_chapter; gint i_chapter;
gint b_active; gint i_nb;
/* cast */ /* cast */
p_intf = (intf_thread_t*)p_data; p_intf = (intf_thread_t*)p_data;
p_title_menu = gtk_menu_new(); p_title_menu = gtk_menu_new();
p_title_group = NULL; p_title_group = NULL;
p_title_submenu = NULL;
p_title_menu_item = NULL;
p_chapter_group = NULL; p_chapter_group = NULL;
p_chapter_submenu = NULL;
p_chapter_menu_item = NULL;
p_item_active = NULL;
i_nb = p_intf->p_input->stream.i_area_nb;
/* loop on titles */ /* loop on titles */
for( i_title = 1 ; for( i_title = 1 ; i_title < i_nb ; i_title++ )
i_title < p_intf->p_input->stream.i_area_nb ;
i_title++ )
{ {
b_active = ( p_intf->p_input->stream.pp_areas[i_title] == /* we group titles in packets of ten for small screens */
p_intf->p_input->stream.p_selected_area ) ? 1 : 0; if( ( i_title % 10 == 1 ))// && ( i_nb > 20 ) )
sprintf( psz_name, "Title %d", i_title ); {
if( i_title != 1 )
p_title_item = gtk_radio_menu_item_new_with_label( p_title_group, {
psz_name ); gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
p_title_group = p_title_submenu );
gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) ); gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item ); }
gtk_widget_show( p_title_item );
sprintf( psz_name, "%d - %d", i_title, i_title + 9 );
p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
gtk_widget_show( p_title_menu_item );
p_title_submenu = gtk_menu_new();
}
sprintf( psz_name, "Title %d", i_title );
if( pf_toggle == on_menubar_title_toggle ) if( pf_toggle == on_menubar_title_toggle )
{ {
p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
psz_name );
p_title_group =
gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
if( p_intf->p_input->stream.pp_areas[i_title] ==
p_intf->p_input->stream.p_selected_area )
{
p_item_active = p_title_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
// gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_title_item ),
// b_active );
/* setup signal hanling */ /* setup signal hanling */
gtk_signal_connect( GTK_OBJECT( p_title_item ), gtk_signal_connect( GTK_OBJECT( p_title_item ),
"toggled", "toggled",
GTK_SIGNAL_FUNC( pf_toggle ), GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)(p_intf->p_input->stream.pp_areas[i_title]) ); (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
if( p_intf->p_input->stream.i_area_nb > 1 )
{
/* be sure that menu is sensitive */
gtk_widget_set_sensitive( p_navigation, TRUE );
}
} }
else else
{ {
p_title_item = gtk_menu_item_new_with_label( psz_name );
p_chapter_menu = gtk_menu_new(); p_chapter_menu = gtk_menu_new();
for( i_chapter = 0; for( i_chapter = 0;
...@@ -586,42 +684,85 @@ static gint GnomeTitleMenu( gpointer p_data, ...@@ -586,42 +684,85 @@ static gint GnomeTitleMenu( gpointer p_data,
p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ; p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ;
i_chapter++ ) i_chapter++ )
{ {
b_active = ( p_intf->p_input->stream.pp_areas[i_title]->i_part /* we group chapters in packets of ten for small screens */
== i_chapter + 1 ) ? 1 : 0; if( ( i_chapter % 10 == 0 ) )// && ( i_nb > 20 ) )
{
if( i_chapter != 0 )
{
gtk_menu_item_set_submenu(
GTK_MENU_ITEM( p_chapter_menu_item ),
p_chapter_submenu );
gtk_menu_append( GTK_MENU( p_chapter_menu ),
p_chapter_menu_item );
}
sprintf( psz_name, "%d - %d", i_chapter + 1,
i_chapter + 10);
p_chapter_menu_item =
gtk_menu_item_new_with_label( psz_name );
gtk_widget_show( p_chapter_menu_item );
p_chapter_submenu = gtk_menu_new();
}
sprintf( psz_name, "Chapter %d", i_chapter + 1 ); sprintf( psz_name, "Chapter %d", i_chapter + 1 );
p_item = gtk_radio_menu_item_new_with_label( p_item = gtk_radio_menu_item_new_with_label(
p_chapter_group, psz_name ); p_chapter_group, psz_name );
p_chapter_group = gtk_radio_menu_item_group( p_chapter_group = gtk_radio_menu_item_group(
GTK_RADIO_MENU_ITEM( p_item ) ); GTK_RADIO_MENU_ITEM( p_item ) );
gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
gtk_widget_show( p_item ); gtk_widget_show( p_item );
// gtk_check_menu_item_set_active(
// GTK_CHECK_MENU_ITEM( p_item ), b_active ); if( p_intf->p_input->stream.pp_areas[i_title]->i_part
== i_chapter + 1 )
{
p_item_active = p_item;
gtk_object_ref( GTK_OBJECT( p_item_active ) );
}
/* setup signal hanling */ /* setup signal hanling */
gtk_signal_connect( GTK_OBJECT( p_item ), gtk_signal_connect( GTK_OBJECT( p_item ),
"toggled", "toggled",
GTK_SIGNAL_FUNC( pf_toggle ), GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)( ( i_title * 100 ) + ( i_chapter + 1) ) ); (gpointer)( ( i_title * 100 ) + ( i_chapter + 1) ) );
}
/* link the new menu to the title menu item */ gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ), }
p_chapter_menu );
} gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
p_chapter_submenu );
gtk_menu_append( GTK_MENU( p_chapter_menu ), p_chapter_menu_item );
/* be sure that chapter menu is sensitive */ /* link the new menu to the title menu item */
gtk_widget_set_sensitive( p_title_menu, TRUE ); gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
p_chapter_menu );
if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
{
/* be sure that menu is sensitive */
gtk_widget_set_sensitive( p_navigation, TRUE );
}
}
gtk_widget_show( p_title_item );
gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
} }
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
p_title_submenu );
gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
/* be sure that menu is sensitive */
gtk_widget_set_sensitive( p_title_menu, TRUE );
/* link the new menu to the menubar item */ /* link the new menu to the menubar item */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu ); gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
/* be sure that menu is sensitive */ if( p_item_active != NULL )
gtk_widget_set_sensitive( p_navigation, TRUE ); {
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
TRUE );
gtk_object_unref( GTK_OBJECT( p_item_active ) );
}
return TRUE; return TRUE;
...@@ -639,20 +780,22 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf ) ...@@ -639,20 +780,22 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
GtkWidget * p_popup_menu; GtkWidget * p_popup_menu;
gint i; gint i;
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
p_intf->p_sys->p_window ), "menubar_title" ) );
GnomeTitleMenu( p_intf, p_menubar_menu, on_menubar_title_toggle );
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_window ), "menubar_chapter" ) );
GnomeChapterMenu( p_intf, p_menubar_menu, on_menubar_chapter_toggle );
p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( if( p_intf->p_input->stream.i_area_nb > 1 )
p_intf->p_sys->p_popup ), "popup_navigation" ) ); {
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_window ), "menubar_title" ) );
GnomeTitleMenu( p_intf, p_menubar_menu, on_menubar_title_toggle );
GnomeTitleMenu( p_intf, p_popup_menu, on_popup_navigation_toggle ); p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_popup ), "popup_navigation" ) );
GnomeTitleMenu( p_intf, p_popup_menu, on_popup_navigation_toggle );
p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_window ), "menubar_chapter" ) );
GnomeChapterMenu( p_intf, p_menubar_menu, on_menubar_chapter_toggle );
}
/* look for selected ES */ /* look for selected ES */
p_audio_es = NULL; p_audio_es = NULL;
...@@ -660,17 +803,19 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf ) ...@@ -660,17 +803,19 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ ) for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
{ {
if( p_intf->p_input->stream.pp_es[i]->b_audio ) if( p_intf->p_input->stream.pp_selected_es[i]->b_audio )
{ {
p_audio_es = p_intf->p_input->stream.pp_es[i]; p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
} }
if( p_intf->p_input->stream.pp_es[i]->b_spu ) if( p_intf->p_input->stream.pp_selected_es[i]->b_spu )
{ {
p_spu_es = p_intf->p_input->stream.pp_es[i]; p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
} }
} }
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
/* audio menus */ /* audio menus */
/* find audio root menu */ /* find audio root menu */
...@@ -681,9 +826,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf ) ...@@ -681,9 +826,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
p_intf->p_sys->p_popup ), "popup_audio" ) ); p_intf->p_sys->p_popup ), "popup_audio" ) );
GnomeLanguageMenus( p_intf, p_menubar_menu, p_audio_es, 1, GnomeLanguageMenus( p_intf, p_menubar_menu, p_audio_es, 1,
on_menubar_audio_toggle ); on_menubar_audio_toggle );
GnomeLanguageMenus( p_intf, p_popup_menu, p_audio_es, 1, GnomeLanguageMenus( p_intf, p_popup_menu, p_audio_es, 1,
on_popup_audio_toggle ); on_popup_audio_toggle );
/* sub picture menus */ /* sub picture menus */
...@@ -695,9 +840,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf ) ...@@ -695,9 +840,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
p_intf->p_sys->p_popup ), "popup_subtitle" ) ); p_intf->p_sys->p_popup ), "popup_subtitle" ) );
GnomeLanguageMenus( p_intf, p_menubar_menu, p_spu_es, 2, GnomeLanguageMenus( p_intf, p_menubar_menu, p_spu_es, 2,
on_menubar_subtitle_toggle ); on_menubar_subtitle_toggle );
GnomeLanguageMenus( p_intf, p_popup_menu, p_spu_es, 2, GnomeLanguageMenus( p_intf, p_popup_menu, p_spu_es, 2,
on_popup_subtitle_toggle ); on_popup_subtitle_toggle );
/* everything is ready */ /* everything is ready */
p_intf->p_sys->b_menus_update = 0; p_intf->p_sys->b_menus_update = 0;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* intf_gnome.h: private Gnome interface description * intf_gnome.h: private Gnome interface description
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: intf_gnome.h,v 1.3 2001/03/15 01:42:19 sam Exp $ * $Id: intf_gnome.h,v 1.4 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -37,7 +37,8 @@ typedef struct intf_sys_s ...@@ -37,7 +37,8 @@ typedef struct intf_sys_s
boolean_t b_window_changed; /* window display toggled ? */ boolean_t b_window_changed; /* window display toggled ? */
boolean_t b_playlist_changed; /* playlist display toggled ? */ boolean_t b_playlist_changed; /* playlist display toggled ? */
boolean_t b_slider_free; /* slider status */ boolean_t b_slider_free; /* slider status */
boolean_t b_menus_update; boolean_t b_menus_update; /* do we need to update menus */
boolean_t b_menus_ready; /* has the update been commpleted */
/* Windows and widgets */ /* Windows and widgets */
GtkWidget * p_window; /* main window */ GtkWidget * p_window; /* main window */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-intf.c: services to the interface * input_ext-intf.c: services to the interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ext-intf.c,v 1.17 2001/03/21 13:42:34 sam Exp $ * $Id: input_ext-intf.c,v 1.18 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -296,3 +296,33 @@ int input_ChangeES( input_thread_t * p_input, es_descriptor_t * p_es, ...@@ -296,3 +296,33 @@ int input_ChangeES( input_thread_t * p_input, es_descriptor_t * p_es,
return 0; return 0;
} }
/*****************************************************************************
* input_ToggleES: answers to a user request with calls to (Un)SelectES
*****************************************************************************
* Useful since the interface plugins know p_es.
* It only works for audio & spu ( to be sure nothing nasty is being done ).
* b_select is a boolean to know if we have to select or unselect ES
*****************************************************************************/
int input_ToggleES( input_thread_t * p_input, es_descriptor_t * p_es,
boolean_t b_select )
{
vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_es != NULL && ( p_es->b_audio || p_es->b_spu ) )
{
if( b_select )
{
input_SelectES( p_input, p_es );
}
else
{
input_UnselectES( p_input, p_es );
}
}
vlc_mutex_unlock( &p_input->stream.stream_lock );
return 0;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_programs.c,v 1.41 2001/03/15 01:42:20 sam Exp $ * $Id: input_programs.c,v 1.42 2001/04/01 07:31:38 stef Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -269,7 +269,7 @@ input_area_t * input_AddArea( input_thread_t * p_input ) ...@@ -269,7 +269,7 @@ input_area_t * input_AddArea( input_thread_t * p_input )
p_input->stream.pp_areas[i_area_index]->i_size = 0; p_input->stream.pp_areas[i_area_index]->i_size = 0;
p_input->stream.pp_areas[i_area_index]->i_tell = 0; p_input->stream.pp_areas[i_area_index]->i_tell = 0;
p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK; p_input->stream.pp_areas[i_area_index]->i_seek = NO_SEEK;
p_input->stream.pp_areas[i_area_index]->i_part_nb = 0; p_input->stream.pp_areas[i_area_index]->i_part_nb = 1;
p_input->stream.pp_areas[i_area_index]->i_part= 0; p_input->stream.pp_areas[i_area_index]->i_part= 0;
return p_input->stream.pp_areas[i_area_index]; return p_input->stream.pp_areas[i_area_index];
...@@ -368,6 +368,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input, ...@@ -368,6 +368,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input,
/* Init its values */ /* Init its values */
p_es->i_id = i_es_id; p_es->i_id = i_es_id;
p_es->psz_desc[0] = '\0';
p_es->p_pes = NULL; p_es->p_pes = NULL;
p_es->p_decoder_fifo = NULL; p_es->p_decoder_fifo = NULL;
p_es->b_audio = 0; p_es->b_audio = 0;
...@@ -591,6 +592,12 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -591,6 +592,12 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
decoder_capabilities_t decoder; decoder_capabilities_t decoder;
void * p_config; void * p_config;
if( p_es == NULL )
{
intf_ErrMsg( "Nothing to do in input_SelectES" );
return -1;
}
#ifdef DEBUG_INPUT #ifdef DEBUG_INPUT
intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id ); intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
#endif #endif
...@@ -683,6 +690,12 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -683,6 +690,12 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
int i_index = 0; int i_index = 0;
if( p_es == NULL )
{
intf_ErrMsg( "Nothing to do in input_UnselectES" );
return -1;
}
#ifdef DEBUG_INPUT #ifdef DEBUG_INPUT
intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id ); intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
#endif #endif
...@@ -693,12 +706,10 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -693,12 +706,10 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
return( -1 ); return( -1 );
} }
/* Release lock, not to block the input thread. */
vlc_mutex_unlock( &p_input->stream.stream_lock );
input_EndDecoder( p_input, p_es ); input_EndDecoder( p_input, p_es );
vlc_mutex_lock( &p_input->stream.stream_lock );
if( p_es->p_decoder_fifo == NULL ) if( ( p_es->p_decoder_fifo == NULL ) &&
( p_input->stream.i_selected_es_number > 0 ) )
{ {
p_input->stream.i_selected_es_number--; p_input->stream.i_selected_es_number--;
...@@ -715,11 +726,14 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -715,11 +726,14 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
p_input->stream.pp_selected_es, p_input->stream.pp_selected_es,
p_input->stream.i_selected_es_number p_input->stream.i_selected_es_number
* sizeof(es_descriptor_t *) ); * sizeof(es_descriptor_t *) );
if( p_input->stream.pp_selected_es == NULL ) if( p_input->stream.pp_selected_es == NULL )
{ {
intf_ErrMsg( "Unable to realloc memory in input_UnSelectES" ); intf_ErrMsg( "No more selected ES in input_UnselectES" );
return(-1); vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 1 );
} }
} }
return( 0 ); return( 0 );
} }
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