dvdnav.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:45k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * dvdnav.c: DVD module using the dvdnav library.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004-2009 the VideoLAN team
  5.  * $Id: b38852cf44c3fa2a2ef1fd0fdd1b116e3957b733 $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <assert.h>
  30. #include <vlc_common.h>
  31. #include <vlc_plugin.h>
  32. #include <vlc_input.h>
  33. #include <vlc_access.h>
  34. #include <vlc_demux.h>
  35. #include <vlc_charset.h>
  36. #include <vlc_dialog.h>
  37. #ifdef HAVE_UNISTD_H
  38. #   include <unistd.h>
  39. #endif
  40. #ifdef HAVE_SYS_TYPES_H
  41. #   include <sys/types.h>
  42. #endif
  43. #ifdef HAVE_SYS_STAT_H
  44. #   include <sys/stat.h>
  45. #endif
  46. #ifdef HAVE_FCNTL_H
  47. #   include <fcntl.h>
  48. #endif
  49. #include "vlc_keys.h"
  50. #include "vlc_iso_lang.h"
  51. /* FIXME we should find a better way than including that */
  52. #include "../../src/text/iso-639_def.h"
  53. #include <dvdnav/dvdnav.h>
  54. #include "../demux/ps.h"
  55. /*****************************************************************************
  56.  * Module descriptor
  57.  *****************************************************************************/
  58. #define ANGLE_TEXT N_("DVD angle")
  59. #define ANGLE_LONGTEXT N_( 
  60.      "Default DVD angle." )
  61. #define CACHING_TEXT N_("Caching value in ms")
  62. #define CACHING_LONGTEXT N_( 
  63.     "Caching value for DVDs. This "
  64.     "value should be set in milliseconds." )
  65. #define MENU_TEXT N_("Start directly in menu")
  66. #define MENU_LONGTEXT N_( 
  67.     "Start the DVD directly in the main menu. This "
  68.     "will try to skip all the useless warning introductions." )
  69. #define LANGUAGE_DEFAULT ("en")
  70. static int  Open ( vlc_object_t * );
  71. static void Close( vlc_object_t * );
  72. vlc_module_begin ()
  73.     set_shortname( N_("DVD with menus") )
  74.     set_description( N_("DVDnav Input") )
  75.     set_category( CAT_INPUT )
  76.     set_subcategory( SUBCAT_INPUT_ACCESS )
  77.     add_integer( "dvdnav-angle", 1, NULL, ANGLE_TEXT,
  78.         ANGLE_LONGTEXT, false )
  79.     add_integer( "dvdnav-caching", DEFAULT_PTS_DELAY / 1000, NULL,
  80.         CACHING_TEXT, CACHING_LONGTEXT, true )
  81.     add_bool( "dvdnav-menu", true, NULL,
  82.         MENU_TEXT, MENU_LONGTEXT, false )
  83.     set_capability( "access_demux", 5 )
  84.     add_shortcut( "dvd" )
  85.     add_shortcut( "dvdnav" )
  86.     add_shortcut( "file" )
  87.     set_callbacks( Open, Close )
  88. vlc_module_end ()
  89. /* Shall we use libdvdnav's read ahead cache? */
  90. #define DVD_READ_CACHE 1
  91. /*****************************************************************************
  92.  * Local prototypes
  93.  *****************************************************************************/
  94. struct demux_sys_t
  95. {
  96.     dvdnav_t    *dvdnav;
  97.     /* */
  98.     bool        b_reset_pcr;
  99.     struct
  100.     {
  101.         bool         b_created;
  102.         bool         b_enabled;
  103.         mtime_t      i_end;
  104.         vlc_mutex_t  lock;
  105.         vlc_cond_t   wait;
  106.         vlc_thread_t thread;
  107.     } still;
  108.     /* track */
  109.     ps_track_t  tk[PS_TK_COUNT];
  110.     int         i_mux_rate;
  111.     /* for spu variables */
  112.     input_thread_t *p_input;
  113.     /* event */
  114.     vlc_object_t *p_vout;
  115.     /* palette for menus */
  116.     uint32_t clut[16];
  117.     uint8_t  palette[4][4];
  118.     bool b_spu_change;
  119.     /* */
  120.     int i_aspect;
  121.     int           i_title;
  122.     input_title_t **title;
  123.     /* lenght of program group chain */
  124.     mtime_t     i_pgc_length;
  125. };
  126. static int Control( demux_t *, int, va_list );
  127. static int Demux( demux_t * );
  128. static int DemuxBlock( demux_t *, const uint8_t *, int );
  129. static void DemuxTitles( demux_t * );
  130. static void ESSubtitleUpdate( demux_t * );
  131. static void ButtonUpdate( demux_t *, bool );
  132. static void ESNew( demux_t *, int );
  133. static int ProbeDVD( demux_t *, char * );
  134. static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var );
  135. static int ControlInternal( demux_t *, int, ... );
  136. static void* StillThread( void * );
  137. static int EventKey( vlc_object_t *, char const *,
  138.                      vlc_value_t, vlc_value_t, void * );
  139. static int EventMouse( vlc_object_t *, char const *,
  140.                        vlc_value_t, vlc_value_t, void * );
  141. static int EventIntf( vlc_object_t *, char const *,
  142.                       vlc_value_t, vlc_value_t, void * );
  143. /*****************************************************************************
  144.  * DemuxOpen:
  145.  *****************************************************************************/
  146. static int Open( vlc_object_t *p_this )
  147. {
  148.     demux_t     *p_demux = (demux_t*)p_this;
  149.     demux_sys_t *p_sys;
  150.     dvdnav_t    *p_dvdnav;
  151.     int         i_angle;
  152.     char        *psz_name;
  153.     char        *psz_code;
  154.     vlc_value_t val;
  155.     if( !p_demux->psz_path || !*p_demux->psz_path )
  156.     {
  157.         /* Only when selected */
  158.         if( !p_this->b_force ) return VLC_EGENERIC;
  159.         psz_name = var_CreateGetString( p_this, "dvd" );
  160.         if( !psz_name )
  161.         {
  162.             psz_name = strdup("");
  163.         }
  164.     }
  165.     else
  166.         psz_name = ToLocaleDup( p_demux->psz_path );
  167. #ifdef WIN32
  168.     /* Remove trailing backslash, otherwise dvdnav_open will fail */
  169.     if( *psz_name && *(psz_name + strlen(psz_name) - 1) == '\' )
  170.     {
  171.         *(psz_name + strlen(psz_name) - 1) = '';
  172.     }
  173. #endif
  174.     /* Try some simple probing to avoid going through dvdnav_open too often */
  175.     if( ProbeDVD( p_demux, psz_name ) != VLC_SUCCESS )
  176.     {
  177.         free( psz_name );
  178.         return VLC_EGENERIC;
  179.     }
  180.     /* Open dvdnav */
  181.     if( dvdnav_open( &p_dvdnav, psz_name ) != DVDNAV_STATUS_OK )
  182.     {
  183.         msg_Warn( p_demux, "cannot open dvdnav" );
  184.         free( psz_name );
  185.         return VLC_EGENERIC;
  186.     }
  187.     free( psz_name );
  188.     /* Fill p_demux field */
  189.     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
  190.     p_sys->dvdnav = p_dvdnav;
  191.     p_sys->b_reset_pcr = false;
  192.     ps_track_init( p_sys->tk );
  193.     p_sys->i_aspect = -1;
  194.     p_sys->i_mux_rate = 0;
  195.     p_sys->i_pgc_length = 0;
  196.     p_sys->b_spu_change = false;
  197.     if( 1 )
  198.     {
  199.         // Hack for libdvdnav CVS.
  200.         // Without it dvdnav_get_number_of_titles() fails.
  201.         // Remove when fixed in libdvdnav CVS.
  202.         uint8_t buffer[DVD_VIDEO_LB_LEN];
  203.         int i_event, i_len;
  204.         if( dvdnav_get_next_block( p_sys->dvdnav, buffer, &i_event, &i_len )
  205.               == DVDNAV_STATUS_ERR )
  206.         {
  207.             msg_Warn( p_demux, "dvdnav_get_next_block failed" );
  208.         }
  209.         dvdnav_sector_search( p_sys->dvdnav, 0, SEEK_SET );
  210.     }
  211.     /* Configure dvdnav */
  212.     if( dvdnav_set_readahead_flag( p_sys->dvdnav, DVD_READ_CACHE ) !=
  213.           DVDNAV_STATUS_OK )
  214.     {
  215.         msg_Warn( p_demux, "cannot set read-a-head flag" );
  216.     }
  217.     if( dvdnav_set_PGC_positioning_flag( p_sys->dvdnav, 1 ) !=
  218.           DVDNAV_STATUS_OK )
  219.     {
  220.         msg_Warn( p_demux, "cannot set PGC positioning flag" );
  221.     }
  222.     /* Set menu language
  223.      * XXX A menu-language may be better than sub-language */
  224.     psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );
  225.     if( dvdnav_menu_language_select( p_sys->dvdnav, psz_code ) !=
  226.         DVDNAV_STATUS_OK )
  227.     {
  228.         msg_Warn( p_demux, "can't set menu language to '%s' (%s)",
  229.                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
  230.         /* We try to fall back to 'en' */
  231.         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
  232.             dvdnav_menu_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
  233.     }
  234.     free( psz_code );
  235.     /* Set audio language */
  236.     psz_code = DemuxGetLanguageCode( p_demux, "audio-language" );
  237.     if( dvdnav_audio_language_select( p_sys->dvdnav, psz_code ) !=
  238.         DVDNAV_STATUS_OK )
  239.     {
  240.         msg_Warn( p_demux, "can't set audio language to '%s' (%s)",
  241.                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
  242.         /* We try to fall back to 'en' */
  243.         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
  244.             dvdnav_audio_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
  245.     }
  246.     free( psz_code );
  247.     /* Set spu language */
  248.     psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );
  249.     if( dvdnav_spu_language_select( p_sys->dvdnav, psz_code ) !=
  250.         DVDNAV_STATUS_OK )
  251.     {
  252.         msg_Warn( p_demux, "can't set spu language to '%s' (%s)",
  253.                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
  254.         /* We try to fall back to 'en' */
  255.         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
  256.             dvdnav_spu_language_select(p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
  257.     }
  258.     free( psz_code );
  259.     DemuxTitles( p_demux );
  260.     var_Create( p_demux, "dvdnav-menu", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
  261.     var_Get( p_demux, "dvdnav-menu", &val );
  262.     if( val.b_bool )
  263.     {
  264.         msg_Dbg( p_demux, "trying to go to dvd menu" );
  265.         if( dvdnav_title_play( p_sys->dvdnav, 1 ) != DVDNAV_STATUS_OK )
  266.         {
  267.             msg_Err( p_demux, "cannot set title (can't decrypt DVD?)" );
  268.             dialog_Fatal( p_demux, _("Playback failure"), "%s",
  269.                             _("VLC cannot set the DVD's title. It possibly "
  270.                               "cannot decrypt the entire disc.") );
  271.             dvdnav_close( p_sys->dvdnav );
  272.             free( p_sys );
  273.             return VLC_EGENERIC;
  274.         }
  275.         if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title ) !=
  276.             DVDNAV_STATUS_OK )
  277.         {
  278.             /* Try going to menu root */
  279.             if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root ) !=
  280.                 DVDNAV_STATUS_OK )
  281.                     msg_Warn( p_demux, "cannot go to dvd menu" );
  282.         }
  283.     }
  284.     var_Create( p_demux, "dvdnav-angle", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  285.     var_Get( p_demux, "dvdnav-angle", &val );
  286.     i_angle = val.i_int > 0 ? val.i_int : 1;
  287.     /* Update default_pts to a suitable value for dvdnav access */
  288.     var_Create( p_demux, "dvdnav-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
  289.     /* FIXME hack hack hack hack FIXME */
  290.     /* Get p_input and create variable */
  291.     p_sys->p_input = vlc_object_find( p_demux, VLC_OBJECT_INPUT, FIND_PARENT );
  292.     var_Create( p_sys->p_input, "x-start", VLC_VAR_INTEGER );
  293.     var_Create( p_sys->p_input, "y-start", VLC_VAR_INTEGER );
  294.     var_Create( p_sys->p_input, "x-end", VLC_VAR_INTEGER );
  295.     var_Create( p_sys->p_input, "y-end", VLC_VAR_INTEGER );
  296.     var_Create( p_sys->p_input, "color", VLC_VAR_ADDRESS );
  297.     var_Create( p_sys->p_input, "menu-palette", VLC_VAR_ADDRESS );
  298.     var_Create( p_sys->p_input, "highlight", VLC_VAR_BOOL );
  299.     var_Create( p_sys->p_input, "highlight-mutex", VLC_VAR_MUTEX );
  300.     /* catch all key event */
  301.     var_AddCallback( p_demux->p_libvlc, "key-action", EventKey, p_demux );
  302.     /* catch vout creation event */
  303.     var_AddCallback( p_sys->p_input, "intf-event", EventIntf, p_demux );
  304.     p_sys->still.b_enabled = false;
  305.     vlc_mutex_init( &p_sys->still.lock );
  306.     return VLC_SUCCESS;
  307. }
  308. /*****************************************************************************
  309.  * Close:
  310.  *****************************************************************************/
  311. static void Close( vlc_object_t *p_this )
  312. {
  313.     demux_t     *p_demux = (demux_t*)p_this;
  314.     demux_sys_t *p_sys = p_demux->p_sys;
  315.     int i;
  316.     /* Stop vout event handler */
  317.     var_DelCallback( p_sys->p_input, "intf-event", EventIntf, p_demux );
  318.     if( p_sys->p_vout != NULL )
  319.     {   /* Should not happen, but better be safe than sorry. */
  320.         msg_Warn( p_sys->p_vout, "removing dangling mouse DVD callbacks" );
  321.         var_DelCallback( p_sys->p_vout, "mouse-moved", EventMouse, p_demux );
  322.         var_DelCallback( p_sys->p_vout, "mouse-clicked", EventMouse, p_demux );
  323.     }
  324.     /* Stop key event handler (FIXME: should really be per-vout too) */
  325.     var_DelCallback( p_demux->p_libvlc, "key-action", EventKey, p_demux );
  326.     /* Stop still image handler */
  327.     if( p_sys->still.b_created )
  328.     {
  329.         vlc_cancel( p_sys->still.thread );
  330.         vlc_join( p_sys->still.thread, NULL );
  331.         vlc_cond_destroy( &p_sys->still.wait );
  332.     }
  333.     vlc_mutex_destroy( &p_sys->still.lock );
  334.     var_Destroy( p_sys->p_input, "highlight-mutex" );
  335.     var_Destroy( p_sys->p_input, "highlight" );
  336.     var_Destroy( p_sys->p_input, "x-start" );
  337.     var_Destroy( p_sys->p_input, "x-end" );
  338.     var_Destroy( p_sys->p_input, "y-start" );
  339.     var_Destroy( p_sys->p_input, "y-end" );
  340.     var_Destroy( p_sys->p_input, "color" );
  341.     var_Destroy( p_sys->p_input, "menu-palette" );
  342.     vlc_object_release( p_sys->p_input );
  343.     for( i = 0; i < PS_TK_COUNT; i++ )
  344.     {
  345.         ps_track_t *tk = &p_sys->tk[i];
  346.         if( tk->b_seen )
  347.         {
  348.             es_format_Clean( &tk->fmt );
  349.             if( tk->es ) es_out_Del( p_demux->out, tk->es );
  350.         }
  351.     }
  352.     dvdnav_close( p_sys->dvdnav );
  353.     free( p_sys );
  354. }
  355. /*****************************************************************************
  356.  * Control:
  357.  *****************************************************************************/
  358. static int Control( demux_t *p_demux, int i_query, va_list args )
  359. {
  360.     demux_sys_t *p_sys = p_demux->p_sys;
  361.     double f, *pf;
  362.     bool *pb;
  363.     int64_t *pi64;
  364.     input_title_t ***ppp_title;
  365.     int          *pi_int;
  366.     int i;
  367.     switch( i_query )
  368.     {
  369.         case DEMUX_SET_POSITION:
  370.         case DEMUX_GET_POSITION:
  371.         case DEMUX_GET_TIME:
  372.         case DEMUX_GET_LENGTH:
  373.         {
  374.             uint32_t pos, len;
  375.             if( dvdnav_get_position( p_sys->dvdnav, &pos, &len ) !=
  376.                   DVDNAV_STATUS_OK || len == 0 )
  377.             {
  378.                 return VLC_EGENERIC;
  379.             }
  380.             if( i_query == DEMUX_GET_POSITION )
  381.             {
  382.                 pf = (double*)va_arg( args, double* );
  383.                 *pf = (double)pos / (double)len;
  384.                 return VLC_SUCCESS;
  385.             }
  386.             else if( i_query == DEMUX_SET_POSITION )
  387.             {
  388.                 f = (double)va_arg( args, double );
  389.                 pos = f * len;
  390.                 if( dvdnav_sector_search( p_sys->dvdnav, pos, SEEK_SET ) ==
  391.                       DVDNAV_STATUS_OK )
  392.                 {
  393.                     return VLC_SUCCESS;
  394.                 }
  395.             }
  396.             else if( i_query == DEMUX_GET_TIME )
  397.             {
  398.                 pi64 = (int64_t*)va_arg( args, int64_t * );
  399.                 if( p_sys->i_pgc_length > 0 )
  400.                 {
  401.                     *pi64 = p_sys->i_pgc_length * pos / len;
  402.                     return VLC_SUCCESS;
  403.                 }
  404.             }
  405.             else if( i_query == DEMUX_GET_LENGTH )
  406.             {
  407.                 pi64 = (int64_t*)va_arg( args, int64_t * );
  408.                 if( p_sys->i_pgc_length > 0 )
  409.                 {
  410.                     *pi64 = (int64_t)p_sys->i_pgc_length;
  411.                     return VLC_SUCCESS;
  412.                 }
  413.             }
  414.             return VLC_EGENERIC;
  415.         }
  416.         /* Special for access_demux */
  417.         case DEMUX_CAN_PAUSE:
  418.         case DEMUX_CAN_SEEK:
  419.         case DEMUX_CAN_CONTROL_PACE:
  420.             /* TODO */
  421.             pb = (bool*)va_arg( args, bool * );
  422.             *pb = true;
  423.             return VLC_SUCCESS;
  424.         case DEMUX_SET_PAUSE_STATE:
  425.             return VLC_SUCCESS;
  426.         case DEMUX_GET_TITLE_INFO:
  427.             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
  428.             pi_int    = (int*)va_arg( args, int* );
  429.             *((int*)va_arg( args, int* )) = 0; /* Title offset */
  430.             *((int*)va_arg( args, int* )) = 1; /* Chapter offset */
  431.             /* Duplicate title infos */
  432.             *pi_int = p_sys->i_title;
  433.             *ppp_title = malloc( sizeof( input_title_t ** ) * p_sys->i_title );
  434.             for( i = 0; i < p_sys->i_title; i++ )
  435.             {
  436.                 (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->title[i] );
  437.             }
  438.             return VLC_SUCCESS;
  439.         case DEMUX_SET_TITLE:
  440.             i = (int)va_arg( args, int );
  441.             if( ( i == 0 && dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root )
  442.                   != DVDNAV_STATUS_OK ) ||
  443.                 ( i != 0 && dvdnav_title_play( p_sys->dvdnav, i )
  444.                   != DVDNAV_STATUS_OK ) )
  445.             {
  446.                 msg_Warn( p_demux, "cannot set title/chapter" );
  447.                 return VLC_EGENERIC;
  448.             }
  449.             p_demux->info.i_update |=
  450.                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
  451.             p_demux->info.i_title = i;
  452.             p_demux->info.i_seekpoint = 0;
  453.             return VLC_SUCCESS;
  454.         case DEMUX_SET_SEEKPOINT:
  455.             i = (int)va_arg( args, int );
  456.             if( p_demux->info.i_title == 0 )
  457.             {
  458.                 int i_ret;
  459.                 /* Special case */
  460.                 switch( i )
  461.                 {
  462.                 case 0:
  463.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Escape );
  464.                     break;
  465.                 case 1:
  466.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root );
  467.                     break;
  468.                 case 2:
  469.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title );
  470.                     break;
  471.                 case 3:
  472.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Part );
  473.                     break;
  474.                 case 4:
  475.                     i_ret = dvdnav_menu_call( p_sys->dvdnav,
  476.                                               DVD_MENU_Subpicture );
  477.                     break;
  478.                 case 5:
  479.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Audio );
  480.                     break;
  481.                 case 6:
  482.                     i_ret = dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Angle );
  483.                     break;
  484.                 default:
  485.                     return VLC_EGENERIC;
  486.                 }
  487.                 if( i_ret != DVDNAV_STATUS_OK )
  488.                     return VLC_EGENERIC;
  489.             }
  490.             else if( dvdnav_part_play( p_sys->dvdnav, p_demux->info.i_title,
  491.                                        i + 1 ) != DVDNAV_STATUS_OK )
  492.             {
  493.                 msg_Warn( p_demux, "cannot set title/chapter" );
  494.                 return VLC_EGENERIC;
  495.             }
  496.             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  497.             p_demux->info.i_seekpoint = i;
  498.             return VLC_SUCCESS;
  499.         case DEMUX_GET_PTS_DELAY:
  500.             pi64 = (int64_t*)va_arg( args, int64_t * );
  501.             *pi64 = (int64_t)var_GetInteger( p_demux, "dvdnav-caching" ) *1000;
  502.             return VLC_SUCCESS;
  503.         case DEMUX_GET_META:
  504.         {
  505.             const char *title_name = NULL;
  506.             dvdnav_get_title_string(p_sys->dvdnav, &title_name);
  507.             if( (NULL != title_name) && ('' != title_name[0]) )
  508.             {
  509.                 vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
  510.                 vlc_meta_Set( p_meta, vlc_meta_Title, title_name );
  511.                 return VLC_SUCCESS;
  512.             }
  513.             return VLC_EGENERIC;
  514.         }
  515.         /* TODO implement others */
  516.         default:
  517.             return VLC_EGENERIC;
  518.     }
  519. }
  520. static int ControlInternal( demux_t *p_demux, int i_query, ... )
  521. {
  522.     va_list args;
  523.     int     i_result;
  524.     va_start( args, i_query );
  525.     i_result = Control( p_demux, i_query, args );
  526.     va_end( args );
  527.     return i_result;
  528. }
  529. /*****************************************************************************
  530.  * Demux:
  531.  *****************************************************************************/
  532. static int Demux( demux_t *p_demux )
  533. {
  534.     demux_sys_t *p_sys = p_demux->p_sys;
  535.     uint8_t buffer[DVD_VIDEO_LB_LEN];
  536.     uint8_t *packet = buffer;
  537.     int i_event;
  538.     int i_len;
  539. #if DVD_READ_CACHE
  540.     if( dvdnav_get_next_cache_block( p_sys->dvdnav, &packet, &i_event, &i_len )
  541.         == DVDNAV_STATUS_ERR )
  542. #else
  543.     if( dvdnav_get_next_block( p_sys->dvdnav, packet, &i_event, &i_len )
  544.         == DVDNAV_STATUS_ERR )
  545. #endif
  546.     {
  547.         msg_Warn( p_demux, "cannot get next block (%s)",
  548.                   dvdnav_err_to_string( p_sys->dvdnav ) );
  549.         if( p_demux->info.i_title == 0 )
  550.         {
  551.             msg_Dbg( p_demux, "jumping to first title" );
  552.             return ControlInternal( p_demux, DEMUX_SET_TITLE, 1 ) == VLC_SUCCESS ? 1 : -1;
  553.         }
  554.         return -1;
  555.     }
  556.     switch( i_event )
  557.     {
  558.     case DVDNAV_BLOCK_OK:   /* mpeg block */
  559.         vlc_mutex_lock( &p_sys->still.lock );
  560.         p_sys->still.b_enabled = false;
  561.         vlc_mutex_unlock( &p_sys->still.lock );
  562.         if( p_sys->b_reset_pcr )
  563.         {
  564.             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  565.             p_sys->b_reset_pcr = false;
  566.         }
  567.         DemuxBlock( p_demux, packet, i_len );
  568.         break;
  569.     case DVDNAV_NOP:    /* Nothing */
  570.         msg_Dbg( p_demux, "DVDNAV_NOP" );
  571.         break;
  572.     case DVDNAV_STILL_FRAME:
  573.     {
  574.         dvdnav_still_event_t *event = (dvdnav_still_event_t*)packet;
  575.         bool b_still_init = false;
  576.         vlc_mutex_lock( &p_sys->still.lock );
  577.         if( !p_sys->still.b_enabled )
  578.         {
  579.             msg_Dbg( p_demux, "DVDNAV_STILL_FRAME" );
  580.             msg_Dbg( p_demux, "     - length=0x%x", event->length );
  581.             /* FIXME: use vlc_timer_create() if it is ever invented */
  582.             p_sys->still.b_enabled = true;
  583.             if( !p_sys->still.b_created )
  584.             {
  585.                 vlc_cond_init( &p_sys->still.wait );
  586.                 p_sys->still.b_created =
  587.                     !vlc_clone( &p_sys->still.thread, StillThread, p_sys,
  588.                                 VLC_THREAD_PRIORITY_LOW );
  589.             }
  590.             b_still_init = true;
  591.             if( event->length == 0xff )
  592.                 p_sys->still.i_end = 0;
  593.             else
  594.                 p_sys->still.i_end = mdate() +
  595.                                      event->length * INT64_C(1000000);
  596.             vlc_cond_signal( &p_sys->still.wait );
  597.         }
  598.         vlc_mutex_unlock( &p_sys->still.lock );
  599.         if( b_still_init )
  600.         {
  601.             /* We send a dummy mpeg2 end of sequence to force still frame display */
  602.             static const uint8_t buffer[] = {
  603.                 0x00, 0x00, 0x01, 0xe0, 0x00, 0x07,
  604.                 0x80, 0x00, 0x00,
  605.                 0x00, 0x00, 0x01, 0xB7,
  606.             };
  607.             DemuxBlock( p_demux, buffer, sizeof(buffer) );
  608.             bool b_empty;
  609.             es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
  610.             p_sys->b_reset_pcr = true;
  611.         }
  612.         msleep( 40000 );
  613.         break;
  614.     }
  615.     case DVDNAV_SPU_CLUT_CHANGE:
  616.     {
  617.         int i;
  618.         msg_Dbg( p_demux, "DVDNAV_SPU_CLUT_CHANGE" );
  619.         /* Update color lookup table (16 *uint32_t in packet) */
  620.         memcpy( p_sys->clut, packet, 16 * sizeof( uint32_t ) );
  621.         /* HACK to get the SPU tracks registered in the right order */
  622.         for( i = 0; i < 0x1f; i++ )
  623.         {
  624.             if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
  625.                 ESNew( p_demux, 0xbd20 + i );
  626.         }
  627.         /* END HACK */
  628.         break;
  629.     }
  630.     case DVDNAV_SPU_STREAM_CHANGE:
  631.     {
  632.         dvdnav_spu_stream_change_event_t *event =
  633.             (dvdnav_spu_stream_change_event_t*)packet;
  634.         int i;
  635.         msg_Dbg( p_demux, "DVDNAV_SPU_STREAM_CHANGE" );
  636.         msg_Dbg( p_demux, "     - physical_wide=%d",
  637.                  event->physical_wide );
  638.         msg_Dbg( p_demux, "     - physical_letterbox=%d",
  639.                  event->physical_letterbox);
  640.         msg_Dbg( p_demux, "     - physical_pan_scan=%d",
  641.                  event->physical_pan_scan );
  642.         ESSubtitleUpdate( p_demux );
  643.         p_sys->b_spu_change = true;
  644.         /* HACK to get the SPU tracks registered in the right order */
  645.         for( i = 0; i < 0x1f; i++ )
  646.         {
  647.             if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
  648.                 ESNew( p_demux, 0xbd20 + i );
  649.         }
  650.         /* END HACK */
  651.         break;
  652.     }
  653.     case DVDNAV_AUDIO_STREAM_CHANGE:
  654.     {
  655.         dvdnav_audio_stream_change_event_t *event =
  656.             (dvdnav_audio_stream_change_event_t*)packet;
  657.         msg_Dbg( p_demux, "DVDNAV_AUDIO_STREAM_CHANGE" );
  658.         msg_Dbg( p_demux, "     - physical=%d", event->physical );
  659.         /* TODO */
  660.         break;
  661.     }
  662.     case DVDNAV_VTS_CHANGE:
  663.     {
  664.         int32_t i_title = 0;
  665.         int32_t i_part  = 0;
  666.         int i;
  667.         dvdnav_vts_change_event_t *event = (dvdnav_vts_change_event_t*)packet;
  668.         msg_Dbg( p_demux, "DVDNAV_VTS_CHANGE" );
  669.         msg_Dbg( p_demux, "     - vtsN=%d", event->new_vtsN );
  670.         msg_Dbg( p_demux, "     - domain=%d", event->new_domain );
  671.         /* dvdnav_get_video_aspect / dvdnav_get_video_scale_permission */
  672.         /* TODO check if we always have VTS and CELL */
  673.         p_sys->i_aspect = dvdnav_get_video_aspect( p_sys->dvdnav );
  674.         /* reset PCR */
  675.         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  676.         for( i = 0; i < PS_TK_COUNT; i++ )
  677.         {
  678.             ps_track_t *tk = &p_sys->tk[i];
  679.             if( tk->b_seen )
  680.             {
  681.                 es_format_Clean( &tk->fmt );
  682.                 if( tk->es ) es_out_Del( p_demux->out, tk->es );
  683.             }
  684.             tk->b_seen = false;
  685.         }
  686.         if( dvdnav_current_title_info( p_sys->dvdnav, &i_title,
  687.                                        &i_part ) == DVDNAV_STATUS_OK )
  688.         {
  689.             if( i_title >= 0 && i_title < p_sys->i_title &&
  690.                 p_demux->info.i_title != i_title )
  691.             {
  692.                 p_demux->info.i_update |= INPUT_UPDATE_TITLE;
  693.                 p_demux->info.i_title = i_title;
  694.             }
  695.         }
  696.         break;
  697.     }
  698.     case DVDNAV_CELL_CHANGE:
  699.     {
  700.         int32_t i_title = 0;
  701.         int32_t i_part  = 0;
  702.         dvdnav_cell_change_event_t *event =
  703.             (dvdnav_cell_change_event_t*)packet;
  704.         msg_Dbg( p_demux, "DVDNAV_CELL_CHANGE" );
  705.         msg_Dbg( p_demux, "     - cellN=%d", event->cellN );
  706.         msg_Dbg( p_demux, "     - pgN=%d", event->pgN );
  707.         msg_Dbg( p_demux, "     - cell_length=%"PRId64, event->cell_length );
  708.         msg_Dbg( p_demux, "     - pg_length=%"PRId64, event->pg_length );
  709.         msg_Dbg( p_demux, "     - pgc_length=%"PRId64, event->pgc_length );
  710.         msg_Dbg( p_demux, "     - cell_start=%"PRId64, event->cell_start );
  711.         msg_Dbg( p_demux, "     - pg_start=%"PRId64, event->pg_start );
  712.         /* Store the lenght in time of the current PGC */
  713.         p_sys->i_pgc_length = event->pgc_length / 90 * 1000;
  714.         /* FIXME is it correct or there is better way to know chapter change */
  715.         if( dvdnav_current_title_info( p_sys->dvdnav, &i_title,
  716.                                        &i_part ) == DVDNAV_STATUS_OK )
  717.         {
  718.             if( i_title >= 0 && i_title < p_sys->i_title &&
  719.                 i_part >= 1 && i_part <= p_sys->title[i_title]->i_seekpoint &&
  720.                 p_demux->info.i_seekpoint != i_part - 1 )
  721.             {
  722.                 p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
  723.                 p_demux->info.i_seekpoint = i_part - 1;
  724.             }
  725.         }
  726.         break;
  727.     }
  728.     case DVDNAV_NAV_PACKET:
  729.     {
  730. #ifdef DVDNAV_DEBUG
  731.         msg_Dbg( p_demux, "DVDNAV_NAV_PACKET" );
  732. #endif
  733.         /* A lot of thing to do here :
  734.          *  - handle packet
  735.          *  - fetch pts (for time display)
  736.          *  - ...
  737.          */
  738.         DemuxBlock( p_demux, packet, i_len );
  739.         if( p_sys->b_spu_change )
  740.         {
  741.             ButtonUpdate( p_demux, false );
  742.             p_sys->b_spu_change = false;
  743.         }
  744.         break;
  745.     }
  746.     case DVDNAV_STOP:   /* EOF */
  747.         msg_Dbg( p_demux, "DVDNAV_STOP" );
  748. #if DVD_READ_CACHE
  749.         dvdnav_free_cache_block( p_sys->dvdnav, packet );
  750. #endif
  751.         return 0;
  752.     case DVDNAV_HIGHLIGHT:
  753.     {
  754.         dvdnav_highlight_event_t *event = (dvdnav_highlight_event_t*)packet;
  755.         msg_Dbg( p_demux, "DVDNAV_HIGHLIGHT" );
  756.         msg_Dbg( p_demux, "     - display=%d", event->display );
  757.         msg_Dbg( p_demux, "     - buttonN=%d", event->buttonN );
  758.         ButtonUpdate( p_demux, false );
  759.         break;
  760.     }
  761.     case DVDNAV_HOP_CHANNEL:
  762.         msg_Dbg( p_demux, "DVDNAV_HOP_CHANNEL" );
  763.         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  764.         break;
  765.     case DVDNAV_WAIT:
  766.         msg_Dbg( p_demux, "DVDNAV_WAIT" );
  767.         bool b_empty;
  768.         es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
  769.         if( !b_empty )
  770.         {
  771.             msleep( 40*1000 );
  772.         }
  773.         else
  774.         {
  775.             dvdnav_wait_skip( p_sys->dvdnav );
  776.             p_sys->b_reset_pcr = true;
  777.         }
  778.         break;
  779.     default:
  780.         msg_Warn( p_demux, "Unknown event (0x%x)", i_event );
  781.         break;
  782.     }
  783. #if DVD_READ_CACHE
  784.     dvdnav_free_cache_block( p_sys->dvdnav, packet );
  785. #endif
  786.     return 1;
  787. }
  788. /* Get a 2 char code
  789.  * FIXME: partiallyy duplicated from src/input/es_out.c
  790.  */
  791. static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var )
  792. {
  793.     const iso639_lang_t *pl;
  794.     char *psz_lang;
  795.     char *p;
  796.     psz_lang = var_CreateGetString( p_demux, psz_var );
  797.     if( !psz_lang )
  798.         return strdup(LANGUAGE_DEFAULT);
  799.     /* XXX: we will use only the first value
  800.      * (and ignore other ones in case of a list) */
  801.     if( ( p = strchr( psz_lang, ',' ) ) )
  802.         *p = '';
  803.     for( pl = p_languages; pl->psz_iso639_1 != NULL; pl++ )
  804.     {
  805.         if( *psz_lang == '' )
  806.             continue;
  807.         if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
  808.             !strcasecmp( pl->psz_native_name, psz_lang ) ||
  809.             !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
  810.             !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
  811.             !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
  812.             break;
  813.     }
  814.     free( psz_lang );
  815.     if( pl->psz_iso639_1 != NULL )
  816.         return strdup( pl->psz_iso639_1 );
  817.     return strdup(LANGUAGE_DEFAULT);
  818. }
  819. static void DemuxTitles( demux_t *p_demux )
  820. {
  821.     demux_sys_t *p_sys = p_demux->p_sys;
  822.     input_title_t *t;
  823.     seekpoint_t *s;
  824.     int32_t i_titles;
  825.     int i;
  826.     /* Menu */
  827.     t = vlc_input_title_New();
  828.     t->b_menu = true;
  829.     t->psz_name = strdup( "DVD Menu" );
  830.     s = vlc_seekpoint_New();
  831.     s->psz_name = strdup( "Resume" );
  832.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  833.     s = vlc_seekpoint_New();
  834.     s->psz_name = strdup( "Root" );
  835.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  836.     s = vlc_seekpoint_New();
  837.     s->psz_name = strdup( "Title" );
  838.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  839.     s = vlc_seekpoint_New();
  840.     s->psz_name = strdup( "Chapter" );
  841.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  842.     s = vlc_seekpoint_New();
  843.     s->psz_name = strdup( "Subtitle" );
  844.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  845.     s = vlc_seekpoint_New();
  846.     s->psz_name = strdup( "Audio" );
  847.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  848.     s = vlc_seekpoint_New();
  849.     s->psz_name = strdup( "Angle" );
  850.     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  851.     TAB_APPEND( p_sys->i_title, p_sys->title, t );
  852.     /* Find out number of titles/chapters */
  853.     dvdnav_get_number_of_titles( p_sys->dvdnav, &i_titles );
  854.     for( i = 1; i <= i_titles; i++ )
  855.     {
  856.         int32_t i_chapters = 0;
  857.         int j;
  858.         dvdnav_get_number_of_parts( p_sys->dvdnav, i, &i_chapters );
  859.         t = vlc_input_title_New();
  860.         for( j = 0; j < __MAX( i_chapters, 1 ); j++ )
  861.         {
  862.             s = vlc_seekpoint_New();
  863.             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
  864.         }
  865.         TAB_APPEND( p_sys->i_title, p_sys->title, t );
  866.     }
  867. }
  868. /*****************************************************************************
  869.  * Update functions:
  870.  *****************************************************************************/
  871. static void ButtonUpdate( demux_t *p_demux, bool b_mode )
  872. {
  873.     demux_sys_t *p_sys = p_demux->p_sys;
  874.     vlc_value_t val;
  875.     int32_t i_title, i_part;
  876.     dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
  877.     if( var_Get( p_sys->p_input, "highlight-mutex", &val ) == VLC_SUCCESS )
  878.     {
  879.         vlc_mutex_t *p_mutex = val.p_address;
  880.         dvdnav_highlight_area_t hl;
  881.         int32_t i_button;
  882.         bool    b_button_ok;
  883.         if( dvdnav_get_current_highlight( p_sys->dvdnav, &i_button )
  884.             != DVDNAV_STATUS_OK )
  885.         {
  886.             msg_Err( p_demux, "dvdnav_get_current_highlight failed" );
  887.             return;
  888.         }
  889.         b_button_ok = false;
  890.         if( i_button > 0 && i_title ==  0 )
  891.         {
  892.             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
  893.             b_button_ok = dvdnav_get_highlight_area( pci, i_button, b_mode, &hl ) == DVDNAV_STATUS_OK;
  894.         }
  895.         if( b_button_ok )
  896.         {
  897.             int i;
  898.             for( i = 0; i < 4; i++ )
  899.             {
  900.                 uint32_t i_yuv = p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
  901.                 uint8_t i_alpha = ( (hl.palette>>(i*4))&0x0f ) * 0xff / 0xf;
  902.                 p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
  903.                 p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
  904.                 p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
  905.                 p_sys->palette[i][3] = i_alpha;
  906.             }
  907.             vlc_mutex_lock( p_mutex );
  908.             val.i_int = hl.sx; var_Set( p_sys->p_input, "x-start", val );
  909.             val.i_int = hl.ex; var_Set( p_sys->p_input, "x-end", val );
  910.             val.i_int = hl.sy; var_Set( p_sys->p_input, "y-start", val );
  911.             val.i_int = hl.ey; var_Set( p_sys->p_input, "y-end", val );
  912.             val.p_address = (void *)p_sys->palette;
  913.             var_Set( p_sys->p_input, "menu-palette", val );
  914.             val.b_bool = true; var_Set( p_sys->p_input, "highlight", val );
  915.             vlc_mutex_unlock( p_mutex );
  916.             msg_Dbg( p_demux, "buttonUpdate %d", i_button );
  917.         }
  918.         else
  919.         {
  920.             msg_Dbg( p_demux, "buttonUpdate not done b=%d t=%d",
  921.                      i_button, i_title );
  922.             /* Show all */
  923.             vlc_mutex_lock( p_mutex );
  924.             val.b_bool = false;
  925.             var_Set( p_sys->p_input, "highlight", val );
  926.             vlc_mutex_unlock( p_mutex );
  927.         }
  928.     }
  929. }
  930. static void ESSubtitleUpdate( demux_t *p_demux )
  931. {
  932.     demux_sys_t *p_sys = p_demux->p_sys;
  933.     int         i_spu = dvdnav_get_active_spu_stream( p_sys->dvdnav );
  934.     int32_t i_title, i_part;
  935.     ButtonUpdate( p_demux, false );
  936.     dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
  937.     if( i_title > 0 ) return;
  938.     if( i_spu >= 0 && i_spu <= 0x1f )
  939.     {
  940.         ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)];
  941.         ESNew( p_demux, 0xbd20 + i_spu );
  942.         /* be sure to unselect it (reset) */
  943.         es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es,
  944.                         (bool)false );
  945.         /* now select it */
  946.         es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es );
  947.     }
  948.     else
  949.     {
  950.         for( i_spu = 0; i_spu <= 0x1F; i_spu++ )
  951.         {
  952.             ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)];
  953.             if( tk->b_seen )
  954.             {
  955.                 es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es,
  956.                                 (bool)false );
  957.             }
  958.         }
  959.     }
  960. }
  961. /*****************************************************************************
  962.  * DemuxBlock: demux a given block
  963.  *****************************************************************************/
  964. static int DemuxBlock( demux_t *p_demux, const uint8_t *pkt, int i_pkt )
  965. {
  966.     demux_sys_t *p_sys = p_demux->p_sys;
  967.     const uint8_t     *p = pkt;
  968.     while( p < &pkt[i_pkt] )
  969.     {
  970.         int i_size = ps_pkt_size( p, &pkt[i_pkt] - p );
  971.         block_t *p_pkt;
  972.         if( i_size <= 0 )
  973.         {
  974.             break;
  975.         }
  976.         /* Create a block */
  977.         p_pkt = block_New( p_demux, i_size );
  978.         memcpy( p_pkt->p_buffer, p, i_size);
  979.         /* Parse it and send it */
  980.         switch( 0x100 | p[3] )
  981.         {
  982.         case 0x1b9:
  983.         case 0x1bb:
  984.         case 0x1bc:
  985. #ifdef DVDNAV_DEBUG
  986.             if( p[3] == 0xbc )
  987.             {
  988.                 msg_Warn( p_demux, "received a PSM packet" );
  989.             }
  990.             else if( p[3] == 0xbb )
  991.             {
  992.                 msg_Warn( p_demux, "received a SYSTEM packet" );
  993.             }
  994. #endif
  995.             block_Release( p_pkt );
  996.             break;
  997.         case 0x1ba:
  998.         {
  999.             int64_t i_scr;
  1000.             int i_mux_rate;
  1001.             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
  1002.             {
  1003.                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr + 1 );
  1004.                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
  1005.             }
  1006.             block_Release( p_pkt );
  1007.             break;
  1008.         }
  1009.         default:
  1010.         {
  1011.             int i_id = ps_pkt_id( p_pkt );
  1012.             if( i_id >= 0xc0 )
  1013.             {
  1014.                 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  1015.                 if( !tk->b_seen )
  1016.                 {
  1017.                     ESNew( p_demux, i_id );
  1018.                 }
  1019.                 if( tk->b_seen && tk->es &&
  1020.                     !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
  1021.                 {
  1022.                     es_out_Send( p_demux->out, tk->es, p_pkt );
  1023.                 }
  1024.                 else
  1025.                 {
  1026.                     block_Release( p_pkt );
  1027.                 }
  1028.             }
  1029.             else
  1030.             {
  1031.                 block_Release( p_pkt );
  1032.             }
  1033.             break;
  1034.         }
  1035.         }
  1036.         p += i_size;
  1037.     }
  1038.     return VLC_SUCCESS;
  1039. }
  1040. /*****************************************************************************
  1041.  * ESNew: register a new elementary stream
  1042.  *****************************************************************************/
  1043. static void ESNew( demux_t *p_demux, int i_id )
  1044. {
  1045.     demux_sys_t *p_sys = p_demux->p_sys;
  1046.     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  1047.     bool  b_select = false;
  1048.     if( tk->b_seen ) return;
  1049.     if( ps_track_fill( tk, 0, i_id ) )
  1050.     {
  1051.         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
  1052.         return;
  1053.     }
  1054.     /* Add a new ES */
  1055.     if( tk->fmt.i_cat == VIDEO_ES )
  1056.     {
  1057.         switch( p_sys->i_aspect )
  1058.         {
  1059.         case 1: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR; break;
  1060.         case 2: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 4 / 3; break;
  1061.         case 3: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 16 / 9; break;
  1062.         case 4: tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * 221 / 10; break;
  1063.         default:
  1064.             tk->fmt.video.i_aspect = 0;
  1065.             break;
  1066.         }
  1067.         b_select = true;
  1068.     }
  1069.     else if( tk->fmt.i_cat == AUDIO_ES )
  1070.     {
  1071.         int i_audio = -1;
  1072.         /* find the audio number PLEASE find another way */
  1073.         if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
  1074.         {
  1075.             i_audio = i_id&0x07;
  1076.         }
  1077.         else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
  1078.         {
  1079.             i_audio = i_id&0xf;
  1080.         }
  1081.         else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
  1082.         {
  1083.             i_audio = i_id&0x1f;
  1084.         }
  1085.         else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
  1086.         {
  1087.             i_audio = i_id&0x1f;
  1088.         }
  1089.         if( i_audio >= 0 )
  1090.         {
  1091.             int i_lang = dvdnav_audio_stream_to_lang( p_sys->dvdnav, i_audio );
  1092.             if( i_lang != 0xffff )
  1093.             {
  1094.                 tk->fmt.psz_language = malloc( 3 );
  1095.                 tk->fmt.psz_language[0] = (i_lang >> 8)&0xff;
  1096.                 tk->fmt.psz_language[1] = (i_lang     )&0xff;
  1097.                 tk->fmt.psz_language[2] = 0;
  1098.             }
  1099.             if( dvdnav_get_active_audio_stream( p_sys->dvdnav ) == i_audio )
  1100.             {
  1101.                 b_select = true;
  1102.             }
  1103.         }
  1104.     }
  1105.     else if( tk->fmt.i_cat == SPU_ES )
  1106.     {
  1107.         int32_t i_title, i_part;
  1108.         int i_lang = dvdnav_spu_stream_to_lang( p_sys->dvdnav, i_id&0x1f );
  1109.         if( i_lang != 0xffff )
  1110.         {
  1111.             tk->fmt.psz_language = malloc( 3 );
  1112.             tk->fmt.psz_language[0] = (i_lang >> 8)&0xff;
  1113.             tk->fmt.psz_language[1] = (i_lang     )&0xff;
  1114.             tk->fmt.psz_language[2] = 0;
  1115.         }
  1116.         /* Palette */
  1117.         tk->fmt.subs.spu.palette[0] = 0xBeef;
  1118.         memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
  1119.                 16 * sizeof( uint32_t ) );
  1120.         /* We select only when we are not in the menu */
  1121.         dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
  1122.         if( i_title > 0 &&
  1123.             dvdnav_get_active_spu_stream( p_sys->dvdnav ) == (i_id&0x1f) )
  1124.         {
  1125.             b_select = true;
  1126.         }
  1127.     }
  1128.     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  1129.     if( b_select )
  1130.     {
  1131.         es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es );
  1132.     }
  1133.     tk->b_seen = true;
  1134.     if( tk->fmt.i_cat == VIDEO_ES ) ButtonUpdate( p_demux, false );
  1135. }
  1136. /*****************************************************************************
  1137.  * Event handler code
  1138.  *****************************************************************************/
  1139. static void* StillThread( void *p_data )
  1140. {
  1141.     demux_sys_t    *p_sys = p_data;
  1142.     vlc_mutex_lock( &p_sys->still.lock );
  1143.     mutex_cleanup_push( &p_sys->still.lock );
  1144.     for( ;; )
  1145.     {
  1146.         if( p_sys->still.b_enabled && p_sys->still.i_end )
  1147.         {
  1148.             if( vlc_cond_timedwait( &p_sys->still.wait, &p_sys->still.lock,
  1149.                                     p_sys->still.i_end ) )
  1150.             {   /* Still image time out */
  1151.                 int canc = vlc_savecancel();
  1152.                 p_sys->still.b_enabled = false;
  1153.                 dvdnav_still_skip( p_sys->dvdnav );
  1154.                 vlc_restorecancel( canc );
  1155.             }
  1156.         }
  1157.         else
  1158.             vlc_cond_wait( &p_sys->still.wait, &p_sys->still.lock );
  1159.     }
  1160.     vlc_cleanup_pop(  );
  1161.     assert( 0 );
  1162. }
  1163. static int EventMouse( vlc_object_t *p_vout, char const *psz_var,
  1164.                        vlc_value_t oldval, vlc_value_t val, void *p_data )
  1165. {
  1166.     demux_t *p_demux = p_data;
  1167.     demux_sys_t *p_sys = p_demux->p_sys;
  1168.     /* FIXME? PCI usage thread safe? */
  1169.     pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
  1170.     int x = var_GetInteger( p_vout, "mouse-x" );
  1171.     int y = var_GetInteger( p_vout, "mouse-y" );
  1172.     if( psz_var[6] == 'm' ) /* mouse-moved */
  1173.         dvdnav_mouse_select( p_sys->dvdnav, pci, x, y );
  1174.     else
  1175.     {
  1176.         assert( psz_var[6] == 'c' ); /* mouse-clicked */
  1177.         ButtonUpdate( p_demux, true );
  1178.         dvdnav_mouse_activate( p_sys->dvdnav, pci, x, y );
  1179.     }
  1180.     (void)oldval; (void)val;
  1181.     return VLC_SUCCESS;
  1182. }
  1183. static int EventKey( vlc_object_t *p_this, char const *psz_var,
  1184.                      vlc_value_t oldval, vlc_value_t newval, void *p_data )
  1185. {
  1186.     demux_t *p_demux = p_data;
  1187.     demux_sys_t *p_sys = p_demux->p_sys;
  1188.     /* FIXME: thread-safe ? */
  1189.     pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
  1190.     switch( newval.i_int )
  1191.     {
  1192.     case ACTIONID_NAV_LEFT:
  1193.         dvdnav_left_button_select( p_sys->dvdnav, pci );
  1194.         break;
  1195.     case ACTIONID_NAV_RIGHT:
  1196.         dvdnav_right_button_select( p_sys->dvdnav, pci );
  1197.         break;
  1198.     case ACTIONID_NAV_UP:
  1199.         dvdnav_upper_button_select( p_sys->dvdnav, pci );
  1200.         break;
  1201.     case ACTIONID_NAV_DOWN:
  1202.         dvdnav_lower_button_select( p_sys->dvdnav, pci );
  1203.         break;
  1204.     case ACTIONID_NAV_ACTIVATE:
  1205.         ButtonUpdate( p_demux, true );
  1206.         dvdnav_button_activate( p_sys->dvdnav, pci );
  1207.         break;
  1208.     }
  1209.     (void)p_this;    (void)psz_var;    (void)oldval;
  1210.     return VLC_SUCCESS;
  1211. }
  1212. static int EventIntf( vlc_object_t *p_input, char const *psz_var,
  1213.                       vlc_value_t oldval, vlc_value_t val, void *p_data )
  1214. {
  1215.     demux_t *p_demux = p_data;
  1216.     demux_sys_t *p_sys = p_demux->p_sys;
  1217.     if (val.i_int == INPUT_EVENT_VOUT)
  1218.     {
  1219.         vlc_object_t *p_vout;
  1220.         p_vout = p_sys->p_vout;
  1221.         if( p_vout != NULL )
  1222.         {
  1223.             var_DelCallback( p_vout, "mouse-moved", EventMouse, p_demux );
  1224.             var_DelCallback( p_vout, "mouse-clicked", EventMouse, p_demux );
  1225.             vlc_object_release( p_vout );
  1226.         }
  1227.         p_vout = (vlc_object_t *)input_GetVout( (input_thread_t *)p_input );
  1228.         p_sys->p_vout = p_vout;
  1229.         if( p_vout != NULL )
  1230.         {
  1231.             var_AddCallback( p_vout, "mouse-moved", EventMouse, p_demux );
  1232.             var_AddCallback( p_vout, "mouse-clicked", EventMouse, p_demux );
  1233.         }
  1234.     }
  1235.     (void) psz_var; (void) oldval;
  1236.     return VLC_SUCCESS;
  1237. }
  1238. /*****************************************************************************
  1239.  * ProbeDVD: very weak probing that avoids going too often into a dvdnav_open()
  1240.  *****************************************************************************/
  1241. static int ProbeDVD( demux_t *p_demux, char *psz_name )
  1242. {
  1243.     (void)p_demux;
  1244. #ifdef HAVE_SYS_STAT_H
  1245.     struct stat stat_info;
  1246.     uint8_t pi_anchor[2];
  1247.     int i_fd, i_ret;
  1248.     if( !*psz_name )
  1249.     {
  1250.         /* Triggers libdvdcss autodetection */
  1251.         return VLC_SUCCESS;
  1252.     }
  1253.     if( !strcmp( psz_name, "-" ) ) /* stdin -> file access */
  1254.         return VLC_EGENERIC;
  1255.     if( (i_fd = utf8_open( psz_name, O_RDONLY |O_NONBLOCK, 0666 )) == -1 )
  1256.     {
  1257.         return VLC_SUCCESS; /* Let dvdnav_open() do the probing */
  1258.     }
  1259.     if( fstat( i_fd, &stat_info ) || !S_ISREG( stat_info.st_mode ) )
  1260.     {
  1261.         close( i_fd );
  1262.         if( S_ISFIFO( stat_info.st_mode ) )
  1263.             return VLC_EGENERIC;
  1264.         return VLC_SUCCESS; /* Let dvdnav_open() do the probing */
  1265.     }
  1266.     /* Try to find the anchor (2 bytes at LBA 256) */
  1267.     i_ret = VLC_EGENERIC;
  1268.     if( lseek( i_fd, 256 * DVD_VIDEO_LB_LEN, SEEK_SET ) != -1
  1269.      && read( i_fd, pi_anchor, 2 ) == 2
  1270.      && GetWLE( pi_anchor ) == 2 )
  1271.         i_ret = VLC_SUCCESS; /* Found a potential anchor */
  1272.     close( i_fd );
  1273.     return i_ret;
  1274. #else
  1275.     return VLC_SUCCESS;
  1276. #endif
  1277. }