]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
Fixed playlist behaviour (draging a file replaces the playlist, and
[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.19 2003/01/14 22:03:38 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     int size = PlaylistSize();
226         bool wasEmpty = ( size < 1 );
227
228     /* delete current playlist */
229     if( replace )
230     {
231         for( int i = 0; i < size; i++ )
232         {
233             playlist_Delete( p_playlist, 0 );
234         }
235     }
236
237     /* append files */
238     while( ( o_file = (BString *)o_files->LastItem() ) )
239     {
240         playlist_Add( p_playlist, o_file->String(),
241                       PLAYLIST_APPEND, PLAYLIST_END );
242         o_files->RemoveItem(o_files->CountItems() - 1);
243     }
244     
245     /* eventually restart playing */
246     if( replace || wasEmpty )
247     {
248         playlist_Stop( p_playlist );
249         playlist_Play( p_playlist );
250     }
251 }
252
253 void VlcWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
254 {
255     BString o_source("");
256     o_source << o_type << ":" << o_device ;
257
258     playlist_Add( p_playlist, o_source.String(),
259                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
260 }
261
262 void VlcWrapper::LoadSubFile( char * psz_file )
263 {
264     config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
265 }
266
267 void VlcWrapper::ToggleLanguage( int i_language )
268 {
269     es_descriptor_t * p_es = NULL;
270     es_descriptor_t * p_es_old = NULL;
271
272     vlc_mutex_lock( &p_input->stream.stream_lock );
273     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
274     {
275         if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
276         {
277             p_es_old = p_input->stream.pp_selected_es[i];
278             break;
279         }
280     }
281     vlc_mutex_unlock( &p_input->stream.stream_lock );
282     
283     if( i_language != -1 )
284     {
285         p_es = p_input->stream.pp_es[i_language];
286     }
287     if( p_es == p_es_old )
288     {
289         return;
290     }
291     if( p_es_old )
292     {
293         input_ToggleES( p_input, p_es_old, VLC_FALSE );
294     }
295     if( p_es )
296     {
297         input_ToggleES( p_input, p_es, VLC_TRUE );
298     }
299 }
300
301 void VlcWrapper::ToggleSubtitle( int i_subtitle )
302 {
303     es_descriptor_t * p_es = NULL;
304     es_descriptor_t * p_es_old = NULL;
305
306     vlc_mutex_lock( &p_input->stream.stream_lock );
307     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
308     {
309         if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
310         {
311             p_es_old = p_input->stream.pp_selected_es[i];
312             break;
313         }
314     }
315     vlc_mutex_unlock( &p_input->stream.stream_lock );
316     
317     if( i_subtitle != -1 )
318     {
319         p_es = p_input->stream.pp_es[i_subtitle];
320     }
321     if( p_es == p_es_old )
322     {
323         return;
324     }
325     if( p_es_old )
326     {
327         input_ToggleES( p_input, p_es_old, VLC_FALSE );
328     }
329     if( p_es )
330     {
331         input_ToggleES( p_input, p_es, VLC_TRUE );
332     }
333 }
334
335 const char*  VlcWrapper::getTimeAsString()
336 {
337     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
338         
339     if( p_input == NULL )
340     {
341         return ("-:--:--");
342     }     
343    
344     input_OffsetToTime( p_input, 
345                         psz_currenttime, 
346                         p_input->stream.p_selected_area->i_tell );        
347
348     return(psz_currenttime);
349 }
350
351 float  VlcWrapper::getTimeAsFloat()
352 {
353     float f_time = 0.0;
354
355     if( p_input != NULL )
356     {
357         f_time = (float)p_input->stream.p_selected_area->i_tell / 
358                  (float)p_input->stream.p_selected_area->i_size;
359     }    
360     else
361     {
362         f_time = 0.0;
363     }
364     return( f_time );
365 }
366
367 void VlcWrapper::setTimeAsFloat(float f_position)
368 {
369     if( p_input != NULL )
370     {
371         input_Seek( p_input, 
372                    (long long int)(p_input->stream.p_selected_area->i_size
373                        * f_position / SEEKSLIDER_RANGE ), 
374                    INPUT_SEEK_SET);
375     }
376 }
377
378 bool VlcWrapper::IsPlaying()
379 {
380
381         bool playing = false;
382         if ( p_input )
383         {
384                 switch ( p_input->stream.control.i_status )
385                 {
386                         case PLAYING_S:
387                         case FORWARD_S:
388                         case BACKWARD_S:
389                         case START_S:
390                                 playing = true;
391                     break;
392                         case PAUSE_S:
393                         case UNDEF_S:
394                         case NOT_STARTED_S:
395                         default:
396                                 break;
397                 }
398         }
399         return playing;
400
401 }
402
403 /******************************
404  * playlist infos and control *
405  ******************************/
406 int VlcWrapper::PlaylistSize()
407 {
408     vlc_mutex_lock( &p_playlist->object_lock );
409     int i_size = p_playlist->i_size;
410     vlc_mutex_unlock( &p_playlist->object_lock );
411     return i_size;
412 }
413
414 char *VlcWrapper::PlaylistItemName( int i )
415 {
416    return p_playlist->pp_items[i]->psz_name;
417 }
418
419 int VlcWrapper::PlaylistCurrent()
420 {
421     return p_playlist->i_index;
422 }
423
424 int  VlcWrapper::PlaylistStatus()
425 {
426     return p_playlist->i_status;
427 }
428
429 bool VlcWrapper::PlaylistPlay()
430 {
431     if( PlaylistSize() )
432     {
433         playlist_Play( p_playlist );
434     }
435     return( true );
436 }
437
438 void VlcWrapper::PlaylistPause()
439 {
440     if( p_input )
441     {
442         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
443     }
444 }
445
446 void VlcWrapper::PlaylistStop()
447 {
448     playlist_Stop( p_playlist );
449 }
450
451 void VlcWrapper::PlaylistNext()
452 {
453     playlist_Next( p_playlist );
454 }
455
456 void VlcWrapper::PlaylistPrev()
457 {
458     playlist_Prev( p_playlist );
459 }
460
461 void VlcWrapper::PlaylistSkip( int i )
462 {
463     playlist_Skip( p_playlist, i );
464 }
465
466 void VlcWrapper::PlaylistGoto( int i )
467 {
468     playlist_Goto( p_playlist, i );
469 }
470
471 void VlcWrapper::PlaylistLoop()
472 {
473     if ( p_intf->p_sys->b_loop )
474     {
475         playlist_Delete( p_playlist, p_playlist->i_size - 1 );
476     }
477     else
478     {
479         playlist_Add( p_playlist, "vlc:loop",
480                       PLAYLIST_APPEND | PLAYLIST_GO,
481                       PLAYLIST_END );
482     }
483     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
484 }
485
486 BList * VlcWrapper::PlaylistAsArray()
487
488     int i;
489     BList* p_list = new BList(p_playlist->i_size);
490     
491     vlc_mutex_lock( &p_playlist->object_lock );
492
493     for( i = 0; i < p_playlist->i_size; i++ )
494     {
495         p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
496     }
497
498     vlc_mutex_unlock( &p_playlist->object_lock );
499     return( p_list );
500 }
501
502 void VlcWrapper::getPlaylistInfo( int32& currentIndex, int32& maxIndex )
503 {
504         currentIndex = -1;
505         maxIndex = -1;
506         if ( p_playlist )
507         {
508                 maxIndex = p_playlist->i_size;
509                 if ( maxIndex > 0 )
510                         currentIndex = p_playlist->i_index + 1;
511                 else
512                         maxIndex = -1;
513         }
514 }
515
516
517 void VlcWrapper::PlaylistJumpTo( int pos )
518 {
519 #if 0
520         // sanity checks
521         if ( pos < 0 )
522                 pos = 0;
523         int size = playlistSize();
524         if (pos >= size)
525                 pos = size - 1;
526         // weird hack
527     if( p_input_bank->pp_input[0] != NULL )
528                 pos--;
529         // stop current stream
530         playlistStop();
531         // modify current position in playlist
532         playlistLock();
533         p_main->p_playlist->i_index = pos;
534         playlistUnlock();
535         // start playing
536         playlistPlay();
537 #endif
538 }
539
540 void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
541 {
542         if ( canSkipPrev && canSkipNext )
543         {
544                 // init the parameters
545                 *canSkipPrev = false;
546                 *canSkipNext = false;
547                 // get playlist info
548                 int pos = PlaylistCurrent();
549                 int size = PlaylistSize();
550
551                 // see if we have got a stream going            
552                 if ( p_input )
553                 {
554                         vlc_mutex_lock( &p_input->stream.stream_lock );
555
556                         bool hasTitles = p_input->stream.i_area_nb > 1;
557                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
558                         bool hasChapters = numChapters > 1;
559                         // first, look for chapters
560                         if ( hasChapters )
561                         {
562                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
563                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
564                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
565                         }
566                         // if one of the skip capabilities is false,
567                         // make it depend on titles instead
568                         if ( !*canSkipPrev && hasTitles )
569                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
570                         if ( !*canSkipNext && hasTitles )
571                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
572                                                    p_input->stream.i_area_nb - 1;
573
574                         vlc_mutex_unlock( &p_input->stream.stream_lock );
575                 }
576                 // last but not least, make capabilities depend on playlist
577                 if ( !*canSkipPrev )
578                         *canSkipPrev = pos > 0;
579                 if ( !*canSkipNext )
580                         *canSkipNext = pos < size - 1;
581         }
582 }
583
584 void VlcWrapper::navigatePrev()
585 {
586         bool hasSkiped = false;
587
588         // see if we have got a stream going            
589         if ( p_input )
590         {
591                 // get information from stream (lock it while looking at it)
592                 vlc_mutex_lock( &p_input->stream.stream_lock );
593
594                 int currentTitle = p_input->stream.p_selected_area->i_id;
595                 int currentChapter = p_input->stream.p_selected_area->i_part;
596                 int numTitles = p_input->stream.i_area_nb;
597                 bool hasTitles = numTitles > 1;
598                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
599                 bool hasChapters = numChapters > 1;
600
601                 vlc_mutex_unlock( &p_input->stream.stream_lock );
602
603                 // first, look for chapters
604                 if ( hasChapters )
605                 {
606                         // skip to the previous chapter
607                         currentChapter--;
608
609                         if ( currentChapter >= 0 )
610                         {
611                                 toggleChapter( currentChapter );
612                                 hasSkiped = true;
613                         }
614                 }
615                 // if we couldn't skip chapters, try titles instead
616                 if ( !hasSkiped && hasTitles )
617                 {
618                         // skip to the previous title
619                         currentTitle--;
620                         // disallow area 0 since it is used for video_ts.vob
621                         if( currentTitle > 0 )
622                         {
623                                 toggleTitle(currentTitle);
624                                 hasSkiped = true;
625                         }
626                 }
627
628         }
629         // last but not least, skip to previous file
630         if ( !hasSkiped )
631                 PlaylistPrev();
632 }
633
634 void VlcWrapper::navigateNext()
635 {
636         bool hasSkiped = false;
637
638         // see if we have got a stream going            
639         if ( p_input )
640         {
641                 // get information from stream (lock it while looking at it)
642                 vlc_mutex_lock( &p_input->stream.stream_lock );
643
644                 int currentTitle = p_input->stream.p_selected_area->i_id;
645                 int currentChapter = p_input->stream.p_selected_area->i_part;
646                 int numTitles = p_input->stream.i_area_nb;
647                 bool hasTitles = numTitles > 1;
648                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
649                 bool hasChapters = numChapters > 1;
650
651                 vlc_mutex_unlock( &p_input->stream.stream_lock );
652
653                 // first, look for chapters
654                 if ( hasChapters )
655                 {
656                         // skip to the next chapter
657                         currentChapter++;
658                         if ( currentChapter < numChapters )
659                         {
660                                 toggleChapter( currentChapter );
661                                 hasSkiped = true;
662                         }
663                 }
664                 // if we couldn't skip chapters, try titles instead
665                 if ( !hasSkiped && hasTitles )
666                 {
667                         // skip to the next title
668                         currentTitle++;
669                         // disallow area 0 since it is used for video_ts.vob
670                         if ( currentTitle < numTitles - 1 )
671                         {
672                                 toggleTitle(currentTitle);
673                                 hasSkiped = true;
674                         }
675                 }
676
677         }
678         // last but not least, skip to next file
679         if ( !hasSkiped )
680                 PlaylistNext();
681 }
682
683
684 /***************************
685  * audio infos and control *
686  ***************************/
687
688 unsigned short VlcWrapper::GetVolume()
689 {
690     if( p_aout != NULL )
691     {
692         unsigned short i_volume;
693         aout_VolumeGet( p_aout, (audio_volume_t*)&i_volume );
694         return i_volume;
695     }
696     return 0;
697 }
698
699 void VlcWrapper::SetVolume(int value)
700 {
701     if( p_aout != NULL )
702     {
703                 if ( p_intf->p_sys->b_mute )
704                 {
705                         p_intf->p_sys->b_mute = 0;
706                 }
707         aout_VolumeSet( p_aout, value );
708     }
709 }
710
711 void VlcWrapper::VolumeMute()
712 {
713     if( p_aout != NULL )
714         {
715             aout_VolumeGet( p_aout, &p_intf->p_sys->i_saved_volume );
716             aout_VolumeMute( p_aout, NULL );
717             p_intf->p_sys->b_mute = 1;
718         }
719 }
720
721 void VlcWrapper::VolumeRestore()
722 {
723     if( p_aout != NULL )
724         {
725         aout_VolumeSet( p_aout, p_intf->p_sys->i_saved_volume );
726         p_intf->p_sys->b_mute = 0;
727         }
728 }
729
730 bool VlcWrapper::IsMuted()
731 {
732     return p_intf->p_sys->b_mute;
733 }
734
735 bool VlcWrapper::HasAudio()
736 {
737     return( p_aout != NULL );
738 }
739
740 /*******
741  * DVD *
742  *******/
743 bool VlcWrapper::HasTitles()
744 {
745     if( !p_input )
746     {
747         return false;
748     }
749     return ( p_input->stream.i_area_nb > 1 );
750 }
751
752 void VlcWrapper::PrevTitle()
753 {
754     int i_id;
755     i_id = p_input->stream.p_selected_area->i_id - 1;
756     if( i_id > 0 )
757     {
758         toggleTitle(i_id);
759     }
760 }
761
762 void VlcWrapper::NextTitle()
763 {
764     unsigned int i_id;
765     i_id = p_input->stream.p_selected_area->i_id + 1;
766     if( i_id < p_input->stream.i_area_nb )
767     {
768         toggleTitle(i_id);
769     }
770 }
771
772 bool VlcWrapper::HasChapters()
773 {
774     if( !p_input )
775     {
776         return false;
777     }
778     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
779 }
780
781 void VlcWrapper::PrevChapter()
782 {
783     int i_id;
784     i_id = p_input->stream.p_selected_area->i_part - 1;
785     if( i_id >= 0 )
786     {
787         toggleChapter(i_id);
788     }
789 }
790
791 void VlcWrapper::NextChapter()
792 {
793     int i_id;
794     i_id = p_input->stream.p_selected_area->i_part + 1;
795     if( i_id >= 0 )
796     {
797         toggleChapter(i_id);
798     }
799 }
800
801 void VlcWrapper::TitleInfo( 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.i_area_nb - 1;
810                 if ( maxIndex > 0)
811                         currentIndex = p_input->stream.p_selected_area->i_id;
812                 else
813                         maxIndex = -1;
814
815                 vlc_mutex_unlock( &p_input->stream.stream_lock );
816         }
817 }
818
819 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
820 {
821         currentIndex = -1;
822         maxIndex = -1;
823         if ( p_input )
824         {
825                 vlc_mutex_lock( &p_input->stream.stream_lock );
826
827                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
828                 if ( maxIndex > 0)
829                         currentIndex = p_input->stream.p_selected_area->i_part;
830                 else
831                         maxIndex = -1;
832
833                 vlc_mutex_unlock( &p_input->stream.stream_lock );
834         }
835 }
836
837 void VlcWrapper::toggleTitle(int i_title)
838 {
839     if( p_input != NULL )
840     {
841         input_ChangeArea( p_input,
842                           p_input->stream.pp_areas[i_title] );
843
844         vlc_mutex_lock( &p_input->stream.stream_lock );
845
846         vlc_mutex_unlock( &p_input->stream.stream_lock );
847     }
848 }
849
850 void VlcWrapper::toggleChapter(int i_chapter)
851 {
852     if( p_input != NULL )
853     {
854         p_input->stream.p_selected_area->i_part = i_chapter;
855         input_ChangeArea( p_input,
856                           p_input->stream.p_selected_area );
857
858         vlc_mutex_lock( &p_input->stream.stream_lock );
859         vlc_mutex_unlock( &p_input->stream.stream_lock );
860     }
861 }