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.106 2003/05/05 22:23:42 gbazin 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 /* Create a few object variables used for navigation in the interfaces */
89 var_Create( p_input, "program", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
90 text.psz_string = _("Program");
91 var_Change( p_input, "program", VLC_VAR_SETTEXT, &text, NULL );
92 var_Create( p_input, "title", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
93 text.psz_string = _("Title");
94 var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
95 var_Create( p_input, "chapter", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
96 text.psz_string = _("Chapter");
97 var_Change( p_input, "chapter", VLC_VAR_SETTEXT, &text, NULL );
98 var_Create( p_input, "navigation", VLC_VAR_VARIABLE | VLC_VAR_HASCHOICE );
99 text.psz_string = _("Navigation");
100 var_Change( p_input, "navigation", VLC_VAR_SETTEXT, &text, NULL );
101 var_Create( p_input, "video-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
102 text.psz_string = _("Video track");
103 var_Change( p_input, "video-es", VLC_VAR_SETTEXT, &text, NULL );
104 var_Create( p_input, "audio-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
105 text.psz_string = _("Audio track");
106 var_Change( p_input, "audio-es", VLC_VAR_SETTEXT, &text, NULL );
107 var_Create( p_input, "spu-es", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
108 text.psz_string = _("Subtitle track");
109 var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
111 var_AddCallback( p_input, "program", ProgramCallback, NULL );
112 var_AddCallback( p_input, "title", TitleCallback, NULL );
113 var_AddCallback( p_input, "chapter", ChapterCallback, NULL );
114 var_AddCallback( p_input, "video-es", ESCallback, NULL );
115 var_AddCallback( p_input, "audio-es", ESCallback, NULL );
116 var_AddCallback( p_input, "spu-es", ESCallback, NULL );
121 /*****************************************************************************
122 * input_EndStream: free all stream descriptors
123 *****************************************************************************/
124 void input_EndStream( input_thread_t * p_input )
126 /* Free all programs and associated ES, and associated decoders. */
127 while( p_input->stream.i_pgrm_number )
129 input_DelProgram( p_input, p_input->stream.pp_programs[0] );
132 /* Free standalone ES */
133 while( p_input->stream.i_es_number )
135 input_DelES( p_input, p_input->stream.pp_es[0] );
139 while( p_input->stream.i_area_nb )
141 input_DelArea( p_input, p_input->stream.pp_areas[0] );
144 /* Free selected ES */
145 if( p_input->stream.pp_selected_es != NULL )
147 free( p_input->stream.pp_selected_es );
150 if( p_input->stream.p_demux_data != NULL )
152 free( p_input->stream.p_demux_data );
155 /* Free navigation variables */
156 var_Destroy( p_input, "program" );
157 var_Destroy( p_input, "title" );
158 var_Destroy( p_input, "chapter" );
159 var_Destroy( p_input, "video-es" );
160 var_Destroy( p_input, "audio-es" );
161 var_Destroy( p_input, "spu-es" );
164 /*****************************************************************************
165 * input_FindProgram: returns a pointer to a program described by its ID
166 *****************************************************************************/
167 pgrm_descriptor_t * input_FindProgram( input_thread_t * p_input,
172 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
174 if( p_input->stream.pp_programs[i]->i_number == i_pgrm_id )
176 return p_input->stream.pp_programs[i];
183 /*****************************************************************************
184 * input_AddProgram: add and init a program descriptor
185 *****************************************************************************
186 * This program descriptor will be referenced in the given stream descriptor
187 *****************************************************************************/
188 pgrm_descriptor_t * input_AddProgram( input_thread_t * p_input,
189 u16 i_pgrm_id, size_t i_data_len )
191 /* Where to add the pgrm */
192 pgrm_descriptor_t * p_pgrm = malloc( sizeof(pgrm_descriptor_t) );
197 msg_Err( p_input, "out of memory" );
201 /* Init this entry */
202 p_pgrm->i_number = i_pgrm_id;
204 p_pgrm->i_version = 0;
206 p_pgrm->i_es_number = 0;
207 p_pgrm->pp_es = NULL;
209 input_ClockInit( p_pgrm );
211 p_pgrm->i_synchro_state = SYNCHRO_START;
215 p_pgrm->p_demux_data = malloc( i_data_len );
216 if( p_pgrm->p_demux_data == NULL )
218 msg_Err( p_input, "out of memory" );
221 memset( p_pgrm->p_demux_data, 0, i_data_len );
225 p_pgrm->p_demux_data = NULL;
228 /* Add an entry to the list of program associated with the stream */
229 INSERT_ELEM( p_input->stream.pp_programs,
230 p_input->stream.i_pgrm_number,
231 p_input->stream.i_pgrm_number,
234 val.i_int = i_pgrm_id;
235 var_Change( p_input, "program", VLC_VAR_ADDCHOICE, &val, NULL );
240 /*****************************************************************************
241 * input_DelProgram: destroy a program descriptor
242 *****************************************************************************
243 * All ES descriptions referenced in the descriptor will be deleted.
244 *****************************************************************************/
245 void input_DelProgram( input_thread_t * p_input, pgrm_descriptor_t * p_pgrm )
247 unsigned int i_pgrm_index;
250 /* Find the program in the programs table */
251 for( i_pgrm_index = 0; i_pgrm_index < p_input->stream.i_pgrm_number;
254 if( p_input->stream.pp_programs[i_pgrm_index] == p_pgrm )
258 /* If the program wasn't found, do nothing */
259 if( i_pgrm_index == p_input->stream.i_pgrm_number )
261 msg_Err( p_input, "program does not belong to this input" );
265 val.i_int = i_pgrm_index;
266 var_Change( p_input, "program", VLC_VAR_DELCHOICE, &val, NULL );
268 /* Free the structures that describe the es that belongs to that program */
269 while( p_pgrm->i_es_number )
271 input_DelES( p_input, p_pgrm->pp_es[0] );
274 /* Free the demux data */
275 if( p_pgrm->p_demux_data != NULL )
277 free( p_pgrm->p_demux_data );
280 /* Remove this program from the stream's list of programs */
281 REMOVE_ELEM( p_input->stream.pp_programs,
282 p_input->stream.i_pgrm_number,
285 /* Free the description of this program */
289 /*****************************************************************************
290 * input_AddArea: add and init an area descriptor
291 *****************************************************************************
292 * This area descriptor will be referenced in the given stream descriptor
293 *****************************************************************************/
294 input_area_t * input_AddArea( input_thread_t * p_input,
295 uint16_t i_area_id, uint16_t i_part_nb )
297 /* Where to add the pgrm */
298 input_area_t * p_area = malloc( sizeof(input_area_t) );
304 msg_Err( p_input, "out of memory" );
308 /* Init this entry */
309 p_area->i_id = i_area_id;
310 p_area->i_part_nb = i_part_nb;
315 p_area->i_seek = NO_SEEK;
317 /* Add an entry to the list of program associated with the stream */
318 INSERT_ELEM( p_input->stream.pp_areas,
319 p_input->stream.i_area_nb,
320 p_input->stream.i_area_nb,
323 /* Don't add empty areas */
327 /* Take care of the navigation variables */
328 val.i_int = i_area_id;
329 var_Change( p_input, "title", VLC_VAR_ADDCHOICE, &val, NULL );
331 val.psz_string = malloc( sizeof("title ") + 5 );
336 sprintf( val.psz_string, "title %2i", i_area_id );
337 var_Destroy( p_input, val.psz_string );
338 var_Create( p_input, val.psz_string, VLC_VAR_INTEGER |
339 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
340 var_AddCallback( p_input, val.psz_string, NavigationCallback,
341 (void *)(int)i_area_id );
343 var_Change( p_input, "navigation", VLC_VAR_ADDCHOICE, &val, NULL );
345 for( i = 1; i <= i_part_nb; i++ )
348 var_Change( p_input, val.psz_string,
349 VLC_VAR_ADDCHOICE, &val2, NULL );
356 /*****************************************************************************
357 * input_SetProgram: changes the current program
358 *****************************************************************************/
359 int input_SetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_new_prg )
361 unsigned int i_es_index;
362 int i_required_audio_es;
363 int i_required_spu_es;
368 if ( p_input->stream.p_selected_program )
370 for ( i_es_index = 1 ; /* 0 should be the PMT */
371 i_es_index < p_input->stream.p_selected_program->
375 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
376 if ( p_es->p_decoder_fifo ) /* if the ES was selected */
378 input_UnselectES( p_input , p_es );
383 /* Get the number of the required audio stream */
384 if( config_GetInt( p_input, "audio" ) )
386 /* Default is the first one */
387 i_required_audio_es = config_GetInt( p_input, "audio-channel" );
388 if( i_required_audio_es < 0 )
390 i_required_audio_es = 1;
395 i_required_audio_es = 0;
398 /* Same thing for subtitles */
399 if( config_GetInt( p_input, "video" ) )
401 /* for spu, default is none */
402 i_required_spu_es = config_GetInt( p_input, "spu-channel" );
403 if( i_required_spu_es < 0 )
405 i_required_spu_es = 0;
410 i_required_spu_es = 0;
413 for( i_es_index = 0 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
415 switch( p_new_prg->pp_es[i_es_index]->i_cat )
418 msg_Dbg( p_input, "selecting ES %x",
419 p_new_prg->pp_es[i_es_index]->i_id );
420 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
424 if( i_audio_es <= i_required_audio_es )
426 msg_Dbg( p_input, "selecting ES %x",
427 p_new_prg->pp_es[i_es_index]->i_id );
428 input_SelectES( p_input, p_new_prg->pp_es[i_es_index]);
431 /* Not sure this one is fully specification-compliant */
434 if( i_spu_es <= i_required_spu_es )
436 msg_Dbg( p_input, "selecting ES %x",
437 p_new_prg->pp_es[i_es_index]->i_id );
438 input_SelectES( p_input, p_new_prg->pp_es[i_es_index] );
442 msg_Dbg( p_input, "ES %x has unknown type",
443 p_new_prg->pp_es[i_es_index]->i_id );
450 p_input->stream.p_selected_program = p_new_prg;
452 /* Update the navigation variables without triggering a callback */
453 val.i_int = p_new_prg->i_number;
454 var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
459 /*****************************************************************************
460 * input_DelArea: destroy a area descriptor
461 *****************************************************************************
462 * All ES descriptions referenced in the descriptor will be deleted.
463 *****************************************************************************/
464 void input_DelArea( input_thread_t * p_input, input_area_t * p_area )
466 unsigned int i_area_index;
469 /* Find the area in the areas table */
470 for( i_area_index = 0; i_area_index < p_input->stream.i_area_nb;
473 if( p_input->stream.pp_areas[i_area_index] == p_area )
477 /* If the area wasn't found, do nothing */
478 if( i_area_index == p_input->stream.i_area_nb )
480 msg_Err( p_input, "area does not belong to this input" );
484 /* Take care of the navigation variables */
485 val.psz_string = malloc( sizeof("title ") + 5 );
488 sprintf( val.psz_string, "title %i", p_area->i_id );
489 var_Change( p_input, "navigation", VLC_VAR_DELCHOICE, &val, NULL );
490 var_Destroy( p_input, val.psz_string );
493 /* Remove this area from the stream's list of areas */
494 REMOVE_ELEM( p_input->stream.pp_areas,
495 p_input->stream.i_area_nb,
498 /* Free the description of this area */
503 /*****************************************************************************
504 * input_FindES: returns a pointer to an ES described by its ID
505 *****************************************************************************/
506 es_descriptor_t * input_FindES( input_thread_t * p_input, uint16_t i_es_id )
510 for( i = 0; i < p_input->stream.i_es_number; i++ )
512 if( p_input->stream.pp_es[i]->i_id == i_es_id )
514 return p_input->stream.pp_es[i];
521 /*****************************************************************************
523 *****************************************************************************
524 * Reserve a slot in the table of ES descriptors for the ES and add it to the
525 * list of ES of p_pgrm. If p_pgrm if NULL, then the ES is considered as stand
527 *****************************************************************************/
528 es_descriptor_t * input_AddES( input_thread_t * p_input,
529 pgrm_descriptor_t * p_pgrm, u16 i_es_id,
530 int i_category, char const *psz_desc,
533 es_descriptor_t * p_es;
534 vlc_value_t val, text;
535 char *psz_var = NULL;
537 p_es = (es_descriptor_t *)malloc( sizeof(es_descriptor_t) );
540 msg_Err( p_input, "out of memory" );
544 INSERT_ELEM( p_input->stream.pp_es,
545 p_input->stream.i_es_number,
546 p_input->stream.i_es_number,
549 /* Init its values */
550 p_es->i_id = i_es_id;
551 p_es->psz_desc = psz_desc ? strdup( psz_desc ) : NULL;
553 p_es->p_decoder_fifo = NULL;
554 p_es->i_cat = i_category;
555 p_es->i_demux_fd = 0;
557 p_es->c_invalid_packets = 0;
558 p_es->b_force_decoder = VLC_FALSE;
562 p_es->p_demux_data = malloc( i_data_len );
563 if( p_es->p_demux_data == NULL )
565 msg_Err( p_input, "out of memory" );
568 memset( p_es->p_demux_data, 0, i_data_len );
572 p_es->p_demux_data = NULL;
574 p_es->p_waveformatex = NULL;
575 p_es->p_bitmapinfoheader = NULL;
577 /* Add this ES to the program definition if one is given */
580 INSERT_ELEM( p_pgrm->pp_es,
584 p_es->p_pgrm = p_pgrm;
594 psz_var = "audio-es";
600 psz_var = "video-es";
606 val.i_int = p_es->i_id;
607 text.psz_string = (char *)psz_desc;
608 var_Change( p_input, psz_var, VLC_VAR_ADDCHOICE, &val, &text );
614 /*****************************************************************************
616 *****************************************************************************/
617 void input_DelES( input_thread_t * p_input, es_descriptor_t * p_es )
619 unsigned int i_index, i_es_index;
620 pgrm_descriptor_t * p_pgrm;
624 /* Find the ES in the ES table */
625 for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
628 if( p_input->stream.pp_es[i_es_index] == p_es )
632 /* If the ES wasn't found, do nothing */
633 if( i_es_index == p_input->stream.i_es_number )
635 msg_Err( p_input, "ES does not belong to this input" );
639 /* Remove es from its associated variable */
640 switch( p_es->i_cat )
643 psz_var = "audio-es";
650 psz_var = "video-es";
653 val.i_int = p_es->i_id;
654 var_Change( p_input, psz_var, VLC_VAR_DELCHOICE, &val, NULL );
656 /* Kill associated decoder, if any. */
657 if( p_es->p_decoder_fifo != NULL )
659 input_EndDecoder( p_input, p_es );
662 /* Remove this ES from the description of the program if it is associated
664 p_pgrm = p_es->p_pgrm;
667 for( i_index = 0; i_index < p_pgrm->i_es_number; i_index++ )
669 if( p_pgrm->pp_es[i_index] == p_es )
671 REMOVE_ELEM( p_pgrm->pp_es,
679 /* Free the demux data */
680 if( p_es->p_demux_data != NULL )
682 free( p_es->p_demux_data );
684 if( p_es->p_waveformatex )
686 free( p_es->p_waveformatex );
688 if( p_es->p_bitmapinfoheader )
690 free( p_es->p_bitmapinfoheader );
693 /* Free the description string */
694 if( p_es->psz_desc != NULL )
696 free( p_es->psz_desc );
699 /* Find the ES in the ES table */
700 for( i_es_index = 0; i_es_index < p_input->stream.i_es_number;
703 if( p_input->stream.pp_es[i_es_index] == p_es )
707 /* Remove this ES from the stream's list of ES */
708 REMOVE_ELEM( p_input->stream.pp_es,
709 p_input->stream.i_es_number,
716 /*****************************************************************************
717 * input_SelectES: selects an ES and spawns the associated decoder
718 *****************************************************************************
719 * Remember we are still supposed to have stream_lock when entering this
721 *****************************************************************************/
722 int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )
728 msg_Err( p_input, "nothing to do in input_SelectES" );
732 if( ((p_es->i_cat == VIDEO_ES) || (p_es->i_cat == SPU_ES))
733 && !config_GetInt( p_input, "video" ) )
736 "video is disabled, not selecting ES 0x%x", p_es->i_id );
740 if( (p_es->i_cat == AUDIO_ES) && !config_GetInt( p_input, "audio" ) )
743 "audio is disabled, not selecting ES 0x%x", p_es->i_id );
747 msg_Dbg( p_input, "selecting ES 0x%x", p_es->i_id );
749 if( p_es->p_decoder_fifo != NULL )
751 msg_Err( p_input, "ES 0x%x is already selected", p_es->i_id );
755 /* Release the lock, not to block the input thread during
756 * the creation of the thread. */
757 vlc_mutex_unlock( &p_input->stream.stream_lock );
758 p_es->p_decoder_fifo = input_RunDecoder( p_input, p_es );
759 vlc_mutex_lock( &p_input->stream.stream_lock );
761 if( p_es->p_decoder_fifo == NULL )
766 /* Update the es variable without triggering a callback */
767 val.i_int = p_es->i_id;
768 var_Change( p_input, "audio-es", VLC_VAR_SETVALUE, &val, NULL );
773 /*****************************************************************************
774 * input_UnselectES: removes an ES from the list of selected ES
775 *****************************************************************************/
776 int input_UnselectES( input_thread_t * p_input, es_descriptor_t * p_es )
779 unsigned int i_index = 0;
783 msg_Err( p_input, "nothing to do in input_UnselectES" );
787 msg_Dbg( p_input, "unselecting ES 0x%x", p_es->i_id );
789 if( p_es->p_decoder_fifo == NULL )
791 msg_Err( p_input, "ES 0x%x is not selected", p_es->i_id );
795 input_EndDecoder( p_input, p_es );
798 if( ( p_es->p_decoder_fifo == NULL ) &&
799 ( p_input->stream.i_selected_es_number > 0 ) )
801 while( ( i_index < p_input->stream.i_selected_es_number - 1 ) &&
802 ( p_input->stream.pp_selected_es[i_index] != p_es ) )
807 /* XXX: no need to memmove, we have unsorted data */
808 REMOVE_ELEM( p_input->stream.pp_selected_es,
809 p_input->stream.i_selected_es_number,
812 if( p_input->stream.i_selected_es_number == 0 )
814 msg_Dbg( p_input, "no more selected ES" );
822 /*****************************************************************************
823 * Navigation callback: a bunch of navigation variables are used as an
824 * alternative to the navigation API.
825 *****************************************************************************/
826 static int ProgramCallback( vlc_object_t *p_this, char const *psz_cmd,
827 vlc_value_t oldval, vlc_value_t newval, void *p_data )
829 input_thread_t *p_input = (input_thread_t *)p_this;
831 if( oldval.i_int == newval.i_int )
834 vlc_mutex_lock( &p_input->stream.stream_lock );
835 if( ( newval.i_int > 0 ) )
837 vlc_mutex_unlock( &p_input->stream.stream_lock );
838 input_ChangeProgram( p_input, (uint16_t)newval.i_int );
839 input_SetStatus( p_input, INPUT_STATUS_PLAY );
840 vlc_mutex_lock( &p_input->stream.stream_lock );
842 vlc_mutex_unlock( &p_input->stream.stream_lock );
847 static int TitleCallback( vlc_object_t *p_this, char const *psz_cmd,
848 vlc_value_t oldval, vlc_value_t newval, void *p_data )
850 input_thread_t *p_input = (input_thread_t *)p_this;
851 input_area_t *p_area;
853 if( oldval.i_int == newval.i_int )
856 /* Sanity check should have already be done by var_Set(). */
857 vlc_mutex_lock( &p_input->stream.stream_lock );
858 p_area = p_input->stream.pp_areas[newval.i_int];
860 vlc_mutex_unlock( &p_input->stream.stream_lock );
861 input_ChangeArea( p_input, p_area );
862 input_SetStatus( p_input, INPUT_STATUS_PLAY );
867 static int ChapterCallback( vlc_object_t *p_this, char const *psz_cmd,
868 vlc_value_t oldval, vlc_value_t newval, void *p_data )
870 input_thread_t *p_input = (input_thread_t *)p_this;
871 input_area_t *p_area;
873 if( oldval.i_int == newval.i_int )
876 /* Sanity check will have already be done by var_Set(). */
877 vlc_mutex_lock( &p_input->stream.stream_lock );
878 p_area = p_input->stream.p_selected_area;
879 p_input->stream.p_selected_area->i_part = newval.i_int;
880 vlc_mutex_unlock( &p_input->stream.stream_lock );
882 input_ChangeArea( p_input, p_area );
883 input_SetStatus( p_input, INPUT_STATUS_PLAY );
888 static int NavigationCallback( vlc_object_t *p_this, char const *psz_cmd,
889 vlc_value_t oldval, vlc_value_t newval, void *p_data )
891 input_thread_t *p_input = (input_thread_t *)p_this;
892 uint16_t i_area_id = (int)p_data;
894 vlc_mutex_lock( &p_input->stream.stream_lock );
896 if( p_input->stream.p_selected_area->i_id == i_area_id &&
897 oldval.i_int == newval.i_int )
900 vlc_mutex_unlock( &p_input->stream.stream_lock );
904 if( ( i_area_id < p_input->stream.i_area_nb ) && ( newval.i_int > 0 ) &&
905 ( (uint16_t)newval.i_int <=
906 p_input->stream.pp_areas[i_area_id]->i_part_nb ) )
908 input_area_t *p_area = p_input->stream.pp_areas[i_area_id];
909 p_input->stream.p_selected_area->i_part = newval.i_int;
910 vlc_mutex_unlock( &p_input->stream.stream_lock );
911 input_ChangeArea( p_input, p_area );
912 input_SetStatus( p_input, INPUT_STATUS_PLAY );
913 vlc_mutex_lock( &p_input->stream.stream_lock );
915 vlc_mutex_unlock( &p_input->stream.stream_lock );
920 static int ESCallback( vlc_object_t *p_this, char const *psz_cmd,
921 vlc_value_t oldval, vlc_value_t newval, void *p_data )
923 input_thread_t *p_input = (input_thread_t *)p_this;
926 vlc_mutex_lock( &p_input->stream.stream_lock );
928 /* Unselect old ES */
929 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
931 if( p_input->stream.pp_es[i]->i_id == oldval.i_int &&
932 p_input->stream.pp_es[i]->p_decoder_fifo != NULL )
934 input_UnselectES( p_input, p_input->stream.pp_es[i] );
939 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
941 if( p_input->stream.pp_es[i]->i_id == newval.i_int &&
942 p_input->stream.pp_es[i]->p_decoder_fifo == NULL )
944 input_SelectES( p_input, p_input->stream.pp_es[i] );
948 vlc_mutex_unlock( &p_input->stream.stream_lock );