]> git.sesse.net Git - vlc/blobdiff - modules/access/dvdnav.c
small cleanup #11362
[vlc] / modules / access / dvdnav.c
index c6a2b7574937dc3fc060b6a4e3f7b0deda5e2696..ac60e3e3847af241a30c578eee33328fca78d7e3 100644 (file)
 #include "vlc_keys.h"
 #include "iso_lang.h"
 
+/* FIXME we should find a better way than including that */
+#include "../../src/misc/iso-639_def.h"
+
+
 #include <dvdnav/dvdnav.h>
 
 #include "../demux/ps.h"
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
+#define ANGLE_TEXT N_("DVD angle")
+#define ANGLE_LONGTEXT N_( \
+    "Allows you to select the default DVD angle." )
+
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Allows you to modify the default caching value for DVDnav streams. This "\
     "Allows you to start the DVD directly in the main menu. This "\
     "will try to skip all the useless warnings introductions." )
 
+#define LANGUAGE_DEFAULT ("en")
+
 static int  Open ( vlc_object_t * );
 static void Close( vlc_object_t * );
 
 vlc_module_begin();
+    set_shortname( _("DVD with menus") );
     set_description( _("DVDnav Input") );
+    set_category( CAT_INPUT );
+    set_subcategory( SUBCAT_INPUT_ACCESS );
+    add_integer( "dvdnav-angle", 1, NULL, ANGLE_TEXT,
+        ANGLE_LONGTEXT, VLC_FALSE );
     add_integer( "dvdnav-caching", DEFAULT_PTS_DELAY / 1000, NULL,
         CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
     add_bool( "dvdnav-menu", VLC_TRUE, NULL,
@@ -82,8 +97,6 @@ vlc_module_end();
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static char *ParseCL( vlc_object_t *, char *, vlc_bool_t, int *, int *, int *);
-
 typedef struct
 {
     VLC_COMMON_MEMBERS
@@ -116,15 +129,19 @@ struct demux_sys_t
     /* event */
     event_thread_t *p_ev;
 
-    /* FIXME */
-    uint8_t     alpha[4];
-    uint32_t    clut[16];
+    /* palette for menus */
+    uint32_t clut[16];
+    uint8_t  palette[4][4];
+    vlc_bool_t b_spu_change;
 
     /* */
     int i_aspect;
 
     int           i_title;
     input_title_t **title;
+
+    /* lenght of program group chain */
+    mtime_t     i_pgc_length;
 };
 
 static int Control( demux_t *, int, va_list );
@@ -133,11 +150,13 @@ static int DemuxBlock( demux_t *, uint8_t *, int );
 
 static void DemuxTitles( demux_t * );
 static void ESSubtitleUpdate( demux_t * );
-static void ButtonUpdate( demux_t * );
+static void ButtonUpdate( demux_t *, vlc_bool_t );
 
 static void ESNew( demux_t *, int );
 static int ProbeDVD( demux_t *, char * );
 
+static char *DemuxGetLanguageCode( demux_t *p_demux, char *psz_var );
+
 /*****************************************************************************
  * DemuxOpen:
  *****************************************************************************/
@@ -146,16 +165,29 @@ static int Open( vlc_object_t *p_this )
     demux_t     *p_demux = (demux_t*)p_this;
     demux_sys_t *p_sys;
     dvdnav_t    *p_dvdnav;
-    int         i_title, i_chapter, i_angle;
+    int         i_angle;
     char        *psz_name;
+    char        *psz_code;
     vlc_value_t val;
 
-    psz_name = ParseCL( VLC_OBJECT(p_demux), p_demux->psz_path, VLC_TRUE,
-                        &i_title, &i_chapter, &i_angle );
-    if( !psz_name )
+    if( !p_demux->psz_path || !*p_demux->psz_path )
     {
-        return VLC_EGENERIC;
+        /* Only when selected */
+        if( !p_this->b_force ) return VLC_EGENERIC;
+
+        psz_name = var_CreateGetString( p_this, "dvd" );
+        if( !psz_name || !*psz_name )
+        {
+            if( psz_name ) free( psz_name );
+            return VLC_EGENERIC;
+        }
     }
+    else psz_name = strdup( p_demux->psz_path );
+
+#ifdef WIN32
+    if( psz_name[0] && psz_name[1] == ':' &&
+        psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
+#endif
 
     /* Try some simple probing to avoid going through dvdnav_open too often */
     if( ProbeDVD( p_demux, psz_name ) != VLC_SUCCESS )
@@ -164,9 +196,6 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    msg_Dbg( p_this, "dvdroot=%s title=%d chapter=%d angle=%d",
-             psz_name, i_title, i_chapter, i_angle );
-
     /* Open dvdnav */
     if( dvdnav_open( &p_dvdnav, psz_name ) != DVDNAV_STATUS_OK )
     {
@@ -186,6 +215,8 @@ static int Open( vlc_object_t *p_this )
     ps_track_init( p_sys->tk );
     p_sys->i_aspect = -1;
     p_sys->i_mux_rate = 0;
+    p_sys->i_pgc_length = 0;
+    p_sys->b_spu_change = VLC_FALSE;
 
     if( 1 )
     {
@@ -217,71 +248,72 @@ static int Open( vlc_object_t *p_this )
         msg_Warn( p_demux, "cannot set PGC positioning flag" );
     }
 
-    if( dvdnav_menu_language_select (p_sys->dvdnav,"en") != DVDNAV_STATUS_OK ||
-        dvdnav_audio_language_select(p_sys->dvdnav,"en") != DVDNAV_STATUS_OK ||
-        dvdnav_spu_language_select  (p_sys->dvdnav,"en") != DVDNAV_STATUS_OK )
+    /* Set menu language ("en")
+     * XXX: maybe it would be better to set it like audio/spu
+     * or to create a --menu-language option */
+    if( dvdnav_menu_language_select( p_sys->dvdnav,LANGUAGE_DEFAULT ) !=
+        DVDNAV_STATUS_OK )
     {
-        msg_Warn( p_demux, "something failed while setting en language (%s)",
-                  dvdnav_err_to_string( p_sys->dvdnav ) );
+        msg_Warn( p_demux, "can't set menu language to '%s' (%s)",
+                  LANGUAGE_DEFAULT, dvdnav_err_to_string( p_sys->dvdnav ) );
     }
 
-    DemuxTitles( p_demux );
-
-    /* Set forced title/chapter */
-    if( i_title > 0 )
+    /* Set audio language */
+    psz_code = DemuxGetLanguageCode( p_demux, "audio-language" );
+    if( dvdnav_audio_language_select( p_sys->dvdnav, psz_code ) !=
+        DVDNAV_STATUS_OK )
     {
-        if( dvdnav_title_play( p_sys->dvdnav, i_title ) != DVDNAV_STATUS_OK )
-        {
-            msg_Warn( p_demux, "cannot set title" );
-            i_title = 0;
-        }
-        else
-        {
-            p_demux->info.i_update |= INPUT_UPDATE_TITLE;
-            p_demux->info.i_title = i_title;
-        }
+        msg_Warn( p_demux, "can't set audio language to '%s' (%s)",
+                  psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
+        /* We try to fall back to 'en' */
+        if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
+            dvdnav_audio_language_select( p_sys->dvdnav, LANGUAGE_DEFAULT );
     }
+    free( psz_code );
 
-    if( i_chapter > 1 && i_title > 0 )
+    /* Set spu language */
+    psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );
+    if( dvdnav_spu_language_select( p_sys->dvdnav, psz_code ) !=
+        DVDNAV_STATUS_OK )
     {
-        if( dvdnav_part_play( p_sys->dvdnav, i_title, i_chapter ) !=
-            DVDNAV_STATUS_OK )
-        {
-            msg_Warn( p_demux, "cannot set chapter" );
-            i_chapter = 1;
-        }
-        else
-        {
-            p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
-            p_demux->info.i_seekpoint = i_chapter;
-        }
+        msg_Warn( p_demux, "can't set spu language to '%s' (%s)",
+                  psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
+        /* We try to fall back to 'en' */
+        if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
+            dvdnav_spu_language_select(p_sys->dvdnav, LANGUAGE_DEFAULT );
     }
+    free( psz_code );
+
+    DemuxTitles( p_demux );
 
     var_Create( p_demux, "dvdnav-menu", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
     var_Get( p_demux, "dvdnav-menu", &val );
-    if( i_title == 0 || val.b_bool )
+    if( val.b_bool )
     {
         msg_Dbg( p_demux, "trying to go to dvd menu" );
 
         if( dvdnav_title_play( p_sys->dvdnav, 1 ) != DVDNAV_STATUS_OK )
         {
-            msg_Warn( p_demux, "cannot set title" );
+            msg_Err( p_demux, "cannot set title (can't decrypt DVD?)" );
+            dvdnav_close( p_sys->dvdnav );
+            free( p_sys );
+            return VLC_EGENERIC;
         }
 
         if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title ) !=
             DVDNAV_STATUS_OK )
         {
-            msg_Warn( p_demux, "cannot go to dvd menu" );
-        }
-        else
-        {
-            p_demux->info.i_update |=
-                INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
-            p_demux->info.i_title = 0;
-            p_demux->info.i_seekpoint = 0;
+            /* Try going to menu root */
+            if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root ) !=
+                DVDNAV_STATUS_OK )
+                    msg_Warn( p_demux, "cannot go to dvd menu" );
         }
     }
 
+    var_Create( p_demux, "dvdnav-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+    var_Get( p_demux, "dvdnav-angle", &val );
+    i_angle = val.i_int > 0 ? val.i_int : 1;
+
     /* Update default_pts to a suitable value for dvdnav access */
     var_Create( p_demux, "dvdnav-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
 
@@ -293,7 +325,7 @@ static int Open( vlc_object_t *p_this )
     var_Create( p_sys->p_input, "x-end", VLC_VAR_INTEGER );
     var_Create( p_sys->p_input, "y-end", VLC_VAR_INTEGER );
     var_Create( p_sys->p_input, "color", VLC_VAR_ADDRESS );
-    var_Create( p_sys->p_input, "contrast", VLC_VAR_ADDRESS );
+    var_Create( p_sys->p_input, "menu-palette", VLC_VAR_ADDRESS );
     var_Create( p_sys->p_input, "highlight", VLC_VAR_BOOL );
     var_Create( p_sys->p_input, "highlight-mutex", VLC_VAR_MUTEX );
 
@@ -327,7 +359,7 @@ static void Close( vlc_object_t *p_this )
     var_Destroy( p_sys->p_input, "y-start" );
     var_Destroy( p_sys->p_input, "y-end" );
     var_Destroy( p_sys->p_input, "color" );
-    var_Destroy( p_sys->p_input, "contrast" );
+    var_Destroy( p_sys->p_input, "menu-palette" );
 
     vlc_object_release( p_sys->p_input );
 
@@ -391,20 +423,18 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             else if( i_query == DEMUX_GET_TIME )
             {
                 pi64 = (int64_t*)va_arg( args, int64_t * );
-                if( p_sys->i_mux_rate > 0 )
+                if( p_sys->i_pgc_length > 0 )
                 {
-                    *pi64 = (int64_t)1000000 * 2048 * pos / 50 /
-                        p_sys->i_mux_rate;
+                    *pi64 = p_sys->i_pgc_length * pos / len;
                     return VLC_SUCCESS;
                 }
             }
             else if( i_query == DEMUX_GET_LENGTH )
             {
                 pi64 = (int64_t*)va_arg( args, int64_t * );
-                if( p_sys->i_mux_rate > 0 )
+                if( p_sys->i_pgc_length > 0 )
                 {
-                    *pi64 = (int64_t)1000000 * len * 2048 / 50 /
-                        p_sys->i_mux_rate;
+                    *pi64 = (int64_t)p_sys->i_pgc_length;
                     return VLC_SUCCESS;
                 }
             }
@@ -426,6 +456,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_GET_TITLE_INFO:
             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
             pi_int    = (int*)va_arg( args, int* );
+            *((int*)va_arg( args, int* )) = 0; /* Title offset */
+            *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
 
             /* Duplicate title infos */
             *pi_int = p_sys->i_title;
@@ -568,10 +600,31 @@ static int Demux( demux_t *p_demux )
         msleep( 40000 );
         break;
     }
+
+    case DVDNAV_SPU_CLUT_CHANGE:
+    {
+        int i;
+
+        msg_Dbg( p_demux, "DVDNAV_SPU_CLUT_CHANGE" );
+        /* Update color lookup table (16 *uint32_t in packet) */
+        memcpy( p_sys->clut, packet, 16 * sizeof( uint32_t ) );
+
+        /* HACK to get the SPU tracks registered in the right order */
+        for( i = 0; i < 0x1f; i++ )
+        {
+            if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
+                ESNew( p_demux, 0xbd20 + i );
+        }
+        /* END HACK */
+        break;
+    }
+
     case DVDNAV_SPU_STREAM_CHANGE:
     {
         dvdnav_spu_stream_change_event_t *event =
             (dvdnav_spu_stream_change_event_t*)packet;
+        int i;
+
         msg_Dbg( p_demux, "DVDNAV_SPU_STREAM_CHANGE" );
         msg_Dbg( p_demux, "     - physical_wide=%d",
                  event->physical_wide );
@@ -581,8 +634,18 @@ static int Demux( demux_t *p_demux )
                  event->physical_pan_scan );
 
         ESSubtitleUpdate( p_demux );
+        p_sys->b_spu_change = VLC_TRUE;
+
+        /* HACK to get the SPU tracks registered in the right order */
+        for( i = 0; i < 0x1f; i++ )
+        {
+            if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
+                ESNew( p_demux, 0xbd20 + i );
+        }
+        /* END HACK */
         break;
     }
+
     case DVDNAV_AUDIO_STREAM_CHANGE:
     {
         dvdnav_audio_stream_change_event_t *event =
@@ -592,6 +655,7 @@ static int Demux( demux_t *p_demux )
         /* TODO */
         break;
     }
+
     case DVDNAV_VTS_CHANGE:
     {
         int32_t i_title = 0;
@@ -633,6 +697,7 @@ static int Demux( demux_t *p_demux )
         }
         break;
     }
+
     case DVDNAV_CELL_CHANGE:
     {
         int32_t i_title = 0;
@@ -649,6 +714,9 @@ static int Demux( demux_t *p_demux )
         msg_Dbg( p_demux, "     - cell_start=%lld", event->cell_start );
         msg_Dbg( p_demux, "     - pg_start=%lld", event->pg_start );
 
+        /* Store the lenght in time of the current PGC */
+        p_sys->i_pgc_length = event->pgc_length / 90 * 1000;
+
         /* FIXME is it correct or there is better way to know chapter change */
         if( dvdnav_current_title_info( p_sys->dvdnav, &i_title,
                                        &i_part ) == DVDNAV_STATUS_OK )
@@ -675,10 +743,20 @@ static int Demux( demux_t *p_demux )
          *  - ...
          */
         DemuxBlock( p_demux, packet, i_len );
+        if( p_sys->b_spu_change ) 
+       {
+               ButtonUpdate( p_demux, VLC_FALSE );
+               p_sys->b_spu_change = VLC_FALSE;
+        }
         break;
     }
+
     case DVDNAV_STOP:   /* EOF */
         msg_Dbg( p_demux, "DVDNAV_STOP" );
+
+#if DVD_READ_CACHE
+        dvdnav_free_cache_block( p_sys->dvdnav, packet );
+#endif
         return 0;
 
     case DVDNAV_HIGHLIGHT:
@@ -687,25 +765,7 @@ static int Demux( demux_t *p_demux )
         msg_Dbg( p_demux, "DVDNAV_HIGHLIGHT" );
         msg_Dbg( p_demux, "     - display=%d", event->display );
         msg_Dbg( p_demux, "     - buttonN=%d", event->buttonN );
-        ButtonUpdate( p_demux );
-        break;
-    }
-
-    case DVDNAV_SPU_CLUT_CHANGE:
-    {
-        int i;
-
-        msg_Dbg( p_demux, "DVDNAV_SPU_CLUT_CHANGE" );
-        /* Update color lookup table (16 *uint32_t in packet) */
-        memcpy( p_sys->clut, packet, 16 * sizeof( uint32_t ) );
-
-        /* HACK to get the SPU tracks registered in the right order */
-        for( i = 0; i < 0x1f; i++ )
-        {
-            if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
-                ESNew( p_demux, 0xbd20 + i );
-        }
-        /* END HACK */
+        ButtonUpdate( p_demux, VLC_FALSE );
         break;
     }
 
