]> git.sesse.net Git - vlc/blobdiff - src/input/input_programs.c
* input_dec.c : handle SPU_ES (and not as VIDEO_ES ....) so subtitle
[vlc] / src / input / input_programs.c
index 77ee512fc55e694b0a886573ae9410fc49796dd6..bb260f454687abbf54c97988be54efa4d367e01b 100644 (file)
@@ -2,7 +2,7 @@
  * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
  *****************************************************************************
  * Copyright (C) 1999-2002 VideoLAN
- * $Id: input_programs.c,v 1.110 2003/05/11 18:43:19 gbazin Exp $
+ * $Id: input_programs.c,v 1.121 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -51,6 +51,8 @@ static int NavigationCallback( vlc_object_t *, char const *,
 static int ESCallback( vlc_object_t *, char const *,
                        vlc_value_t, vlc_value_t, void * );
 
+static es_format_t null_es_format = {0};
+
 /*****************************************************************************
  * input_InitStream: init the stream descriptor of the given input
  *****************************************************************************/
@@ -84,7 +86,7 @@ int input_InitStream( input_thread_t * p_input, size_t i_data_len )
     {
         p_input->stream.p_demux_data = NULL;
     }
-    
+
     var_Create( p_input, "intf-change", VLC_VAR_BOOL );
     val.b_bool = VLC_TRUE;
     var_Set( p_input, "intf-change", val );
@@ -93,15 +95,19 @@ int input_InitStream( input_thread_t * p_input, size_t i_data_len )
     var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
     text.psz_string = _("Program");
     var_Change( p_input, "program", VLC_VAR_SETTEXT, &text, NULL );
+
     var_Create( p_input, "title", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
     text.psz_string = _("Title");
     var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
+
     var_Create( p_input, "chapter", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
     text.psz_string = _("Chapter");
     var_Change( p_input, "chapter", VLC_VAR_SETTEXT, &text, NULL );
+
     var_Create( p_input, "navigation", VLC_VAR_VARIABLE | VLC_VAR_HASCHOICE );
     text.psz_string = _("Navigation");
     var_Change( p_input, "navigation", VLC_VAR_SETTEXT, &text, NULL );
+
     var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
     text.psz_string = _("Video track");
     var_Change( p_input, "video-es", VLC_VAR_SETTEXT, &text, NULL );
@@ -109,7 +115,7 @@ int input_InitStream( input_thread_t * p_input, size_t i_data_len )
     text.psz_string = _("Audio track");
     var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, &text, NULL );
     var_Create( p_input, "spu-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
-    text.psz_string = _("Subtitle track");
+    text.psz_string = _("Subtitles track");
     var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
 
     var_AddCallback( p_input, "program", ProgramCallback, NULL );
@@ -191,7 +197,7 @@ pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input,
  * This program descriptor will be referenced in the given stream descriptor
  *****************************************************************************/
 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
-                                      u16 i_pgrm_id, size_t i_data_len )
+                                      uint16_t i_pgrm_id, size_t i_data_len )
 {
     /* Where to add the pgrm */
     pgrm_descriptor_t * p_pgrm = malloc( sizeof(pgrm_descriptor_t) );
@@ -267,7 +273,7 @@ void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
         return;
     }
 
-    val.i_int = i_pgrm_index;
+    val.i_int = p_input->stream.pp_programs[i_pgrm_index]->i_number;
     var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
 
     /* Free the structures that describe the es that belongs to that program */
@@ -287,6 +293,9 @@ void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
                  p_input->stream.i_pgrm_number,
                  i_pgrm_index );
 
+    if( p_pgrm == p_input->stream.p_selected_program )
+        p_input->stream.p_selected_program = NULL;
+
     /* Free the description of this program */
     free( p_pgrm );
 }
