1 /*****************************************************************************
2 * input_programs.c: es_descriptor_t, pgrm_descriptor_t management
3 *****************************************************************************
4 * Copyright (C) 1999-2002 VideoLAN
5 * $Id: input_programs.c,v 1.109 2003/05/11 18:40:11 hartman Exp $
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
28 #include <string.h> /* memcpy(), memset() */
32 #include "stream_control.h"
33 #include "input_ext-intf.h"
34 #include "input_ext-dec.h"
35 #include "input_ext-plugins.h"
38 * NOTICE : all of these functions expect you to have taken the lock on
39 * p_input->stream.lock
42 /* Navigation callbacks */
43 static int ProgramCallback( vlc_object_t *, char const *,
44 vlc_value_t, vlc_value_t, void * );
45 static int TitleCallback( vlc_object_t *, char const *,
46 vlc_value_t, vlc_value_t, void * );
47 static int ChapterCallback( vlc_object_t *, char const *,
48 vlc_value_t, vlc_value_t, void * );
49 static int NavigationCallback( vlc_object_t *, char const *,
50 vlc_value_t, vlc_value_t, void * );
51 static int ESCallback( vlc_object_t *, char const *,
52 vlc_value_t, vlc_value_t, void * );
54 /*****************************************************************************
55 * input_InitStream: init the stream descriptor of the given input
56 *****************************************************************************/
57 int input_InitStream( input_thread_t * p_input, size_t i_data_len )
61 p_input->stream.i_stream_id = 0;
63 /* initialized to 0 since we don't give the signal to the interface
64 * before the end of input initialization */
65 p_input->stream.b_changed = 0;
66 p_input->stream.pp_es = NULL;
67 p_input->stream.pp_selected_es = NULL;
68 p_input->stream.p_removed_es = NULL;
69 p_input->stream.p_newly_selected_es = NULL;
70 p_input->stream.pp_programs = NULL;
71 p_input->stream.p_selected_program = NULL;
72 p_input->stream.p_new_program = NULL;
76 if ( (p_input->stream.p_demux_data = malloc( i_data_len )) == NULL )
78 msg_Err( p_input, "out of memory" );
81 memset( p_input->stream.p_demux_data, 0, i_data_len );
85 p_input->stream.p_demux_data = NULL;
88 var_Create( p_input, "intf-change", VLC_VAR_BOOL );
89 val.b_bool = VLC_TRUE;
90 var_Set( p_input, "intf-change", val );
92 /* Create a few object variables used for navigation in the interfaces */
93 var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
94 text.psz_string = _("Program");
95 var_Change( p_input, "program", VLC_VAR_SETTEXT, &text, NULL );
96 var_Create( p_input, "title", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
97 text.psz_string = _("Title");
98 var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
99 var_Create( p_input, "chapter", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
100 text.psz_string = _("Chapter");
101 var_Change( p_input, "chapter", VLC_VAR_SETTEXT, &text, NULL );
102 var_Create( p_input, "navigation", VLC_VAR_VARIABLE | VLC_VAR_HASCHOICE );
103 text.psz_string = _("Navigation");
104 var_Change( p_input, "navigation", VLC_VAR_SETTEXT, &text, NULL );
105 var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
106 text.psz_string = _("Video track");
107 var_Change( p_input, "video-es", VLC_VAR_SETTEXT, &text, NULL );
108 var_Create( p_input, "audio-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
109 text.psz_string = _("Audio track");
110 var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, &text, NULL );
111 var_Create( p_input, "spu-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
112 text.psz_string = _("Subtitle track");
113 var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
115 var_AddCallback( p_input, "program", ProgramCallback, NULL );
116 var_AddCallback( p_input, "title", TitleCallback, NULL );
117 var_AddCallback( p_input, "chapter", ChapterCallback, NULL );
118 var_AddCallback( p_input, "video-es", ESCallback, NULL );
119 var_AddCallback( p_input, "audio-es", ESCallback, NULL );
120 var_AddCallback( p_input, "spu-es", ESCallback, NULL );
125 /*****************************************************************************
126 * input_EndStream: free all stream descriptors
127 *****************************************************************************/
128 void input_EndStream( input_thread_t * p_input )
130 /* Free all programs and associated ES, and associated decoders. */
131 while( p_input->stream.i_pgrm_number )
133 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
136 /* Free standalone ES */
137 while( p_input->stream.i_es_number )
139 input_DelES( p_input, p_input->stream.pp_es[0] );
143 while( p_input->stream.i_area_nb )
145 input_DelArea( p_input, p_input->stream.pp_areas[0] );
148 /* Free selected ES */
149 if( p_input->stream.pp_selected_es != NULL )
151 free( p_input->stream.pp_selected_es );
154 if( p_input->stream.p_demux_data != NULL )
156 free( p_input->stream.p_demux_data );
159 /* Free navigation variables */
160 var_Destroy( p_input, "program" );
161 var_Destroy( p_input, "title" );
162 var_Destroy( p_input, "chapter" );
163 var_Destroy( p_input, "video-es" );
164 var_Destroy( p_input, "audio-es" );
165 var_Destroy( p_input, "spu-es" );
166 var_Destroy( p_input, "intf-change" );
169 /*****************************************************************************
170 * input_FindProgram: returns a pointer to a program described by its ID
171 *****************************************************************************/
172 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input,
177 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
179 if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
181 return p_input->stream.pp_programs[i];
188 /*****************************************************************************
189 * input_AddProgram: add and init a program descriptor
190 *****************************************************************************
191 * This program descriptor will be referenced in the given stream descriptor
192 *****************************************************************************/
193 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
194 u16 i_pgrm_id, size_t i_data_len )
196 /* Where to add the pgrm */
197 pgrm_descriptor_t * p_pgrm = malloc( sizeof(pgrm_descriptor_t) );
202 msg_Err( p_input, "out of memory" );
206 /* Init this entry */
207 p_pgrm->i_number = i_pgrm_id;
209 p_pgrm->i_version = 0;
211 p_pgrm->i_es_number = 0;
212 p_pgrm->pp_es = NULL;
214 input_ClockInit( p_pgrm );
216 p_pgrm->i_synchro_state = SYNCHRO_START;
220 p_pgrm->p_demux_data = malloc( i_data_len );
221 if( p_pgrm->p_demux_data == NULL )
223 msg_Err( p_input, "out of memory" );
226 memset( p_pgrm->p_demux_data, 0, i_data_len );
230 p_pgrm->p_demux_data = NULL;
233 /* Add an entry to the list of program associated with the stream */
234 INSERT_ELEM( p_input->stream.pp_programs,
235 p_input->stream.i_pgrm_number,
236 p_input->stream.i_pgrm_number,
239 val.i_int = i_pgrm_id;
240 var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, NULL );
245 /*****************************************************************************
246 * input_DelProgram: destroy a program descriptor
247 *****************************************************************************
248 * All ES descriptions referenced in the descriptor will be deleted.
249 *****************************************************************************/
250 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
252 unsigned int i_pgrm_index;
255 /* Find the program in the programs table */
256 for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
259 if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
263 /* If the program wasn't found, do nothing */
264 if( i_pgrm_index == p_input->stream.i_pgrm_number )
266 msg_Err( p_input, "program does not belong to this input" );
270 val.i_int = i_pgrm_index;
271 var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
273 /* Free the structures that describe the es that belongs to that program */
274 while( p_pgrm->i_es_number )
276 input_DelES( p_input, p_pgrm->pp_es[0] );
279 /* Free the demux data */
280 if( p_pgrm->p_demux_data != NULL )
282 free( p_pgrm->p_demux_data );
285 /* Remove this program from the stream's list of programs */
286 REMOVE_ELEM( p_input->stream.pp_programs,
287 p_input->stream.i_pgrm_number,
290 /* Free the description of this program */
294 /*****************************************************************************
295 * input_AddArea: add and init an area descriptor
296 *****************************************************************************
297 * This area descriptor will be referenced in the given stream descriptor
298 *****************************************************************************/
299 input_area_t * input_AddArea( input_thread_t * p_input,
300 uint16_t i_area_id, uint16_t i_part_nb )
302 /* Where to add the pgrm */
303 input_area_t * p_area = malloc( sizeof(input_area_t) );
309 msg_Err( p_input, "out of memory" );
313 /* Init this entry */
314 p_area->i_id = i_area_id;
315 p_area->i_part_nb = i_part_nb;
320 p_area->i_seek = NO_SEEK;
322 /* Add an entry to the list of program associated with the stream */
323 INSERT_ELEM( p_input->stream.pp_areas,
324 p_input->stream.i_area_nb,
325 p_input->stream.i_area_nb,
328 /* Don't add empty areas */
332 /* Take care of the navigation variables */
333 val.i_int = i_area_id;
334 var_Change( p_input, "title", VLC_VAR_ADDCHOICE, &val, NULL );
336 val.psz_string = malloc( sizeof("title ") + 5 );
341 sprintf( val.psz_string, "title %2i", i_area_id );
342 var_Destroy( p_input, val.psz_string );
343 var_Create( p_input, val.psz_string, VLC_VAR_INTEGER |
344 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
345 var_AddCallback( p_input, val.psz_string, NavigationCallback,
346 (void *)(int)i_area_id );
348 var_Change( p_input, "navigation", VLC_VAR_ADDCHOICE, &val, NULL );
350 for( i = 1; i <= i_part_nb; i++ )
353 var_Change( p_input, val.psz_string,
354 VLC_VAR_ADDCHOICE, &val2, NULL );
361 /*****************************************************************************
362 * input_SetProgram: changes the current program
363 *****************************************************************************/
364 int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
366 unsigned int i_es_index;
367 int i_required_audio_es;
368 int i_required_spu_es;
373 if ( p_input->stream.p_selected_program )
375 for ( i_es_index = 1 ; /* 0 should be the PMT */
376 i_es_index < p_input->stream.p_selected_program->
380 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
381 if ( p_es->p_decoder_fifo ) /* if the ES was selected */
383 input_UnselectES( p_input , p_es );
388 /* Get the number of the required audio stream */
389 if( config_GetInt( p_input, "audio" ) )
391 /* Default is the first one */
392 i_required_audio_es = config_GetInt( p_input, "audio-channel" );
393 if( i_required_audio_es < 0 )
395 i_required_audio_es = 1;
400 i_required_audio_es = 0;
403 /* Same thing for subtitles */
404 if( config_GetInt( p_input, "video" ) )
406 /* for spu, default is none */
407 i_required_spu_es = config_GetInt( p_input, "spu-channel" );
408 if( i_required_spu_es < 0 )
410 i_required_spu_es = 0;
415 i_required_spu_es = 0;
418 for( i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
420 switch( p_new_prg->pp_es[i_es_index]->i_cat )
423 msg_Dbg( p_input, "selecting ES %x",
424 p_new_prg->pp_es[i_es_index]->i_id );
425 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
429 if( i_audio_es <= i_required_audio_es )
431 msg_Dbg( p_input, "selecting ES %x",
432 p_new_prg->pp_es[i_es_index]->i_id );
433 input_SelectES( p_input, p_new_prg->pp_es[i_es_index]);
436 /* Not sure this one is fully specification-compliant */
439 if( i_spu_es <= i_required_spu_es )
441 msg_Dbg( p_input, "selecting ES %x",
442 p_new_prg->pp_es[i_es_index]->i_id );
443 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
447 msg_Dbg( p_input, "ES %x has unknown type",
448 p_new_prg->pp_es[i_es_index]->i_id );
455 p_input->stream.p_selected_program = p_new_prg;
457 /* Update the navigation variables without triggering a callback */
458 val.i_int = p_new_prg->i_number;
459 var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
464 /*****************************************************************************
465 * input_DelArea: destroy a area descriptor
466 *****************************************************************************
467 * All ES descriptions referenced in the descriptor will be deleted.
468 *****************************************************************************/
469 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
471 unsigned int i_area_index;
474 /* Find the area in the areas table */
475 for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
478 if( p_input->stream.pp_areas[i_area_index] == p_area )
482 /* If the area wasn't found, do nothing */
483 if( i_area_index == p_input->stream.i_area_nb )
485 msg_Err( p_input, "area does not belong to this input" );
489 /* Take care of the navigation variables */
490 val.psz_string = malloc( sizeof("title ") + 5 );
493 sprintf( val.psz_string, "title %i", p_area->i_id );
494 var_Change( p_input, "navigation", VLC_VAR_DELCHOICE, &val, NULL );
495 var_Destroy( p_input, val.psz_string );
498 /* Remove this area from the stream's list of areas */
499 REMOVE_ELEM( p_input->stream.pp_areas,
500 p_input->stream.i_area_nb,
503 /* Free the description of this area */
508 /*****************************************************************************
509 * input_FindES: returns a pointer to an ES described by its ID
510 *****************************************************************************/
511 es_descriptor_t * input_FindES( input_thread_t * p_input, uint16_t i_es_id )
515 for( i = 0; i < p_input->stream.i_es_number; i++ )
517 if( p_input->stream.pp_es[i]->i_id == i_es_id )
519 return p_input->stream.pp_es[i];
526 /*****************************************************************************
528 *****************************************************************************
529 * Reserve a slot in the table of ES descriptors for the ES and add it to the
530 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
532 *****************************************************************************/
533 es_descriptor_t * input_AddES( input_thread_t * p_input,
534 pgrm_descriptor_t * p_pgrm, u16 i_es_id,
535 int i_category, char const *psz_desc,
538 es_descriptor_t * p_es;
539 vlc_value_t val, text;
540 char *psz_var = NULL;
542 p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
545 msg_Err( p_input, "out of memory" );
549 INSERT_ELEM( p_input->stream.pp_es,
550 p_input->stream.i_es_number,
551 p_input->stream.i_es_number,
554 /* Init its values */
555 p_es->i_id = i_es_id;
557 p_es->p_decoder_fifo = NULL;
558 p_es->i_cat = i_category;
559 p_es->i_demux_fd = 0;
561 p_es->c_invalid_packets = 0;
562 p_es->b_force_decoder = VLC_FALSE;
566 p_es->p_demux_data = malloc( i_data_len );
567 if( p_es->p_demux_data == NULL )
569 msg_Err( p_input, "out of memory" );
572 memset( p_es->p_demux_data, 0, i_data_len );
576 p_es->p_demux_data = NULL;
578 p_es->p_waveformatex = NULL;
579 p_es->p_bitmapinfoheader = NULL;
581 /* Add this ES to the program definition if one is given */
584 INSERT_ELEM( p_pgrm->pp_es,
588 p_es->p_pgrm = p_pgrm;
598 psz_var = "audio-es";
604 psz_var = "video-es";
610 /* Get the number of ES already added */
611 var_Change( p_input, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
616 /* First one, we need to add the "Disable" choice */
617 val2.i_int = -1; text.psz_string = _("Disable");
618 var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val2, &text );
622 /* Take care of the ES description */
625 p_es->psz_desc = strdup( psz_desc );
629 p_es->psz_desc = malloc( strlen( _("Track %i") ) + 20 );
631 sprintf( p_es->psz_desc, _("Track %i"), val.i_int );
634 val.i_int = p_es->i_id;
635 text.psz_string = p_es->psz_desc;
636 var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val, &text );
642 /*****************************************************************************
644 *****************************************************************************/
645 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
647 unsigned int i_index, i_es_index;
648 pgrm_descriptor_t * p_pgrm;
649 char * psz_var = NULL;
652 /* Find the ES in the ES table */
653 for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
656 if( p_input->stream.pp_es[i_es_index] == p_es )
660 /* If the ES wasn't found, do nothing */
661 if( i_es_index == p_input->stream.i_es_number )
663 msg_Err( p_input, "ES does not belong to this input" );
667 /* Remove es from its associated variable */
668 switch( p_es->i_cat )
671 psz_var = "audio-es";
677 psz_var = "video-es";
683 val.i_int = p_es->i_id;
684 var_Change( p_input, psz_var, VLC_VAR_DELCHOICE, &val, NULL );
686 /* Remove the "Disable" entry if needed */
687 var_Change( p_input, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
691 var_Change( p_input, psz_var, VLC_VAR_DELCHOICE, &val, NULL );
695 /* Kill associated decoder, if any. */
696 if( p_es->p_decoder_fifo != NULL )
698 input_EndDecoder( p_input, p_es );
701 /* Remove this ES from the description of the program if it is associated
703 p_pgrm = p_es->p_pgrm;
706 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
708 if( p_pgrm->pp_es[i_index] == p_es )
710 REMOVE_ELEM( p_pgrm->pp_es,
718 /* Free the demux data */
719 if( p_es->p_demux_data != NULL )
721 free( p_es->p_demux_data );
723 if( p_es->p_waveformatex )
725 free( p_es->p_waveformatex );
727 if( p_es->p_bitmapinfoheader )
729 free( p_es->p_bitmapinfoheader );
732 /* Free the description string */
733 if( p_es->psz_desc != NULL )
735 free( p_es->psz_desc );
738 /* Find the ES in the ES table */
739 for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
742 if( p_input->stream.pp_es[i_es_index] == p_es )
746 /* Remove this ES from the stream's list of ES */
747 REMOVE_ELEM( p_input->stream.pp_es,
748 p_input->stream.i_es_number,
755 /*****************************************************************************
756 * input_SelectES: selects an ES and spawns the associated decoder
757 *****************************************************************************
758 * Remember we are still supposed to have stream_lock when entering this
760 *****************************************************************************/
761 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
764 char *psz_var = NULL;
768 msg_Err( p_input, "nothing to do in input_SelectES" );
772 if( ((p_es->i_cat == VIDEO_ES) || (p_es->i_cat == SPU_ES))
773 && !config_GetInt( p_input, "video" ) )
776 "video is disabled, not selecting ES 0x%x", p_es->i_id );
780 if( (p_es->i_cat == AUDIO_ES) && !config_GetInt( p_input, "audio" ) )
783 "audio is disabled, not selecting ES 0x%x", p_es->i_id );
787 msg_Dbg( p_input, "selecting ES 0x%x", p_es->i_id );
789 if( p_es->p_decoder_fifo != NULL )
791 msg_Err( p_input, "ES 0x%x is already selected", p_es->i_id );
795 /* Release the lock, not to block the input thread during
796 * the creation of the thread. */
797 vlc_mutex_unlock( &p_input->stream.stream_lock );
798 p_es->p_decoder_fifo = input_RunDecoder( p_input, p_es );
799 vlc_mutex_lock( &p_input->stream.stream_lock );
801 if( p_es->p_decoder_fifo == NULL )
806 /* Update the es variable without triggering a callback */
807 switch( p_es->i_cat )
810 psz_var = "audio-es";
816 psz_var = "video-es";
822 val.i_int = p_es->i_id;
823 var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
829 /*****************************************************************************
830 * input_UnselectES: removes an ES from the list of selected ES
831 *****************************************************************************/
832 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
834 unsigned int i_index = 0;
836 char *psz_var = NULL;
840 msg_Err( p_input, "nothing to do in input_UnselectES" );
844 msg_Dbg( p_input, "unselecting ES 0x%x", p_es->i_id );
846 if( p_es->p_decoder_fifo == NULL )
848 msg_Err( p_input, "ES 0x%x is not selected", p_es->i_id );
852 /* Update the es variable without triggering a callback */
853 switch( p_es->i_cat )
856 psz_var = "audio-es";
862 psz_var = "video-es";
869 var_Change( p_input, psz_var, VLC_VAR_SETVALUE, &val, NULL );
872 /* Actually unselect the ES */
873 input_EndDecoder( p_input, p_es );
876 if( ( p_es->p_decoder_fifo == NULL ) &&
877 ( p_input->stream.i_selected_es_number > 0 ) )
879 while( ( i_index < p_input->stream.i_selected_es_number - 1 ) &&
880 ( p_input->stream.pp_selected_es[i_index] != p_es ) )
885 /* XXX: no need to memmove, we have unsorted data */
886 REMOVE_ELEM( p_input->stream.pp_selected_es,
887 p_input->stream.i_selected_es_number,
890 if( p_input->stream.i_selected_es_number == 0 )
892 msg_Dbg( p_input, "no more selected ES" );
900 /*****************************************************************************
901 * Navigation callback: a bunch of navigation variables are used as an
902 * alternative to the navigation API.
903 *****************************************************************************/
904 static int ProgramCallback( vlc_object_t *p_this, char const *psz_cmd,
905 vlc_value_t oldval, vlc_value_t newval, void *p_data )
907 input_thread_t *p_input = (input_thread_t *)p_this;
910 if( oldval.i_int == newval.i_int )
913 vlc_mutex_lock( &p_input->stream.stream_lock );
914 if( ( newval.i_int > 0 ) )
916 vlc_mutex_unlock( &p_input->stream.stream_lock );
917 input_ChangeProgram( p_input, (uint16_t)newval.i_int );
918 input_SetStatus( p_input, INPUT_STATUS_PLAY );
919 vlc_mutex_lock( &p_input->stream.stream_lock );
921 vlc_mutex_unlock( &p_input->stream.stream_lock );
923 val.b_bool = VLC_TRUE;
924 var_Set( p_input, "intf-change", val );
929 static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
930 vlc_value_t oldval, vlc_value_t newval, void *p_data )
932 input_thread_t *p_input = (input_thread_t *)p_this;
933 input_area_t *p_area;
936 if( oldval.i_int == newval.i_int )
939 /* Sanity check should have already be done by var_Set(). */
940 vlc_mutex_lock( &p_input->stream.stream_lock );
941 p_area = p_input->stream.pp_areas[newval.i_int];
943 vlc_mutex_unlock( &p_input->stream.stream_lock );
944 input_ChangeArea( p_input, p_area );
945 input_SetStatus( p_input, INPUT_STATUS_PLAY );
947 val.b_bool = VLC_TRUE;
948 var_Set( p_input, "intf-change", val );
953 static int ChapterCallback( vlc_object_t *p_this, char const *psz_cmd,
954 vlc_value_t oldval, vlc_value_t newval, void *p_data )
956 input_thread_t *p_input = (input_thread_t *)p_this;
957 input_area_t *p_area;
960 if( oldval.i_int == newval.i_int )
963 /* Sanity check will have already be done by var_Set(). */
964 vlc_mutex_lock( &p_input->stream.stream_lock );
965 p_area = p_input->stream.p_selected_area;
966 p_input->stream.p_selected_area->i_part = newval.i_int;
967 vlc_mutex_unlock( &p_input->stream.stream_lock );
969 input_ChangeArea( p_input, p_area );
970 input_SetStatus( p_input, INPUT_STATUS_PLAY );
972 val.b_bool = VLC_TRUE;
973 var_Set( p_input, "intf-change", val );
978 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
979 vlc_value_t oldval, vlc_value_t newval, void *p_data )
981 input_thread_t *p_input = (input_thread_t *)p_this;
982 uint16_t i_area_id = (int)p_data;
985 vlc_mutex_lock( &p_input->stream.stream_lock );
987 if( p_input->stream.p_selected_area->i_id == i_area_id &&
988 oldval.i_int == newval.i_int )
991 vlc_mutex_unlock( &p_input->stream.stream_lock );
995 if( ( i_area_id < p_input->stream.i_area_nb ) && ( newval.i_int > 0 ) &&
996 ( (uint16_t)newval.i_int <=
997 p_input->stream.pp_areas[i_area_id]->i_part_nb ) )
999 input_area_t *p_area = p_input->stream.pp_areas[i_area_id];
1000 p_input->stream.p_selected_area->i_part = newval.i_int;
1001 vlc_mutex_unlock( &p_input->stream.stream_lock );
1002 input_ChangeArea( p_input, p_area );
1003 input_SetStatus( p_input, INPUT_STATUS_PLAY );
1004 vlc_mutex_lock( &p_input->stream.stream_lock );
1006 vlc_mutex_unlock( &p_input->stream.stream_lock );
1008 val.b_bool = VLC_TRUE;
1009 var_Set( p_input, "intf-change", val );
1014 static int ESCallback( vlc_object_t *p_this, char const *psz_cmd,
1015 vlc_value_t oldval, vlc_value_t newval, void *p_data )
1017 input_thread_t *p_input = (input_thread_t *)p_this;
1021 vlc_mutex_lock( &p_input->stream.stream_lock );
1023 /* Unselect old ES */
1024 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
1026 if( p_input->stream.pp_es[i]->i_id == oldval.i_int &&
1027 p_input->stream.pp_es[i]->p_decoder_fifo != NULL )
1029 input_UnselectES( p_input, p_input->stream.pp_es[i] );
1034 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
1036 if( p_input->stream.pp_es[i]->i_id == newval.i_int &&
1037 p_input->stream.pp_es[i]->p_decoder_fifo == NULL )
1039 input_SelectES( p_input, p_input->stream.pp_es[i] );
1043 vlc_mutex_unlock( &p_input->stream.stream_lock );
1045 val.b_bool = VLC_TRUE;
1046 var_Set( p_input, "intf-change", val );