@@ -717,6 +777,8 @@ static int Demux( demux_t *p_demux )
     case DVDNAV_WAIT:
         msg_Dbg( p_demux, "DVDNAV_WAIT" );
 
+        /* reset PCR */
+        es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
         dvdnav_wait_skip( p_sys->dvdnav );
         break;
 
@@ -732,71 +794,36 @@ static int Demux( demux_t *p_demux )
     return 1;
 }
 
-/*****************************************************************************
- * ParseCL: parse command line.
- * Titles start from 0 (menu), chapters and angles start from 1.
- *****************************************************************************/
-static char *ParseCL( vlc_object_t *p_this, char *psz_name, vlc_bool_t b_force,
-                      int *i_title, int *i_chapter, int *i_angle )
+/* Get a 2 char code
+ * FIXME: partiallyy duplicated from src/input/es_out.c
+ */
+static char *DemuxGetLanguageCode( demux_t *p_demux, char *psz_var )
 {
-    char *psz_parser, *psz_source, *psz_next;
-
-    psz_source = strdup( psz_name );
-    if( psz_source == NULL ) return NULL;
+    const iso639_lang_t *pl;
+    char *psz_lang;
+    char *p;
 
-    *i_title = -1;
-    *i_chapter = 1;
-    *i_angle = 1;
+    psz_lang = var_CreateGetString( p_demux, psz_var );
+    /* XXX: we will use only the first value
+     * (and ignore other ones in case of a list) */
+    if( ( p = strchr( psz_lang, ',' ) ) ) *p = '\0';
 
-    /* Start with the end, because you could have :
-     * dvdnav:/Volumes/my@toto/VIDEO_TS@1,1
-     * (yes, this is kludgy). */
-    for( psz_parser = psz_source + strlen(psz_source) - 1;
-         psz_parser >= psz_source && *psz_parser != '@';
-         psz_parser-- );
-
-    if( psz_parser >= psz_source && *psz_parser == '@' )
+    for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ )
     {
-        /* Found options */
-        *psz_parser = '\0';
-        ++psz_parser;
-
-        *i_title = (int)strtol( psz_parser, &psz_next, 10 );
-        if( *psz_next )
-        {
-            psz_parser = psz_next + 1;
-            *i_chapter = (int)strtol( psz_parser, &psz_next, 10 );
-            if( *psz_next )
-            {
-                *i_angle = (int)strtol( psz_next + 1, NULL, 10 );
-            }
-        }
+        if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
+            !strcasecmp( pl->psz_native_name, psz_lang ) ||
+            !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
+            !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
+            !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
+            break;
     }
 