@@ -336,7 +345,7 @@ input_area_t * input_AddArea( input_thread_t * p_input,
     val.psz_string = malloc( sizeof("title ") + 5 );
     if( val.psz_string )
     {
-        vlc_value_t val2;
+        vlc_value_t val2, text, text2;
 
         sprintf( val.psz_string, "title %2i", i_area_id );
         var_Destroy( p_input, val.psz_string );
@@ -345,14 +354,52 @@ input_area_t * input_AddArea( input_thread_t * p_input,
         var_AddCallback( p_input, val.psz_string, NavigationCallback,
                          (void *)(int)i_area_id );
 
-        var_Change( p_input, "navigation", VLC_VAR_ADDCHOICE, &val, NULL );
+        text.psz_string = malloc( strlen( _("Title %i") ) + 20 );
+        if( text.psz_string )
+            sprintf( text.psz_string, _("Title %i"), i_area_id );
+
+        var_Change( p_input, "navigation", VLC_VAR_ADDCHOICE, &val, &text );
+
+        if( text.psz_string ) free( text.psz_string );
+
+        text2.psz_string = malloc( strlen( _("Chapter %i") ) + 20 );
 
         for( i = 1; i <= i_part_nb; i++ )
         {
             val2.i_int = i;
+
+            if( text2.psz_string )
+                sprintf( text2.psz_string, _("Chapter %i"), i );
+
             var_Change( p_input, val.psz_string,
-                        VLC_VAR_ADDCHOICE, &val2, NULL );
+                        VLC_VAR_ADDCHOICE, &val2, &text2 );
         }
+
+        if( text2.psz_string ) free( text2.psz_string );
+    }
+
+    if( p_input->stream.i_area_nb == 2 )
+    {
+        vlc_value_t text;
+
+        /* Add another bunch of navigation object variables */
+        var_Create( p_input, "next-title", VLC_VAR_VOID );
+        text.psz_string = _("Next title");
+        var_Change( p_input, "next-title", VLC_VAR_SETTEXT, &text, NULL );
+        var_Create( p_input, "prev-title", VLC_VAR_VOID );
+        text.psz_string = _("Previous title");
+        var_Change( p_input, "prev-title", VLC_VAR_SETTEXT, &text, NULL );
+        var_AddCallback( p_input, "next-title", TitleCallback, NULL );
+        var_AddCallback( p_input, "prev-title", TitleCallback, NULL );
+
+        var_Create( p_input, "next-chapter", VLC_VAR_VOID );
+        text.psz_string = _("Next Chapter");
+        var_Change( p_input, "next-chapter", VLC_VAR_SETTEXT, &text, NULL );
+        var_Create( p_input, "prev-chapter", VLC_VAR_VOID );
+        text.psz_string = _("Previous Chapter");
+        var_Change( p_input, "prev-chapter", VLC_VAR_SETTEXT, &text, NULL );
+        var_AddCallback( p_input, "next-chapter", ChapterCallback, NULL );
+        var_AddCallback( p_input, "prev-chapter", ChapterCallback, NULL );
     }
 
     return p_area;
@@ -385,11 +432,14 @@ int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
 #undef p_es
         }
     }
+
     /* Get the number of the required audio stream */
