07093b1a96b19e7af77c035ad81e4914c9b74147
[vlc.git] / modules / access / dvdnav.c
1 /*****************************************************************************
2  * dvdnav.c: DVD module using the dvdnav library.
3  *****************************************************************************
4  * Copyright (C) 2004-2009 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * NOTA BENE: this module requires the linking against a library which is
26  * known to require licensing under the GNU General Public License version 2
27  * (or later). Therefore, the result of compiling this module will normally
28  * be subject to the terms of that later license.
29  *****************************************************************************/
30
31
32 /*****************************************************************************
33  * Preamble
34  *****************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <assert.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #include <unistd.h>     /* close() */
45
46 #include <vlc_common.h>
47 #include <vlc_plugin.h>
48 #include <vlc_input.h>
49 #include <vlc_access.h>
50 #include <vlc_demux.h>
51 #include <vlc_charset.h>
52 #include <vlc_fs.h>
53 #include <vlc_vout.h>
54 #include <vlc_dialog.h>
55 #include <vlc_iso_lang.h>
56
57 /* FIXME we should find a better way than including that */
58 #include "../../src/text/iso-639_def.h"
59
60
61 #include <dvdnav/dvdnav.h>
62
63 #include "../demux/mpeg/pes.h"
64 #include "../demux/mpeg/ps.h"
65
66 /*****************************************************************************
67  * Module descriptor
68  *****************************************************************************/
69 #define ANGLE_TEXT N_("DVD angle")
70 #define ANGLE_LONGTEXT N_( \
71      "Default DVD angle." )
72
73 #define MENU_TEXT N_("Start directly in menu")
74 #define MENU_LONGTEXT N_( \
75     "Start the DVD directly in the main menu. This "\
76     "will try to skip all the useless warning introductions." )
77
78 #define LANGUAGE_DEFAULT ("en")
79
80 static int  AccessDemuxOpen ( vlc_object_t * );
81 static void Close( vlc_object_t * );
82
83 #if DVDREAD_VERSION >= 50300 && defined( HAVE_STREAM_CB_IN_DVDNAV_H )
84 #define HAVE_DVDNAV_DEMUX
85 static int  DemuxOpen ( vlc_object_t * );
86 #endif
87
88 vlc_module_begin ()
89     set_shortname( N_("DVD with menus") )
90     set_description( N_("DVDnav Input") )
91     set_category( CAT_INPUT )
92     set_subcategory( SUBCAT_INPUT_ACCESS )
93     add_integer( "dvdnav-angle", 1, ANGLE_TEXT,
94         ANGLE_LONGTEXT, false )
95     add_bool( "dvdnav-menu", true,
96         MENU_TEXT, MENU_LONGTEXT, false )
97     set_capability( "access_demux", 5 )
98     add_shortcut( "dvd", "dvdnav", "file" )
99     set_callbacks( AccessDemuxOpen, Close )
100 #ifdef HAVE_DVDNAV_DEMUX
101     add_submodule()
102         set_description( N_("DVDnav demuxer") )
103         set_category( CAT_INPUT )
104         set_subcategory( SUBCAT_INPUT_DEMUX )
105         set_capability( "demux", 5 )
106         set_callbacks( DemuxOpen, Close )
107         add_shortcut( "dvd", "iso" )
108 #endif
109 vlc_module_end ()
110
111 /* Shall we use libdvdnav's read ahead cache? */
112 #ifdef __OS2__
113 #define DVD_READ_CACHE 0
114 #else
115 #define DVD_READ_CACHE 1
116 #endif
117
118 /*****************************************************************************
119  * Local prototypes
120  *****************************************************************************/
121 struct demux_sys_t
122 {
123     dvdnav_t    *dvdnav;
124
125     /* */
126     bool        b_reset_pcr;
127     bool        b_readahead;
128
129     struct
130     {
131         bool         b_created;
132         bool         b_enabled;
133         vlc_mutex_t  lock;
134         vlc_timer_t  timer;
135     } still;
136
137     /* track */
138     ps_track_t  tk[PS_TK_COUNT];
139     int         i_mux_rate;
140
141     /* event */
142     vout_thread_t *p_vout;
143
144     /* palette for menus */
145     uint32_t clut[16];
146     uint8_t  palette[4][4];
147     bool b_spu_change;
148
149     /* Aspect ration */
150     struct {
151         unsigned i_num;
152         unsigned i_den;
153     } sar;
154
155     /* */
156     int           i_title;
157     input_title_t **title;
158
159     /* length of program group chain */
160     mtime_t     i_pgc_length;
161     int         i_vobu_index;
162     int         i_vobu_flush;
163 };
164
165 static int Control( demux_t *, int, va_list );
166 static int Demux( demux_t * );
167 static int DemuxBlock( demux_t *, const uint8_t *, int );
168 static void DemuxForceStill( demux_t * );
169
170 static void DemuxTitles( demux_t * );
171 static void ESSubtitleUpdate( demux_t * );
172 static void ButtonUpdate( demux_t *, bool );
173
174 static void ESNew( demux_t *, int );
175 static int ProbeDVD( const char * );
176
177 static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var );
178
179 static int ControlInternal( demux_t *, int, ... );
180
181 static void StillTimer( void * );
182
183 static int EventMouse( vlc_object_t *, char const *,
184                        vlc_value_t, vlc_value_t, void * );
185 static int EventIntf( vlc_object_t *, char const *,
186                       vlc_value_t, vlc_value_t, void * );
187
188 /*****************************************************************************
189  * CommonOpen:
190  *****************************************************************************/
191 static int CommonOpen( vlc_object_t *p_this,
192                        dvdnav_t *p_dvdnav, bool b_readahead )
193 {
194     demux_t     *p_demux = (demux_t*)p_this;
195     demux_sys_t *p_sys;
196     int         i_angle;
197     char        *psz_code;
198
199     assert( p_dvdnav );
200
201     /* Fill p_demux field */
202     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
203     p_sys->dvdnav = p_dvdnav;
204     p_sys->b_reset_pcr = false;
205
206     ps_track_init( p_sys->tk );
207     p_sys->sar.i_num = 0;
208     p_sys->sar.i_den = 0;
209     p_sys->i_mux_rate = 0;
210     p_sys->i_pgc_length = 0;
211     p_sys->b_spu_change = false;
212     p_sys->i_vobu_index = 0;
213     p_sys->i_vobu_flush = 0;
214     p_sys->b_readahead = b_readahead;
215
216     if( 1 )
217     {
218         // Hack for libdvdnav CVS.
219         // Without it dvdnav_get_number_of_titles() fails.
220         // Remove when fixed in libdvdnav CVS.
221         uint8_t buffer[DVD_VIDEO_LB_LEN];
222         int i_event, i_len;
223
224         if( dvdnav_get_next_block( p_sys->dvdnav, buffer, &i_event, &i_len )
225               == DVDNAV_STATUS_ERR )
226         {
227             msg_Warn( p_demux, "dvdnav_get_next_block failed" );
228         }
229
230         dvdnav_sector_search( p_sys->dvdnav, 0, SEEK_SET );
231     }
232
233     /* Configure dvdnav */
234     if( dvdnav_set_readahead_flag( p_sys->dvdnav, p_sys->b_readahead ) !=
235           DVDNAV_STATUS_OK )
236     {
237         msg_Warn( p_demux, "cannot set read-a-head flag" );
238     }
239
240     if( dvdnav_set_PGC_positioning_flag( p_sys->dvdnav, 1 ) !=
241           DVDNAV_STATUS_OK )
242     {
243         msg_Warn( p_demux, "cannot set PGC positioning flag" );
244     }
245
246     /* Set menu language */
247     psz_code = DemuxGetLanguageCode( p_demux, "menu-language" );
248     if( dvdnav_menu_language_select( p_sys->dvdnav, psz_code ) !=
249         DVDNAV_STATUS_OK )
250     {
251         msg_Warn( p_demux, "can't set menu language to '%s' (%s)",
252                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
253         /* We try to fall back to 'en' */
254         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
255             dvdnav_menu_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
256     }
257     free( psz_code );
258
259     /* Set audio language */
260     psz_code = DemuxGetLanguageCode( p_demux, "audio-language" );
261     if( dvdnav_audio_language_select( p_sys->dvdnav, psz_code ) !=
262         DVDNAV_STATUS_OK )
263     {
264         msg_Warn( p_demux, "can't set audio language to '%s' (%s)",
265                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
266         /* We try to fall back to 'en' */
267         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
268             dvdnav_audio_language_select( p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
269     }
270     free( psz_code );
271
272     /* Set spu language */
273     psz_code = DemuxGetLanguageCode( p_demux, "sub-language" );
274     if( dvdnav_spu_language_select( p_sys->dvdnav, psz_code ) !=
275         DVDNAV_STATUS_OK )
276     {
277         msg_Warn( p_demux, "can't set spu language to '%s' (%s)",
278                   psz_code, dvdnav_err_to_string( p_sys->dvdnav ) );
279         /* We try to fall back to 'en' */
280         if( strcmp( psz_code, LANGUAGE_DEFAULT ) )
281             dvdnav_spu_language_select(p_sys->dvdnav, (char*)LANGUAGE_DEFAULT );
282     }
283     free( psz_code );
284
285     DemuxTitles( p_demux );
286
287     if( var_CreateGetBool( p_demux, "dvdnav-menu" ) )
288     {
289         msg_Dbg( p_demux, "trying to go to dvd menu" );
290
291         if( dvdnav_title_play( p_sys->dvdnav, 1 ) != DVDNAV_STATUS_OK )
292         {
293             msg_Err( p_demux, "cannot set title (can't decrypt DVD?)" );
294             dialog_Fatal( p_demux, _("Playback failure"), "%s",
295                             _("VLC cannot set the DVD's title. It possibly "
296                               "cannot decrypt the entire disc.") );
297             free( p_sys );
298             return VLC_EGENERIC;
299         }
300
301         if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Title ) !=
302             DVDNAV_STATUS_OK )
303         {
304             /* Try going to menu root */
305             if( dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root ) !=
306                 DVDNAV_STATUS_OK )
307                     msg_Warn( p_demux, "cannot go to dvd menu" );
308         }
309     }
310
311     i_angle = var_CreateGetInteger( p_demux, "dvdnav-angle" );
312     if( i_angle <= 0 ) i_angle = 1;
313
314     /* FIXME hack hack hack hack FIXME */
315     /* Get p_input and create variable */
316     var_Create( p_demux->p_input, "x-start", VLC_VAR_INTEGER );
317     var_Create( p_demux->p_input, "y-start", VLC_VAR_INTEGER );
318     var_Create( p_demux->p_input, "x-end", VLC_VAR_INTEGER );
319     var_Create( p_demux->p_input, "y-end", VLC_VAR_INTEGER );
320     var_Create( p_demux->p_input, "color", VLC_VAR_ADDRESS );
321     var_Create( p_demux->p_input, "menu-palette", VLC_VAR_ADDRESS );
322     var_Create( p_demux->p_input, "highlight", VLC_VAR_BOOL );
323
324     /* catch vout creation event */
325     var_AddCallback( p_demux->p_input, "intf-event", EventIntf, p_demux );
326
327     p_sys->still.b_enabled = false;
328     vlc_mutex_init( &p_sys->still.lock );
329     if( !vlc_timer_create( &p_sys->still.timer, StillTimer, p_sys ) )
330         p_sys->still.b_created = true;
331
332     return VLC_SUCCESS;
333 }
334
335 /*****************************************************************************
336  * AccessDemuxOpen:
337  *****************************************************************************/
338 static int AccessDemuxOpen ( vlc_object_t *p_this )
339 {
340     demux_t *p_demux = (demux_t*)p_this;
341     dvdnav_t *p_dvdnav = NULL;
342     char *psz_file = NULL;
343     const char *psz_path = NULL;
344     int i_ret = VLC_EGENERIC;
345     bool forced = false;
346
347     if( p_demux->psz_access != NULL
348      && !strncmp(p_demux->psz_access, "dvd", 3) )
349         forced = true;
350
351     if( !p_demux->psz_file || !*p_demux->psz_file )
352     {
353         /* Only when selected */
354         if( !forced )
355             return VLC_EGENERIC;
356
357         psz_file = var_InheritString( p_this, "dvd" );
358     }
359     else
360         psz_file = strdup( p_demux->psz_file );
361
362 #if defined( _WIN32 ) || defined( __OS2__ )
363     if( psz_file != NULL )
364     {
365         /* Remove trailing backslash, otherwise dvdnav_open will fail */
366         size_t flen = strlen( psz_file );
367         if( flen > 0 && psz_file[flen - 1] == '\\' )
368             psz_file[flen - 1] = '\0';
369     }
370     else
371         psz_file = strdup("");
372 #endif
373
374     if( unlikely(psz_file == NULL) )
375         return VLC_EGENERIC;
376
377     /* Try some simple probing to avoid going through dvdnav_open too often */
378     if( !forced && ProbeDVD( psz_file ) != VLC_SUCCESS )
379         goto bailout;
380
381     /* Open dvdnav */
382     psz_path = ToLocale( psz_file );
383     if( dvdnav_open( &p_dvdnav, psz_path ) != DVDNAV_STATUS_OK )
384     {
385         msg_Warn( p_demux, "cannot open DVD (%s)", psz_file);
386         goto bailout;
387     }
388
389     i_ret = CommonOpen( p_this, p_dvdnav, !!DVD_READ_CACHE );
390     if( i_ret != VLC_SUCCESS )
391         dvdnav_close( p_dvdnav );
392
393 bailout:
394     free( psz_file );
395     if( psz_path )
396         LocaleFree( psz_path );
397     return i_ret;
398 }
399
400 #ifdef HAVE_DVDNAV_DEMUX
401 /*****************************************************************************
402  * StreamProbeDVD: very weak probing that avoids going too often into a dvdnav_open()
403  *****************************************************************************/
404 static int StreamProbeDVD( stream_t *s )
405 {
406     /* first sector should be filled with zeros */
407     size_t i_peek;
408     const uint8_t *p_peek;
409     i_peek = stream_Peek( s, &p_peek, 2048 );
410     if( i_peek < 512 ) {
411         return VLC_EGENERIC;
412     }
413     while (i_peek > 0) {
414         if (p_peek[ --i_peek ]) {
415             return VLC_EGENERIC;
416         }
417     }
418
419     /* ISO 9660 volume descriptor */
420     char iso_dsc[6];
421     if( stream_Seek( s, 0x8000 + 1 ) != VLC_SUCCESS
422      || stream_Read( s, iso_dsc, sizeof (iso_dsc) ) < (int)sizeof (iso_dsc)
423      || memcmp( iso_dsc, "CD001\x01", 6 ) )
424         return VLC_EGENERIC;
425
426     /* Try to find the anchor (2 bytes at LBA 256) */
427     uint16_t anchor;
428
429     if( stream_Seek( s, 256 * DVD_VIDEO_LB_LEN ) == VLC_SUCCESS
430      && stream_Read( s, &anchor, 2 ) == 2
431      && GetWLE( &anchor ) == 2 )
432         return VLC_SUCCESS;
433     else
434         return VLC_EGENERIC;
435 }
436
437 /*****************************************************************************
438  * dvdnav stream callbacks
439  *****************************************************************************/
440 static int stream_cb_seek( void *s, uint64_t pos )
441 {
442     return stream_Seek( (stream_t *)s, pos );
443 }
444
445 static int stream_cb_read( void *s, void* buffer, int size )
446 {
447     return stream_Read( (stream_t *)s, buffer, size );
448 }
449
450 /*****************************************************************************
451  * DemuxOpen:
452  *****************************************************************************/
453 static int DemuxOpen ( vlc_object_t *p_this )
454 {
455     demux_t *p_demux = (demux_t*)p_this;
456     dvdnav_t *p_dvdnav = NULL;
457     int i_ret = VLC_EGENERIC;
458     int64_t i_init_pos;
459     bool forced = false, b_seekable = false;
460
461     if( p_demux->psz_demux != NULL
462      && !strncmp(p_demux->psz_demux, "dvd", 3) )
463         forced = true;
464
465     /* StreamProbeDVD need FASTSEEK, but if dvd is forced, we don't probe thus
466      * don't need fastseek */
467     stream_Control( p_demux->s, forced ? STREAM_CAN_SEEK : STREAM_CAN_FASTSEEK,
468                     &b_seekable );
469     if( !b_seekable )
470         return VLC_EGENERIC;
471
472     i_init_pos = stream_Tell( p_demux->s );
473
474     /* Try some simple probing to avoid going through dvdnav_open too often */
475     if( !forced && StreamProbeDVD( p_demux->s ) != VLC_SUCCESS )
476         goto bailout;
477
478     static dvdnav_stream_cb stream_cb =
479     {
480         .pf_seek = stream_cb_seek,
481         .pf_read = stream_cb_read,
482         .pf_readv = NULL,
483     };
484
485     /* Open dvdnav with stream callbacks */
486     if( dvdnav_open_stream( &p_dvdnav, p_demux->s,
487                             &stream_cb ) != DVDNAV_STATUS_OK )
488     {
489         msg_Warn( p_demux, "cannot open DVD with open_stream" );
490         goto bailout;
491     }
492
493     i_ret = CommonOpen( p_this, p_dvdnav, false );
494     if( i_ret != VLC_SUCCESS )
495         dvdnav_close( p_dvdnav );
496
497 bailout:
498     if( i_ret != VLC_SUCCESS )
499         stream_Seek( p_demux->s, i_init_pos );
500     return i_ret;
501 }
502 #endif
503
504 /*****************************************************************************
505  * Close:
506  *****************************************************************************/
507 static void Close( vlc_object_t *p_this )
508 {
509     demux_t     *p_demux = (demux_t*)p_this;
510     demux_sys_t *p_sys = p_demux->p_sys;
511
512     /* Stop vout event handler */
513     var_DelCallback( p_demux->p_input, "intf-event", EventIntf, p_demux );
514     if( p_sys->p_vout != NULL )
515     {   /* Should not happen, but better be safe than sorry. */
516         msg_Warn( p_sys->p_vout, "removing dangling mouse DVD callbacks" );
517         var_DelCallback( p_sys->p_vout, "mouse-moved", EventMouse, p_demux );
518         var_DelCallback( p_sys->p_vout, "mouse-clicked", EventMouse, p_demux );
519     }
520
521     /* Stop still image handler */
522     if( p_sys->still.b_created )
523         vlc_timer_destroy( p_sys->still.timer );
524     vlc_mutex_destroy( &p_sys->still.lock );
525
526     var_Destroy( p_demux->p_input, "highlight" );
527     var_Destroy( p_demux->p_input, "x-start" );
528     var_Destroy( p_demux->p_input, "x-end" );
529     var_Destroy( p_demux->p_input, "y-start" );
530     var_Destroy( p_demux->p_input, "y-end" );
531     var_Destroy( p_demux->p_input, "color" );
532     var_Destroy( p_demux->p_input, "menu-palette" );
533
534     for( int i = 0; i < PS_TK_COUNT; i++ )
535     {
536         ps_track_t *tk = &p_sys->tk[i];
537         if( tk->b_seen )
538         {
539             es_format_Clean( &tk->fmt );
540             if( tk->es ) es_out_Del( p_demux->out, tk->es );
541         }
542     }
543
544     /* Free the array of titles */
545     for( int i = 0; i < p_sys->i_title; i++ )
546         vlc_input_title_Delete( p_sys->title[i] );
547     TAB_CLEAN( p_sys->i_title, p_sys->title );
548
549     dvdnav_close( p_sys->dvdnav );
550     free( p_sys );
551 }
552
553 /*****************************************************************************
554  * Control:
555  *****************************************************************************/
556 static int Control( demux_t *p_demux, int i_query, va_list args )
557 {
558     demux_sys_t *p_sys = p_demux->p_sys;
559     input_title_t ***ppp_title;
560     int i;
561
562     switch( i_query )
563     {
564         case DEMUX_SET_POSITION:
565         case DEMUX_GET_POSITION:
566         case DEMUX_GET_TIME:
567         case DEMUX_GET_LENGTH:
568         {
569             uint32_t pos, len;
570             if( dvdnav_get_position( p_sys->dvdnav, &pos, &len ) !=
571                   DVDNAV_STATUS_OK || len == 0 )
572             {
573                 return VLC_EGENERIC;
574             }
575
576             switch( i_query )
577             {
578             case DEMUX_GET_POSITION:
579                 *va_arg( args, double* ) = (double)pos / (double)len;
580                 return VLC_SUCCESS;
581
582             case DEMUX_SET_POSITION:
583                 pos = va_arg( args, double ) * len;
584                 if( dvdnav_sector_search( p_sys->dvdnav, pos, SEEK_SET ) ==
585                       DVDNAV_STATUS_OK )
586                 {
587                     return VLC_SUCCESS;
588                 }
589                 break;
590
591             case DEMUX_GET_TIME:
592                 if( p_sys->i_pgc_length > 0 )
593                 {
594                     *va_arg( args, int64_t * ) = p_sys->i_pgc_length*pos/len;
595                     return VLC_SUCCESS;
596                 }
597                 break;
598
599             case DEMUX_GET_LENGTH:
600                 if( p_sys->i_pgc_length > 0 )
601                 {
602                     *va_arg( args, int64_t * ) = (int64_t)p_sys->i_pgc_length;
603                     return VLC_SUCCESS;
604                 }
605                 break;
606             }
607             return VLC_EGENERIC;
608         }
609
610         /* Special for access_demux */
611         case DEMUX_CAN_PAUSE:
612         case DEMUX_CAN_SEEK:
613         case DEMUX_CAN_CONTROL_PACE:
614             /* TODO */
615             *va_arg( args, bool * ) = true;
616             return VLC_SUCCESS;
617
618         case DEMUX_SET_PAUSE_STATE:
619             return VLC_SUCCESS;
620
621         case DEMUX_GET_TITLE_INFO:
622             ppp_title = va_arg( args, input_title_t*** );
623             *va_arg( args, int* ) = p_sys->i_title;
624             *va_arg( args, int* ) = 0; /* Title offset */
625             *va_arg( args, int* ) = 1; /* Chapter offset */
626
627             /* Duplicate title infos */
628             *ppp_title = malloc( p_sys->i_title * sizeof( input_title_t * ) );
629             for( i = 0; i < p_sys->i_title; i++ )
630             {
631                 (*ppp_title)[i] = vlc_input_title_Duplicate( p_sys->title[i] );
632             }
633             return VLC_SUCCESS;
634
635         case DEMUX_SET_TITLE:
636             i = (int)va_arg( args, int );
637             if( ( i == 0 && dvdnav_menu_call( p_sys->dvdnav, DVD_MENU_Root )
638                   != DVDNAV_STATUS_OK ) ||
639                 ( i != 0 && dvdnav_title_play( p_sys->dvdnav, i )
640                   != DVDNAV_STATUS_OK ) )
641             {
642                 msg_Warn( p_demux, "cannot set title/chapter" );
643                 return VLC_EGENERIC;
644             }
645             p_demux->info.i_update |=
646                 INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
647             p_demux->info.i_title = i;
648             p_demux->info.i_seekpoint = 0;
649             return VLC_SUCCESS;
650
651         case DEMUX_SET_SEEKPOINT:
652             i = va_arg( args, int );
653             if( p_demux->info.i_title == 0 )
654             {
655                 static const int argtab[] = {
656                     DVD_MENU_Escape,
657                     DVD_MENU_Root,
658                     DVD_MENU_Title,
659                     DVD_MENU_Part,
660                     DVD_MENU_Subpicture,
661                     DVD_MENU_Audio,
662                     DVD_MENU_Angle
663                 };
664                 enum { numargs = sizeof(argtab)/sizeof(int) };
665                 if( (unsigned)i >= numargs || DVDNAV_STATUS_OK !=
666                            dvdnav_menu_call(p_sys->dvdnav,argtab[i]) )
667                     return VLC_EGENERIC;
668             }
669             else if( dvdnav_part_play( p_sys->dvdnav, p_demux->info.i_title,
670                                        i + 1 ) != DVDNAV_STATUS_OK )
671             {
672                 msg_Warn( p_demux, "cannot set title/chapter" );
673                 return VLC_EGENERIC;
674             }
675             p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
676             p_demux->info.i_seekpoint = i;
677             return VLC_SUCCESS;
678
679         case DEMUX_GET_PTS_DELAY:
680             *va_arg( args, int64_t * ) =
681                 INT64_C(1000) * var_InheritInteger( p_demux, "disc-caching" );
682             return VLC_SUCCESS;
683
684         case DEMUX_GET_META:
685         {
686             const char *title_name = NULL;
687
688             dvdnav_get_title_string(p_sys->dvdnav, &title_name);
689             if( (NULL != title_name) && ('\0' != title_name[0]) )
690             {
691                 vlc_meta_t *p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
692                 vlc_meta_Set( p_meta, vlc_meta_Title, title_name );
693                 return VLC_SUCCESS;
694             }
695             return VLC_EGENERIC;
696         }
697
698         case DEMUX_NAV_ACTIVATE:
699         {
700             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
701
702             ButtonUpdate( p_demux, true );
703             dvdnav_button_activate( p_sys->dvdnav, pci );
704             break;
705         }
706
707         case DEMUX_NAV_UP:
708         {
709             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
710
711             dvdnav_upper_button_select( p_sys->dvdnav, pci );
712             break;
713         }
714
715         case DEMUX_NAV_DOWN:
716         {
717             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
718
719             dvdnav_lower_button_select( p_sys->dvdnav, pci );
720             break;
721         }
722
723         case DEMUX_NAV_LEFT:
724         {
725             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
726
727             dvdnav_left_button_select( p_sys->dvdnav, pci );
728             break;
729         }
730
731         case DEMUX_NAV_RIGHT:
732         {
733             pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
734
735             dvdnav_right_button_select( p_sys->dvdnav, pci );
736             break;
737         }
738
739         /* TODO implement others */
740         default:
741             return VLC_EGENERIC;
742     }
743
744     return VLC_SUCCESS;
745 }
746
747 static int ControlInternal( demux_t *p_demux, int i_query, ... )
748 {
749     va_list args;
750     int     i_result;
751
752     va_start( args, i_query );
753     i_result = Control( p_demux, i_query, args );
754     va_end( args );
755
756     return i_result;
757 }
758 /*****************************************************************************
759  * Demux:
760  *****************************************************************************/
761 static int Demux( demux_t *p_demux )
762 {
763     demux_sys_t *p_sys = p_demux->p_sys;
764
765     uint8_t buffer[DVD_VIDEO_LB_LEN];
766     uint8_t *packet = buffer;
767     int i_event;
768     int i_len;
769     dvdnav_status_t status;
770
771     if( p_sys->b_readahead )
772         status = dvdnav_get_next_cache_block( p_sys->dvdnav, &packet, &i_event,
773                                               &i_len );
774     else
775         status = dvdnav_get_next_block( p_sys->dvdnav, packet, &i_event,
776                                         &i_len );
777     if( status == DVDNAV_STATUS_ERR )
778     {
779         msg_Warn( p_demux, "cannot get next block (%s)",
780                   dvdnav_err_to_string( p_sys->dvdnav ) );
781         if( p_demux->info.i_title == 0 )
782         {
783             msg_Dbg( p_demux, "jumping to first title" );
784             return ControlInternal( p_demux, DEMUX_SET_TITLE, 1 ) == VLC_SUCCESS ? 1 : -1;
785         }
786         return -1;
787     }
788
789     switch( i_event )
790     {
791     case DVDNAV_BLOCK_OK:   /* mpeg block */
792         vlc_mutex_lock( &p_sys->still.lock );
793         vlc_timer_schedule( p_sys->still.timer, false, 0, 0 );
794         p_sys->still.b_enabled = false;
795         vlc_mutex_unlock( &p_sys->still.lock );
796         if( p_sys->b_reset_pcr )
797         {
798             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
799             p_sys->b_reset_pcr = false;
800         }
801         DemuxBlock( p_demux, packet, i_len );
802         if( p_sys->i_vobu_index > 0 )
803         {
804             if( p_sys->i_vobu_flush == p_sys->i_vobu_index )
805                 DemuxForceStill( p_demux );
806             p_sys->i_vobu_index++;
807         }
808         break;
809
810     case DVDNAV_NOP:    /* Nothing */
811         msg_Dbg( p_demux, "DVDNAV_NOP" );
812         break;
813
814     case DVDNAV_STILL_FRAME:
815     {
816         dvdnav_still_event_t *event = (dvdnav_still_event_t*)packet;
817         bool b_still_init = false;
818
819         vlc_mutex_lock( &p_sys->still.lock );
820         if( !p_sys->still.b_enabled )
821         {
822             msg_Dbg( p_demux, "DVDNAV_STILL_FRAME" );
823             msg_Dbg( p_demux, "     - length=0x%x", event->length );
824             p_sys->still.b_enabled = true;
825
826             if( event->length != 0xff && p_sys->still.b_created )
827             {
828                 mtime_t delay = event->length * CLOCK_FREQ;
829                 vlc_timer_schedule( p_sys->still.timer, false, delay, 0 );
830             }
831
832             b_still_init = true;
833         }
834         vlc_mutex_unlock( &p_sys->still.lock );
835
836         if( b_still_init )
837         {
838             DemuxForceStill( p_demux );
839             p_sys->b_reset_pcr = true;
840         }
841         msleep( 40000 );
842         break;
843     }
844
845     case DVDNAV_SPU_CLUT_CHANGE:
846     {
847         int i;
848
849         msg_Dbg( p_demux, "DVDNAV_SPU_CLUT_CHANGE" );
850         /* Update color lookup table (16 *uint32_t in packet) */
851         memcpy( p_sys->clut, packet, 16 * sizeof( uint32_t ) );
852
853         /* HACK to get the SPU tracks registered in the right order */
854         for( i = 0; i < 0x1f; i++ )
855         {
856             if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
857                 ESNew( p_demux, 0xbd20 + i );
858         }
859         /* END HACK */
860         break;
861     }
862
863     case DVDNAV_SPU_STREAM_CHANGE:
864     {
865         dvdnav_spu_stream_change_event_t *event =
866             (dvdnav_spu_stream_change_event_t*)packet;
867         int i;
868
869         msg_Dbg( p_demux, "DVDNAV_SPU_STREAM_CHANGE" );
870         msg_Dbg( p_demux, "     - physical_wide=%d",
871                  event->physical_wide );
872         msg_Dbg( p_demux, "     - physical_letterbox=%d",
873                  event->physical_letterbox);
874         msg_Dbg( p_demux, "     - physical_pan_scan=%d",
875                  event->physical_pan_scan );
876
877         ESSubtitleUpdate( p_demux );
878         p_sys->b_spu_change = true;
879
880         /* HACK to get the SPU tracks registered in the right order */
881         for( i = 0; i < 0x1f; i++ )
882         {
883             if( dvdnav_spu_stream_to_lang( p_sys->dvdnav, i ) != 0xffff )
884                 ESNew( p_demux, 0xbd20 + i );
885         }
886         /* END HACK */
887         break;
888     }
889
890     case DVDNAV_AUDIO_STREAM_CHANGE:
891     {
892         dvdnav_audio_stream_change_event_t *event =
893             (dvdnav_audio_stream_change_event_t*)packet;
894         msg_Dbg( p_demux, "DVDNAV_AUDIO_STREAM_CHANGE" );
895         msg_Dbg( p_demux, "     - physical=%d", event->physical );
896         /* TODO */
897         break;
898     }
899
900     case DVDNAV_VTS_CHANGE:
901     {
902         int32_t i_title = 0;
903         int32_t i_part  = 0;
904         int i;
905
906         dvdnav_vts_change_event_t *event = (dvdnav_vts_change_event_t*)packet;
907         msg_Dbg( p_demux, "DVDNAV_VTS_CHANGE" );
908         msg_Dbg( p_demux, "     - vtsN=%d", event->new_vtsN );
909         msg_Dbg( p_demux, "     - domain=%d", event->new_domain );
910
911         /* reset PCR */
912         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
913
914         for( i = 0; i < PS_TK_COUNT; i++ )
915         {
916             ps_track_t *tk = &p_sys->tk[i];
917             if( tk->b_seen )
918             {
919                 es_format_Clean( &tk->fmt );
920                 if( tk->es ) es_out_Del( p_demux->out, tk->es );
921             }
922             tk->b_seen = false;
923         }
924
925         uint32_t i_width, i_height;
926         if( dvdnav_get_video_resolution( p_sys->dvdnav,
927                                          &i_width, &i_height ) )
928             i_width = i_height = 0;
929         switch( dvdnav_get_video_aspect( p_sys->dvdnav ) )
930         {
931         case 0:
932             p_sys->sar.i_num = 4 * i_height;
933             p_sys->sar.i_den = 3 * i_width;
934             break;
935         case 3:
936             p_sys->sar.i_num = 16 * i_height;
937             p_sys->sar.i_den =  9 * i_width;
938             break;
939         default:
940             p_sys->sar.i_num = 0;
941             p_sys->sar.i_den = 0;
942             break;
943         }
944
945         if( dvdnav_current_title_info( p_sys->dvdnav, &i_title,
946                                        &i_part ) == DVDNAV_STATUS_OK )
947         {
948             if( i_title >= 0 && i_title < p_sys->i_title &&
949                 p_demux->info.i_title != i_title )
950             {
951                 p_demux->info.i_update |= INPUT_UPDATE_TITLE;
952                 p_demux->info.i_title = i_title;
953             }
954         }
955         break;
956     }
957
958     case DVDNAV_CELL_CHANGE:
959     {
960         int32_t i_title = 0;
961         int32_t i_part  = 0;
962
963         dvdnav_cell_change_event_t *event =
964             (dvdnav_cell_change_event_t*)packet;
965         msg_Dbg( p_demux, "DVDNAV_CELL_CHANGE" );
966         msg_Dbg( p_demux, "     - cellN=%d", event->cellN );
967         msg_Dbg( p_demux, "     - pgN=%d", event->pgN );
968         msg_Dbg( p_demux, "     - cell_length=%"PRId64, event->cell_length );
969         msg_Dbg( p_demux, "     - pg_length=%"PRId64, event->pg_length );
970         msg_Dbg( p_demux, "     - pgc_length=%"PRId64, event->pgc_length );
971         msg_Dbg( p_demux, "     - cell_start=%"PRId64, event->cell_start );
972         msg_Dbg( p_demux, "     - pg_start=%"PRId64, event->pg_start );
973
974         /* Store the length in time of the current PGC */
975         p_sys->i_pgc_length = event->pgc_length / 90 * 1000;
976         p_sys->i_vobu_index = 0;
977         p_sys->i_vobu_flush = 0;
978
979         /* FIXME is it correct or there is better way to know chapter change */
980         if( dvdnav_current_title_info( p_sys->dvdnav, &i_title,
981                                        &i_part ) == DVDNAV_STATUS_OK )
982         {
983             if( i_title >= 0 && i_title < p_sys->i_title )
984             {
985                 p_demux->info.i_update |= INPUT_UPDATE_TITLE;
986                 p_demux->info.i_title = i_title;
987
988                 if( i_part >= 1 && i_part <= p_sys->title[i_title]->i_seekpoint )
989                 {
990                     p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
991                     p_demux->info.i_seekpoint = i_part - 1;
992                 }
993             }
994         }
995         break;
996     }
997
998     case DVDNAV_NAV_PACKET:
999     {
1000         p_sys->i_vobu_index = 1;
1001         p_sys->i_vobu_flush = 0;
1002
1003         /* Look if we have need to force a flush (and when) */
1004         const pci_gi_t *p_pci_gi = &dvdnav_get_current_nav_pci( p_sys->dvdnav )->pci_gi;
1005         if( p_pci_gi->vobu_se_e_ptm != 0 && p_pci_gi->vobu_se_e_ptm < p_pci_gi->vobu_e_ptm )
1006         {
1007             const dsi_gi_t *p_dsi_gi = &dvdnav_get_current_nav_dsi( p_sys->dvdnav )->dsi_gi;
1008             if( p_dsi_gi->vobu_3rdref_ea != 0 )
1009                 p_sys->i_vobu_flush = p_dsi_gi->vobu_3rdref_ea;
1010             else if( p_dsi_gi->vobu_2ndref_ea != 0 )
1011                 p_sys->i_vobu_flush = p_dsi_gi->vobu_2ndref_ea;
1012             else if( p_dsi_gi->vobu_1stref_ea != 0 )
1013                 p_sys->i_vobu_flush = p_dsi_gi->vobu_1stref_ea;
1014         }
1015
1016 #ifdef DVDNAV_DEBUG
1017         msg_Dbg( p_demux, "DVDNAV_NAV_PACKET" );
1018 #endif
1019         /* A lot of thing to do here :
1020          *  - handle packet
1021          *  - fetch pts (for time display)
1022          *  - ...
1023          */
1024         DemuxBlock( p_demux, packet, i_len );
1025         if( p_sys->b_spu_change )
1026         {
1027             ButtonUpdate( p_demux, false );
1028             p_sys->b_spu_change = false;
1029         }
1030         break;
1031     }
1032
1033     case DVDNAV_STOP:   /* EOF */
1034         msg_Dbg( p_demux, "DVDNAV_STOP" );
1035
1036         if( p_sys->b_readahead )
1037             dvdnav_free_cache_block( p_sys->dvdnav, packet );
1038         return 0;
1039
1040     case DVDNAV_HIGHLIGHT:
1041     {
1042         dvdnav_highlight_event_t *event = (dvdnav_highlight_event_t*)packet;
1043         msg_Dbg( p_demux, "DVDNAV_HIGHLIGHT" );
1044         msg_Dbg( p_demux, "     - display=%d", event->display );
1045         msg_Dbg( p_demux, "     - buttonN=%d", event->buttonN );
1046         ButtonUpdate( p_demux, false );
1047         break;
1048     }
1049
1050     case DVDNAV_HOP_CHANNEL:
1051         msg_Dbg( p_demux, "DVDNAV_HOP_CHANNEL" );
1052         p_sys->i_vobu_index = 0;
1053         p_sys->i_vobu_flush = 0;
1054         es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
1055         break;
1056
1057     case DVDNAV_WAIT:
1058         msg_Dbg( p_demux, "DVDNAV_WAIT" );
1059
1060         bool b_empty;
1061         es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
1062         if( !b_empty )
1063         {
1064             msleep( 40*1000 );
1065         }
1066         else
1067         {
1068             dvdnav_wait_skip( p_sys->dvdnav );
1069             p_sys->b_reset_pcr = true;
1070         }
1071         break;
1072
1073     default:
1074         msg_Warn( p_demux, "Unknown event (0x%x)", i_event );
1075         break;
1076     }
1077
1078     if( p_sys->b_readahead )
1079         dvdnav_free_cache_block( p_sys->dvdnav, packet );
1080
1081     return 1;
1082 }
1083
1084 /* Get a 2 char code
1085  * FIXME: partiallyy duplicated from src/input/es_out.c
1086  */
1087 static char *DemuxGetLanguageCode( demux_t *p_demux, const char *psz_var )
1088 {
1089     const iso639_lang_t *pl;
1090     char *psz_lang;
1091     char *p;
1092
1093     psz_lang = var_CreateGetString( p_demux, psz_var );
1094     if( !psz_lang )
1095         return strdup(LANGUAGE_DEFAULT);
1096
1097     /* XXX: we will use only the first value
1098      * (and ignore other ones in case of a list) */
1099     if( ( p = strchr( psz_lang, ',' ) ) )
1100         *p = '\0';
1101
1102     for( pl = p_languages; pl->psz_eng_name != NULL; pl++ )
1103     {
1104         if( *psz_lang == '\0' )
1105             continue;
1106         if( !strcasecmp( pl->psz_eng_name, psz_lang ) ||
1107             !strcasecmp( pl->psz_iso639_1, psz_lang ) ||
1108             !strcasecmp( pl->psz_iso639_2T, psz_lang ) ||
1109             !strcasecmp( pl->psz_iso639_2B, psz_lang ) )
1110             break;
1111     }
1112
1113     free( psz_lang );
1114
1115     if( pl->psz_eng_name != NULL )
1116         return strdup( pl->psz_iso639_1 );
1117
1118     return strdup(LANGUAGE_DEFAULT);
1119 }
1120
1121 static void DemuxTitles( demux_t *p_demux )
1122 {
1123     demux_sys_t *p_sys = p_demux->p_sys;
1124     input_title_t *t;
1125     seekpoint_t *s;
1126     int32_t i_titles;
1127     int i;
1128
1129     /* Menu */
1130     t = vlc_input_title_New();
1131     t->i_flags = INPUT_TITLE_MENU | INPUT_TITLE_INTERACTIVE;
1132     t->psz_name = strdup( "DVD Menu" );
1133
1134     s = vlc_seekpoint_New();
1135     s->psz_name = strdup( "Resume" );
1136     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1137
1138     s = vlc_seekpoint_New();
1139     s->psz_name = strdup( "Root" );
1140     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1141
1142     s = vlc_seekpoint_New();
1143     s->psz_name = strdup( "Title" );
1144     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1145
1146     s = vlc_seekpoint_New();
1147     s->psz_name = strdup( "Chapter" );
1148     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1149
1150     s = vlc_seekpoint_New();
1151     s->psz_name = strdup( "Subtitle" );
1152     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1153
1154     s = vlc_seekpoint_New();
1155     s->psz_name = strdup( "Audio" );
1156     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1157
1158     s = vlc_seekpoint_New();
1159     s->psz_name = strdup( "Angle" );
1160     TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1161
1162     TAB_APPEND( p_sys->i_title, p_sys->title, t );
1163
1164     /* Find out number of titles/chapters */
1165     dvdnav_get_number_of_titles( p_sys->dvdnav, &i_titles );
1166
1167     if( i_titles > 90 )
1168         msg_Err( p_demux, "This is probably an Arccos Protected DVD. This could take time..." );
1169
1170     for( i = 1; i <= i_titles; i++ )
1171     {
1172         int32_t i_chapters;
1173         uint64_t i_title_length;
1174         uint64_t *p_chapters_time;
1175
1176         i_chapters = dvdnav_describe_title_chapters( p_sys->dvdnav, i,
1177                                                      &p_chapters_time,
1178                                                      &i_title_length );
1179         if( i_chapters < 1 )
1180         {
1181             i_title_length = 0;
1182             p_chapters_time = NULL;
1183         }
1184         t = vlc_input_title_New();
1185         t->i_length = i_title_length * 1000 / 90;
1186         for( int j = 0; j < __MAX( i_chapters, 1 ); j++ )
1187         {
1188             s = vlc_seekpoint_New();
1189             if( p_chapters_time )
1190                 s->i_time_offset = p_chapters_time[j] * 1000 / 90;
1191             TAB_APPEND( t->i_seekpoint, t->seekpoint, s );
1192         }
1193         free( p_chapters_time );
1194         TAB_APPEND( p_sys->i_title, p_sys->title, t );
1195     }
1196 }
1197
1198 /*****************************************************************************
1199  * Update functions:
1200  *****************************************************************************/
1201 static void ButtonUpdate( demux_t *p_demux, bool b_mode )
1202 {
1203     demux_sys_t *p_sys = p_demux->p_sys;
1204     int32_t i_title, i_part;
1205
1206     dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
1207
1208     dvdnav_highlight_area_t hl;
1209     int32_t i_button;
1210     bool    b_button_ok;
1211
1212     if( dvdnav_get_current_highlight( p_sys->dvdnav, &i_button )
1213         != DVDNAV_STATUS_OK )
1214     {
1215         msg_Err( p_demux, "dvdnav_get_current_highlight failed" );
1216         return;
1217     }
1218
1219     b_button_ok = false;
1220     if( i_button > 0 && i_title ==  0 )
1221     {
1222         pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
1223
1224         b_button_ok = DVDNAV_STATUS_OK ==
1225                   dvdnav_get_highlight_area( pci, i_button, b_mode, &hl );
1226     }
1227
1228     if( b_button_ok )
1229     {
1230         for( unsigned i = 0; i < 4; i++ )
1231         {
1232             uint32_t i_yuv = p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
1233             uint8_t i_alpha = ( (hl.palette>>(i*4))&0x0f ) * 0xff / 0xf;
1234
1235             p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
1236             p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
1237             p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
1238             p_sys->palette[i][3] = i_alpha;
1239         }
1240
1241         vlc_global_lock( VLC_HIGHLIGHT_MUTEX );
1242         var_SetInteger( p_demux->p_input, "x-start", hl.sx );
1243         var_SetInteger( p_demux->p_input, "x-end",  hl.ex );
1244         var_SetInteger( p_demux->p_input, "y-start", hl.sy );
1245         var_SetInteger( p_demux->p_input, "y-end", hl.ey );
1246
1247         var_SetAddress( p_demux->p_input, "menu-palette", p_sys->palette );
1248         var_SetBool( p_demux->p_input, "highlight", true );
1249
1250         msg_Dbg( p_demux, "buttonUpdate %d", i_button );
1251     }
1252     else
1253     {
1254         msg_Dbg( p_demux, "buttonUpdate not done b=%d t=%d",
1255                  i_button, i_title );
1256
1257         /* Show all */
1258         vlc_global_lock( VLC_HIGHLIGHT_MUTEX );
1259         var_SetBool( p_demux->p_input, "highlight", false );
1260     }
1261     vlc_global_unlock( VLC_HIGHLIGHT_MUTEX );
1262 }
1263
1264 static void ESSubtitleUpdate( demux_t *p_demux )
1265 {
1266     demux_sys_t *p_sys = p_demux->p_sys;
1267     int         i_spu = dvdnav_get_active_spu_stream( p_sys->dvdnav );
1268     int32_t i_title, i_part;
1269
1270     ButtonUpdate( p_demux, false );
1271
1272     dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
1273     if( i_title > 0 ) return;
1274
1275     if( i_spu >= 0 && i_spu <= 0x1f )
1276     {
1277         ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)];
1278
1279         ESNew( p_demux, 0xbd20 + i_spu );
1280
1281         /* be sure to unselect it (reset) */
1282         es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es,
1283                         (bool)false );
1284
1285         /* now select it */
1286         es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es );
1287     }
1288     else
1289     {
1290         for( i_spu = 0; i_spu <= 0x1F; i_spu++ )
1291         {
1292             ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(0xbd20 + i_spu)];
1293             if( tk->b_seen )
1294             {
1295                 es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->es,
1296                                 (bool)false );
1297             }
1298         }
1299     }
1300 }
1301
1302 /*****************************************************************************
1303  * DemuxBlock: demux a given block
1304  *****************************************************************************/
1305 static int DemuxBlock( demux_t *p_demux, const uint8_t *p, int len )
1306 {
1307     demux_sys_t *p_sys = p_demux->p_sys;
1308
1309     while( len > 0 )
1310     {
1311         int i_size = ps_pkt_size( p, len );
1312         if( i_size <= 0 || i_size > len )
1313         {
1314             break;
1315         }
1316
1317         /* Create a block */
1318         block_t *p_pkt = block_Alloc( i_size );
1319         memcpy( p_pkt->p_buffer, p, i_size);
1320
1321         /* Parse it and send it */
1322         switch( 0x100 | p[3] )
1323         {
1324         case 0x1b9:
1325         case 0x1bb:
1326         case 0x1bc:
1327 #ifdef DVDNAV_DEBUG
1328             if( p[3] == 0xbc )
1329             {
1330                 msg_Warn( p_demux, "received a PSM packet" );
1331             }
1332             else if( p[3] == 0xbb )
1333             {
1334                 msg_Warn( p_demux, "received a SYSTEM packet" );
1335             }
1336 #endif
1337             block_Release( p_pkt );
1338             break;
1339
1340         case 0x1ba:
1341         {
1342             int64_t i_scr;
1343             int i_mux_rate;
1344             if( !ps_pkt_parse_pack( p_pkt, &i_scr, &i_mux_rate ) )
1345             {
1346                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, i_scr + 1 );
1347                 if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
1348             }
1349             block_Release( p_pkt );
1350             break;
1351         }
1352         default:
1353         {
1354             int i_id = ps_pkt_id( p_pkt );
1355             if( i_id >= 0xc0 )
1356             {
1357                 ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
1358
1359                 if( !tk->b_seen )
1360                 {
1361                     ESNew( p_demux, i_id );
1362                 }
1363                 if( tk->b_seen && tk->es &&
1364                     !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) )
1365                 {
1366                     es_out_Send( p_demux->out, tk->es, p_pkt );
1367                 }
1368                 else
1369                 {
1370                     block_Release( p_pkt );
1371                 }
1372             }
1373             else
1374             {
1375                 block_Release( p_pkt );
1376             }
1377             break;
1378         }
1379         }
1380
1381         p += i_size;
1382         len -= i_size;
1383     }
1384
1385     return VLC_SUCCESS;
1386 }
1387
1388 /*****************************************************************************
1389  * Force still images to be displayed by sending EOS and stopping buffering.
1390  *****************************************************************************/
1391 static void DemuxForceStill( demux_t *p_demux )
1392 {
1393     static const uint8_t buffer[] = {
1394         0x00, 0x00, 0x01, 0xe0, 0x00, 0x07,
1395         0x80, 0x00, 0x00,
1396         0x00, 0x00, 0x01, 0xB7,
1397     };
1398     DemuxBlock( p_demux, buffer, sizeof(buffer) );
1399
1400     bool b_empty;
1401     es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
1402 }
1403
1404 /*****************************************************************************
1405  * ESNew: register a new elementary stream
1406  *****************************************************************************/
1407 static void ESNew( demux_t *p_demux, int i_id )
1408 {
1409     demux_sys_t *p_sys = p_demux->p_sys;
1410     ps_track_t  *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
1411     bool  b_select = false;
1412
1413     if( tk->b_seen ) return;
1414
1415     if( ps_track_fill( tk, 0, i_id, NULL ) )
1416     {
1417         msg_Warn( p_demux, "unknown codec for id=0x%x", i_id );
1418         return;
1419     }
1420
1421     /* Add a new ES */
1422     if( tk->fmt.i_cat == VIDEO_ES )
1423     {
1424         tk->fmt.video.i_sar_num = p_sys->sar.i_num;
1425         tk->fmt.video.i_sar_den = p_sys->sar.i_den;
1426         b_select = true;
1427     }
1428     else if( tk->fmt.i_cat == AUDIO_ES )
1429     {
1430         int i_audio = -1;
1431         /* find the audio number PLEASE find another way */
1432         if( (i_id&0xbdf8) == 0xbd88 )       /* dts */
1433         {
1434             i_audio = i_id&0x07;
1435         }
1436         else if( (i_id&0xbdf0) == 0xbd80 )  /* a52 */
1437         {
1438             i_audio = i_id&0xf;
1439         }
1440         else if( (i_id&0xbdf0) == 0xbda0 )  /* lpcm */
1441         {
1442             i_audio = i_id&0x1f;
1443         }
1444         else if( ( i_id&0xe0 ) == 0xc0 )    /* mpga */
1445         {
1446             i_audio = i_id&0x1f;
1447         }
1448         if( i_audio >= 0 )
1449         {
1450             int i_lang = dvdnav_audio_stream_to_lang( p_sys->dvdnav, i_audio );
1451             if( i_lang != 0xffff )
1452             {
1453                 tk->fmt.psz_language = malloc( 3 );
1454                 tk->fmt.psz_language[0] = (i_lang >> 8)&0xff;
1455                 tk->fmt.psz_language[1] = (i_lang     )&0xff;
1456                 tk->fmt.psz_language[2] = 0;
1457             }
1458             if( dvdnav_get_active_audio_stream( p_sys->dvdnav ) == i_audio )
1459             {
1460                 b_select = true;
1461             }
1462         }
1463     }
1464     else if( tk->fmt.i_cat == SPU_ES )
1465     {
1466         int32_t i_title, i_part;
1467         int i_lang = dvdnav_spu_stream_to_lang( p_sys->dvdnav, i_id&0x1f );
1468         if( i_lang != 0xffff )
1469         {
1470             tk->fmt.psz_language = malloc( 3 );
1471             tk->fmt.psz_language[0] = (i_lang >> 8)&0xff;
1472             tk->fmt.psz_language[1] = (i_lang     )&0xff;
1473             tk->fmt.psz_language[2] = 0;
1474         }
1475
1476         /* Palette */
1477         tk->fmt.subs.spu.palette[0] = 0xBeef;
1478         memcpy( &tk->fmt.subs.spu.palette[1], p_sys->clut,
1479                 16 * sizeof( uint32_t ) );
1480
1481         /* We select only when we are not in the menu */
1482         dvdnav_current_title_info( p_sys->dvdnav, &i_title, &i_part );
1483         if( i_title > 0 &&
1484             dvdnav_get_active_spu_stream( p_sys->dvdnav ) == (i_id&0x1f) )
1485         {
1486             b_select = true;
1487         }
1488     }
1489
1490     tk->es = es_out_Add( p_demux->out, &tk->fmt );
1491     if( b_select )
1492     {
1493         es_out_Control( p_demux->out, ES_OUT_SET_ES, tk->es );
1494     }
1495     tk->b_seen = true;
1496
1497     if( tk->fmt.i_cat == VIDEO_ES ) ButtonUpdate( p_demux, false );
1498 }
1499
1500 /*****************************************************************************
1501  * Still image end
1502  *****************************************************************************/
1503 static void StillTimer( void *p_data )
1504 {
1505     demux_sys_t    *p_sys = p_data;
1506
1507     vlc_mutex_lock( &p_sys->still.lock );
1508     if( likely(p_sys->still.b_enabled) )
1509     {
1510         p_sys->still.b_enabled = false;
1511         dvdnav_still_skip( p_sys->dvdnav );
1512     }
1513     vlc_mutex_unlock( &p_sys->still.lock );
1514 }
1515
1516 static int EventMouse( vlc_object_t *p_vout, char const *psz_var,
1517                        vlc_value_t oldval, vlc_value_t val, void *p_data )
1518 {
1519     demux_t *p_demux = p_data;
1520     demux_sys_t *p_sys = p_demux->p_sys;
1521
1522     /* FIXME? PCI usage thread safe? */
1523     pci_t *pci = dvdnav_get_current_nav_pci( p_sys->dvdnav );
1524     int x = val.coords.x;
1525     int y = val.coords.y;
1526
1527     if( psz_var[6] == 'm' ) /* mouse-moved */
1528         dvdnav_mouse_select( p_sys->dvdnav, pci, x, y );
1529     else
1530     {
1531         assert( psz_var[6] == 'c' ); /* mouse-clicked */
1532
1533         ButtonUpdate( p_demux, true );
1534         dvdnav_mouse_activate( p_sys->dvdnav, pci, x, y );
1535     }
1536     (void)p_vout;
1537     (void)oldval;
1538     return VLC_SUCCESS;
1539 }
1540
1541 static int EventIntf( vlc_object_t *p_input, char const *psz_var,
1542                       vlc_value_t oldval, vlc_value_t val, void *p_data )
1543 {
1544     demux_t *p_demux = p_data;
1545     demux_sys_t *p_sys = p_demux->p_sys;
1546
1547     if (val.i_int == INPUT_EVENT_VOUT)
1548     {
1549         if( p_sys->p_vout != NULL )
1550         {
1551             var_DelCallback( p_sys->p_vout, "mouse-moved", EventMouse, p_demux );
1552             var_DelCallback( p_sys->p_vout, "mouse-clicked", EventMouse, p_demux );
1553             vlc_object_release( p_sys->p_vout );
1554         }
1555
1556         p_sys->p_vout = input_GetVout( (input_thread_t *)p_input );
1557         if( p_sys->p_vout != NULL )
1558         {
1559             var_AddCallback( p_sys->p_vout, "mouse-moved", EventMouse, p_demux );
1560             var_AddCallback( p_sys->p_vout, "mouse-clicked", EventMouse, p_demux );
1561         }
1562     }
1563     (void) psz_var; (void) oldval;
1564     return VLC_SUCCESS;
1565 }
1566
1567 /*****************************************************************************
1568  * ProbeDVD: very weak probing that avoids going too often into a dvdnav_open()
1569  *****************************************************************************/
1570 static int ProbeDVD( const char *psz_name )
1571 {
1572     if( !*psz_name )
1573         /* Triggers libdvdcss autodetection */
1574         return VLC_SUCCESS;
1575
1576     int fd = vlc_open( psz_name, O_RDONLY | O_NONBLOCK );
1577     if( fd == -1 )
1578 #ifdef HAVE_FDOPENDIR
1579         return VLC_EGENERIC;
1580 #else
1581         return (errno == ENOENT) ? VLC_EGENERIC : VLC_SUCCESS;
1582 #endif
1583
1584     int ret = VLC_EGENERIC;
1585     struct stat stat_info;
1586
1587     if( fstat( fd, &stat_info ) == -1 )
1588          goto bailout;
1589     if( !S_ISREG( stat_info.st_mode ) )
1590     {
1591         if( S_ISDIR( stat_info.st_mode ) || S_ISBLK( stat_info.st_mode ) )
1592             ret = VLC_SUCCESS; /* Let dvdnav_open() do the probing */
1593         goto bailout;
1594     }
1595
1596     /* ISO 9660 volume descriptor */
1597     char iso_dsc[6];
1598     if( lseek( fd, 0x8000 + 1, SEEK_SET ) == -1
1599      || read( fd, iso_dsc, sizeof (iso_dsc) ) < (int)sizeof (iso_dsc)
1600      || memcmp( iso_dsc, "CD001\x01", 6 ) )
1601         goto bailout;
1602
1603     /* Try to find the anchor (2 bytes at LBA 256) */
1604     uint16_t anchor;
1605
1606     if( lseek( fd, 256 * DVD_VIDEO_LB_LEN, SEEK_SET ) != -1
1607      && read( fd, &anchor, 2 ) == 2
1608      && GetWLE( &anchor ) == 2 )
1609         ret = VLC_SUCCESS; /* Found a potential anchor */
1610 bailout:
1611     close( fd );
1612     return ret;
1613 }