-    *i_title   = *i_title >= 0 ? *i_title : -1;
-    *i_chapter = *i_chapter > 0 ? *i_chapter : 1;
-    *i_angle   = *i_angle > 0 ? *i_angle : 1;
-
-    if( !*psz_source )
-    {
-        free( psz_source );
-        if( !b_force )
-        {
-            return NULL;
-        }
-        psz_source = config_GetPsz( p_this, "dvd" );
-        if( !psz_source ) return NULL;
-    }
+    free( psz_lang );
 
-#ifdef WIN32
-    if( psz_source[0] && psz_source[1] == ':' &&
-        psz_source[2] == '\\' && psz_source[3] == '\0' )
-    {
-        psz_source[2] = '\0';
-    }
-#endif
+    if( pl->psz_iso639_1 != NULL )
+        return strdup( pl->psz_iso639_1 );
 
-    return psz_source;
+    return strdup(LANGUAGE_DEFAULT);
 }
 
 static void DemuxTitles( demux_t *p_demux )
@@ -855,8 +882,6 @@ static void DemuxTitles( demux_t *p_demux )
         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
         {
             s = vlc_seekpoint_New();
-            s->psz_name = malloc( strlen( _("Chapter %i") ) + 20 );
-            sprintf( s->psz_name, _("Chapter %i"), j + 1 );
             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
         }
 