-    if( config_GetInt( p_input, "audio" ) )
+    var_Get( p_input, "audio", &val );
+    if( val.b_bool )
     {
         /* Default is the first one */
-        i_required_audio_es = config_GetInt( p_input, "audio-channel" );
+        var_Get( p_input, "audio-channel", &val );
+        i_required_audio_es = val.i_int;
         if( i_required_audio_es < 0 )
         {
             i_required_audio_es = 1;
@@ -401,10 +451,12 @@ int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
     }
 
     /* Same thing for subtitles */
-    if( config_GetInt( p_input, "video" ) )
+    var_Get( p_input, "video", &val );
+    if( val.b_bool )
     {
         /* for spu, default is none */
-        i_required_spu_es = config_GetInt( p_input, "spu-channel" );
+        var_Get( p_input, "spu-channel", &val );
+        i_required_spu_es = val.i_int;
         if( i_required_spu_es < 0 )
         {
             i_required_spu_es = 0;
@@ -451,7 +503,6 @@ int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
 
     }
 
-
     p_input->stream.p_selected_program = p_new_prg;
 
     /* Update the navigation variables without triggering a callback */
@@ -502,6 +553,15 @@ void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
 
     /* Free the description of this area */
     free( p_area );
+
+    if( p_input->stream.i_area_nb == 1 )
+    {
+        /* Del unneeded navigation object variables */
+        var_Destroy( p_input, "next-title" );
+        var_Destroy( p_input, "prev-title" );
+        var_Destroy( p_input, "next-chapter" );
+        var_Destroy( p_input, "prev-chapter" );
+    }
 }
 
 
@@ -531,7 +591,7 @@ es_descriptor_t * input_FindES( input_thread_t * p_input, uint16_t i_es_id )
  * alone (PSI ?)
  *****************************************************************************/
 es_descriptor_t * input_AddES( input_thread_t * p_input,
-                               pgrm_descriptor_t * p_pgrm, u16 i_es_id,
+                               pgrm_descriptor_t * p_pgrm, uint16_t i_es_id,
                                int i_category, char const *psz_desc,
                                size_t i_data_len )
 {
@@ -560,6 +620,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input,
     p_es->c_packets = 0;
     p_es->c_invalid_packets = 0;
     p_es->b_force_decoder = VLC_FALSE;
+    p_es->fmt = null_es_format;
 
     if( i_data_len )
     {
@@ -577,6 +638,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input,
     }
     p_es->p_waveformatex     = NULL;
     p_es->p_bitmapinfoheader = NULL;
+    p_es->p_spuinfo = NULL;
 
     /* Add this ES to the program definition if one is given */
     if( p_pgrm )
@@ -620,7 +682,7 @@ es_descriptor_t * input_AddES( input_thread_t * p_input,
         }
 
         /* Take care of the ES description */
-        if( psz_desc )
+        if( psz_desc && *psz_desc )
         {
             p_es->psz_desc = strdup( psz_desc );
         }
@@ -696,7 +758,7 @@ void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
     /* Kill associated decoder, if any. */
     if( p_es->p_decoder_fifo != NULL )
     {
-        input_EndDecoder( p_input, p_es );
+        input_UnselectES( p_input, p_es );
     }
 
     /* Remove this ES from the description of the program if it is associated
@@ -729,6 +791,10 @@ void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
     {
         free( p_es->p_bitmapinfoheader );
     }
+    if( p_es->p_spuinfo )
+    {
+        free( p_es->p_spuinfo );
+    }
 
     /* Free the description string */
     if( p_es->psz_desc != NULL )
@@ -770,19 +836,26 @@ int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
         return -1;
     }
 
-    if( ((p_es->i_cat == VIDEO_ES) || (p_es->i_cat == SPU_ES))
-        && !config_GetInt( p_input, "video" ) )
+    if( p_es->i_cat == VIDEO_ES || p_es->i_cat == SPU_ES )
     {
-        msg_Dbg( p_input,
-                 "video is disabled, not selecting ES 0x%x", p_es->i_id );
-        return -1;
+        var_Get( p_input, "video", &val );
+        if( !val.b_bool )
+        {
+            msg_Dbg( p_input, "video is disabled, not selecting ES 0x%x",
+                     p_es->i_id );
+            return -1;
+        }
     }
 
-    if( (p_es->i_cat == AUDIO_ES) && !config_GetInt( p_input, "audio" ) )
+    if( p_es->i_cat == AUDIO_ES )
     {
-        msg_Dbg( p_input,
-                 "audio is disabled, not selecting ES 0x%x", p_es->i_id );
-        return -1;
+        var_Get( p_input, "audio", &val );
+        if( !val.b_bool )
+        {
+            msg_Dbg( p_input, "audio is disabled, not selecting ES 0x%x",
+                     p_es->i_id );
+            return -1;
+        }
     }
 
     msg_Dbg( p_input, "selecting ES 0x%x", p_es->i_id );
@@ -932,16 +1005,38 @@ static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
 {
     input_thread_t *p_input = (input_thread_t *)p_this;
     input_area_t *p_area;
-    vlc_value_t val;
+    vlc_value_t val, val_list;
+    int i, i_step = 0;
 
-    if( oldval.i_int == newval.i_int )
-       return VLC_SUCCESS;
+    if( !strcmp( psz_cmd, "next-title" ) ) i_step++;
+    else if( !strcmp( psz_cmd, "prev-title" ) ) i_step--;
+
+    if( !i_step && oldval.i_int == newval.i_int ) return VLC_SUCCESS;
 
-    /* Sanity check should have already be done by var_Set(). */
+    /* Sanity check should have already been done by var_Set(). */
     vlc_mutex_lock( &p_input->stream.stream_lock );
+
+    if( i_step )
+    {
+        var_Get( p_this, "title", &newval );
+        var_Change( p_this, "title", VLC_VAR_GETCHOICES, &val_list, NULL );
+        for( i = 0; i < val_list.p_list->i_count; i++ )
+        {
+            if( val_list.p_list->p_values[i].i_int == newval.i_int &&
+                i + i_step >= 0 && i + i_step < val_list.p_list->i_count )
+            {
+                newval.i_int = val_list.p_list->p_values[i + i_step].i_int;
+                break;
+            }
+        }
+        var_Change( p_this, "title", VLC_VAR_FREELIST, &val_list, NULL );
+    }
+
     p_area = p_input->stream.pp_areas[newval.i_int];
     p_area->i_part = 1;
+
     vlc_mutex_unlock( &p_input->stream.stream_lock );
+
     input_ChangeArea( p_input, p_area );
     input_SetStatus( p_input, INPUT_STATUS_PLAY );
 
@@ -956,13 +1051,33 @@ static int ChapterCallback( vlc_object_t *p_this, char const *psz_cmd,
 {
     input_thread_t *p_input = (input_thread_t *)p_this;
     input_area_t *p_area;
-    vlc_value_t val;
+    vlc_value_t val, val_list;
+    int i, i_step = 0;
 
-    if( oldval.i_int == newval.i_int )
-       return VLC_SUCCESS;
+    if( !strcmp( psz_cmd, "next-chapter" ) ) i_step++;
+    else if( !strcmp( psz_cmd, "prev-chapter" ) ) i_step--;
 
-    /* Sanity check will have already be done by var_Set(). */
+    if( !i_step && oldval.i_int == newval.i_int ) return VLC_SUCCESS;
+
+    /* Sanity check should have already been done by var_Set(). */
     vlc_mutex_lock( &p_input->stream.stream_lock );
+
+    if( i_step )
+    {
+        var_Get( p_this, "chapter", &newval );
+        var_Change( p_this, "chapter", VLC_VAR_GETCHOICES, &val_list, NULL );
+        for( i = 0; i < val_list.p_list->i_count; i++ )
+        {
+            if( val_list.p_list->p_values[i].i_int == newval.i_int &&
+                i + i_step >= 0 && i + i_step < val_list.p_list->i_count )
+            {
+                newval.i_int = val_list.p_list->p_values[i + i_step].i_int;
+                break;
+            }
+        }
+        var_Change( p_this, "chapter", VLC_VAR_FREELIST, &val_list, NULL );
+    }
+
     p_area = p_input->stream.p_selected_area;
     p_input->stream.p_selected_area->i_part = newval.i_int;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
@@ -998,7 +1113,7 @@ static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
           p_input->stream.pp_areas[i_area_id]->i_part_nb ) )
     {
         input_area_t *p_area = p_input->stream.pp_areas[i_area_id];
-        p_input->stream.p_selected_area->i_part = newval.i_int;
+        p_area->i_part = newval.i_int;
         vlc_mutex_unlock( &p_input->stream.stream_lock );
         input_ChangeArea( p_input, p_area );
         input_SetStatus( p_input, INPUT_STATUS_PLAY );