From: Stéphane Borel Date: Thu, 22 Feb 2001 08:44:45 +0000 (+0000) Subject: -New ES detection based on .ifo for DVD module. It might fail (I have X-Git-Tag: 0.2.70~108 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=17a54d55f3f5b989f217c5377ae85f97eda76e29;p=vlc -New ES detection based on .ifo for DVD module. It might fail (I have found one DVD for which ifo seems false). -Title and chapter selection on the command line (see -t and -T options) It will allow to watch some DVD that went through menus by default. -beginning of menus in gnome interface. --- diff --git a/include/config.h.in b/include/config.h.in index e38845f093..7292c8479d 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -213,6 +213,8 @@ #define INPUT_DVD_DEVICE_VAR "vlc_dvd_device" #define INPUT_DVD_DEVICE_DEFAULT "/dev/dvd" +#define INPUT_TITLE_VAR "vlc_input_title" +#define INPUT_CHAPTER_VAR "vlc_input_chapter" #define INPUT_AUDIO_VAR "vlc_input_audio" #define INPUT_CHANNEL_VAR "vlc_input_channel" #define INPUT_SUBTITLE_VAR "vlc_input_subtitle" diff --git a/include/input.h b/include/input.h index e95ec4c499..655a49782d 100644 --- a/include/input.h +++ b/include/input.h @@ -2,7 +2,7 @@ * input.h: structures of the input not exported to other modules ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: input.h,v 1.30 2001/02/20 02:53:13 stef Exp $ + * $Id: input.h,v 1.31 2001/02/22 08:44:45 stef Exp $ * * Authors: Christophe Massiot * @@ -66,6 +66,7 @@ struct es_descriptor_s * input_AddES ( struct input_thread_s *, size_t ); void input_DelES ( struct input_thread_s *, struct es_descriptor_s * ); int input_SelectES ( struct input_thread_s *, struct es_descriptor_s * ); +int input_UnSelectES( struct input_thread_s *, struct es_descriptor_s * ); /***************************************************************************** * Prototypes from input_dec.c diff --git a/plugins/dvd/dvd_css.c b/plugins/dvd/dvd_css.c index 9b5c3ec220..9da6cd87d6 100644 --- a/plugins/dvd/dvd_css.c +++ b/plugins/dvd/dvd_css.c @@ -2,7 +2,7 @@ * dvd_css.c: Functions for DVD authentification and unscrambling ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: dvd_css.c,v 1.14 2001/02/20 23:30:15 sam Exp $ + * $Id: dvd_css.c,v 1.15 2001/02/22 08:44:45 stef Exp $ * * Author: Stéphane Borel * @@ -1199,7 +1199,7 @@ int CSSGetKey( css_t * p_css ) * produces multiple keys (RT) */ intf_WarnMsg( 3, "CSS: Title %d key: %02X %02X %02X %02X %02X", - i_title + 1, + i_title, p_title_key[i_highest].pi_key[0], p_title_key[i_highest].pi_key[1], p_title_key[i_highest].pi_key[2], diff --git a/plugins/dvd/dvd_ifo.c b/plugins/dvd/dvd_ifo.c index d3996f402e..4f6ecd565f 100644 --- a/plugins/dvd/dvd_ifo.c +++ b/plugins/dvd/dvd_ifo.c @@ -2,7 +2,7 @@ * dvd_ifo.c: Functions for ifo parsing ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: dvd_ifo.c,v 1.13 2001/02/20 07:49:12 sam Exp $ + * $Id: dvd_ifo.c,v 1.14 2001/02/22 08:44:45 stef Exp $ * * Author: Stéphane Borel * @@ -528,6 +528,7 @@ static vobu_admap_t ReadMap( ifo_t* p_ifo ) 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; @@ -561,20 +562,21 @@ static vmgi_mat_t ReadVMGInfMat( ifo_t* p_ifo ) GETL( &mat.i_c_adt_ssector ); GETL( &mat.i_vobu_admap_ssector ); FLUSH( 32 ); - GETS( &mat.i_video_atrt ); +// GETS( &mat.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++ ) { - GETLL( &mat.pi_audio_atrt[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++ ) { - GET( &mat.pi_subpic_atrt[i], 6 ); + GET( &i_temp, 6 ); /* FIXME : take care of endianness */ } @@ -685,6 +687,7 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) { vmg_vts_atrt_t atrt; int i, j; + u64 i_temp; off_t i_start = p_ifo->i_pos; //fprintf( stderr, "VTS ATTR\n" ); @@ -718,37 +721,39 @@ static vmg_vts_atrt_t ReadVTSAttr( ifo_t* p_ifo ) 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].i_vtsm_video_atrt ); +// 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( &atrt.p_vts_atrt[i].pi_vtsm_audio_atrt[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( &atrt.p_vts_atrt[i].pi_vtsm_subpic_atrt[j], 6 ); + GET( &i_temp, 6 ); /* FIXME : Fix endianness issue here */ } FLUSH( 2 ); - GETS( &atrt.p_vts_atrt[i].i_vtstt_video_atrt ); +// GETS( &atrt.p_vts_atrt[i].vtstt_video_atrt ); +FLUSH(2); FLUSH( 1 ); GETL( &atrt.p_vts_atrt[i].i_vtstt_audio_nb ); //fprintf( stderr, "tt audio nb : %d\n", atrt.p_vts_atrt[i].i_vtstt_audio_nb ); for( j=0 ; j<8 ; j++ ) { - GETLL( &atrt.p_vts_atrt[i].pi_vtstt_audio_atrt[j] ); + 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( &atrt.p_vts_atrt[i].pi_vtstt_subpic_atrt[j], 6 ); + GET( &i_temp, 6 ); /* FIXME : Fix endianness issue here */ } } @@ -825,6 +830,7 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) { vtsi_mat_t mat; int i; + u64 i_temp; // off_t i_start = p_ifo->i_pos; //fprintf( stderr, "VTSI\n" ); @@ -851,36 +857,61 @@ static vtsi_mat_t ReadVTSInfMat( ifo_t* p_ifo ) GETL( &mat.i_c_adt_ssector ); GETL( &mat.i_vobu_admap_ssector ); FLUSH( 24 ); - GETS( &mat.i_m_video_atrt ); +// GETS( &mat.m_video_atrt ); +FLUSH(2); FLUSH( 1 ); GETC( &mat.i_m_audio_nb ); for( i=0 ; i<8 ; i++ ) { - GETLL( &mat.pi_m_audio_atrt[i] ); + GETLL( &i_temp ); } FLUSH( 17 ); GETC( &mat.i_m_subpic_nb ); for( i=0 ; i<28 ; i++ ) { - GET( &mat.pi_m_subpic_atrt[i], 6 ); + GET( &i_temp, 6 ); /* FIXME : take care of endianness */ } FLUSH( 2 ); - GETS( &mat.i_video_atrt ); +// 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++ ) { - GETLL( &mat.pi_audio_atrt[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; } FLUSH( 17 ); GETC( &mat.i_subpic_nb ); //fprintf( stderr, "vtsi subpic nb : %d\n", mat.i_subpic_nb ); for( i=0 ; i> 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; } return mat; @@ -999,7 +1030,8 @@ int IfoReadVTS( ifo_t* p_ifo ) 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].i_ssector ) *DVD_LB_SIZE + i_off = (off_t)( p_ifo->vmg.ptt_srpt.p_tts[i_title-1].i_ssector ) + * DVD_LB_SIZE + p_ifo->i_off; p_ifo->i_pos = lseek( p_ifo->i_fd, i_off, SEEK_SET ); diff --git a/plugins/dvd/dvd_ifo.h b/plugins/dvd/dvd_ifo.h index 9d3da34053..58e1ed6e27 100644 --- a/plugins/dvd/dvd_ifo.h +++ b/plugins/dvd/dvd_ifo.h @@ -2,7 +2,7 @@ * dvd_ifo.h: Structures for ifo parsing ***************************************************************************** * Copyright (C) 1999-2001 VideoLAN - * $Id: dvd_ifo.h,v 1.7 2001/02/20 02:53:13 stef Exp $ + * $Id: dvd_ifo.h,v 1.8 2001/02/22 08:44:45 stef Exp $ * * Author: Stéphane Borel * @@ -33,6 +33,47 @@ /* * Program Chain structures */ +typedef struct ifo_video_s +{ + u8 i_compression ;// 2; + u8 i_system ;// 2; + u8 i_ratio ;// 2; + u8 i_perm_displ ;// 2; + + u8 i_line21_1 ;// 1; + u8 i_line21_2 ;// 1; + u8 i_source_res ;// 2; + u8 i_letterboxed ;// 1; + u8 i_mode ;// 1; +} ifo_video_t; + +/* Audio type information */ +typedef struct ifo_audio_s +{ + u8 i_coding_mode ;// 3; + u8 i_multichannel_extension ;// 1; + u8 i_type ;// 2; + u8 i_appl_mode ;// 2; + + u8 i_quantization ;// 2; + u8 i_sample_freq ;// 2; +// u8 ;// 1; + u8 i_num_channels ;// 3; + u16 i_lang_code ;// 16; // description + u8 i_foo ;// 8; // 0x00000000 ? + u8 i_caption ;// 8; + u8 i_bar ;// 8; // 0x00000000 ? +} ifo_audio_t; + +typedef struct ifo_spu_t +{ + u16 i_prefix ;// 16; // 0x0100 ? + u16 i_lang_code ;// 16; // description + u8 i_foo ;// 8; // dont know + u8 i_caption ;// 8; // 0x00 ? +} ifo_spu_t; + + /* Ifo vitual machine Commands */ typedef struct ifo_command_s @@ -241,13 +282,13 @@ typedef struct vmgi_mat_s u32 i_c_adt_ssector; // 4 bytes u32 i_vobu_admap_ssector; // 4 bytes // char[2] ??? - u16 i_video_atrt; // 2 bytes + ifo_video_t video_atrt; // 2 bytes // char ??? u8 i_audio_nb; // 1 byte - u64 pi_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes + ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes // char[16] ??? u8 i_subpic_nb; // 1 byte - u64 pi_subpic_atrt[32]; // i_subpic_nb * 6 bytes + ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes } vmgi_mat_t; @@ -315,21 +356,21 @@ typedef struct vts_atrt_s { u32 i_ebyte; // 4 bytes u32 i_cat_app_type; // 4 bytes - u16 i_vtsm_video_atrt; // 2 bytes + ifo_video_t vtsm_video_atrt; // 2 bytes // char ??? u8 i_vtsm_audio_nb; // 1 byte - u64 pi_vtsm_audio_atrt[8]; // 8 * 8 bytes + ifo_audio_t p_vtsm_audio_atrt[8]; // 8 * 8 bytes // char[17] ??? u8 i_vtsm_subpic_nb; // 1 byte - u64 pi_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes + ifo_spu_t p_vtsm_subpic_atrt[28]; // i_vtsm_subpic_nb * 6 bytes // char[2] ??? - u16 i_vtstt_video_atrt; // 2 bytes + ifo_video_t vtstt_video_atrt; // 2 bytes // char ??? u8 i_vtstt_audio_nb; // 1 byte - u64 pi_vtstt_audio_atrt[8]; // 8 * 8 bytes + ifo_audio_t p_vtstt_audio_atrt[8]; // 8 * 8 bytes // char[17] ??? u8 i_vtstt_subpic_nb; // 1 byte - u64 pi_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes + ifo_spu_t p_vtstt_subpic_atrt[28]; // i_vtstt_subpic_nb * 6 bytes } vts_atrt_t; /* Main struct for vts attributes @@ -388,22 +429,22 @@ typedef struct vtsi_mat_s u32 i_c_adt_ssector; // 4 bytes u32 i_vobu_admap_ssector; // 4 bytes // char[24] ??? - u16 i_m_video_atrt; // 2 bytes + ifo_video_t m_video_atrt; // 2 bytes // char ??? u8 i_m_audio_nb; // 1 byte - u64 pi_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes + ifo_audio_t p_m_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes // char[16] ??? u8 i_m_subpic_nb; // 1 byte - u64 pi_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes + ifo_spu_t p_m_subpic_atrt[32]; // i_subpic_nb * 6 bytes // !!! only 28 subpics ??? // char[2] ??? - u16 i_video_atrt; // 2 bytes + ifo_video_t video_atrt; // 2 bytes // char ??? u8 i_audio_nb; // 1 byte - u64 pi_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes + ifo_audio_t p_audio_atrt[8]; // i_vmgm_audio_nb * 8 bytes // char[16] ??? u8 i_subpic_nb; // 1 byte - u64 pi_subpic_atrt[32]; // i_subpic_nb * 6 bytes + ifo_spu_t p_subpic_atrt[32]; // i_subpic_nb * 6 bytes } vtsi_mat_t; /* diff --git a/plugins/dvd/input_dvd.c b/plugins/dvd/input_dvd.c index 64d7f8907a..ff7ae20d88 100644 --- a/plugins/dvd/input_dvd.c +++ b/plugins/dvd/input_dvd.c @@ -10,7 +10,7 @@ * -dvd_udf to find files ***************************************************************************** * Copyright (C) 1998-2001 VideoLAN - * $Id: input_dvd.c,v 1.18 2001/02/20 23:30:15 sam Exp $ + * $Id: input_dvd.c,v 1.19 2001/02/22 08:44:45 stef Exp $ * * Author: Stéphane Borel * @@ -278,11 +278,12 @@ void _M( input_getfunctions )( function_list_t * p_function_list ) /***************************************************************************** * Language: gives the long language name from the two-letters ISO-639 code *****************************************************************************/ -static char * Language( char * p_code ) +static char * Language( u16 i_code ) { int i = 0; - while( !memcmp( lang_tbl[i].p_code, p_code, 2 ) && lang_tbl[i].p_lang_long ) + while( memcmp( lang_tbl[i].p_code, &i_code, 2 ) && + lang_tbl[i].p_lang_long[0] ) { i++; } @@ -336,291 +337,316 @@ static int DVDCheckCSS( input_thread_t * p_input ) } /***************************************************************************** - * DVDSetArea: initialize input data for title x, chapter y. - * It should be called for each user navigation request, and to change - * audio or sub-picture streams. - * --- - * Take care that i_title and i_chapter start from 0. + * DVDChapterSelect: find the cell corresponding to requested chapter *****************************************************************************/ -static int DVDSetArea( input_thread_t * p_input, - int i_title, int i_chapter, - int i_audio, int i_spu ) +static int DVDChapterSelect( thread_dvd_data_t * p_dvd, int i_chapter ) { - thread_dvd_data_t * p_method; -// es_descriptor_t * p_es; - off_t i_start; - off_t i_size; pgc_t * p_pgc; int i_start_cell; int i_end_cell; int i_index; int i_cell; -// int i_nb; -// int i_id; -// int i; - - p_method = (thread_dvd_data_t*)p_input->p_plugin_data; - /* Ifo structures reading */ - p_method->ifo.i_title = i_title; - IfoReadVTS( &(p_method->ifo) ); - intf_WarnMsg( 2, "Ifo: VTS initialized" ); + p_pgc = &p_dvd->ifo.vts.pgci_ti.p_srp[0].pgc; - if( p_method->b_encrypted ) - { - p_method->css.i_title = i_title; - p_method->css.i_title_pos = - p_method->ifo.vts.i_pos + - p_method->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE; - CSSGetKey( &(p_method->css) ); - intf_WarnMsg( 2, "CSS: VTS key initialized" ); - } - - /* Set selected title start and size */ - p_pgc = &p_method->ifo.vts.pgci_ti.p_srp[0].pgc; - - /* Find cell index in Program chain */ - i_index = p_pgc->prg_map.pi_entry_cell[i_chapter] - 1; + /* Find cell index in Program chain for current chapter */ + i_index = p_pgc->prg_map.pi_entry_cell[i_chapter-1] - 1; /* Search for cell_index in cell adress_table */ i_cell = 0; while( p_pgc->p_cell_pos_inf[i_index].i_vob_id > - p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id ) + p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_vob_id ) { i_cell++; } while( p_pgc->p_cell_pos_inf[i_index].i_cell_id > - p_method->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id ) + p_dvd->ifo.vts.c_adt.p_cell_inf[i_cell].i_cell_id ) { i_cell++; } - i_start_cell = i_cell; - i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1; - - intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d", - i_start_cell, i_end_cell ); - p_method->i_start_cell = i_start_cell; - p_method->i_end_cell = i_end_cell; + i_start_cell = i_cell; - /* start is : beginning of vts + offset to vobs + offset to vob x */ - i_start = p_method->ifo.vts.i_pos + DVD_LB_SIZE * - ( p_method->ifo.vts.mat.i_tt_vobs_ssector + - p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector ); + p_dvd->i_start = p_dvd->ifo.vts.i_pos + DVD_LB_SIZE * + (off_t)( p_dvd->ifo.vts.mat.i_tt_vobs_ssector + + p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector ); - i_start = lseek( p_input->i_handle, i_start, SEEK_SET ); - intf_WarnMsg( 2, "DVD: VOBstart at: %lld", i_start ); + if( i_chapter == 1 ) + { + i_end_cell = i_start_cell + p_pgc->i_cell_nb - 1; + p_dvd->i_size = (off_t)DVD_LB_SIZE * + ( p_dvd->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector - + p_dvd->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 ); + p_dvd->i_chapter_nb = p_pgc->i_cell_nb; + intf_WarnMsg( 3, "DVD: Start cell: %d End Cell: %d", + i_start_cell, i_end_cell ); + } - i_size = (off_t) - ( p_method->ifo.vts.c_adt.p_cell_inf[i_end_cell].i_esector - - p_method->ifo.vts.c_adt.p_cell_inf[i_start_cell].i_ssector + 1 ) - *DVD_LB_SIZE; - intf_WarnMsg( 2, "DVD: stream size: %lld", i_size ); + return 0; +} -#if 0 - p_es = NULL; +/***************************************************************************** + * DVDSetArea: initialize input data for title x, chapter y. + * It should be called for each user navigation request, and to change + * audio or sub-picture streams. + * --- + * Take care that i_title starts from 0 (vmg) and i_chapter start from 1. + * i_audio, i_spu start from 1 ; 0 means off. + * A negative value for an argument means it does not change + *****************************************************************************/ +static int DVDSetArea( input_thread_t * p_input, + int i_title, int i_chapter, + int i_audio, int i_spu ) +{ + thread_dvd_data_t * p_method; + es_descriptor_t * p_es; + int i_index; + int i_nb; + u16 i_id; + u8 i_ac3; + u8 i_mpeg; + u8 i_sub_pic; + u8 i; + boolean_t b_last; + + p_method = (thread_dvd_data_t*)p_input->p_plugin_data; vlc_mutex_lock( &p_input->stream.stream_lock ); - /* ES 0 -> video MPEG2 */ - intf_WarnMsg( 1, "DVD: Video MPEG2 stream" ); - p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 ); - p_es->i_stream_id = 0xe0; - p_es->i_type = MPEG2_VIDEO_ES; - input_SelectES( p_input, p_es ); - - /* Audio ES, in the order they appear in .ifo */ - i_nb = p_method->ifo.vts.mat.i_audio_nb; - intf_WarnMsg( 1, "DVD: Audio streams %d", i_nb ); - for( i = 0 ; i < i_nb ; i++ ) + if( i_title >= 0 ) { - i_id = ( ( 0x80 + i ) << 8 ) | 0xbd; - p_es = input_AddES( p_input, - p_input->stream.pp_programs[0], i_id, 0 ); - p_es->i_stream_id = 0xbd; - p_es->i_type = AC3_AUDIO_ES; - p_es->b_audio = 1; -// p_es->psz_desc = p_method->ifo.vts.mat.pi_audio_attr[i]; - if( i == 0 ) + /* + * We have to load all title information + */ + + /* Change the default area */ + p_input->stream.p_selected_area = p_input->stream.pp_areas[i_title]; + + /* Ifo VTS, and CSS reading */ + p_method->ifo.i_title = i_title; + IfoReadVTS( &(p_method->ifo) ); + intf_WarnMsg( 2, "Ifo: VTS initialized" ); + + if( p_method->b_encrypted ) { - input_SelectES( p_input, p_es ); + p_method->css.i_title = i_title; + p_method->css.i_title_pos = + p_method->ifo.vts.i_pos + + p_method->ifo.vts.mat.i_tt_vobs_ssector * DVD_LB_SIZE; + CSSGetKey( &(p_method->css) ); + intf_WarnMsg( 2, "CSS: VTS key initialized" ); } - } - - /* Sub Picture ES */ - i_nb = p_method->ifo.vts.mat.i_subpic_nb; - intf_WarnMsg( 1, "DVD: Subpic streams %d", i_nb ); - for( i = 0 ; i < i_nb ; i++ ) - { - i_id = ( ( 0x20 + i ) << 8 ) | 0xbd; - p_es = input_AddES( p_input, - p_input->stream.pp_programs[0], i_id, 0 ); - p_es->i_stream_id = 0xbd; - p_es->i_type = DVD_SPU_ES; -// p_es->psz_desc = p_method->ifo.vts.mat.pi_subpic_attr[i]; - if( i == 12 ) + + /* + * Set selected title start and size + */ + DVDChapterSelect( p_method, 1 ); + + /* start is : beginning of vts + offset to vobs + offset to vob x */ + + p_method->i_start = + lseek( p_input->i_handle, p_method->i_start, SEEK_SET ); + + intf_WarnMsg( 2, "DVD: vobstart at: %lld", p_method->i_start ); + intf_WarnMsg( 2, "DVD: stream size: %lld", p_method->i_size ); + intf_WarnMsg( 2, "DVD: number of chapters: %lld", + p_method->i_chapter_nb ); + + /* Area definition */ + p_input->stream.p_selected_area->i_start = p_method->i_start; + p_input->stream.p_selected_area->i_size = p_method->i_size; + p_input->stream.p_selected_area->i_part_nb = p_method->i_chapter_nb; + + /* + * Destroy obsolete ES by reinitializing program 0 + * and find all ES in title with ifo data + */ + if( p_input->stream.pp_programs != NULL ) { - input_SelectES( p_input, p_es ); + input_DelProgram( p_input, p_input->stream.pp_programs[0] ); } - } - - /* area definition */ - p_input->stream.pp_areas[i_title]->i_start = i_start; - p_input->stream.pp_areas[i_title]->i_size = i_size; - - /* No PSM to read in DVD mode */ - p_input->stream.pp_programs[0]->b_is_ok = 1; + input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); - /* Init has been successfull ; change the default area */ - p_input->stream.p_selected_area = p_input->stream.pp_areas[i_title]; + p_es = NULL; - vlc_mutex_unlock( &p_input->stream.stream_lock ); + /* ES 0 -> video MPEG2 */ + p_es = input_AddES( p_input, p_input->stream.pp_programs[0], 0xe0, 0 ); + p_es->i_stream_id = 0xe0; + p_es->i_type = MPEG2_VIDEO_ES; + input_SelectES( p_input, p_es ); + intf_WarnMsg( 1, "DVD: Video MPEG2 stream" ); + + /* Audio ES, in the order they appear in .ifo */ + i_nb = p_method->ifo.vts.mat.i_audio_nb; + + i_ac3 = 0x80; + i_mpeg = 0xc0; -#else - p_input->stream.p_selected_area = p_input->stream.pp_areas[0]; + for( i = 1 ; i <= i_nb ; i++ ) + { - if( p_input->stream.b_seekable ) - { - stream_ps_data_t * p_demux_data = - (stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data; +#if 0 + fprintf( stderr, "Audio %d: %x %x %x %x %x %x\n", i, + p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode, + p_method->ifo.vts.mat.p_audio_atrt[i].i_multichannel_extension, + p_method->ifo.vts.mat.p_audio_atrt[i].i_type, + p_method->ifo.vts.mat.p_audio_atrt[i].i_appl_mode, + p_method->ifo.vts.mat.p_audio_atrt[i].i_foo, + p_method->ifo.vts.mat.p_audio_atrt[i].i_bar ); +#endif - /* Pre-parse the stream to gather stream_descriptor_t. */ - p_input->stream.pp_programs[0]->b_is_ok = 0; - p_demux_data->i_PSM_version = EMPTY_PSM_VERSION; + switch( p_method->ifo.vts.mat.p_audio_atrt[i].i_coding_mode ) + { + case 0x00: /* AC3 */ + i_id = ( ( 0x7f + i ) << 8 ) | 0xbd; + p_es = input_AddES( p_input, + p_input->stream.pp_programs[0], i_id, 0 ); + p_es->i_stream_id = 0xbd; + p_es->i_type = AC3_AUDIO_ES; + p_es->b_audio = 1; + strcpy( p_es->psz_desc, Language( hton16( + p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) ); - while( !p_input->b_die && !p_input->b_error - && !p_demux_data->b_has_PSM ) - { - int i_result, i; - data_packet_t * pp_packets[INPUT_READ_ONCE]; + break; + case 0x02: + case 0x03: /* MPEG audio */ + i_id = 0xbf + i; + p_es = input_AddES( p_input, + p_input->stream.pp_programs[0], i_id, 0 ); + p_es->i_stream_id = i_id; + p_es->i_type = MPEG2_AUDIO_ES; + p_es->b_audio = 1; + strcpy( p_es->psz_desc, Language( hton16( + p_method->ifo.vts.mat.p_audio_atrt[i-1].i_lang_code ) ) ); - i_result = DVDRead( p_input, pp_packets ); - if( i_result == 1 ) - { - /* EOF */ - vlc_mutex_lock( &p_input->stream.stream_lock ); - p_input->stream.pp_programs[0]->b_is_ok = 1; - vlc_mutex_unlock( &p_input->stream.stream_lock ); break; - } - if( i_result == -1 ) - { - p_input->b_error = 1; + case 0x04: /* LPCM */ + i_id = 0; + intf_ErrMsg( "DVD: LPCM audio not handled yet" ); + break; + case 0x06: /* DTS */ + i_id = 0; + intf_ErrMsg( "DVD: DTS audio not handled yet" ); break; + default: + i_id = 0; + intf_ErrMsg( "DVD: unkown audio" ); } - - for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ ) + + intf_WarnMsg( 1, "DVD: Audio stream %d %s\t(0x%x)", + i, p_es->psz_desc, i_id ); + } + + /* Sub Picture ES */ + i_nb = p_method->ifo.vts.mat.i_subpic_nb; + + b_last = 0; + i_sub_pic = 0x20; + for( i = 1 ; i <= i_nb ; i++ ) + { + if( !b_last ) { - /* FIXME: use i_p_config_t */ - input_ParsePS( p_input, pp_packets[i] ); - input_NetlistDeletePacket( p_input->p_method_data, - pp_packets[i] ); + i_id = ( i_sub_pic++ << 8 ) | 0xbd; + p_es = input_AddES( p_input, + p_input->stream.pp_programs[0], i_id, 0 ); + p_es->i_stream_id = 0xbd; + p_es->i_type = DVD_SPU_ES; + strcpy( p_es->psz_desc, Language( hton16( + p_method->ifo.vts.mat.p_subpic_atrt[i-1].i_lang_code ) ) ); + intf_WarnMsg( 1, "DVD: 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_method->ifo.vts.mat.p_subpic_atrt[i].i_prefix == 0 ); } + } + + } // i_title >= 0 - /* File too big. */ - if( p_input->stream.p_selected_area->i_tell > - INPUT_PREPARSE_LENGTH ) + /* + * Select requested ES + */ + if( ( i_audio >= 0 ) || ( i_title >= 0 ) ) + { + + /* Audio: we check it is in the range and + * default it to the first if not */ + if( i_audio > p_method->ifo.vts.mat.i_audio_nb ) + { + i_audio = 1; + } + + p_es = p_input->stream.pp_programs[0]->pp_es[i_audio]; + + /* We can only have one audio channel */ + /* Look for a preselected one */ + i_index = -1; + for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ ) + { + if( p_input->stream.pp_selected_es[i]->b_audio ) { + i_index = i; break; } } - lseek( p_input->i_handle, i_start, SEEK_SET ); - vlc_mutex_lock( &p_input->stream.stream_lock ); - /* i_tell is an indicator from the beginning of the stream, - * not of the DVD */ - p_input->stream.p_selected_area->i_tell = 0; - - if( p_demux_data->b_has_PSM ) + if( i_index != -1 ) { - /* (The PSM decoder will care about spawning the decoders) */ - p_input->stream.pp_programs[0]->b_is_ok = 1; + + if( p_input->stream.pp_selected_es[i_index] != p_es ) + { + input_UnSelectES( p_input, + p_input->stream.pp_selected_es[i_index] ); + input_SelectES( p_input, p_es ); + intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)", + i_audio, p_es->psz_desc, p_es->i_id ); + } } -#ifdef AUTO_SPAWN else { - /* (We have to do it ourselves) */ - int i_es; - - /* FIXME: we should do multiple passes in case an audio type - * is not present */ - for( i_es = 0; - i_es < p_input->stream.pp_programs[0]->i_es_number; - i_es++ ) - { -#define p_es p_input->stream.pp_programs[0]->pp_es[i_es] - switch( p_es->i_type ) - { - case MPEG1_VIDEO_ES: - case MPEG2_VIDEO_ES: - input_SelectES( p_input, p_es ); - break; - - case MPEG1_AUDIO_ES: - case MPEG2_AUDIO_ES: - if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 ) - == (p_es->i_id & 0x1F) ) - switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) ) - { - case 0: - main_PutIntVariable( INPUT_AUDIO_VAR, - REQUESTED_MPEG ); - case REQUESTED_MPEG: - input_SelectES( p_input, p_es ); - } - break; - - case AC3_AUDIO_ES: - if( main_GetIntVariable( INPUT_CHANNEL_VAR, 0 ) - == ((p_es->i_id & 0xF00) >> 8) ) - switch( main_GetIntVariable( INPUT_AUDIO_VAR, 0 ) ) - { - case 0: - main_PutIntVariable( INPUT_AUDIO_VAR, - REQUESTED_AC3 ); - case REQUESTED_AC3: - input_SelectES( p_input, p_es ); - } - break; - - case DVD_SPU_ES: - if( main_GetIntVariable( INPUT_SUBTITLE_VAR, -1 ) - == ((p_es->i_id & 0x1F00) >> 8) ) - { - input_SelectES( p_input, p_es ); - } - break; - - case LPCM_AUDIO_ES: - /* FIXME ! */ - break; - } - } - + input_SelectES( p_input, p_es ); + intf_WarnMsg( 1, "DVD: Audio %d selected -> %s (0x%x)", + i_audio, p_es->psz_desc, p_es->i_id ); } -#endif -#ifdef STATS - input_DumpStream( p_input ); -#endif - - /* FIXME : ugly kludge */ - p_input->stream.p_selected_area->i_size = i_size; + } - vlc_mutex_unlock( &p_input->stream.stream_lock ); + if( ( i_spu >= 0 ) || ( i_title >= 0 ) ) + { + /* For spu: no one if none or a not existed one requested */ + if( ( i_spu <= p_method->ifo.vts.mat.i_subpic_nb ) && ( i_spu > 0 ) ) + { + input_SelectES( p_input, ( p_es = p_input->stream.pp_programs[0]-> + pp_es[ i_spu + p_method->ifo.vts.mat.i_audio_nb ] ) ); + + intf_WarnMsg( 1, "DVD: SPU %d selected -> %s (0x%x)", + i_spu, p_es->psz_desc, p_es->i_id ); + } } - else + + /* + * Chapter selection + */ + + if( ( i_chapter > 0 ) && + ( i_chapter <= p_input->stream.p_selected_area->i_part_nb ) ) { - /* The programs will be added when we read them. */ - vlc_mutex_lock( &p_input->stream.stream_lock ); - p_input->stream.pp_programs[0]->b_is_ok = 0; + DVDChapterSelect( p_method, i_chapter ); + + p_input->stream.p_selected_area->i_part = i_chapter; - /* FIXME : ugly kludge */ - p_input->stream.p_selected_area->i_size = i_size; + DVDSeek( p_input, p_method->i_start - + p_input->stream.p_selected_area->i_start ); - vlc_mutex_unlock( &p_input->stream.stream_lock ); + intf_WarnMsg( 2, "DVD: Chapter %d start at: %lld", i_chapter, + p_input->stream.p_selected_area->i_tell ); } -#endif + + /* No PSM to read in DVD mode, we already have all information */ + p_input->stream.pp_programs[0]->b_is_ok = 1; + + vlc_mutex_unlock( &p_input->stream.stream_lock ); return 0; } @@ -631,6 +657,10 @@ static int DVDSetArea( input_thread_t * p_input, static void DVDInit( input_thread_t * p_input ) { thread_dvd_data_t * p_method; + int i_title; + int i_chapter; + int i_audio; + int i_spu; int i; if( (p_method = malloc( sizeof(thread_dvd_data_t) )) == NULL ) @@ -674,7 +704,6 @@ static void DVDInit( input_thread_t * p_input ) /* Initialize ES structures */ input_InitStream( p_input, sizeof( stream_ps_data_t ) ); - input_AddProgram( p_input, 0, sizeof( stream_ps_data_t ) ); /* Set stream and area data */ vlc_mutex_lock( &p_input->stream.stream_lock ); @@ -682,9 +711,12 @@ static void DVDInit( input_thread_t * p_input ) /* FIXME: We consider here that one title is one title set * it is not true !!! */ + intf_WarnMsg( 2, "DVD: Number of titles: %d\n", + p_method->ifo.vmg.mat.i_tts_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 < p_method->ifo.vmg.mat.i_tts_nb ; i++ ) + for( i = 1 ; i <= p_method->ifo.vmg.mat.i_tts_nb ; i++ ) { input_AddArea( p_input ); @@ -709,10 +741,32 @@ static void DVDInit( input_thread_t * p_input ) vlc_mutex_unlock( &p_input->stream.stream_lock ); - /* By default, set all parameters to 0 */ - /* FIXME: wrong kludge to get first title number */ - DVDSetArea( p_input, p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb - 1, - 0, 0, 0 ); + /* Get requested title - if none try to find one where is the movie */ + i_title = main_GetIntVariable( INPUT_TITLE_VAR, + p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb ); + if( i_title <= 0 || i_title >= p_method->ifo.vmg.mat.i_tts_nb ) + { + i_title = p_method->ifo.vmg.ptt_srpt.p_tts[0].i_tts_nb; + } + + /* Get requested chapter - if none defaults to first one */ + i_chapter = main_GetIntVariable( INPUT_CHAPTER_VAR, 1 ); + if( i_chapter <= 0 ) + { + i_chapter = 1; + } + + /* 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; + } + + i_spu = main_GetIntVariable( INPUT_SUBTITLE_VAR, 0 ); + + DVDSetArea( p_input, i_title, i_chapter, i_audio, i_spu ); return; } @@ -739,102 +793,120 @@ static void DVDEnd( input_thread_t * p_input ) static int DVDRead( input_thread_t * p_input, data_packet_t ** pp_packets ) { - thread_dvd_data_t * p_method; - netlist_t * p_netlist; - struct iovec * p_vec; - struct data_packet_s * p_data; - u8 * pi_cur; - int i_packet_size; - int i_packet; - int i_pos; - int i; - boolean_t b_first_packet; - - p_method = ( thread_dvd_data_t * ) p_input->p_plugin_data; - p_netlist = ( netlist_t * ) p_input->p_method_data; - - /* Get an iovec pointer */ - if( ( p_vec = input_NetlistGetiovec( p_netlist ) ) == NULL ) - { - intf_ErrMsg( "DVD: read error" ); - return -1; - } + byte_t p_header[6]; + data_packet_t * p_data; + size_t i_packet_size; + int i_packet, i_error; + thread_dvd_data_t * p_method; - /* Reads from DVD */ - readv( p_input->i_handle, p_vec, p_method->i_read_once ); + p_method = (thread_dvd_data_t *)p_input->p_plugin_data; - if( p_method->b_encrypted ) + memset( pp_packets, 0, INPUT_READ_ONCE * sizeof(data_packet_t *) ); + for( i_packet = 0; i_packet < INPUT_READ_ONCE; i_packet++ ) { - for( i=0 ; ii_read_once ; i++ ) + /* Read what we believe to be a packet header. */ + if( (i_error = SafeRead( p_input, p_header, 6 )) ) { - CSSDescrambleSector( p_method->css.pi_title_key, - p_vec[i].iov_base ); - ((u8*)(p_vec[i].iov_base))[0x14] &= 0x8F; + return( i_error ); } - } - /* Update netlist indexes */ - input_NetlistMviovec( p_netlist, p_method->i_read_once, &p_data ); - - i_packet = 0; - /* Read headers to compute payload length */ - for( i = 0 ; i < p_method->i_read_once ; i++ ) - { - i_pos = 0; - b_first_packet = 1; - while( i_pos < p_netlist->i_buffer_size ) + if( (U32_AT(p_header) & 0xFFFFFF00) != 0x100L ) { - pi_cur = (u8*)(p_vec[i].iov_base + i_pos); - /*default header */ - if( U32_AT( pi_cur ) != 0x1BA ) + /* This is not the startcode of a packet. Read the stream + * until we find one. */ + u32 i_startcode = U32_AT(p_header); + int i_nb; + byte_t i_dummy; + + if( i_startcode ) { - /* That's the case for all packets, except pack header. */ - i_packet_size = U16_AT( pi_cur + 4 ); + /* It is common for MPEG-1 streams to pad with zeros + * (although it is forbidden by the recommendation), so + * don't bother everybody in this case. */ + intf_WarnMsg( 1, "Garbage at input (%x)", i_startcode ); } - else + + while( (i_startcode & 0xFFFFFF00) != 0x100L ) { - /* Pack header. */ - if( ( pi_cur[4] & 0xC0 ) == 0x40 ) - { - /* MPEG-2 */ - i_packet_size = 8; - } - else if( ( pi_cur[4] & 0xF0 ) == 0x20 ) + i_startcode <<= 8; + if( (i_nb = SafeRead( p_input, &i_dummy, 1 )) != 0 ) { - /* MPEG-1 */ - i_packet_size = 6; + i_startcode |= i_dummy; } else { - intf_ErrMsg( "Unable to determine stream type" ); - return( -1 ); + return( 1 ); } } - if( b_first_packet ) + + /* Packet found. */ + *(u32 *)p_header = U32_AT(&i_startcode); + if( (i_error = SafeRead( p_input, p_header + 4, 2 )) ) + { + return( i_error ); + } + } + + if( U32_AT(p_header) != 0x1BA ) + { + /* That's the case for all packets, except pack header. */ + i_packet_size = U16_AT(&p_header[4]); + } + else + { + /* Pack header. */ + if( (p_header[4] & 0xC0) == 0x40 ) { - p_data->b_discard_payload = 0; - b_first_packet = 0; + /* MPEG-2 */ + i_packet_size = 8; + } + else if( (p_header[4] & 0xF0) == 0x20 ) + { + /* MPEG-1 */ + i_packet_size = 6; } else - { - p_data = input_NetlistNewPacket( p_netlist , - i_packet_size + 6 ); - memcpy( p_data->p_buffer, - p_vec[i].iov_base + i_pos , i_packet_size + 6 ); + { + intf_ErrMsg( "Unable to determine stream type" ); + return( -1 ); } + } - p_data->p_payload_end = p_data->p_payload_start + i_packet_size + 6; - pp_packets[i_packet] = p_data; - i_packet++; - i_pos += i_packet_size + 6; + /* Fetch a packet of the appropriate size. */ + if( (p_data = NewPacket( p_input, i_packet_size + 6 )) == NULL ) + { + intf_ErrMsg( "Out of memory" ); + return( -1 ); } - } - pp_packets[i_packet] = NULL; - vlc_mutex_lock( &p_input->stream.stream_lock ); - p_input->stream.p_selected_area->i_tell += - p_method->i_read_once *DVD_LB_SIZE; - vlc_mutex_unlock( &p_input->stream.stream_lock ); + /* Copy the header we already read. */ + memcpy( p_data->p_buffer, p_header, 6 ); + + /* Read the remaining of the packet. */ + if( i_packet_size && (i_error = + SafeRead( p_input, p_data->p_buffer + 6, i_packet_size )) ) + { + return( i_error ); + } + + /* In MPEG-2 pack headers we still have to read stuffing bytes. */ + if( U32_AT(p_header) == 0x1BA ) + { + if( i_packet_size == 8 && (p_data->p_buffer[13] & 0x7) != 0 ) + { + /* MPEG-2 stuffing bytes */ + byte_t p_garbage[8]; + if( (i_error = SafeRead( p_input, p_garbage, + p_data->p_buffer[13] & 0x7)) ) + { + return( i_error ); + } + } + } + + /* Give the packet to the other input stages. */ + pp_packets[i_packet] = p_data; + } return( 0 ); } diff --git a/plugins/dvd/input_dvd.h b/plugins/dvd/input_dvd.h index 9eb97b1157..8c2cee89eb 100644 --- a/plugins/dvd/input_dvd.h +++ b/plugins/dvd/input_dvd.h @@ -35,9 +35,9 @@ typedef struct thread_dvd_data_s boolean_t b_encrypted; // CSS encryption int i_read_once; // NB of bytes read by DVDRead - int i_start_byte; - int i_start_cell; - int i_end_cell; + int i_chapter_nb; + off_t i_start; + off_t i_size; /* Scrambling Information */ struct css_s css; diff --git a/plugins/gnome/gnome_callbacks.c b/plugins/gnome/gnome_callbacks.c index 5bcad8632d..7f410d6de9 100644 --- a/plugins/gnome/gnome_callbacks.c +++ b/plugins/gnome/gnome_callbacks.c @@ -584,3 +584,51 @@ on_intf_window_drag_data_received (GtkWidget *widget, } } + +void +on_menubar_audio_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_menubar_subtitles_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_popup_title_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_popup_chapter_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_popup_audio_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + + +void +on_popup_subtitle_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + +} + diff --git a/plugins/gnome/gnome_callbacks.h b/plugins/gnome/gnome_callbacks.h index f39fb396fa..57e91e16ca 100644 --- a/plugins/gnome/gnome_callbacks.h +++ b/plugins/gnome/gnome_callbacks.h @@ -197,3 +197,27 @@ on_intf_window_drag_data_received (GtkWidget *widget, guint info, guint time, gpointer user_data); + +void +on_menubar_audio_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_menubar_subtitles_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_popup_title_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_popup_chapter_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_popup_audio_activate (GtkMenuItem *menuitem, + gpointer user_data); + +void +on_popup_subtitle_activate (GtkMenuItem *menuitem, + gpointer user_data); diff --git a/plugins/gnome/gnome_interface.c b/plugins/gnome/gnome_interface.c index 8896d44107..72b10c5995 100644 --- a/plugins/gnome/gnome_interface.c +++ b/plugins/gnome/gnome_interface.c @@ -46,6 +46,21 @@ static GnomeUIInfo menubar_view_menu_uiinfo[] = static GnomeUIInfo menubar_settings_menu_uiinfo[] = { + { + GNOME_APP_UI_ITEM, N_("_Audio"), + N_("Select audio channel"), + (gpointer) on_menubar_audio_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("_Subtitles"), + N_("Select subtitle unit"), + (gpointer) on_menubar_subtitles_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_MENU_PREFERENCES_ITEM (on_menubar_preferences_activate, NULL), GNOMEUIINFO_END }; @@ -143,10 +158,25 @@ create_intf_window (void) (GtkDestroyNotify) gtk_widget_unref); gtk_widget_ref (menubar_settings_menu_uiinfo[0].widget); - gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences", + gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_audio", menubar_settings_menu_uiinfo[0].widget, (GtkDestroyNotify) gtk_widget_unref); - gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[0].widget, FALSE); + + gtk_widget_ref (menubar_settings_menu_uiinfo[1].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_subtitles", + menubar_settings_menu_uiinfo[1].widget, + (GtkDestroyNotify) gtk_widget_unref); + + gtk_widget_ref (menubar_settings_menu_uiinfo[2].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator5", + menubar_settings_menu_uiinfo[2].widget, + (GtkDestroyNotify) gtk_widget_unref); + + gtk_widget_ref (menubar_settings_menu_uiinfo[3].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_preferences", + menubar_settings_menu_uiinfo[3].widget, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_set_sensitive (menubar_settings_menu_uiinfo[3].widget, FALSE); gtk_widget_ref (menubar_uiinfo[3].widget); gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_help", @@ -394,6 +424,18 @@ create_intf_window (void) return intf_window; } +static GnomeUIInfo popup_title_menu_uiinfo[] = +{ + { + GNOME_APP_UI_ITEM, N_("_Chapter"), + NULL, + (gpointer) on_popup_chapter_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_END +}; + static GnomeUIInfo intf_popup_uiinfo[] = { { @@ -427,6 +469,28 @@ static GnomeUIInfo intf_popup_uiinfo[] = GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_MENU_OPEN_ITEM (on_popup_open_activate, NULL), GNOMEUIINFO_SEPARATOR, + { + GNOME_APP_UI_SUBTREE, N_("_Title"), + N_("Select Title"), + popup_title_menu_uiinfo, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("Audio"), + N_("Select audio channel"), + (gpointer) on_popup_audio_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + { + GNOME_APP_UI_ITEM, N_("_Subtitle"), + NULL, + (gpointer) on_popup_subtitle_activate, NULL, NULL, + GNOME_APP_PIXMAP_NONE, NULL, + 0, (GdkModifierType) 0, NULL + }, + GNOMEUIINFO_SEPARATOR, GNOMEUIINFO_MENU_ABOUT_ITEM (on_popup_about_activate, NULL), GNOMEUIINFO_MENU_EXIT_ITEM (on_popup_exit_activate, NULL), GNOMEUIINFO_END @@ -478,15 +542,40 @@ create_intf_popup (void) (GtkDestroyNotify) gtk_widget_unref); gtk_widget_ref (intf_popup_uiinfo[7].widget); - gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about", + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_title", intf_popup_uiinfo[7].widget, (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_ref (popup_title_menu_uiinfo[0].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_chapter", + popup_title_menu_uiinfo[0].widget, + (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_ref (intf_popup_uiinfo[8].widget); - gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit", + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_audio", intf_popup_uiinfo[8].widget, (GtkDestroyNotify) gtk_widget_unref); + gtk_widget_ref (intf_popup_uiinfo[9].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_subtitle", + intf_popup_uiinfo[9].widget, + (GtkDestroyNotify) gtk_widget_unref); + + gtk_widget_ref (intf_popup_uiinfo[10].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "separator4", + intf_popup_uiinfo[10].widget, + (GtkDestroyNotify) gtk_widget_unref); + + gtk_widget_ref (intf_popup_uiinfo[11].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_about", + intf_popup_uiinfo[11].widget, + (GtkDestroyNotify) gtk_widget_unref); + + gtk_widget_ref (intf_popup_uiinfo[12].widget); + gtk_object_set_data_full (GTK_OBJECT (intf_popup), "popup_exit", + intf_popup_uiinfo[12].widget, + (GtkDestroyNotify) gtk_widget_unref); + return intf_popup; } diff --git a/plugins/gnome/intf_gnome.glade b/plugins/gnome/intf_gnome.glade index 663b8f4e36..4af6b49e86 100644 --- a/plugins/gnome/intf_gnome.glade +++ b/plugins/gnome/intf_gnome.glade @@ -162,6 +162,38 @@ GtkMenu menubar_settings_menu + + GtkMenuItem + menubar_audio + Select audio channel + + activate + on_menubar_audio_activate + Thu, 22 Feb 2001 05:42:43 GMT + + + False + + + + GtkMenuItem + menubar_subtitles + Select subtitle unit + + activate + on_menubar_subtitles_activate + Thu, 22 Feb 2001 05:42:43 GMT + + + False + + + + GtkMenuItem + separator5 + False + + GtkPixmapMenuItem menubar_preferences @@ -559,6 +591,67 @@ False + + GtkMenuItem + popup_title + Select Title + + activate + on_popup_title_activate + Thu, 22 Feb 2001 05:35:57 GMT + + + False + + + GtkMenu + popup_title_menu + + + GtkMenuItem + popup_chapter + + activate + on_popup_chapter_activate + Thu, 22 Feb 2001 05:48:48 GMT + + + False + + + + + + GtkMenuItem + popup_audio + Select audio channel + + activate + on_popup_audio_activate + Thu, 22 Feb 2001 05:35:57 GMT + + + False + + + + GtkMenuItem + popup_subtitle + + activate + on_popup_subtitle_activate + Thu, 22 Feb 2001 05:35:57 GMT + + + False + + + + GtkMenuItem + separator4 + False + + GtkPixmapMenuItem popup_about diff --git a/src/input/input_programs.c b/src/input/input_programs.c index 785f0e0763..69cd646966 100644 --- a/src/input/input_programs.c +++ b/src/input/input_programs.c @@ -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.33 2001/02/20 08:47:25 stef Exp $ + * $Id: input_programs.c,v 1.34 2001/02/22 08:44:45 stef Exp $ * * Authors: Christophe Massiot * @@ -263,7 +263,7 @@ input_area_t * input_AddArea( input_thread_t * p_input ) p_input->stream.pp_areas[i_area_index]->i_start = 0; p_input->stream.pp_areas[i_area_index]->i_size = 0; p_input->stream.pp_areas[i_area_index]->i_tell = 0; - p_input->stream.pp_areas[i_area_index]->i_seek = 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= 0; @@ -281,7 +281,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area ) ASSERT( p_area ); - intf_DbgMsg("Deleting description for area %d", p_area->i_number); + intf_DbgMsg("Deleting description for area %d", p_area->i_nb ); /* Find the area in the areas table */ for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb; @@ -303,7 +303,7 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area ) if( p_input->stream.i_area_nb && p_input->stream.pp_areas == NULL) { intf_ErrMsg( "input error: unable to realloc area list" - " in input_Delarea" ); + " in input_DelArea" ); } /* Free the description of this area */ @@ -680,3 +680,49 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es ) } return( 0 ); } + +/***************************************************************************** + * input_UnSelectES: removes an ES from the list of selected ES + *****************************************************************************/ +int input_UnSelectES( input_thread_t * p_input, es_descriptor_t * p_es ) +{ + + int i_index = 0; + +#ifdef DEBUG_INPUT + intf_DbgMsg( "UnSelecting ES 0x%x", p_es->i_id ); +#endif + + if( p_es->p_decoder_fifo == NULL ) + { + intf_ErrMsg( "ES %d is not selected", p_es->i_id ); + return( -1 ); + } + + input_EndDecoder( p_input, p_es ); + + if( p_es->p_decoder_fifo == NULL ) + { + p_input->stream.i_selected_es_number--; + + while( ( i_index < p_input->stream.i_selected_es_number ) && + ( p_input->stream.pp_selected_es[i_index] != p_es ) ) + { + i_index++; + } + + p_input->stream.pp_selected_es[i_index] = + p_input->stream.pp_selected_es[p_input->stream.i_selected_es_number]; + + p_input->stream.pp_selected_es = realloc( + 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_SelectES" ); + return(-1); + } + } + return( 0 ); +} diff --git a/src/interface/main.c b/src/interface/main.c index c54dddc809..7a82964776 100644 --- a/src/interface/main.c +++ b/src/interface/main.c @@ -140,6 +140,8 @@ static const struct option longopts[] = { "overlay", 0, 0, OPT_OVERLAY }, /* DVD options */ + { "dvdtitle", 1, 0, 't' }, + { "dvdchapter", 1, 0, 'T' }, { "dvdaudio", 1, 0, 'a' }, { "dvdchannel", 1, 0, 'c' }, { "dvdsubtitle", 1, 0, 's' }, @@ -157,7 +159,7 @@ static const struct option longopts[] = }; /* Short options */ -static const char *psz_shortopts = "hHvga:s:c:"; +static const char *psz_shortopts = "hHvgt:T:a:s:c:"; #endif @@ -624,6 +626,12 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) break; /* DVD options */ + case 't': + main_PutIntVariable( INPUT_TITLE_VAR, atoi(optarg) ); + break; + case 'T': + main_PutIntVariable( INPUT_CHAPTER_VAR, atoi(optarg) ); + break; case 'a': if ( ! strcmp(optarg, "ac3") ) main_PutIntVariable( INPUT_AUDIO_VAR, REQUESTED_AC3 ); @@ -734,6 +742,8 @@ static void Usage( int i_fashion ) "\n --yuv \tYUV method" "\n --synchro \tforce synchro algorithm" "\n" + "\n -t, --dvdtitle \tchoose DVD title" + "\n -T, --dvdchapter \tchoose DVD chapter" "\n -a, --dvdaudio \tchoose DVD audio type" "\n -c, --dvdchannel \tchoose DVD audio channel" "\n -s, --dvdsubtitle \tchoose DVD subtitle channel" @@ -783,6 +793,8 @@ static void Usage( int i_fashion ) /* DVD parameters */ intf_MsgImm( "\nDVD parameters:" "\n " INPUT_DVD_DEVICE_VAR "= \tDVD device" + "\n " INPUT_TITLE_VAR "= \ttitle number" + "\n " INPUT_CHAPTER_VAR "=<chapter> \tchapter number" "\n " INPUT_AUDIO_VAR "={ac3|lpcm|mpeg|off} \taudio type" "\n " INPUT_CHANNEL_VAR "=[0-15] \taudio channel" "\n " INPUT_SUBTITLE_VAR "=[0-31] \tsubtitle channel" );