@@ -867,7 +892,7 @@ static void DemuxTitles( demux_t *p_demux )
 /*****************************************************************************
  * Update functions:
  *****************************************************************************/
-static void ButtonUpdate( demux_t *p_demux )
+static void ButtonUpdate( demux_t *p_demux, vlc_bool_t b_mode )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
     vlc_value_t val;
@@ -890,16 +915,22 @@ static void ButtonUpdate( demux_t *p_demux )
 
         if( i_button > 0 && i_title ==  0 )
         {
+            int i;
             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
 
-            dvdnav_get_highlight_area( pci, i_button, 1, &hl );
+            dvdnav_get_highlight_area( pci, i_button, b_mode, &hl );
 
-            /* I fear it is plain wrong */
-            //val.p_address = (void *)&hl.palette;
-            p_sys->alpha[0] = hl.palette&0x0f;
-            p_sys->alpha[1] = (hl.palette>>4)&0x0f;
-            p_sys->alpha[2] = (hl.palette>>8)&0x0f;
-            p_sys->alpha[3] = (hl.palette>>12)&0x0f;
+            for( i = 0; i < 4; i++ )
+            {
+                uint32_t i_yuv = p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
+                uint8_t i_alpha = (hl.palette>>(i*4))&0x0f;
+                i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
+
+                p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
+                p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
+                p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
+                p_sys->palette[i][3] = i_alpha;
+            }
 
             vlc_mutex_lock( p_mutex );
             val.i_int = hl.sx; var_Set( p_sys->p_input, "x-start", val );
@@ -907,8 +938,8 @@ static void ButtonUpdate( demux_t *p_demux )
             val.i_int = hl.sy; var_Set( p_sys->p_input, "y-start", val );
             val.i_int = hl.ey; var_Set( p_sys->p_input, "y-end", val );
 
-            val.p_address = (void *)p_sys->alpha;
-            var_Set( p_sys->p_input, "contrast", val );
+            val.p_address = (void *)p_sys->palette;
+            var_Set( p_sys->p_input, "menu-palette", val );
 
             val.b_bool = VLC_TRUE; var_Set( p_sys->p_input, "highlight", val );
             vlc_mutex_unlock( p_mutex );
@@ -935,22 +966,17 @@ static void ESSubtitleUpdate( demux_t *p_demux )
     int         i_spu = dvdnav_get_active_spu_stream( p_sys->dvdnav );
     int32_t i_title, i_part;
 
-    ButtonUpdate( p_demux );
+    ButtonUpdate( p_demux, VLC_FALSE );
 
     dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
-    if( i_title > 0 )
-    {
-        return;
-    }
+    if( i_title > 0 ) return;
 
     if( i_spu >= 0 && i_spu <= 0x1f )
     {
         ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)];
 
