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 @@
* control the pace of reading.
*****************************************************************************
* 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>
*
......@@ -353,3 +353,6 @@ void input_Seek ( struct input_thread_s *, off_t );
void input_DumpStream( struct input_thread_s * );
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_ToggleES ( struct input_thread_s *,
struct es_descriptor_s *,
boolean_t );
......@@ -2,7 +2,7 @@
* dvd_ifo.c: Functions for ifo parsing
*****************************************************************************
* 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>
*
......@@ -49,95 +49,18 @@
/*
* Local prototypes
*/
static vmg_t ReadVMG ( ifo_t* );
void CommandRead( ifo_command_t );
/*
* IFO Management.
*/
/*****************************************************************************
* IfoInit : Creates an ifo structure and prepares for parsing directly
* on DVD device.
*****************************************************************************/
ifo_t IfoInit( int i_fd )
{
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;
}
void CommandRead ( command_desc_t );
static int ReadTitle ( ifo_t * , title_t * );
static int FreeTitle ( title_t * );
static int ReadUnitInf ( ifo_t * , unit_inf_t * );
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 * );
static int FreeVobuMap ( vobu_map_t * );
static int ReadCellInf ( ifo_t * , cell_inf_t * );
static int FreeCellInf ( cell_inf_t * );
static int FreeTitleSet ( vts_t * );
/*
* Macros to process ifo files
......@@ -198,960 +121,1252 @@ void IfoEnd( ifo_t* p_ifo )
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 ) \
{ \
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; \
int IfoInit( ifo_t ** pp_ifo, int i_fd )
{
ifo_t * p_ifo;
u64 i_temp;
u32 i_lba;
int i, j, k;
off_t i_start;
p_ifo = malloc( sizeof(ifo_t) );
if( p_ifo == NULL )
{
intf_ErrMsg( "ifo error: unable to allocate memory. aborting" );
return -1;
}
static pgc_t ReadPGC( ifo_t* p_ifo )
{
pgc_t pgc;
int i;
off_t i_start = p_ifo->i_pos;
*pp_ifo = p_ifo;
//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);
GETC( &pgc.i_prg_nb );
GETC( &pgc.i_cell_nb );
//fprintf( stderr, "PGC: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb );
GETL( &pgc.i_play_time );
GETL( &pgc.i_prohibited_user_op );
for( i=0 ; i<8 ; i++ )
FLUSH( 1 );
GETC( &manager_inf.i_audio_nb );
//fprintf( stderr, "vmgi audio nb : %d\n", manager_inf.i_audio_nb );
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 );
//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 );
GETC( &pgc.i_play_mode );
for( i=0 ; i<16 ; i++ )
/*
* read first play title.
*/
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_first_play_title_start_byte,
SEEK_SET );
if( ReadTitle( p_ifo, &p_ifo->vmg.title ) < 0)
{
GETL( &pgc.pi_yuv_color[i] );
/* FIXME : We have to erase the extra bit */
return -1;
}
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
+ pgc.i_com_tab_sbyte, SEEK_SET );
GETS( &pgc.com_tab.i_pre_com_nb );
GETS( &pgc.com_tab.i_post_com_nb );
GETS( &pgc.com_tab.i_cell_com_nb );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_title_inf_start_sector *DVD_LB_SIZE,
SEEK_SET );
//fprintf( stderr, "title inf\n" );
GETS( &title_inf.i_title_nb );
//fprintf( stderr, "title_inf: TTU nb %d\n", title_inf.i_title_nb );
FLUSH( 2 );
if( pgc.com_tab.i_pre_com_nb )
{
pgc.com_tab.p_pre_com =
malloc(pgc.com_tab.i_pre_com_nb *sizeof(ifo_command_t));
if( pgc.com_tab.p_pre_com == 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 )
GETL( &title_inf.i_end_byte );
/* parsing of title attributes */
title_inf.p_attr = malloc( title_inf.i_title_nb *sizeof(title_attr_t) );
if( title_inf.p_attr == NULL )
{
pgc.com_tab.p_post_com =
malloc(pgc.com_tab.i_post_com_nb *sizeof(ifo_command_t));
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] );
}
intf_ErrMsg( "ifo error: out of memory in IfoInit" );
return -1;
}
if( pgc.com_tab.i_cell_com_nb )
for( i = 0 ; i < title_inf.i_title_nb ; i++ )
{
pgc.com_tab.p_cell_com =
malloc(pgc.com_tab.i_cell_com_nb *sizeof(ifo_command_t));
if( pgc.com_tab.p_cell_com == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
for( i=0 ; i<pgc.com_tab.i_cell_com_nb ; i++ )
{
GETCOMMAND( &pgc.com_tab.p_cell_com[i] );
}
GETC( &title_inf.p_attr[i].i_play_type );
GETC( &title_inf.p_attr[i].i_angle_nb );
GETS( &title_inf.p_attr[i].i_chapter_nb );
GETS( &title_inf.p_attr[i].i_parental_id );
GETC( &title_inf.p_attr[i].i_title_set_num );
GETC( &title_inf.p_attr[i].i_title_num );
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 );
}
}
/* Parsing of pgc_prg_map_t */
if( pgc.i_prg_map_sbyte )
else
{
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+ 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 */
title_inf.p_attr = NULL;
}
/* Parsing of cell_play_inf_t */
if( pgc.i_cell_play_inf_sbyte )
#undef title_inf
/*
* fills the title unit structure.
*/
if( manager_inf.i_title_unit_start_sector )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start
+ pgc.i_cell_play_inf_sbyte, SEEK_SET );
pgc.p_cell_play_inf = malloc( pgc.i_cell_nb *sizeof(cell_play_inf_t) );
if( pgc.p_cell_play_inf == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgc;
}
for( i=0 ; i<pgc.i_cell_nb ; i++ )
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_title_unit_start_sector *DVD_LB_SIZE,
SEEK_SET );
if( ReadTitleUnit( p_ifo, &p_ifo->vmg.title_unit ) < 0 )
{
GETS( &pgc.p_cell_play_inf[i].i_cat );
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 );
return -1;
}
}
/* 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
+ pgc.i_cell_pos_inf_sbyte, SEEK_SET );
pgc.p_cell_pos_inf = malloc( pgc.i_cell_nb *sizeof(cell_pos_inf_t) );
if( pgc.p_cell_pos_inf == NULL )
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_parental_inf_start_sector *DVD_LB_SIZE,
SEEK_SET );
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" );
p_ifo->b_error = 1;
return pgc;
intf_ErrMsg( "ifo error: out of memory in IfoInit" );
return -1;
}
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 );
FLUSH( 1 );
GETC( &pgc.p_cell_pos_inf[i].i_cell_id );
GET( parental.p_parental_desc[i].ps_country_code, 2 );
FLUSH( 2 );
GETS( &parental.p_parental_desc[i].i_parental_mask_start_byte );
FLUSH( 2 );
}
}
return pgc;
}
/*****************************************************************************
* ReadUnit : Fills Menu Language Unit Table/ PGC Info Table
*****************************************************************************/
static pgci_inf_t ReadUnit( ifo_t* p_ifo )
{
pgci_inf_t inf;
int i;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "Unit\n" );
parental.p_parental_mask = malloc( parental.i_country_nb *
sizeof(parental_mask_t) );
if( parental.p_parental_mask == NULL )
{
intf_ErrMsg( "ifo erro: out of memory in IfoInit" );
return -1;
}
GETS( &inf.i_srp_nb );
FLUSH( 2 );
GETL( &inf.i_lu_ebyte );
inf.p_srp = malloc( inf.i_srp_nb *sizeof(pgci_srp_t) );
if( inf.p_srp == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return inf;
}
for( i=0 ; i<inf.i_srp_nb ; i++ )
{
GETC( &inf.p_srp[i].i_pgc_cat_mask );
GETC( &inf.p_srp[i].i_pgc_cat );
GETS( &inf.p_srp[i].i_par_mask );
GETL( &inf.p_srp[i].i_pgci_sbyte );
for( i = 0 ; i < parental.i_country_nb ; i++ )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
parental.p_parental_desc[i].i_parental_mask_start_byte,
SEEK_SET );
for( j = 0 ; j < 8 ; j++ )
{
parental.p_parental_mask[i].ppi_mask[j] =
malloc( ( parental.i_vts_nb + 1 ) *sizeof(u16) );
if( parental.p_parental_mask[i].ppi_mask[j] == NULL )
{
intf_ErrMsg( "ifo error: out of memory in IfoInit" );
return -1;
}
for( k = 0 ; k < parental.i_vts_nb + 1 ; k++ )
{
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,
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 );
}
u64 i_temp;
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;
}
/*****************************************************************************
* ReadUnitTable : Fills the PGCI Unit structure.
*****************************************************************************/
static pgci_ut_t ReadUnitTable( ifo_t* p_ifo )
{
pgci_ut_t pgci;
int i;
off_t i_start = p_ifo->i_pos;
for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
{
GETL( &vts_inf.pi_vts_attr_start_byte[i] );
}
//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 );
FLUSH( 2 );
GETL( &pgci.i_ebyte );
pgci.p_lu = malloc( pgci.i_lu_nb *sizeof(pgci_lu_t) );
if( pgci.p_lu == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgci;
}
for( i=0 ; i<pgci.i_lu_nb ; i++ )
{
GET( pgci.p_lu[i].ps_lang_code, 2 );
FLUSH( 1 );
GETC( &pgci.p_lu[i].i_existence_mask );
GETL( &pgci.p_lu[i].i_lu_sbyte );
for( i = 0 ; i < vts_inf.i_vts_nb ; i++ )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
vts_inf.pi_vts_attr_start_byte[i],
SEEK_SET );
GETL( &vts_inf.p_vts_attr[i].i_end_byte );
GETL( &vts_inf.p_vts_attr[i].i_cat_app_type );
// GETS( &vts_inf.p_vts_attr[i].vts_menu_video_attr );
FLUSH(2);
FLUSH( 1 );
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 );
for( j = 0 ; j < 8 ; j++ )
{
GETLL( &i_temp );
}
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) );
if( pgci.p_pgci_inf == NULL )
#undef vts_inf
/*
* global cell map.
*/
if( manager_inf.i_cell_inf_start_sector )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return pgci;
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE,
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 +
pgci.p_lu[i].i_lu_sbyte,
SEEK_SET );
pgci.p_pgci_inf[i] = ReadUnit( p_ifo );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE,
SEEK_SET );
if( ReadVobuMap( p_ifo, &p_ifo->vmg.vobu_map ) < 0 )
{
return -1;
}
}
#undef manager_inf
return pgci;
}
/*****************************************************************************
* 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;
p_ifo->vts.b_initialized = 0;
//fprintf( stderr, "CELL ADD\n" );
intf_WarnMsg( 1, "ifo info: vmg initialized" );
GETS( &c_adt.i_vob_nb );
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;
return 0;
}
/*****************************************************************************
* 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;
int i, i_max;
off_t i_start = p_ifo->i_pos;
//fprintf( stderr, "VOBU ADMAP\n" );
off_t i_off;
off_t i_start;
u64 i_temp;
int i, j;
GETL( &map.i_ebyte );
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++ )
if( p_ifo->vts.b_initialized )
{
GETL( &map.pi_vobu_ssector[i] );
FreeTitleSet( &p_ifo->vts );
}
return map;
}
/*
* Video Manager Information Processing.
* This is what is contained in video_ts.ifo.
*/
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;
/*****************************************************************************
* 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;
p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET );
//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 );
mat.psz_id[12] = '\0';
GETL( &mat.i_lsector );
GET( manager_inf.psz_id , 12 );
manager_inf.psz_id[12] = '\0';
GETL( &manager_inf.i_end_sector );
FLUSH( 12 );
GETL( &mat.i_i_lsector );
GETL( &manager_inf.i_inf_end_sector );
FLUSH( 1 );
GETC( &mat.i_spec_ver );
GETL( &mat.i_cat );
GETS( &mat.i_vol_nb );
GETS( &mat.i_vol );
GETC( &mat.i_disc_side );
FLUSH( 19 );
GETS( &mat.i_tts_nb );
GET( mat.ps_provider_id, 32 );
GETLL( &mat.i_pos_code );
GETC( &manager_inf.i_spec_ver );
GETL( &manager_inf.i_cat );
FLUSH( 90 );
GETL( &manager_inf.i_inf_end_byte );
FLUSH( 60 );
GETL( &manager_inf.i_menu_vob_start_sector );
GETL( &manager_inf.i_title_vob_start_sector );
GETL( &manager_inf.i_title_inf_start_sector );
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 );
GETL( &mat.i_i_mat_ebyte );
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 );
// GETS( &manager_inf.m_video_atrt );
FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_audio_nb );
//fprintf( stderr, "vmgi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i < 8 ; i++ )
GETC( &manager_inf.i_menu_audio_nb );
for( i=0 ; i<8 ; i++ )
{
GETLL( &i_temp );
}
FLUSH( 17 );
GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vmgi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i < mat.i_subpic_nb ; i++ )
GETC( &manager_inf.i_menu_spu_nb );
for( i=0 ; i<28 ; i++ )
{
GET( &i_temp, 6 );
/* 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 );
/*****************************************************************************
* ReadVMGTitlePointer : Fills the Part Of Title Search Pointer structure.
*****************************************************************************/
static vmg_ptt_srpt_t ReadVMGTitlePointer( ifo_t* p_ifo )
{
vmg_ptt_srpt_t ptr;
int i;
// off_t i_start = p_ifo->i_pos;
i_start = p_ifo->i_pos;
//fprintf( stderr, "VTS PTR\n" );
GETS( &title_inf.i_title_nb );
//fprintf( stderr, "VTS title_inf nb: %d\n", title_inf.i_title_nb );
FLUSH( 2 );
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 );
//fprintf( stderr, "PTR: TTU nb %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
/* Parsing of tts */
ptr.p_tts = malloc( ptr.i_ttu_nb *sizeof(tts_t) );
if( ptr.p_tts == NULL )
for( i = 0 ; i < title_inf.i_title_nb ; i++ )
{
GETL( &title_inf.pi_start_byte[i] );
}
/* Parsing of tts */
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->b_error = 1;
return ptr;
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_menu_unit_start_sector *DVD_LB_SIZE,
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 );
GETC( &ptr.p_tts[i].i_angle_nb );
GETS( &ptr.p_tts[i].i_ptt_nb );
GETS( &ptr.p_tts[i].i_parental_id );
GETC( &ptr.p_tts[i].i_tts_nb );
GETC( &ptr.p_tts[i].i_vts_ttn );
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 );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_title_unit_start_sector *DVD_LB_SIZE,
SEEK_SET );
if( ReadUnitInf( p_ifo, &p_ifo->vts.title_unit ) < 0 )
{
return -1;
}
}
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 );
/*****************************************************************************
* 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, "TMAP\n" );
//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 );
GETS( &par.i_vts_nb );
GETL( &par.i_ebyte );
par.p_ptl_desc = malloc( par.i_country_nb *sizeof(vmg_ptl_mai_desc_t) );
if( par.p_ptl_desc == NULL )
for( i = 0 ; i < time_inf.i_nb ; i++ )
{
GETC( &time_inf.p_time_map[i].i_time_unit );
FLUSH( 1 );
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->b_error = 1;
return par;
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_menu_cell_inf_start_sector *DVD_LB_SIZE,
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 );
FLUSH( 2 );
GETS( &par.p_ptl_desc[i].i_ptl_mai_sbyte );
FLUSH( 2 );
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_menu_vobu_map_start_sector *DVD_LB_SIZE,
SEEK_SET );
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->b_error = 1;
return par;
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_cell_inf_start_sector *DVD_LB_SIZE,
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 +
par.p_ptl_desc[i].i_ptl_mai_sbyte, SEEK_SET );
for( j=1 ; j<=8 ; j++ )
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->vts.i_pos +
manager_inf.i_vobu_map_start_sector *DVD_LB_SIZE,
SEEK_SET );
if( ReadVobuMap( p_ifo, &p_ifo->vts.vobu_map ) )
{
par.p_ptl_mask[i].ppi_ptl_mask[j] =
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 -1;
}
}
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, j;
u64 i_temp;
off_t i_start = p_ifo->i_pos;
int i;
//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 );
//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 )
if( p_vts->manager_inf.i_cell_inf_start_sector )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return atrt;
FreeCellInf( &p_vts->cell_inf );
}
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" );
p_ifo->b_error = 1;
return atrt;
FreeCellInf( &p_vts->menu_cell_inf );
}
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 +
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++ )
for( i = 0 ; i < p_vts->time_inf.i_nb ; i++ )
{
GETLL( &i_temp );
}
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[i].pi_sector );
}
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);
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 )
if( p_ifo->vmg.manager_inf.i_vobu_map_start_sector )
{
p_ifo->i_pos = lseek( p_ifo->i_fd, p_ifo->i_off +
vmg.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.ptt_srpt = ReadVMGTitlePointer( p_ifo );
FreeVobuMap( &p_ifo->vmg.vobu_map );
}
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 +
vmg.mat.i_pgci_ut_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.pgci_ut = ReadUnitTable( p_ifo );
FreeCellInf( &p_ifo->vmg.cell_inf );
}
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 +
vmg.mat.i_ptl_mait_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.ptl_mait = ReadParentalInf( p_ifo );
free( p_ifo->vmg.vts_inf.p_vts_attr );
free( p_ifo->vmg.vts_inf.pi_vts_attr_start_byte );
}
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 +
vmg.mat.i_vts_atrt_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.vts_atrt = ReadVTSAttr( p_ifo );
for( i = 0 ; i < p_ifo->vmg.parental_inf.i_country_nb ; i++ )
{
for( j = 0 ; j < 8 ; j++ )
{
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 +
vmg.mat.i_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.c_adt = ReadCellInf( p_ifo );
FreeTitleUnit( &p_ifo->vmg.title_unit );
}
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 +
vmg.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vmg.vobu_admap = ReadMap( p_ifo );
free( p_ifo->vmg.title_inf.p_attr );
}
return vmg;
}
FreeTitle( &p_ifo->vmg.title );
free( p_ifo );
return;
}
/*
* Video Title Set Information Processing.
* This is what is contained in vts_*.ifo.
* Function common to Video Manager and Video Title set Processing
*/
/*****************************************************************************
* 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;
int i;
u64 i_temp;
// off_t i_start = p_ifo->i_pos;
off_t i_start;
int i;
//fprintf( stderr, "VTSI\n" );
i_start = p_ifo->i_pos;
GET( mat.psz_id , 12 );
mat.psz_id[12] = '\0';
GETL( &mat.i_lsector );
FLUSH( 12 );
GETL( &mat.i_i_lsector );
FLUSH( 1 );
GETC( &mat.i_spec_ver );
GETL( &mat.i_cat );
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 );
//fprintf( stderr, "PGC\n" );
FLUSH(2);
GETC( &p_title->i_chapter_nb );
GETC( &p_title->i_cell_nb );
//fprintf( stderr, "title: Prg: %d Cell: %d\n", pgc.i_prg_nb, pgc.i_cell_nb );
GETL( &p_title->i_play_time );
GETL( &p_title->i_prohibited_user_op );
for( i=0 ; i<8 ; i++ )
{
GETLL( &i_temp );
GETS( &p_title->pi_audio_status[i] );
}
FLUSH( 17 );
GETC( &mat.i_m_subpic_nb );
for( i=0 ; i<28 ; i++ )
for( i=0 ; i<32 ; i++ )
{
GET( &i_temp, 6 );
/* FIXME : take care of endianness */
GETL( &p_title->pi_subpic_status[i] );
}
FLUSH( 2 );
// GETS( &mat.video_atrt );
FLUSH(2);
FLUSH( 1 );
GETC( &mat.i_audio_nb );
//fprintf( stderr, "vtsi audio nb : %d\n", mat.i_audio_nb );
for( i=0 ; i<8 ; i++ )
GETS( &p_title->i_next_title_num );
GETS( &p_title->i_prev_title_num );
GETS( &p_title->i_go_up_title_num );
//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( &p_title->i_still_time );
GETC( &p_title->i_play_mode );
for( i=0 ; i<16 ; i++ )
{
GETLL( &i_temp );
//fprintf( stderr, "Audio %d: %llx\n", i, i_temp );
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;
GETL( &p_title->pi_yuv_color[i] );
/* FIXME : We have to erase the extra bit */
}
FLUSH( 17 );
GETC( &mat.i_subpic_nb );
//fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb );
for( i=0 ; i<mat.i_subpic_nb ; i++ )
GETS( &p_title->i_command_start_byte );
GETS( &p_title->i_chapter_map_start_byte );
GETS( &p_title->i_cell_play_start_byte );
GETS( &p_title->i_cell_pos_start_byte );
/* parsing of command_t */
if( p_title->i_command_start_byte )
{
GET( &i_temp, 6 );
i_temp = hton64( i_temp ) >> 16;
//fprintf( stderr, "Subpic %d: %llx\n", i, i_temp );
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;
}
p_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + p_title->i_command_start_byte,
SEEK_SET );
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 );
/*****************************************************************************
* ReadVTSTitlePointer : Fills the Part Of Title Search Pointer structure.
*****************************************************************************/
static vts_ptt_srpt_t ReadVTSTitlePointer( ifo_t* p_ifo )
{
vts_ptt_srpt_t ptr;
int i;
off_t i_start = p_ifo->i_pos;
/* pre-title commands */
if( p_title->command.i_pre_command_nb )
{
p_title->command.p_pre_command =
malloc( p_title->command.i_pre_command_nb
*sizeof(command_desc_t) );
//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 );
//fprintf( stderr, "VTS PTR nb: %d\n", ptr.i_ttu_nb );
FLUSH( 2 );
GETL( &ptr.i_ebyte );
ptr.pi_ttu_sbyte = malloc( ptr.i_ttu_nb *sizeof(u32) );
if( ptr.pi_ttu_sbyte == NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return ptr;
for( i = 0 ; i < p_title->command.i_pre_command_nb ; i++ )
{
GETCOMMAND( &p_title->command.p_pre_command[i] );
}
}
else
{
p_title->command.p_pre_command = NULL;
}
/* 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 */
ptr.p_ttu = malloc( ptr.i_ttu_nb *sizeof(ttu_t) );
if( ptr.p_ttu == NULL )
else
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return ptr;
p_title->chapter_map.pi_start_cell = NULL;
}
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 +
ptr.pi_ttu_sbyte[i], SEEK_SET );
GETS( &ptr.p_ttu[i].i_pgc_nb );
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_ifo->i_pos = lseek( p_ifo->i_fd,
i_start + p_title->i_cell_play_start_byte,
SEEK_SET );
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;
int i,j;
// off_t i_start = p_ifo->i_pos;
if( p_title->i_command_start_byte )
{
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 );
FLUSH( 2 );
GETL( &tmap.i_ebyte );
tmap.pi_sbyte = malloc( tmap.i_nb *sizeof(u32) );
if( tmap.pi_sbyte == NULL )
{
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 )
if( p_title->command.i_cell_command_nb )
{
free( p_title->command.p_cell_command );
}
if( p_title->i_chapter_map_start_byte )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return tmap;
free( p_title->chapter_map.pi_start_cell );
}
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_off;
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;
off_t i_start;
int i;
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 );
if( vts.mat.i_ptt_srpt_ssector )
p_unit_inf->p_title =
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 +
vts.mat.i_ptt_srpt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.ptt_srpt = ReadVTSTitlePointer( p_ifo );
intf_ErrMsg( "ifo error: out of memory in ReadUnit" );
return -1;
}
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 +
vts.mat.i_m_pgci_ut_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.pgci_ut = ReadUnitTable( p_ifo );
GETC( &p_unit_inf->p_title[i].i_category_mask );
GETC( &p_unit_inf->p_title[i].i_category );
GETS( &p_unit_inf->p_title[i].i_parental_mask );
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 +
vts.mat.i_pgcit_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.pgci_ti = ReadUnit( p_ifo );
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
p_unit_inf->p_title[i].i_title_start_byte,
SEEK_SET );
//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 +
vts.mat.i_tmap_ti_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.tmap_ti = ReadVTSTimeMap( p_ifo );
free( p_unit_inf->p_title );
}
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 +
vts.mat.i_m_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.m_c_adt = ReadCellInf( p_ifo );
intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
return -1;
}
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 +
vts.mat.i_m_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.m_vobu_admap = ReadMap( p_ifo );
GET( p_title_unit->p_unit[i].ps_lang_code, 2 );
FLUSH( 1 );
GETC( &p_title_unit->p_unit[i].i_existence_mask );
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 +
vts.mat.i_c_adt_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.c_adt = ReadCellInf( p_ifo );
intf_ErrMsg( "ifo error: out of memory in ReadTitleUnit" );
return -1;
}
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 +
vts.mat.i_vobu_admap_ssector *DVD_LB_SIZE,
SEEK_SET );
vts.vobu_admap = ReadMap( p_ifo );
p_ifo->i_pos = lseek( p_ifo->i_fd, i_start +
p_title_unit->p_unit[i].i_unit_inf_start_byte,
SEEK_SET );
ReadUnitInf( p_ifo, &p_title_unit->p_unit_inf[i] );
}
p_ifo->vts = vts;
return 0;
}
/*
* DVD Information Management
*/
#if 0
/*****************************************************************************
* IfoRead : Function that fills structure and calls specified functions
* to do it.
* FreeTitleUnit: frees a structure allocateed by ReadTitleUnit
*****************************************************************************/
void IfoRead( ifo_t* p_ifo )
static int FreeTitleUnit( title_unit_t * p_title_unit )
{
int i;
off_t i_off;
/* Video Title Sets initialization */
p_ifo->p_vts = malloc( p_ifo->vmg.mat.i_tts_nb *sizeof(vts_t) );
if( p_ifo->p_vts == NULL )
if( p_title_unit->p_unit_inf != NULL )
{
intf_ErrMsg( "Out of memory" );
p_ifo->b_error = 1;
return;
for( i = 0 ; i < p_title_unit->i_unit_nb ; i++ )
{
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
* interactive behaviour of the dvd
*/
#if 1
#if 0
#define OP_VAL_16(i) (ntoh16( com.data.pi_16[i]))
#define OP_VAL_8(i) ((com.data.pi_8[i]))
......
......@@ -2,7 +2,7 @@
* dvd_ifo.h: Structures for ifo parsing
*****************************************************************************
* 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>
*
......@@ -76,7 +76,7 @@ typedef struct ifo_spu_t
/* Ifo vitual machine Commands */
typedef struct ifo_command_s
typedef struct command_desc_s
{
u8 i_type :3;
u8 i_direct :1;
......@@ -89,162 +89,162 @@ typedef struct ifo_command_s
u8 pi_8[6];
u16 pi_16[3];
} data;
} ifo_command_t;
} command_desc_t;
/* Program Chain Command Table
- 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_post_com_nb; // 2 bytes
u16 i_cell_com_nb; // 2 bytes
u16 i_pre_command_nb; // 2 bytes
u16 i_post_command_nb; // 2 bytes
u16 i_cell_command_nb; // 2 bytes
// char[2] ???
ifo_command_t* p_pre_com; // i_pre_com_nb * 8 bytes
ifo_command_t* p_post_com; // i_post_com_nb * 8 bytes
ifo_command_t* p_cell_com; // i_cell_com_nb * 8 bytes
} pgc_com_tab_t;
command_desc_t* p_pre_command; // i_pre_com_nb * 8 bytes
command_desc_t* p_post_command; // i_post_com_nb * 8 bytes
command_desc_t* p_cell_command; // i_cell_com_nb * 8 bytes
} command_t;
/* Program Chain Map Table
* - 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
} pgc_prg_map_t;
u8* pi_start_cell; // i_prg_nb * 1 byte
} chapter_map_t;
/* Cell Playback Information Table
* we have a pointer to such a structure for each cell
* - 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 */
u16 i_cat; // 2 bytes
u16 i_category; // 2 bytes
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_entry_sector; // 4 bytes
u32 i_start_sector; // 4 bytes
u32 i_first_ilvu_vobu_esector; // 4 bytes; ???
u32 i_lvobu_ssector; // 4 bytes
u32 i_lsector; // 4 bytes
} cell_play_inf_t;
u32 i_last_vobu_start_sector; // 4 bytes
u32 i_end_sector; // 4 bytes
} cell_play_t;
/* Cell Position Information Table
* we have a pointer to such a structure for each cell
* - 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 */
u16 i_vob_id; // 2 bytes
// char ???
u8 i_cell_id; // 1 byte
} cell_pos_inf_t;
} cell_pos_t;
/* Main structure for Program Chain
* - start at i_fp_pgc_sbyte
* - or at i_vmgm_pgci_sbyte in vmgm_pgci_srp_t */
typedef struct pgc_s
typedef struct title_s
{
/* Global features of program chain */
// char[2] ???
u8 i_prg_nb; // 1 byte
u8 i_chapter_nb; // 1 byte
u8 i_cell_nb; // 1 byte
u32 i_play_time; // 4 bytes
u32 i_prohibited_user_op; // 4 bytes
u16 pi_audio_status[8]; // 8*2 bytes
u32 pi_subpic_status[32]; // 32*4 bytes
u16 i_next_pgc_nb; // 2 bytes
u16 i_prev_pgc_nb; // 2 bytes
u16 i_goup_pgc_nb; // 2 bytes
u16 i_next_title_num; // 2 bytes
u16 i_prev_title_num; // 2 bytes
u16 i_go_up_title_num; // 2 bytes
u8 i_still_time; // 1 byte ; in seconds
u8 i_play_mode; // 1 byte
/* In video_ts.ifo, the 3 significant bytes of each color are
* preceded by 1 unsignificant byte */
u32 pi_yuv_color[16]; // 16*3 bytes
/* Here come the start bytes of the following structures */
u16 i_com_tab_sbyte; // 2 bytes
u16 i_prg_map_sbyte; // 2 bytes
u16 i_cell_play_inf_sbyte; // 2 bytes
u16 i_cell_pos_inf_sbyte; // 2 bytes
u16 i_command_start_byte; // 2 bytes
u16 i_chapter_map_start_byte; // 2 bytes
u16 i_cell_play_start_byte; // 2 bytes
u16 i_cell_pos_start_byte; // 2 bytes
/* Predefined structures */
pgc_com_tab_t com_tab;
pgc_prg_map_t prg_map;
cell_play_inf_t* p_cell_play_inf; // i_cell_nb * 24 bytes
cell_pos_inf_t* p_cell_pos_inf; // i_cell_nb * 4 bytes
} pgc_t;
command_t command;
chapter_map_t chapter_map;
cell_play_t* p_cell_play; // i_cell_nb * 24 bytes
cell_pos_t* p_cell_pos; // i_cell_nb * 4 bytes
} title_t;
/*
* Menu PGCI Unit Table
*/
/* Menu PGCI Language unit Descriptor */
typedef struct pgci_lu_s
typedef struct unit_s
{
char ps_lang_code[2]; // 2 bytes (ISO-xx)
// char ???
u8 i_existence_mask; // 1 byte
u32 i_lu_sbyte; // 4 bytes
} pgci_lu_t;
u32 i_unit_inf_start_byte; // 4 bytes
} unit_t;
typedef struct pgci_srp_s
typedef struct unit_title_s
{
u8 i_pgc_cat_mask; // 1 byte
u8 i_pgc_cat; // 1 byte
u16 i_par_mask; // 2 bytes
u32 i_pgci_sbyte; // 4 bytes
pgc_t pgc;
} pgci_srp_t;
u8 i_category_mask; // 1 byte
u8 i_category; // 1 byte
u16 i_parental_mask; // 2 bytes
u32 i_title_start_byte; // 4 bytes
title_t title;
} unit_title_t;
/* Menu PGCI Language Unit Table
* - 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] ???
u32 i_lu_ebyte; // 4 bytes
pgci_srp_t* p_srp; // i_srp_nb * 8 bytes
} pgci_inf_t;
u32 i_end_byte; // 4 bytes
unit_title_t * p_title; // i_srp_nb * 8 bytes
} unit_inf_t;
/* Main Struct for Menu PGCI
* - 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] ???
u32 i_ebyte; // 4 bytes
pgci_lu_t* p_lu; // i_lu_nb * 8 bytes
pgci_inf_t* p_pgci_inf; // i_lu_nb * 8 bytes
} pgci_ut_t;
u32 i_end_byte; // 4 bytes
unit_t* p_unit; // i_lu_nb * 8 bytes
unit_inf_t* p_unit_inf; // i_lu_nb * 8 bytes
} title_unit_t;
/*
* Cell Adress Table Information
*/
typedef struct cell_inf_s
typedef struct cell_map_s
{
u16 i_vob_id; // 2 bytes
u8 i_cell_id; // 1 byte
// char ???
u32 i_ssector; // 4 bytes
u32 i_esector; // 4 bytes
} cell_inf_t;
u32 i_start_sector; // 4 bytes
u32 i_end_sector; // 4 bytes
} cell_map_t;
typedef struct c_adt_s
typedef struct cell_inf_s
{
u16 i_vob_nb; // 2 bytes
// char[2] ???
u32 i_ebyte; // 4 bytes
u32 i_end_byte; // 4 bytes
u16 i_cell_nb; // not in ifo; computed
// with e_byte
cell_inf_t* p_cell_inf;
} c_adt_t;
cell_map_t* p_cell_map;
} cell_inf_t;
/*
* VOBU Adress Map Table
*/
typedef struct vobu_admap_s
typedef struct vobu_map_s
{
u32 i_ebyte; // 4 bytes
u32* pi_vobu_ssector; // (nb of vobu) * 4 bytes
} vobu_admap_t;
u32 i_end_byte; // 4 bytes
u32* pi_vobu_start_sector; // (nb of vobu) * 4 bytes
} vobu_map_t;
/*****************************************************************************
* Structures for Video Management (cf video_ts.ifo)
......@@ -253,43 +253,43 @@ typedef struct vobu_admap_s
/*
* Video Manager Information Management Table
*/
typedef struct vmgi_mat_s
typedef struct manager_inf_s
{
char psz_id[13]; // 12 bytes (DVDVIDEO-VMG)
u32 i_lsector; // 4 bytes
u32 i_vmg_end_sector; // 4 bytes
// char[12] ???
u32 i_i_lsector; // 4 bytes
u32 i_vmg_inf_end_sector; // 4 bytes
// char ???
u8 i_spec_ver; // 1 byte
u32 i_cat; // 4 bytes
u16 i_vol_nb; // 2 bytes
u16 i_vol; // 2 bytes
u16 i_volume_nb; // 2 bytes
u16 i_volume; // 2 bytes
u8 i_disc_side; // 1 bytes
// char[20] ???
u16 i_tts_nb; // 2 bytes
u16 i_title_set_nb; // 2 bytes
char ps_provider_id[32]; // 32 bytes
u64 i_pos_code; // 8 bytes
// char[24] ???
u32 i_i_mat_ebyte; // 4 bytes
u32 i_fp_pgc_sbyte; // 4 bytes
u32 i_vmg_inf_end_byte; // 4 bytes
u32 i_first_play_title_start_byte; // 4 bytes
// char[56] ???
u32 i_vobs_ssector; // 4 bytes
u32 i_ptt_srpt_ssector; // 4 bytes
u32 i_pgci_ut_ssector; // 4 bytes
u32 i_ptl_mait_ssector; // 4 bytes
u32 i_vts_atrt_ssector; // 4 bytes
u32 i_txtdt_mg_ssector; // 4 bytes
u32 i_c_adt_ssector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes
u32 i_vob_start_sector; // 4 bytes
u32 i_title_inf_start_sector; // 4 bytes
u32 i_title_unit_start_sector; // 4 bytes
u32 i_parental_inf_start_sector; // 4 bytes
u32 i_vts_inf_start_sector; // 4 bytes
u32 i_text_data_start_sector; // 4 bytes
u32 i_cell_inf_start_sector; // 4 bytes
u32 i_vobu_map_start_sector; // 4 bytes
// char[2] ???
ifo_video_t video_atrt; // 2 bytes
ifo_video_t video_attr; // 2 bytes
// char ???
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] ???
u8 i_subpic_nb; // 1 byte
ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes
} vmgi_mat_t;
u8 i_spu_nb; // 1 byte
ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
} manager_inf_t;
/*
......@@ -298,53 +298,53 @@ typedef struct vmgi_mat_s
/* Title sets structure
* 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_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
u8 i_tts_nb; // 1 byte (VTS#)
u8 i_vts_ttn; // 1 byte ???
u32 i_ssector; // 4 bytes
} tts_t;
u8 i_title_set_num; // 1 byte (VTS#)
u8 i_title_num; // 1 byte ???
u32 i_start_sector; // 4 bytes
} title_attr_t;
/* Main struct for tts
* - 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] ???
u32 i_ebyte; // 4 bytes
tts_t* p_tts; // i_ttu_nb * 12 bytes
} vmg_ptt_srpt_t;
u32 i_end_byte; // 4 bytes
title_attr_t * p_attr; // i_ttu_nb * 12 bytes
} title_inf_t;
/*
* Parental Management Information Table
*/
typedef struct vmg_ptl_mai_desc_s
typedef struct parental_desc_s
{
char ps_country_code[2]; // 2 bytes
// char[2] ???
u16 i_ptl_mai_sbyte; // 2 bytes
u16 i_parental_mask_start_byte; // 2 bytes
// 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
} vmg_ptl_mask_t;
u16* ppi_mask[8]; // (i_vts_nb +1) * 8 * 2 bytes
} parental_mask_t;
/* Main struct for parental management
* - 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_vts_nb; // 2 bytes
u32 i_ebyte; // 4 bytes
vmg_ptl_mai_desc_t* p_ptl_desc; // i_country_nb * 8 bytes
vmg_ptl_mask_t* p_ptl_mask; // i_country_nb * sizeof(vmg_ptl_mask_t)
} vmg_ptl_mait_t;
u32 i_end_byte; // 4 bytes
parental_desc_t* p_parental_desc; // i_country_nb * 8 bytes
parental_mask_t* p_parental_mask; // i_country_nb * sizeof(vmg_ptl_mask_t)
} parental_inf_t;
/*
* Video Title Set Attribute Table
......@@ -352,51 +352,51 @@ typedef struct vmg_ptl_mait_s
/* Attribute structure : one for each vts
* - 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
ifo_video_t vtsm_video_atrt; // 2 bytes
ifo_video_t vts_menu_video_attr; // 2 bytes
// char ???
u8 i_vtsm_audio_nb; // 1 byte
ifo_audio_t p_vtsm_audio_atrt[8]; // 8 * 8 bytes
u8 i_vts_menu_audio_nb; // 1 byte
ifo_audio_t p_vts_menu_audio_attr[8]; // 8 * 8 bytes
// char[17] ???
u8 i_vtsm_subpic_nb; // 1 byte
ifo_spu_t p_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes
u8 i_vts_menu_spu_nb; // 1 byte
ifo_spu_t p_vts_menu_spu_attr[28]; // i_vtsm_subpic_nb * 6 bytes
// char[2] ???
ifo_video_t vtstt_video_atrt; // 2 bytes
ifo_video_t vts_title_video_attr; // 2 bytes
// char ???
u8 i_vtstt_audio_nb; // 1 byte
ifo_audio_t p_vtstt_audio_atrt[8]; // 8 * 8 bytes
u8 i_vts_title_audio_nb; // 1 byte
ifo_audio_t p_vts_title_audio_attr[8]; // 8 * 8 bytes
// char[17] ???
u8 i_vtstt_subpic_nb; // 1 byte
ifo_spu_t p_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes
} vts_atrt_t;
u8 i_vts_title_spu_nb; // 1 byte
ifo_spu_t p_vts_title_spu_attr[28]; // i_vtstt_subpic_nb * 6 bytes
} vts_attr_t;
/* Main struct for vts attributes
* - start at i_vmg_vts_atrt_ssector */
typedef struct vmg_vts_atrt_s
typedef struct vts_inf_s
{
u16 i_vts_nb; // 2 bytes
// char[2] ???
u32 i_ebyte; // 4 bytes
u32* pi_vts_atrt_sbyte; // i_vts_nb * 4 bytes
vts_atrt_t* p_vts_atrt;
} vmg_vts_atrt_t;
u32 i_end_byte; // 4 bytes
u32* pi_vts_attr_start_byte; // i_vts_nb * 4 bytes
vts_attr_t* p_vts_attr;
} vts_inf_t;
/*
* Global Structure for Video Manager
*/
typedef struct vmg_s
{
vmgi_mat_t mat;
pgc_t pgc;
vmg_ptt_srpt_t ptt_srpt;
pgci_ut_t pgci_ut;
vmg_ptl_mait_t ptl_mait;
vmg_vts_atrt_t vts_atrt;
c_adt_t c_adt;
vobu_admap_t vobu_admap;
manager_inf_t manager_inf;
title_t title;
title_inf_t title_inf;
title_unit_t title_unit;
parental_inf_t parental_inf;
vts_inf_t vts_inf;
cell_inf_t cell_inf;
vobu_map_t vobu_map;
} vmg_t;
/*****************************************************************************
......@@ -406,46 +406,46 @@ typedef struct vmg_s
/*
* Video Title Sets Information Management Table
*/
typedef struct vtsi_mat_s
typedef struct vts_manager_s
{
char psz_id[13]; // 12 bytes (DVDVIDEO-VTS)
u32 i_lsector; // 4 bytes
u32 i_end_sector; // 4 bytes
// char[12] ???
u32 i_i_lsector; // 4 bytes
u32 i_inf_end_sector; // 4 bytes
// char ???
u8 i_spec_ver; // 1 byte
u32 i_cat; // 4 bytes
// char[90] ???
u32 i_mat_ebyte; // 4 bytes
u32 i_inf_end_byte; // 4 bytes
// char[60] ???
u32 i_m_vobs_ssector; // 4 bytes
u32 i_tt_vobs_ssector; // 4 bytes
u32 i_ptt_srpt_ssector; // 4 bytes
u32 i_pgcit_ssector; // 4 bytes
u32 i_m_pgci_ut_ssector; // 4 bytes
u32 i_tmap_ti_ssector; // 4 bytes
u32 i_m_c_adt_ssector; // 4 bytes
u32 i_m_vobu_admap_ssector; // 4 bytes
u32 i_c_adt_ssector; // 4 bytes
u32 i_vobu_admap_ssector; // 4 bytes
u32 i_menu_vob_start_sector; // 4 bytes
u32 i_title_vob_start_sector; // 4 bytes
u32 i_title_inf_start_sector; // 4 bytes
u32 i_title_unit_start_sector; // 4 bytes
u32 i_menu_unit_start_sector; // 4 bytes
u32 i_time_inf_start_sector; // 4 bytes
u32 i_menu_cell_inf_start_sector; // 4 bytes
u32 i_menu_vobu_map_start_sector; // 4 bytes
u32 i_cell_inf_start_sector; // 4 bytes
u32 i_vobu_map_start_sector; // 4 bytes
// char[24] ???
ifo_video_t m_video_atrt; // 2 bytes
ifo_video_t menu_video_attr; // 2 bytes
// char ???
u8 i_m_audio_nb; // 1 byte
ifo_audio_t p_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes
u8 i_menu_audio_nb; // 1 byte
ifo_audio_t p_menu_audio_attr[8]; // i_vmgm_audio_nb * 8 bytes
// char[16] ???
u8 i_m_subpic_nb; // 1 byte
ifo_spu_t p_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes
u8 i_menu_spu_nb; // 1 byte
ifo_spu_t p_menu_spu_attr[32]; // i_subpic_nb * 6 bytes
// !!! only 28 subpics ???
// char[2] ???
ifo_video_t video_atrt; // 2 bytes
ifo_video_t video_attr; // 2 bytes
// char ???
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] ???
u8 i_subpic_nb; // 1 byte
ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes
} vtsi_mat_t;
u8 i_spu_nb; // 1 byte
ifo_spu_t p_spu_attr[32]; // i_subpic_nb * 6 bytes
} vts_manager_t;
/*
* Part Of Title Search Pointer Table Information
......@@ -453,70 +453,63 @@ typedef struct vtsi_mat_s
/* Title sets structure
* 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_prg_nb; // 2 bytes
} ttu_t;
u16 i_program_chain_num; // 2 bytes; Chapters/PGs
u16 i_program_num; // 2 bytes
} title_start_t;
/* Main struct for tts
* - 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] ???
u32 i_ebyte; // 4 bytes
u32* pi_ttu_sbyte;
ttu_t* p_ttu; // i_ttu_nb * 4 bytes
} vts_ptt_srpt_t;
u32 i_end_byte; // 4 bytes
u32* pi_start_byte;
title_start_t * p_title_start; // i_ttu_nb * 4 bytes
} vts_title_t;
/*
* Time Map table information
*/
/* Time Map structure */
typedef struct tmap_s
typedef struct time_map_s
{
u8 i_time_unit; // 1 byte
// char ???
u16 i_entry_nb; // 2 bytes
u32* pi_sector; // i_entry_nb * 4 bytes
} tmap_t;
} time_map_t;
/* Main structure for tmap_ti
* - start at "i_tmap_ti_ssector" */
typedef struct vts_tmap_ti_s
typedef struct time_inf_s
{
u16 i_nb; // 2 bytes
// char[2] ???
u32 i_ebyte; // 4 bytes
u32* pi_sbyte; // i_tmap_nb * 4 bytes
tmap_t* p_tmap;
} vts_tmap_ti_t;
u32 i_end_byte; // 4 bytes
u32* pi_start_byte; // i_tmap_nb * 4 bytes
time_map_t* p_time_map;
} time_inf_t;
/*
* Video Title Set
*/
typedef struct vts_s
{
boolean_t b_initialized;
off_t i_pos;
vtsi_mat_t mat;
/* Part Of Title Search Pointer Table Info */
vts_ptt_srpt_t ptt_srpt;
/* Video Title Set Menu PGCI Unit Table */
pgci_ut_t pgci_ut;
/* Video Title Set Program Chain Info Table */
pgci_inf_t pgci_ti;
/* Video Title Set Time Map Table */
vts_tmap_ti_t tmap_ti;
/* 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_manager_t manager_inf;
vts_title_t title_inf;
title_unit_t menu_unit;
unit_inf_t title_unit;
time_inf_t time_inf;
cell_inf_t menu_cell_inf;
vobu_map_t menu_vobu_map;
cell_inf_t cell_inf;
vobu_map_t vobu_map;
} vts_t;
/*
......@@ -524,19 +517,12 @@ typedef struct vts_s
*/
typedef struct ifo_s
{
/* File descriptor for the device */
int i_fd;
/* Offset to video_ts.ifo on the device */
off_t i_off;
/* Position of stream pointer */
off_t i_pos;
/* Error Management */
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;
int i_fd; /* File descriptor for the device */
off_t i_off; /* Offset to video_ts.ifo on the device */
off_t i_pos; /* Position of stream pointer */
boolean_t b_error; /* Error Management */
vmg_t vmg; /* Structure described in video_ts */
int i_title; /* Current title number */
vts_t vts; /* Vts ifo for current title set */
} ifo_t;
......@@ -7,7 +7,7 @@
* will only be given back to netlist when refcount is zero.
*****************************************************************************
* 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>
* Stphane Borel <stef@videolan.org>
......@@ -357,7 +357,7 @@ struct data_packet_s * DVDNewPacket( void * p_method_data,
{
dvd_netlist_t * p_netlist;
struct data_packet_s * p_packet;
//intf_ErrMsg( "netlist: New packet" );
/* cast */
p_netlist = (dvd_netlist_t *)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_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_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->i_iovec_start ++;
p_netlist->i_iovec_start &= p_netlist->i_nb_iovec;
......@@ -411,6 +415,7 @@ struct pes_packet_s * DVDNewPES( void * p_method_data )
dvd_netlist_t * p_netlist;
pes_packet_t * p_return;
//intf_ErrMsg( "netlist: New pes" );
/* cast */
p_netlist = (dvd_netlist_t *)p_method_data;
......@@ -433,9 +438,10 @@ struct pes_packet_s * DVDNewPES( void * p_method_data )
vlc_mutex_unlock (&p_netlist->lock);
/* initialize PES */
p_return->b_data_alignment =
p_return->b_discontinuity =
p_return->i_pts = p_return->i_dts = 0;
p_return->b_data_alignment = 0;
p_return->b_discontinuity = 0;
p_return->i_pts = 0;
p_return->i_dts = 0;
p_return->i_pes_size = 0;
p_return->p_first = NULL;
......@@ -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_data->p_next = NULL;
p_data->b_discard_payload = 0;
/* Update reference counter */
(*p_data->pi_refcount)--;
......@@ -510,7 +519,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
/* Update reference counter */
(*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_nb_iovec;
......@@ -520,6 +529,7 @@ void DVDDeletePES( void * p_method_data, pes_packet_t * p_pes )
p_next_packet = p_current_packet->p_next;
p_current_packet->p_next = NULL;
p_current_packet->b_discard_payload = 0;
p_current_packet = p_next_packet;
}
......
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* 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>
*
......@@ -354,25 +354,26 @@ static int DVDCheckCSS( input_thread_t * p_input )
*****************************************************************************/
static int DVDFindCell( thread_dvd_data_t * p_dvd )
{
pgc_t * p_pgc;
int i_cell;
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_index = p_dvd->i_prg_cell;
while( ( ( p_pgc->p_cell_pos_inf[i_index].i_vob_id !=
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id ) ||
( p_pgc->p_cell_pos_inf[i_index].i_cell_id !=
p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id ) ) &&
( i_cell < p_dvd->ifo.vts.c_adt.i_cell_nb ) )
while( ( ( title.p_cell_pos[i_index].i_vob_id !=
cell.p_cell_map[i_cell].i_vob_id ) ||
( title.p_cell_pos[i_index].i_cell_id !=
cell.p_cell_map[i_cell].i_cell_id ) ) &&
( i_cell < cell.i_cell_nb ) )
{
i_cell++;
}
if( i_cell == p_dvd->ifo.vts.c_adt.i_cell_nb )
if( i_cell == cell.i_cell_nb )
{
return -1;
}
......@@ -381,6 +382,8 @@ static int DVDFindCell( thread_dvd_data_t * p_dvd )
p_dvd->i_cell = i_cell;
return 0;
}
#undef title
#undef cell
}
/*****************************************************************************
......@@ -389,11 +392,10 @@ static int DVDFindCell( 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 > p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector )
if( p_dvd->i_sector > title.p_cell_play[p_dvd->i_prg_cell].i_end_sector )
{
p_dvd->i_prg_cell++;
}
......@@ -405,13 +407,14 @@ static int DVDFindSector( thread_dvd_data_t * p_dvd )
/* Find start and end sectors of new cell */
p_dvd->i_sector = MAX(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_ssector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_entry_sector );
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_start_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_start_sector );
p_dvd->i_end_sector = MIN(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector );
p_dvd->p_ifo->vts.cell_inf.p_cell_map[p_dvd->i_cell].i_end_sector,
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;
}
......@@ -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 )
{
pgc_t * p_pgc;
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
/* 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;
/* 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 )
p_dvd->i_start = lseek( p_dvd->i_fd, p_dvd->i_start, SEEK_SET );
p_dvd->i_chapter = i_chapter;
#undef title
return 0;
}
......@@ -458,7 +460,8 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
{
thread_dvd_data_t * p_dvd;
es_descriptor_t * p_es;
int i_nb;
int i_audio;
int i_spu;
u16 i_id;
u8 i_ac3;
u8 i_mpeg;
......@@ -482,26 +485,28 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
/* title number: it is not vts nb! */
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 */
p_dvd->i_vts_title =
p_dvd->ifo.vmg.ptt_srpt.p_tts[p_dvd->i_title-1].i_vts_ttn;
/* vts number */
p_dvd->ifo.i_title = p_dvd->i_title;
vmg.title_inf.p_attr[p_dvd->i_title-1].i_title_num;
p_dvd->i_program_chain =
vts.title_inf.p_title_start[p_dvd->i_vts_title-1].i_program_chain_num;
/* ifo vts */
IfoReadVTS( &(p_dvd->ifo) );
intf_WarnMsg( 2, "ifo info: vts initialized" );
/* css title key for current vts */
if( p_dvd->b_encrypted )
{
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->ifo.vts.i_pos +
p_dvd->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE;
vts.i_pos +
vts.manager_inf.i_title_vob_start_sector * DVD_LB_SIZE;
CSSGetKey( p_dvd->p_css );
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 )
*/
/* title set offset */
p_dvd->i_title_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE *
(off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector );
p_dvd->i_title_start = vts.i_pos + DVD_LB_SIZE *
(off_t)( vts.manager_inf.i_title_vob_start_sector );
/* last video cell */
p_dvd->i_cell = 0;
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 );
/* 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_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 );
......@@ -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: stream size: %lld", p_dvd->i_size );
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 */
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 )
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.i_selected_es_number = 0;
}
......@@ -576,33 +580,31 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
input_SelectES( p_input, p_es );
intf_WarnMsg( 1, "dvd info: video MPEG2 stream" );
/* Audio ES, in the order they appear in .ifo */
i_nb = p_dvd->ifo.vts.mat.i_audio_nb;
i_ac3 = 0x7f;
i_mpeg = 0xc0;
for( i = 1 ; i <= i_nb ; i++ )
for( i = 1 ; i <= vts.manager_inf.i_audio_nb ; i++ )
{
#ifdef DEBUG
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,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_coding_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_multichannel_extension,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_type,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_foo,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_bar,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_appl_mode,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_quantization,
p_dvd->ifo.vts.mat.p_audio_atrt[i-1].i_sample_freq,
p_dvd->ifo.vts.mat.p_audio_atrt[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_num_channels,
vts.manager_inf.p_audio_attr[i-1].i_coding_mode,
vts.manager_inf.p_audio_attr[i-1].i_multichannel_extension,
vts.manager_inf.p_audio_attr[i-1].i_type,
vts.manager_inf.p_audio_attr[i-1].i_appl_mode,
vts.manager_inf.p_audio_attr[i-1].i_foo,
vts.manager_inf.p_audio_attr[i-1].i_bar,
vts.manager_inf.p_audio_attr[i-1].i_appl_mode,
vts.manager_inf.p_audio_attr[i-1].i_quantization,
vts.manager_inf.p_audio_attr[i-1].i_sample_freq,
vts.manager_inf.p_audio_attr[i-1].i_lang_code,
vts.manager_inf.p_audio_attr[i-1].i_caption );
#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 */
i_id = ( ( i_ac3 + i ) << 8 ) | 0xbd;
......@@ -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->b_audio = 1;
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)",
i, p_es->psz_desc, i_id );
......@@ -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->b_audio = 1;
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)",
i, p_es->psz_desc, i_id );
......@@ -645,17 +647,16 @@ static int DVDSetArea( input_thread_t * p_input, input_area_t * p_area )
default:
i_id = 0;
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 */
i_nb = p_dvd->ifo.vts.mat.i_subpic_nb;
b_last = 0;
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 )
{
......@@ -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->b_spu = 1;
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)",
i, p_es->psz_desc, i_id );
/* The before the last spu has a 0x0 prefix */
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
else
{
......@@ -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 );
}
/* 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 */
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 );
#undef vts
#undef vmg
return 0;
}
......@@ -718,8 +742,6 @@ static void DVDInit( input_thread_t * p_input )
thread_dvd_data_t * p_dvd;
int i_title;
int i_chapter;
int i_audio;
int i_spu;
int i;
if( (p_dvd = malloc( sizeof(thread_dvd_data_t) )) == NULL )
......@@ -747,8 +769,13 @@ static void DVDInit( input_thread_t * p_input )
intf_WarnMsg( 2, "dvd info: netlist initialized" );
/* Ifo initialisation */
p_dvd->ifo = IfoInit( p_input->i_handle );
intf_WarnMsg( 2, "ifo info: vmg initialized" );
if( IfoInit( &p_dvd->p_ifo, p_input->i_handle ) < 0 )
{
intf_ErrMsg( "ifo error: fatal failure" );
free( p_dvd );
p_input->b_error = 1;
return;
}
/* CSS initialisation */
if( p_dvd->b_encrypted )
......@@ -758,6 +785,7 @@ static void DVDInit( input_thread_t * p_input )
if( p_dvd->p_css == NULL )
{
intf_ErrMsg( "css error: fatal failure" );
free( p_dvd );
p_input->b_error = 1;
return;
}
......@@ -771,12 +799,12 @@ static void DVDInit( input_thread_t * p_input )
/* Set stream and area data */
vlc_mutex_lock( &p_input->stream.stream_lock );
#define srpt p_dvd->ifo.vmg.ptt_srpt
intf_WarnMsg( 2, "dvd info: number of titles: %d", srpt.i_ttu_nb );
#define title_inf p_dvd->p_ifo->vmg.title_inf
intf_WarnMsg( 2, "dvd info: number of titles: %d", title_inf.i_title_nb );
#define area p_input->stream.pp_areas
/* 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 );
......@@ -790,12 +818,12 @@ static void DVDInit( input_thread_t * p_input )
area[i]->i_size = 0;
/* 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;
/* Offset to vts_i_0.ifo */
area[i]->i_plugin_data = p_dvd->ifo.i_off +
( srpt.p_tts[i-1].i_ssector * DVD_LB_SIZE );
area[i]->i_plugin_data = p_dvd->p_ifo->i_off +
( title_inf.p_attr[i-1].i_start_sector * DVD_LB_SIZE );
}
#undef area
......@@ -803,11 +831,11 @@ static void DVDInit( input_thread_t * p_input )
/* Get requested title - if none try the first title */
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;
}
#undef srpt
#undef title_inf
/* Get requested chapter - if none defaults to first one */
i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 );
if( i_chapter <= 0 )
......@@ -816,28 +844,9 @@ static void DVDInit( input_thread_t * p_input )
}
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 */
i_audio = main_GetIntVariable( INPUT_CHANNEL_VAR, 1 );
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 );
/* set title, chapter, audio and subpic */
DVDSetArea( p_input, p_input->stream.pp_areas[i_title] );
return;
}
......@@ -853,8 +862,12 @@ static void DVDEnd( input_thread_t * p_input )
p_dvd = (thread_dvd_data_t*)p_input->p_plugin_data;
p_netlist = (dvd_netlist_t *)p_input->p_method_data;
CSSEnd( p_dvd->p_css );
// IfoEnd( p_dvd->p_ifo ) );
if( p_dvd->b_encrypted )
{
CSSEnd( p_dvd->p_css );
}
IfoEnd( p_dvd->p_ifo );
free( p_dvd );
DVDNetlistEnd( p_netlist );
}
......@@ -870,7 +883,6 @@ static int DVDRead( input_thread_t * p_input,
{
thread_dvd_data_t * p_dvd;
dvd_netlist_t * p_netlist;
pgc_t * p_pgc;
struct iovec * p_vec;
struct data_packet_s * pp_data[p_input->i_read_once];
u8 * pi_cur;
......@@ -886,7 +898,8 @@ static int DVDRead( input_thread_t * p_input,
p_dvd = (thread_dvd_data_t *)p_input->p_plugin_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 */
if( ( p_vec = DVDGetiovec( p_netlist ) ) == NULL )
......@@ -917,7 +930,7 @@ static int DVDRead( input_thread_t * p_input,
/* update chapter : it will be easier when we have navigation
* 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_chapter++;
......@@ -1042,6 +1055,7 @@ static int DVDRead( input_thread_t * p_input,
{
return 1;
}
#undef title
}
......@@ -1063,14 +1077,14 @@ static int DVDRewind( input_thread_t * p_input )
static void DVDSeek( input_thread_t * p_input, off_t i_off )
{
thread_dvd_data_t * p_dvd;
pgc_t * p_pgc;
off_t i_pos;
int i_prg_cell;
int i_cell;
int i_chapter;
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 */
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 )
i_chapter = 1;
/* 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++;
}
......@@ -1095,9 +1109,9 @@ static void DVDSeek( input_thread_t * p_input, off_t i_off )
DVDFindCell( p_dvd );
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 */
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++;
}
......@@ -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_end_sector = MIN(
p_dvd->ifo.vts.c_adt.p_cell_inf[p_dvd->i_cell].i_esector,
p_pgc->p_cell_play_inf[p_dvd->i_prg_cell].i_lsector );
cell.i_end_sector,
title.p_cell_play[p_dvd->i_prg_cell].i_end_sector );
/* 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++;
}
......
......@@ -2,7 +2,7 @@
* input_dvd.h: thread structure of the DVD plugin
*****************************************************************************
* 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>
*
......@@ -41,6 +41,7 @@ typedef struct thread_dvd_data_s
/* Navigation information */
int i_title;
int i_vts_title;
int i_program_chain;
int i_chapter_nb;
int i_chapter;
......@@ -59,17 +60,16 @@ typedef struct thread_dvd_data_s
struct css_s * p_css;
/* Structure that contains all information of the DVD */
struct ifo_s ifo;
struct ifo_s * p_ifo;
} thread_dvd_data_t;
/*****************************************************************************
* Prototypes in dvd_ifo.c
*****************************************************************************/
struct ifo_s IfoInit ( int );
int IfoReadVTS ( struct ifo_s * );
void IfoRead ( struct ifo_s * );
void IfoEnd ( ifo_t * );
int IfoInit ( struct ifo_s **, int );
int IfoTitleSet ( struct ifo_s * );
void IfoEnd ( struct ifo_s * );
/*****************************************************************************
* Prototypes in dvd_css.c
......
......@@ -2,9 +2,10 @@
* gnome_callbacks.c : Callbacks for the Gnome plugin.
*****************************************************************************
* 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>
* Stphane Borel <stef@via.ecp.fr>
*
* 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
......@@ -244,7 +245,10 @@ on_menubar_audio_toggle (GtkCheckMenuItem *menuitem,
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,
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,
{
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 );
p_intf->p_sys->b_menus_update = 1;
input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
if( menuitem->active && p_intf->p_sys->b_menus_ready )
{
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,
input_area_t * p_area = p_intf->p_input->stream.p_selected_area;
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 );
}
......@@ -558,7 +572,10 @@ on_popup_audio_toggle (GtkCheckMenuItem *menuitem,
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,
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
on_popup_navigation_toggle (GtkCheckMenuItem *menuitem,
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;
gint i_title;
gint i_chapter;
i_title = (gint)(user_data) / 100 ;
i_title = (gint)(user_data) / 100;
i_chapter = (gint)(user_data) - ( 100 * i_title );
if( i_title != p_intf->p_input->stream.p_selected_area->i_id )
......@@ -598,7 +619,7 @@ on_popup_navigation_toggle (GtkCheckMenuItem *menuitem,
p_area->i_part = i_chapter;
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 @@
* intf_gnome.c: Gnome interface
*****************************************************************************
* 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>
* Stphane Borel <stef@via.ecp.fr>
*
* 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
......@@ -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_playlist_changed = 0;
p_intf->p_sys->b_menus_update = 1;
p_intf->p_sys->b_menus_ready = 0;
p_intf->p_sys->b_slider_free = 1;
......@@ -298,7 +300,9 @@ static gint GnomeManage( gpointer p_data )
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_ready = 0;
GnomeSetupMenu( p_intf );
p_intf->p_sys->b_menus_ready = 1;
}
/* Manage the slider */
......@@ -372,12 +376,12 @@ static gint GnomeLanguageMenus( gpointer p_data,
GtkWidget * p_menu;
GtkWidget * p_separator;
GtkWidget * p_item;
GtkWidget * p_item_off;
GtkWidget * p_item_active;
GSList * p_group;
char * psz_name;
gint b_active;
gint b_audio;
gint b_spu;
gint i_item;
gint i;
......@@ -385,32 +389,37 @@ static gint GnomeLanguageMenus( gpointer p_data,
/* cast */
p_intf = (intf_thread_t *)p_data;
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
/* removes previous menu */
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;
/* menu container */
p_menu = gtk_menu_new();
/* special case for "off" item */
b_active = ( p_es == NULL ) ? TRUE : FALSE;
psz_name = "Off";
p_item_off = 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 ) );
gtk_widget_show( p_item_off );
gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_off ),
b_active );
gtk_menu_append( GTK_MENU( p_menu ), p_item_off );
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 ) );
gtk_widget_show( p_item );
/* 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();
gtk_widget_set_sensitive( p_separator, FALSE );
gtk_widget_show( 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 */
for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
......@@ -421,16 +430,24 @@ static gint GnomeLanguageMenus( gpointer p_data,
if( b_audio || b_spu )
{
b_active = ( p_es == p_intf->p_input->stream.pp_es[i] ) ? TRUE :
FALSE;
i_item++;
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_group =
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 );
gtk_menu_append( GTK_MENU( p_menu ), p_item );
if( p_es == p_intf->p_input->stream.pp_es[i] )
{
/* 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 );
/* setup signal hanling */
......@@ -438,21 +455,29 @@ static gint GnomeLanguageMenus( gpointer p_data,
GTK_SIGNAL_FUNC( pf_toggle ),
(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
* if it is before the loop */
gtk_signal_connect( GTK_OBJECT( p_item_off ), "toggled",
GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
/* link the new menu to the menubar item */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
/* be sure that menu is sensitive */
gtk_widget_set_sensitive( p_root, TRUE );
/* acitvation will call signals so we can only do it
* 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;
}
......@@ -466,54 +491,96 @@ static gint GnomeChapterMenu( gpointer p_data, GtkWidget * p_chapter,
intf_thread_t * p_intf;
char psz_name[10];
GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu;
GtkWidget * p_menu_item;
GtkWidget * p_item;
GtkWidget * p_item_selected;
GSList * p_chapter_group;
gint i_title;
gint i_chapter;
gint b_active;
gint i_nb;
/* cast */
p_intf = (intf_thread_t*)p_data;
/* removes previous menu */
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_item_selected = NULL;
p_menu_item = NULL;
i_title = p_intf->p_input->stream.p_selected_area->i_id;
p_chapter_menu = gtk_menu_new();
i_nb = p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
for( i_chapter = 0;
i_chapter < p_intf->p_input->stream.pp_areas[i_title]->i_part_nb ;
i_chapter++ )
for( i_chapter = 0 ; i_chapter < i_nb ; i_chapter++ )
{
b_active = ( p_intf->p_input->stream.pp_areas[i_title]->i_part
== i_chapter + 1 ) ? 1 : 0;
/* we group chapters in packets of ten for small screens */
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 );
p_item = gtk_radio_menu_item_new_with_label( p_chapter_group,
psz_name );
p_chapter_group =
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_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item ),
b_active );
/* setup signal hanling */
gtk_signal_connect( GTK_OBJECT( p_item ),
"toggled",
GTK_SIGNAL_FUNC( pf_toggle ),
(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 */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter ),
p_chapter_menu );
/* be sure that chapter menu is sensitive */
gtk_widget_set_sensitive( p_chapter, TRUE );
/* toggle currently selected chapter */
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;
}
......@@ -532,53 +599,84 @@ static gint GnomeTitleMenu( gpointer p_data,
intf_thread_t * p_intf;
char psz_name[10];
GtkWidget * p_title_menu;
GtkWidget * p_title_submenu;
GtkWidget * p_title_item;
GtkWidget * p_item_active;
GtkWidget * p_chapter_menu;
GtkWidget * p_chapter_submenu;
GtkWidget * p_title_menu_item;
GtkWidget * p_chapter_menu_item;
GtkWidget * p_item;
GSList * p_title_group;
GSList * p_chapter_group;
gint i_title;
gint i_chapter;
gint b_active;
gint i_nb;
/* cast */
p_intf = (intf_thread_t*)p_data;
p_title_menu = gtk_menu_new();
p_title_group = NULL;
p_title_submenu = NULL;
p_title_menu_item = 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 */
for( i_title = 1 ;
i_title < p_intf->p_input->stream.i_area_nb ;
i_title++ )
for( i_title = 1 ; i_title < i_nb ; i_title++ )
{
b_active = ( p_intf->p_input->stream.pp_areas[i_title] ==
p_intf->p_input->stream.p_selected_area ) ? 1 : 0;
sprintf( psz_name, "Title %d", i_title );
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 ) );
gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
gtk_widget_show( p_title_item );
/* we group titles in packets of ten for small screens */
if( ( i_title % 10 == 1 ))// && ( i_nb > 20 ) )
{
if( i_title != 1 )
{
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 );
}
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 )
{
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 */
gtk_signal_connect( GTK_OBJECT( p_title_item ),
"toggled",
GTK_SIGNAL_FUNC( pf_toggle ),
(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
{
p_title_item = gtk_menu_item_new_with_label( psz_name );
p_chapter_menu = gtk_menu_new();
for( i_chapter = 0;
......@@ -586,42 +684,85 @@ static gint GnomeTitleMenu( gpointer p_data,
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
== i_chapter + 1 ) ? 1 : 0;
/* we group chapters in packets of ten for small screens */
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 );
p_item = gtk_radio_menu_item_new_with_label(
p_chapter_group, psz_name );
p_chapter_group = gtk_radio_menu_item_group(
GTK_RADIO_MENU_ITEM( p_item ) );
gtk_menu_append( GTK_MENU( p_chapter_menu ), 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 */
gtk_signal_connect( GTK_OBJECT( p_item ),
"toggled",
GTK_SIGNAL_FUNC( pf_toggle ),
(gpointer)( ( i_title * 100 ) + ( i_chapter + 1) ) );
}
/* link the new menu to the title menu item */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
p_chapter_menu );
}
gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
}
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 */
gtk_widget_set_sensitive( p_title_menu, TRUE );
/* link the new menu to the title menu item */
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 */
gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
/* be sure that menu is sensitive */
gtk_widget_set_sensitive( p_navigation, TRUE );
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 ) );
}
return TRUE;
......@@ -639,20 +780,22 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
GtkWidget * p_popup_menu;
gint i;
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 );
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 );
vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
p_intf->p_sys->p_popup ), "popup_navigation" ) );
if( p_intf->p_input->stream.i_area_nb > 1 )
{
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 */
p_audio_es = NULL;
......@@ -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++ )
{
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 */
/* find audio root menu */
......@@ -681,9 +826,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
p_intf->p_sys->p_popup ), "popup_audio" ) );
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,
on_popup_audio_toggle );
on_popup_audio_toggle );
/* sub picture menus */
......@@ -695,9 +840,9 @@ static gint GnomeSetupMenu( intf_thread_t * p_intf )
p_intf->p_sys->p_popup ), "popup_subtitle" ) );
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,
on_popup_subtitle_toggle );
on_popup_subtitle_toggle );
/* everything is ready */
p_intf->p_sys->b_menus_update = 0;
......
......@@ -2,7 +2,7 @@
* intf_gnome.h: private Gnome interface description
*****************************************************************************
* 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>
*
......@@ -37,7 +37,8 @@ typedef struct intf_sys_s
boolean_t b_window_changed; /* window display toggled ? */
boolean_t b_playlist_changed; /* playlist display toggled ? */
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 */
GtkWidget * p_window; /* main window */
......
......@@ -2,7 +2,7 @@
* input_ext-intf.c: services to the interface
*****************************************************************************
* 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>
*
......@@ -296,3 +296,33 @@ int input_ChangeES( input_thread_t * p_input, es_descriptor_t * p_es,
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 @@
* input_programs.c: es_descriptor_t, pgrm_descriptor_t management
*****************************************************************************
* 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>
*
......@@ -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_tell = 0;
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;
return p_input->stream.pp_areas[i_area_index];
......@@ -368,6 +368,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input,
/* Init its values */
p_es->i_id = i_es_id;
p_es->psz_desc[0] = '\0';
p_es->p_pes = NULL;
p_es->p_decoder_fifo = NULL;
p_es->b_audio = 0;
......@@ -591,6 +592,12 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
decoder_capabilities_t decoder;
void * p_config;
if( p_es == NULL )
{
intf_ErrMsg( "Nothing to do in input_SelectES" );
return -1;
}
#ifdef DEBUG_INPUT
intf_DbgMsg( "Selecting ES 0x%x", p_es->i_id );
#endif
......@@ -683,6 +690,12 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
int i_index = 0;
if( p_es == NULL )
{
intf_ErrMsg( "Nothing to do in input_UnselectES" );
return -1;
}
#ifdef DEBUG_INPUT
intf_DbgMsg( "Unselecting ES 0x%x", p_es->i_id );
#endif
......@@ -693,12 +706,10 @@ int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
return( -1 );
}
/* Release lock, not to block the input thread. */
vlc_mutex_unlock( &p_input->stream.stream_lock );
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--;
......@@ -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.i_selected_es_number
* sizeof(es_descriptor_t *) );
if( p_input->stream.pp_selected_es == NULL )
{
intf_ErrMsg( "Unable to realloc memory in input_UnSelectES" );
return(-1);
intf_ErrMsg( "No more selected ES in input_UnselectES" );
vlc_mutex_unlock( &p_input->stream.stream_lock );
return( 1 );
}
}
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