]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
* Added a file panel for subtitles file selection.
[vlc] / modules / gui / beos / VlcWrapper.cpp
1 /*****************************************************************************
2  * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port)
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: VlcWrapper.cpp,v 1.18 2003/01/14 14:48:55 titer Exp $
6  *
7  * Authors: Florian G. Pflug <fgp@phlo.org>
8  *          Jon Lech Johansen <jon-vl@nanocrew.net>
9  *          Tony Casltey <tony@castley.net>
10  *          Stephan Aßmus <stippi@yellowbites.com>
11  *          Eric Petit <titer@videolan.org>
12  *
13  * This program is free software{} you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation{} either version 2 of the License, or
16  * (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY{} without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program{} if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27 #include <AppKit.h>
28 #include <InterfaceKit.h>
29 #include <SupportKit.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33 extern "C" {
34 #include <audio_output.h>
35 #include <aout_internal.h>
36 }
37
38 #include "VlcWrapper.h"
39 #include "MsgVals.h"
40
41 /* constructor */
42 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
43 {
44     p_intf = p_interface;
45     p_input = NULL;
46     p_aout = NULL;
47     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
48                                                 FIND_ANYWHERE );
49 }
50
51 /* destructor */
52 VlcWrapper::~VlcWrapper()
53 {
54     if( p_input )
55     {
56         vlc_object_release( p_input );
57     }
58     if( p_playlist )
59     {
60         vlc_object_release( p_playlist );
61     }
62     if( p_aout )
63     {
64         vlc_object_release( p_aout );
65     }
66 }
67
68 /* UpdateInputAndAOut: updates p_input and p_aout, returns true if the
69    interface needs to be updated */
70 bool VlcWrapper::UpdateInputAndAOut()
71 {
72     if( p_input == NULL )
73     {
74         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
75                                                      FIND_ANYWHERE );
76     }
77     if( p_aout == NULL )
78     {
79         p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
80                                                     FIND_ANYWHERE );
81     }
82         
83     if( p_input != NULL )
84     {
85         if( p_input->b_dead )
86         {
87             vlc_object_release( p_input );
88             p_input = NULL;
89             
90             if( p_aout )
91             {
92                 vlc_object_release( p_aout );
93                 p_aout = NULL;
94             }
95         }
96         return true;
97     }
98     return false;
99 }
100
101
102 /***************************
103  * input infos and control *
104  ***************************/
105
106 bool VlcWrapper::HasInput()
107 {
108     return ( p_input != NULL );
109 //    return ( PlaylistSize() > 0 );
110 }
111
112 /* status (UNDEF_S, PLAYING_S, PAUSE_S, FORWARD_S, BACKWARD_S,
113    REWIND_S, NOT_STARTED_S, START_S) */
114 int VlcWrapper::InputStatus()
115 {
116     if( !p_input )
117     {
118         return UNDEF_S;
119     }
120     return p_input->stream.control.i_status;
121 }
122
123 int VlcWrapper::InputRate()
124 {
125     if( !p_input )
126     {
127         return DEFAULT_RATE;
128     }
129     return p_input->stream.control.i_rate;
130 }
131
132 void VlcWrapper::InputSlower()
133 {
134     if( p_input != NULL )
135     {
136         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
137     }
138 }
139
140 void VlcWrapper::InputFaster()
141 {
142     if( p_input != NULL )
143     {
144         input_SetStatus( p_input, INPUT_STATUS_FASTER );
145     }
146 }
147
148 BList * VlcWrapper::InputGetChannels( int i_cat )
149 {
150     if( p_input )
151     {
152         unsigned int i;
153         uint32 what;
154         const char* fieldName;
155
156         switch( i_cat )
157         {
158             case AUDIO_ES:
159             {
160                 what = SELECT_CHANNEL;
161                 fieldName = "channel";
162                 break;
163             }
164             case SPU_ES:
165             {
166                 what = SELECT_SUBTITLE;
167                 fieldName = "subtitle";
168                 break;
169             }
170             default:
171             return NULL;
172        }
173
174         vlc_mutex_lock( &p_input->stream.stream_lock );
175       
176         /* find which track is currently playing */
177         es_descriptor_t *p_es = NULL;
178         for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
179         {
180             if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
181                 p_es = p_input->stream.pp_selected_es[i];
182         }
183         
184         /* build a list of all tracks */
185         BList *list = new BList( p_input->stream.i_es_number );
186         BMenuItem *menuItem;
187         BMessage *message;
188         char *trackName;
189         
190         /* "None" */
191         message = new BMessage( what );
192         message->AddInt32( fieldName, -1 );
193         menuItem = new BMenuItem( "None", message );
194         if( !p_es )
195             menuItem->SetMarked( true );
196         list->AddItem( menuItem );
197         
198         for( i = 0; i < p_input->stream.i_es_number; i++ )
199         {
200             if( p_input->stream.pp_es[i]->i_cat == i_cat )
201             {
202                 message = new BMessage( what );
203                 message->AddInt32( fieldName, i );
204                 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
205                     trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
206                 else
207                     trackName = "<unknown>";
208                 menuItem = new BMenuItem( trackName, message );
209                 if( p_input->stream.pp_es[i] == p_es )
210                     menuItem->SetMarked( true );
211                 list->AddItem( menuItem );
212             }
213         }
214         
215         vlc_mutex_unlock( &p_input->stream.stream_lock );
216
217         return list;
218     }
219     return NULL;
220 }
221
222 void VlcWrapper::openFiles( BList* o_files, bool replace )
223 {
224     BString *o_file;
225
226     while( ( o_file = (BString *)o_files->LastItem() ) )
227     {
228         o_files->RemoveItem(o_files->CountItems() - 1);
229         playlist_Add( p_playlist, o_file->String(),
230                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
231         delete o_file;
232     }
233 }
234
235 void VlcWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
236 {
237     BString o_source("");
238     o_source << o_type << ":" << o_device ;
239
240     playlist_Add( p_playlist, o_source.String(),
241                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
242 }
243
244 void VlcWrapper::LoadSubFile( char * psz_file )
245 {
246     config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
247 }
248
249 void VlcWrapper::ToggleLanguage( int i_language )
250 {
251     es_descriptor_t * p_es = NULL;
252     es_descriptor_t * p_es_old = NULL;
253
254     vlc_mutex_lock( &p_input->stream.stream_lock );
255     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
256     {
257         if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
258         {
259             p_es_old = p_input->stream.pp_selected_es[i];
260             break;
261         }
262     }
263     vlc_mutex_unlock( &p_input->stream.stream_lock );
264     
265     if( i_language != -1 )
266     {
267         p_es = p_input->stream.pp_es[i_language];
268     }
269     if( p_es == p_es_old )
270     {
271         return;
272     }
273     if( p_es_old )
274     {
275         input_ToggleES( p_input, p_es_old, VLC_FALSE );
276     }
277     if( p_es )
278     {
279         input_ToggleES( p_input, p_es, VLC_TRUE );
280     }
281 }
282
283 void VlcWrapper::ToggleSubtitle( int i_subtitle )
284 {
285     es_descriptor_t * p_es = NULL;
286     es_descriptor_t * p_es_old = NULL;
287
288     vlc_mutex_lock( &p_input->stream.stream_lock );
289     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
290     {
291         if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
292         {
293             p_es_old = p_input->stream.pp_selected_es[i];
294             break;
295         }
296     }
297     vlc_mutex_unlock( &p_input->stream.stream_lock );
298     
299     if( i_subtitle != -1 )
300     {
301         p_es = p_input->stream.pp_es[i_subtitle];
302     }
303     if( p_es == p_es_old )
304     {
305         return;
306     }
307     if( p_es_old )
308     {
309         input_ToggleES( p_input, p_es_old, VLC_FALSE );
310     }
311     if( p_es )
312     {
313         input_ToggleES( p_input, p_es, VLC_TRUE );
314     }
315 }
316
317 const char*  VlcWrapper::getTimeAsString()
318 {
319     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
320         
321     if( p_input == NULL )
322     {
323         return ("-:--:--");
324     }     
325    
326     input_OffsetToTime( p_input, 
327                         psz_currenttime, 
328                         p_input->stream.p_selected_area->i_tell );        
329
330     return(psz_currenttime);
331 }
332
333 float  VlcWrapper::getTimeAsFloat()
334 {
335     float f_time = 0.0;
336
337     if( p_input != NULL )
338     {
339         f_time = (float)p_input->stream.p_selected_area->i_tell / 
340                  (float)p_input->stream.p_selected_area->i_size;
341     }    
342     else
343     {
344         f_time = 0.0;
345     }
346     return( f_time );
347 }
348
349 void VlcWrapper::setTimeAsFloat(float f_position)
350 {
351     if( p_input != NULL )
352     {
353         input_Seek( p_input, 
354                    (long long int)(p_input->stream.p_selected_area->i_size
355                        * f_position / SEEKSLIDER_RANGE ), 
356                    INPUT_SEEK_SET);
357     }
358 }
359
360 bool VlcWrapper::IsPlaying()
361 {
362
363         bool playing = false;
364         if ( p_input )
365         {
366                 switch ( p_input->stream.control.i_status )
367                 {
368                         case PLAYING_S:
369                         case FORWARD_S:
370                         case BACKWARD_S:
371                         case START_S:
372                                 playing = true;
373                     break;
374                         case PAUSE_S:
375                         case UNDEF_S:
376                         case NOT_STARTED_S:
377                         default:
378                                 break;
379                 }
380         }
381         return playing;
382
383 }
384
385 /******************************
386  * playlist infos and control *
387  ******************************/
388 int VlcWrapper::PlaylistSize()
389 {
390     vlc_mutex_lock( &p_playlist->object_lock );
391     int i_size = p_playlist->i_size;
392     vlc_mutex_unlock( &p_playlist->object_lock );
393     return i_size;
394 }
395
396 char *VlcWrapper::PlaylistItemName( int i )
397 {
398    return p_playlist->pp_items[i]->psz_name;
399 }
400
401 int VlcWrapper::PlaylistCurrent()
402 {
403     return p_playlist->i_index;
404 }
405
406 int  VlcWrapper::PlaylistStatus()
407 {
408     return p_playlist->i_status;
409 }
410
411 bool VlcWrapper::PlaylistPlay()
412 {
413     if( PlaylistSize() )
414     {
415         playlist_Play( p_playlist );
416     }
417     return( true );
418 }
419
420 void VlcWrapper::PlaylistPause()
421 {
422     if( p_input )
423     {
424         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
425     }
426 }
427
428 void VlcWrapper::PlaylistStop()
429 {
430     playlist_Stop( p_playlist );
431 }
432
433 void VlcWrapper::PlaylistNext()
434 {
435     playlist_Next( p_playlist );
436 }
437
438 void VlcWrapper::PlaylistPrev()
439 {
440     playlist_Prev( p_playlist );
441 }
442
443 void VlcWrapper::PlaylistSkip( int i )
444 {
445     playlist_Skip( p_playlist, i );
446 }
447
448 void VlcWrapper::PlaylistGoto( int i )
449 {
450     playlist_Goto( p_playlist, i );
451 }
452
453 void VlcWrapper::PlaylistLoop()
454 {
455     if ( p_intf->p_sys->b_loop )
456     {
457         playlist_Delete( p_playlist, p_playlist->i_size - 1 );
458     }
459     else
460     {
461         playlist_Add( p_playlist, "vlc:loop",
462                       PLAYLIST_APPEND | PLAYLIST_GO,
463                       PLAYLIST_END );
464     }
465     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
466 }
467
468 BList * VlcWrapper::PlaylistAsArray()
469
470     int i;
471     BList* p_list = new BList(p_playlist->i_size);
472     
473     vlc_mutex_lock( &p_playlist->object_lock );
474
475     for( i = 0; i < p_playlist->i_size; i++ )
476     {
477         p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
478     }
479
480     vlc_mutex_unlock( &p_playlist->object_lock );
481     return( p_list );
482 }
483
484 void VlcWrapper::getPlaylistInfo( int32& currentIndex, int32& maxIndex )
485 {
486         currentIndex = -1;
487         maxIndex = -1;
488         if ( p_playlist )
489         {
490                 maxIndex = p_playlist->i_size;
491                 if ( maxIndex > 0 )
492                         currentIndex = p_playlist->i_index + 1;
493                 else
494                         maxIndex = -1;
495         }
496 }
497
498
499 void VlcWrapper::PlaylistJumpTo( int pos )
500 {
501 #if 0
502         // sanity checks
503         if ( pos < 0 )
504                 pos = 0;
505         int size = playlistSize();
506         if (pos >= size)
507                 pos = size - 1;
508         // weird hack
509     if( p_input_bank->pp_input[0] != NULL )
510                 pos--;
511         // stop current stream
512         playlistStop();
513         // modify current position in playlist
514         playlistLock();
515         p_main->p_playlist->i_index = pos;
516         playlistUnlock();
517         // start playing
518         playlistPlay();
519 #endif
520 }
521
522 void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
523 {
524         if ( canSkipPrev && canSkipNext )
525         {
526                 // init the parameters
527                 *canSkipPrev = false;
528                 *canSkipNext = false;
529                 // get playlist info
530                 int pos = PlaylistCurrent();
531                 int size = PlaylistSize();
532
533                 // see if we have got a stream going            
534                 if ( p_input )
535                 {
536                         vlc_mutex_lock( &p_input->stream.stream_lock );
537
538                         bool hasTitles = p_input->stream.i_area_nb > 1;
539                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
540                         bool hasChapters = numChapters > 1;
541                         // first, look for chapters
542                         if ( hasChapters )
543                         {
544                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
545                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
546                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
547                         }
548                         // if one of the skip capabilities is false,
549                         // make it depend on titles instead
550                         if ( !*canSkipPrev && hasTitles )
551                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
552                         if ( !*canSkipNext && hasTitles )
553                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
554                                                    p_input->stream.i_area_nb - 1;
555
556                         vlc_mutex_unlock( &p_input->stream.stream_lock );
557                 }
558                 // last but not least, make capabilities depend on playlist
559                 if ( !*canSkipPrev )
560                         *canSkipPrev = pos > 0;
561                 if ( !*canSkipNext )
562                         *canSkipNext = pos < size - 1;
563         }
564 }
565
566 void VlcWrapper::navigatePrev()
567 {
568         bool hasSkiped = false;
569
570         // see if we have got a stream going            
571         if ( p_input )
572         {
573                 // get information from stream (lock it while looking at it)
574                 vlc_mutex_lock( &p_input->stream.stream_lock );
575
576                 int currentTitle = p_input->stream.p_selected_area->i_id;
577                 int currentChapter = p_input->stream.p_selected_area->i_part;
578                 int numTitles = p_input->stream.i_area_nb;
579                 bool hasTitles = numTitles > 1;
580                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
581                 bool hasChapters = numChapters > 1;
582
583                 vlc_mutex_unlock( &p_input->stream.stream_lock );
584
585                 // first, look for chapters
586                 if ( hasChapters )
587                 {
588                         // skip to the previous chapter
589                         currentChapter--;
590
591                         if ( currentChapter >= 0 )
592                         {
593                                 toggleChapter( currentChapter );
594                                 hasSkiped = true;
595                         }
596                 }
597                 // if we couldn't skip chapters, try titles instead
598                 if ( !hasSkiped && hasTitles )
599                 {
600                         // skip to the previous title
601                         currentTitle--;
602                         // disallow area 0 since it is used for video_ts.vob
603                         if( currentTitle > 0 )
604                         {
605                                 toggleTitle(currentTitle);
606                                 hasSkiped = true;
607                         }
608                 }
609
610         }
611         // last but not least, skip to previous file
612         if ( !hasSkiped )
613                 PlaylistPrev();
614 }
615
616 void VlcWrapper::navigateNext()
617 {
618         bool hasSkiped = false;
619
620         // see if we have got a stream going            
621         if ( p_input )
622         {
623                 // get information from stream (lock it while looking at it)
624                 vlc_mutex_lock( &p_input->stream.stream_lock );
625
626                 int currentTitle = p_input->stream.p_selected_area->i_id;
627                 int currentChapter = p_input->stream.p_selected_area->i_part;
628                 int numTitles = p_input->stream.i_area_nb;
629                 bool hasTitles = numTitles > 1;
630                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
631                 bool hasChapters = numChapters > 1;
632
633                 vlc_mutex_unlock( &p_input->stream.stream_lock );
634
635                 // first, look for chapters
636                 if ( hasChapters )
637                 {
638                         // skip to the next chapter
639                         currentChapter++;
640                         if ( currentChapter < numChapters )
641                         {
642                                 toggleChapter( currentChapter );
643                                 hasSkiped = true;
644                         }
645                 }
646                 // if we couldn't skip chapters, try titles instead
647                 if ( !hasSkiped && hasTitles )
648                 {
649                         // skip to the next title
650                         currentTitle++;
651                         // disallow area 0 since it is used for video_ts.vob
652                         if ( currentTitle < numTitles - 1 )
653                         {
654                                 toggleTitle(currentTitle);
655                                 hasSkiped = true;
656                         }
657                 }
658
659         }
660         // last but not least, skip to next file
661         if ( !hasSkiped )
662                 PlaylistNext();
663 }
664
665
666 /***************************
667  * audio infos and control *
668  ***************************/
669
670 unsigned short VlcWrapper::GetVolume()
671 {
672     if( p_aout != NULL )
673     {
674         unsigned short i_volume;
675         aout_VolumeGet( p_aout, (audio_volume_t*)&i_volume );
676         return i_volume;
677     }
678     return 0;
679 }
680
681 void VlcWrapper::SetVolume(int value)
682 {
683     if( p_aout != NULL )
684     {
685                 if ( p_intf->p_sys->b_mute )
686                 {
687                         p_intf->p_sys->b_mute = 0;
688                 }
689         aout_VolumeSet( p_aout, value );
690     }
691 }
692
693 void VlcWrapper::VolumeMute()
694 {
695     if( p_aout != NULL )
696         {
697             aout_VolumeGet( p_aout, &p_intf->p_sys->i_saved_volume );
698             aout_VolumeMute( p_aout, NULL );
699             p_intf->p_sys->b_mute = 1;
700         }
701 }
702
703 void VlcWrapper::VolumeRestore()
704 {
705     if( p_aout != NULL )
706         {
707         aout_VolumeSet( p_aout, p_intf->p_sys->i_saved_volume );
708         p_intf->p_sys->b_mute = 0;
709         }
710 }
711
712 bool VlcWrapper::IsMuted()
713 {
714     return p_intf->p_sys->b_mute;
715 }
716
717 bool VlcWrapper::HasAudio()
718 {
719     return( p_aout != NULL );
720 }
721
722 /*******
723  * DVD *
724  *******/
725 bool VlcWrapper::HasTitles()
726 {
727     if( !p_input )
728     {
729         return false;
730     }
731     return ( p_input->stream.i_area_nb > 1 );
732 }
733
734 void VlcWrapper::PrevTitle()
735 {
736     int i_id;
737     i_id = p_input->stream.p_selected_area->i_id - 1;
738     if( i_id > 0 )
739     {
740         toggleTitle(i_id);
741     }
742 }
743
744 void VlcWrapper::NextTitle()
745 {
746     unsigned int i_id;
747     i_id = p_input->stream.p_selected_area->i_id + 1;
748     if( i_id < p_input->stream.i_area_nb )
749     {
750         toggleTitle(i_id);
751     }
752 }
753
754 bool VlcWrapper::HasChapters()
755 {
756     if( !p_input )
757     {
758         return false;
759     }
760     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
761 }
762
763 void VlcWrapper::PrevChapter()
764 {
765     int i_id;
766     i_id = p_input->stream.p_selected_area->i_part - 1;
767     if( i_id >= 0 )
768     {
769         toggleChapter(i_id);
770     }
771 }
772
773 void VlcWrapper::NextChapter()
774 {
775     int i_id;
776     i_id = p_input->stream.p_selected_area->i_part + 1;
777     if( i_id >= 0 )
778     {
779         toggleChapter(i_id);
780     }
781 }
782
783 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
784 {
785         currentIndex = -1;
786         maxIndex = -1;
787         if ( p_input )
788         {
789                 vlc_mutex_lock( &p_input->stream.stream_lock );
790
791                 maxIndex = p_input->stream.i_area_nb - 1;
792                 if ( maxIndex > 0)
793                         currentIndex = p_input->stream.p_selected_area->i_id;
794                 else
795                         maxIndex = -1;
796
797                 vlc_mutex_unlock( &p_input->stream.stream_lock );
798         }
799 }
800
801 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
802 {
803         currentIndex = -1;
804         maxIndex = -1;
805         if ( p_input )
806         {
807                 vlc_mutex_lock( &p_input->stream.stream_lock );
808
809                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
810                 if ( maxIndex > 0)
811                         currentIndex = p_input->stream.p_selected_area->i_part;
812                 else
813                         maxIndex = -1;
814
815                 vlc_mutex_unlock( &p_input->stream.stream_lock );
816         }
817 }
818
819 void VlcWrapper::toggleTitle(int i_title)
820 {
821     if( p_input != NULL )
822     {
823         input_ChangeArea( p_input,
824                           p_input->stream.pp_areas[i_title] );
825
826         vlc_mutex_lock( &p_input->stream.stream_lock );
827
828         vlc_mutex_unlock( &p_input->stream.stream_lock );
829     }
830 }
831
832 void VlcWrapper::toggleChapter(int i_chapter)
833 {
834     if( p_input != NULL )
835     {
836         p_input->stream.p_selected_area->i_part = i_chapter;
837         input_ChangeArea( p_input,
838                           p_input->stream.p_selected_area );
839
840         vlc_mutex_lock( &p_input->stream.stream_lock );
841         vlc_mutex_unlock( &p_input->stream.stream_lock );
842     }
843 }