-        if( !tk->b_seen )
-        {
-            ESNew( p_demux, 0xbd20 + i_spu);
-        }
+        ESNew( p_demux, 0xbd20 + i_spu );
+
         /* be sure to unselect it (reset) */
         es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es,
                         (vlc_bool_t)VLC_FALSE );
@@ -1068,12 +1094,9 @@ static void ESNew( demux_t *p_demux, int i_id )
     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
     vlc_bool_t  b_select = VLC_FALSE;
 
-    if( tk->b_seen )
-    {
-        return;
-    }
+    if( tk->b_seen ) return;
 
-    if( ps_track_fill( tk, i_id ) )
+    if( ps_track_fill( tk, 0, i_id ) )
     {
         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
         return;
@@ -1156,6 +1179,8 @@ static void ESNew( demux_t *p_demux, int i_id )
         es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es );
     }
     tk->b_seen = VLC_TRUE;
+
+    if( tk->fmt.i_cat == VIDEO_ES ) ButtonUpdate( p_demux, VLC_FALSE );
 }
 
 /*****************************************************************************
@@ -1222,6 +1247,7 @@ static int EventThread( vlc_object_t *p_this )
             case ACTIONID_NAV_ACTIVATE:
                 b_activated = VLC_TRUE;
                 dvdnav_button_activate( p_sys->dvdnav, pci );
+                ButtonUpdate( p_ev->p_demux, VLC_TRUE );
                 break;
             default:
                 break;
@@ -1250,6 +1276,7 @@ static int EventThread( vlc_object_t *p_this )
                 b_activated = VLC_TRUE;
                 dvdnav_mouse_activate( p_sys->dvdnav, pci, valx.i_int,
                                        valy.i_int );
+                ButtonUpdate( p_ev->p_demux, VLC_TRUE );
             }
 
             p_ev->b_moved = VLC_FALSE;