modules/gui/beos/PreferenceWindow.h/.cpp
[vlc.git] / 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.26 2003/02/09 17:10:52 stippi 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 #include <vlc/vout.h>
34 extern "C"
35 {
36   #include <input_ext-plugins.h>        // needed here when compiling without plugins
37   #include <audio_output.h>
38   #include <aout_internal.h>
39 }
40
41 #include "VlcWrapper.h"
42 #include "MsgVals.h"
43
44 /* constructor */
45 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
46 {
47     p_intf = p_interface;
48     p_input = NULL;
49     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
50                                                 FIND_ANYWHERE );
51 }
52
53 /* destructor */
54 VlcWrapper::~VlcWrapper()
55 {
56     if( p_input )
57     {
58         vlc_object_release( p_input );
59     }
60     if( p_playlist )
61     {
62         vlc_object_release( p_playlist );
63     }
64 }
65
66 /* UpdateInput: updates p_input, returns true if the interface needs to
67    be updated */
68 bool VlcWrapper::UpdateInput()
69 {
70     if( p_input == NULL )
71     {
72         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
73                                                      FIND_ANYWHERE );
74     }
75         
76     if( p_input != NULL )
77     {
78         if( p_input->b_dead )
79         {
80             vlc_object_release( p_input );
81             p_input = NULL;
82         }
83         return true;
84     }
85     return false;
86 }
87
88
89 /***************************
90  * input infos and control *
91  ***************************/
92
93 bool VlcWrapper::HasInput()
94 {
95     return ( p_input != NULL );
96 }
97
98 int VlcWrapper::InputStatus()
99 {
100     if( !p_input )
101     {
102         return UNDEF_S;
103     }
104     return p_input->stream.control.i_status;
105 }
106
107 int VlcWrapper::InputRate()
108 {
109     if( !p_input )
110     {
111         return DEFAULT_RATE;
112     }
113     return p_input->stream.control.i_rate;
114 }
115
116 void VlcWrapper::InputSlower()
117 {
118     if( p_input != NULL )
119     {
120         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
121     }
122 }
123
124 void VlcWrapper::InputFaster()
125 {
126     if( p_input != NULL )
127     {
128         input_SetStatus( p_input, INPUT_STATUS_FASTER );
129     }
130 }
131
132 BList * VlcWrapper::GetChannels( int i_cat )
133 {
134     if( p_input )
135     {
136         unsigned int i;
137         uint32 what;
138         const char* fieldName;
139
140         switch( i_cat )
141         {
142             case AUDIO_ES:
143             {
144                 what = SELECT_CHANNEL;
145                 fieldName = "channel";
146                 break;
147             }
148             case SPU_ES:
149             {
150                 what = SELECT_SUBTITLE;
151                 fieldName = "subtitle";
152                 break;
153             }
154             default:
155             return NULL;
156        }
157
158         vlc_mutex_lock( &p_input->stream.stream_lock );
159       
160         /* find which track is currently playing */
161         es_descriptor_t *p_es = NULL;
162         for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
163         {
164             if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
165                 p_es = p_input->stream.pp_selected_es[i];
166         }
167         
168         /* build a list of all tracks */
169         BList *list = new BList( p_input->stream.i_es_number );
170         BMenuItem *menuItem;
171         BMessage *message;
172         char *trackName;
173         
174         /* "None" */
175         message = new BMessage( what );
176         message->AddInt32( fieldName, -1 );
177         menuItem = new BMenuItem( "None", message );
178         if( !p_es )
179             menuItem->SetMarked( true );
180         list->AddItem( menuItem );
181         
182         for( i = 0; i < p_input->stream.i_es_number; i++ )
183         {
184             if( p_input->stream.pp_es[i]->i_cat == i_cat )
185             {
186                 message = new BMessage( what );
187                 message->AddInt32( fieldName, i );
188                 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
189                     trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
190                 else
191                     trackName = "<unknown>";
192                 menuItem = new BMenuItem( trackName, message );
193                 if( p_input->stream.pp_es[i] == p_es )
194                     menuItem->SetMarked( true );
195                 list->AddItem( menuItem );
196             }
197         }
198         
199         vlc_mutex_unlock( &p_input->stream.stream_lock );
200
201         return list;
202     }
203     return NULL;
204 }
205
206 void VlcWrapper::ToggleLanguage( int i_language )
207 {
208     es_descriptor_t * p_es = NULL;
209     es_descriptor_t * p_es_old = NULL;
210
211     vlc_mutex_lock( &p_input->stream.stream_lock );
212     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
213     {
214         if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
215         {
216             p_es_old = p_input->stream.pp_selected_es[i];
217             break;
218         }
219     }
220     vlc_mutex_unlock( &p_input->stream.stream_lock );
221     
222     if( i_language != -1 )
223     {
224         p_es = p_input->stream.pp_es[i_language];
225     }
226     if( p_es == p_es_old )
227     {
228         return;
229     }
230     if( p_es_old )
231     {
232         input_ToggleES( p_input, p_es_old, VLC_FALSE );
233     }
234     if( p_es )
235     {
236         input_ToggleES( p_input, p_es, VLC_TRUE );
237     }
238 }
239
240 void VlcWrapper::ToggleSubtitle( int i_subtitle )
241 {
242     es_descriptor_t * p_es = NULL;
243     es_descriptor_t * p_es_old = NULL;
244
245     vlc_mutex_lock( &p_input->stream.stream_lock );
246     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
247     {
248         if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
249         {
250             p_es_old = p_input->stream.pp_selected_es[i];
251             break;
252         }
253     }
254     vlc_mutex_unlock( &p_input->stream.stream_lock );
255     
256     if( i_subtitle != -1 )
257     {
258         p_es = p_input->stream.pp_es[i_subtitle];
259     }
260     if( p_es == p_es_old )
261     {
262         return;
263     }
264     if( p_es_old )
265     {
266         input_ToggleES( p_input, p_es_old, VLC_FALSE );
267     }
268     if( p_es )
269     {
270         input_ToggleES( p_input, p_es, VLC_TRUE );
271     }
272 }
273
274 const char * VlcWrapper::GetTimeAsString()
275 {
276     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
277         
278     if( p_input == NULL )
279     {
280         return ("-:--:--");
281     }     
282    
283     input_OffsetToTime( p_input, 
284                         psz_currenttime, 
285                         p_input->stream.p_selected_area->i_tell );        
286
287     return(psz_currenttime);
288 }
289
290 float VlcWrapper::GetTimeAsFloat()
291 {
292     float f_time = 0.0;
293
294     if( p_input != NULL )
295     {
296         f_time = (float)p_input->stream.p_selected_area->i_tell / 
297                  (float)p_input->stream.p_selected_area->i_size;
298     }    
299     else
300     {
301         f_time = 0.0;
302     }
303     return( f_time );
304 }
305
306 void VlcWrapper::SetTimeAsFloat( float f_position )
307 {
308     if( p_input != NULL )
309     {
310         input_Seek( p_input, 
311                    (long long int)(p_input->stream.p_selected_area->i_size
312                        * f_position / SEEKSLIDER_RANGE ), 
313                    INPUT_SEEK_SET);
314     }
315 }
316
317 bool VlcWrapper::IsPlaying()
318 {
319
320         bool playing = false;
321         if ( p_input )
322         {
323                 switch ( p_input->stream.control.i_status )
324                 {
325                         case PLAYING_S:
326                         case FORWARD_S:
327                         case BACKWARD_S:
328                         case START_S:
329                                 playing = true;
330                     break;
331                         case PAUSE_S:
332                         case UNDEF_S:
333                         case NOT_STARTED_S:
334                         default:
335                                 break;
336                 }
337         }
338         return playing;
339
340 }
341
342 /************
343  * playlist *
344  ************/
345
346 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
347 {
348         if ( o_files && o_files->CountItems() > 0)
349         {
350             int size = PlaylistSize();
351                 bool wasEmpty = ( size < 1 );
352                 if ( index == -1 )
353                         index = PLAYLIST_END;
354                 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
355         
356             /* delete current playlist */
357             if( replace )
358             {
359                 for( int i = 0; i < size; i++ )
360                 {
361                     playlist_Delete( p_playlist, 0 );
362                 }
363             }
364         
365             /* insert files */
366             int32 count = o_files->CountItems();
367             for ( int32 i = count - 1; i >= 0; i-- )
368             {
369                 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
370                 {
371                         playlist_Add( p_playlist, o_file->String(),
372                                       mode, index );
373                         if ( mode == PLAYLIST_INSERT )
374                                 index++;
375                         delete o_file;
376                 }
377             }
378             // TODO: implement a user setting
379             // if to start automatically
380             /* eventually restart playing */
381             if( replace || wasEmpty )
382             {
383                 playlist_Stop( p_playlist );
384                 playlist_Play( p_playlist );
385             }
386         }
387 }
388  
389 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
390 {
391     if( p_intf->p_sys->b_dvdmenus )
392         o_device.Prepend( "dvd:" );
393     else
394         o_device.Prepend( "dvdold:" );
395     playlist_Add( p_playlist, o_device.String(),
396                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
397 }
398
399 int VlcWrapper::PlaylistSize()
400 {
401     vlc_mutex_lock( &p_playlist->object_lock );
402     int i_size = p_playlist->i_size;
403     vlc_mutex_unlock( &p_playlist->object_lock );
404     return i_size;
405 }
406
407 char * VlcWrapper::PlaylistItemName( int i )
408 {
409    return p_playlist->pp_items[i]->psz_name;
410 }
411
412 int VlcWrapper::PlaylistCurrent()
413 {
414     return p_playlist->i_index;
415 }
416
417 bool VlcWrapper::PlaylistPlay()
418 {
419     if( PlaylistSize() )
420     {
421         playlist_Play( p_playlist );
422     }
423     return( true );
424 }
425
426 void VlcWrapper::PlaylistPause()
427 {
428     if( p_input )
429     {
430         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
431     }
432 }
433
434 void VlcWrapper::PlaylistStop()
435 {
436     playlist_Stop( p_playlist );
437 }
438
439 void VlcWrapper::PlaylistNext()
440 {
441     playlist_Next( p_playlist );
442 }
443
444 void VlcWrapper::PlaylistPrev()
445 {
446     playlist_Prev( p_playlist );
447 }
448
449 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
450 {
451         currentIndex = -1;
452         maxIndex = -1;
453         if ( p_playlist )
454         {
455             vlc_mutex_lock( &p_playlist->object_lock );
456
457                 maxIndex = p_playlist->i_size;
458                 if ( maxIndex > 0 )
459                         currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
460                 else
461                         maxIndex = -1;
462
463             vlc_mutex_unlock( &p_playlist->object_lock );
464         }
465 }
466
467 void VlcWrapper::PlaylistJumpTo( int pos )
468 {
469     playlist_Goto( p_playlist, pos );
470 }
471
472 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
473 {
474         if ( canSkipPrev && canSkipNext )
475         {
476                 // init the parameters
477                 *canSkipPrev = false;
478                 *canSkipNext = false;
479                 // get playlist info
480                 int pos = PlaylistCurrent();
481                 int size = PlaylistSize();
482
483                 // see if we have got a stream going            
484                 if ( p_input )
485                 {
486                         vlc_mutex_lock( &p_input->stream.stream_lock );
487
488                         bool hasTitles = p_input->stream.i_area_nb > 1;
489                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
490                         bool hasChapters = numChapters > 1;
491                         // first, look for chapters
492                         if ( hasChapters )
493                         {
494                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
495                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
496                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
497                         }
498                         // if one of the skip capabilities is false,
499                         // make it depend on titles instead
500                         if ( !*canSkipPrev && hasTitles )
501                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
502                         if ( !*canSkipNext && hasTitles )
503                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
504                                                    p_input->stream.i_area_nb - 1;
505
506                         vlc_mutex_unlock( &p_input->stream.stream_lock );
507                 }
508                 // last but not least, make capabilities depend on playlist
509                 if ( !*canSkipPrev )
510                         *canSkipPrev = pos > 0;
511                 if ( !*canSkipNext )
512                         *canSkipNext = pos < size - 1;
513         }
514 }
515
516 void VlcWrapper::NavigatePrev()
517 {
518         bool hasSkiped = false;
519
520         // see if we have got a stream going            
521         if ( p_input )
522         {
523                 // get information from stream (lock it while looking at it)
524                 vlc_mutex_lock( &p_input->stream.stream_lock );
525
526                 int currentTitle = p_input->stream.p_selected_area->i_id;
527                 int currentChapter = p_input->stream.p_selected_area->i_part;
528                 int numTitles = p_input->stream.i_area_nb;
529                 bool hasTitles = numTitles > 1;
530                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
531                 bool hasChapters = numChapters > 1;
532
533                 vlc_mutex_unlock( &p_input->stream.stream_lock );
534
535                 // first, look for chapters
536                 if ( hasChapters )
537                 {
538                         // skip to the previous chapter
539                         currentChapter--;
540
541                         if ( currentChapter >= 0 )
542                         {
543                                 ToggleChapter( currentChapter );
544                                 hasSkiped = true;
545                         }
546                 }
547                 // if we couldn't skip chapters, try titles instead
548                 if ( !hasSkiped && hasTitles )
549                 {
550                         // skip to the previous title
551                         currentTitle--;
552                         // disallow area 0 since it is used for video_ts.vob
553                         if( currentTitle > 0 )
554                         {
555                                 ToggleTitle(currentTitle);
556                                 hasSkiped = true;
557                         }
558                 }
559
560         }
561         // last but not least, skip to previous file
562         if ( !hasSkiped )
563                 PlaylistPrev();
564 }
565
566 void VlcWrapper::NavigateNext()
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 next chapter
589                         currentChapter++;
590                         if ( currentChapter < numChapters )
591                         {
592                                 ToggleChapter( currentChapter );
593                                 hasSkiped = true;
594                         }
595                 }
596                 // if we couldn't skip chapters, try titles instead
597                 if ( !hasSkiped && hasTitles )
598                 {
599                         // skip to the next title
600                         currentTitle++;
601                         // disallow area 0 since it is used for video_ts.vob
602                         if ( currentTitle < numTitles - 1 )
603                         {
604                                 ToggleTitle(currentTitle);
605                                 hasSkiped = true;
606                         }
607                 }
608
609         }
610         // last but not least, skip to next file
611         if ( !hasSkiped )
612                 PlaylistNext();
613 }
614
615 /*************************
616  * Playlist manipulation *
617  *************************/
618
619 // PlaylistLock
620 bool
621 VlcWrapper::PlaylistLock() const
622 {
623 // TODO: search and destroy -> deadlock!
624 return true;
625         if ( p_playlist )
626         {
627                 vlc_mutex_lock( &p_playlist->object_lock );
628                 return true;
629         }
630         return false;
631 }
632
633 // PlaylistUnlock
634 void
635 VlcWrapper::PlaylistUnlock() const
636 {
637 // TODO: search and destroy -> deadlock!
638 return;
639         vlc_mutex_unlock( &p_playlist->object_lock );
640 }
641
642 // PlaylistItemAt
643 void*
644 VlcWrapper::PlaylistItemAt( int index ) const
645 {
646         playlist_item_t* item = NULL;
647         if ( index >= 0 && index < p_playlist->i_size )
648                 item = p_playlist->pp_items[index];
649         return (void*)item;
650 }
651
652 // PlaylistRemoveItem
653 void*
654 VlcWrapper::PlaylistRemoveItem( int index ) const
655 {
656         playlist_item_t* copy = NULL;
657         // check if item exists at the provided index
658         if ( index >= 0 && index < p_playlist->i_size )
659         {
660                 playlist_item_t* item = p_playlist->pp_items[index];
661                 if ( item )
662                 {
663                         // make a copy of the removed item
664                         copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
665                         // remove item from playlist (unfortunately, this frees it)
666                         playlist_Delete( p_playlist, index );
667                 }
668         }
669         return (void*)copy;
670 }
671
672 // PlaylistRemoveItem
673 void*
674 VlcWrapper::PlaylistRemoveItem( void* item ) const
675 {
676         playlist_item_t* copy = NULL;
677         for ( int32 i = 0; i < p_playlist->i_size; i++ )
678         {
679                 if ( p_playlist->pp_items[i] == item )
680                 {
681                         copy = (playlist_item_t*)PlaylistRemoveItem( i );
682                         break;
683                 }
684         }
685         return (void*)copy;
686 }
687
688 // PlaylistAddItem
689 bool
690 VlcWrapper::PlaylistAddItem( void* item, int index ) const
691 {
692         if ( item )
693         {
694                 playlist_AddItem( p_playlist, (playlist_item_t*)item,
695                                                   PLAYLIST_INSERT, index );
696         }
697         // TODO: once playlist is returning useful info, return that instead
698         return true;
699 }
700
701 // PlaylistCloneItem
702 void*
703 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
704 {
705         playlist_item_t* copy = NULL;
706         playlist_item_t* item = (playlist_item_t*)castToItem;
707         if ( item )
708         {
709                 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
710                 if ( copy )
711                 {
712                         // make a copy of the item at index
713                         copy->psz_name = strdup( item->psz_name );
714                         copy->psz_uri  = strdup( item->psz_uri );
715                         copy->i_type = item->i_type;
716                         copy->i_status = item->i_status;
717                         copy->b_autodeletion = item->b_autodeletion;
718                 }
719         }
720         return (void*)copy;
721 }
722
723 // Careful! You need to know what you're doing here!
724 // The reason for having it, is to be able to deal with
725 // the rather lame list implementation of the playlist.
726 // It is meant to help manipulate the playlist with the above
727 // methods while keeping it valid.
728 //
729 // PlaylistSetPlaying
730 void
731 VlcWrapper::PlaylistSetPlaying( int index ) const
732 {
733         if ( index < 0 )
734                 index = 0;
735         if ( index >= p_playlist->i_size )
736                 index = p_playlist->i_size - 1;
737         p_playlist->i_index = index;
738 }
739
740
741 /*********
742  * audio *
743  *********/
744
745 unsigned short VlcWrapper::GetVolume()
746 {
747     unsigned short i_volume;
748     aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
749     return i_volume;
750 }
751
752 void VlcWrapper::SetVolume( int value )
753 {
754     if ( p_intf->p_sys->b_mute )
755     {
756         p_intf->p_sys->b_mute = 0;
757     }
758     aout_VolumeSet( p_intf, value );
759 }
760
761 void VlcWrapper::VolumeMute()
762 {
763         aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
764     aout_VolumeMute( p_intf, NULL );
765     p_intf->p_sys->b_mute = 1;
766 }
767
768 void VlcWrapper::VolumeRestore()
769 {
770     aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
771     p_intf->p_sys->b_mute = 0;
772 }
773
774 bool VlcWrapper::IsMuted()
775 {
776     return p_intf->p_sys->b_mute;
777 }
778
779 /*******
780  * DVD *
781  *******/
782
783 bool VlcWrapper::HasTitles()
784 {
785     if( !p_input )
786     {
787         return false;
788     }
789     return ( p_input->stream.i_area_nb > 1 );
790 }
791
792 BList * VlcWrapper::GetTitles()
793 {
794     if( p_input )
795     {
796         vlc_mutex_lock( &p_input->stream.stream_lock );
797       
798         BList *list = new BList( p_input->stream.i_area_nb );
799         BMenuItem *menuItem;
800         BMessage *message;
801         
802         for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
803         {
804             message = new BMessage( TOGGLE_TITLE );
805             message->AddInt32( "index", i );
806             BString helper( "" );
807             helper << i;
808             menuItem = new BMenuItem( helper.String(), message );
809             menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
810             list->AddItem( menuItem );
811         }
812         
813         vlc_mutex_unlock( &p_input->stream.stream_lock );
814
815         return list;
816     }
817     return NULL;
818 }
819
820 void VlcWrapper::PrevTitle()
821 {
822     int i_id;
823     i_id = p_input->stream.p_selected_area->i_id - 1;
824     if( i_id > 0 )
825     {
826         ToggleTitle(i_id);
827     }
828 }
829
830 void VlcWrapper::NextTitle()
831 {
832     unsigned int i_id;
833     i_id = p_input->stream.p_selected_area->i_id + 1;
834     if( i_id < p_input->stream.i_area_nb )
835     {
836         ToggleTitle(i_id);
837     }
838 }
839
840 void VlcWrapper::ToggleTitle(int i_title)
841 {
842     if( p_input != NULL )
843     {
844         input_ChangeArea( p_input,
845                           p_input->stream.pp_areas[i_title] );
846
847         vlc_mutex_lock( &p_input->stream.stream_lock );
848
849         vlc_mutex_unlock( &p_input->stream.stream_lock );
850     }
851 }
852
853 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
854 {
855         currentIndex = -1;
856         maxIndex = -1;
857         if ( p_input )
858         {
859                 vlc_mutex_lock( &p_input->stream.stream_lock );
860
861                 maxIndex = p_input->stream.i_area_nb - 1;
862                 if ( maxIndex > 0)
863                         currentIndex = p_input->stream.p_selected_area->i_id;
864                 else
865                         maxIndex = -1;
866
867                 vlc_mutex_unlock( &p_input->stream.stream_lock );
868         }
869 }
870
871 bool VlcWrapper::HasChapters()
872 {
873     if( !p_input )
874     {
875         return false;
876     }
877     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
878 }
879
880 BList * VlcWrapper::GetChapters()
881 {
882     if( p_input )
883     {
884         vlc_mutex_lock( &p_input->stream.stream_lock );
885       
886         BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
887         BMenuItem *menuItem;
888         BMessage *message;
889         
890         for( unsigned int i = 1;
891              i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
892         {
893             message = new BMessage( TOGGLE_CHAPTER );
894             message->AddInt32( "index", i );
895             BString helper( "" );
896             helper << i;
897             menuItem = new BMenuItem( helper.String(), message );
898             menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
899             list->AddItem( menuItem );
900         }
901         
902         vlc_mutex_unlock( &p_input->stream.stream_lock );
903
904         return list;
905     }
906     return NULL;
907 }
908
909 void VlcWrapper::PrevChapter()
910 {
911     int i_id;
912     i_id = p_input->stream.p_selected_area->i_part - 1;
913     if( i_id >= 0 )
914     {
915         ToggleChapter(i_id);
916     }
917 }
918
919 void VlcWrapper::NextChapter()
920 {
921     int i_id;
922     i_id = p_input->stream.p_selected_area->i_part + 1;
923     if( i_id >= 0 )
924     {
925         ToggleChapter(i_id);
926     }
927 }
928
929 void VlcWrapper::ToggleChapter(int i_chapter)
930 {
931     if( p_input != NULL )
932     {
933         p_input->stream.p_selected_area->i_part = i_chapter;
934         input_ChangeArea( p_input,
935                           p_input->stream.p_selected_area );
936
937         vlc_mutex_lock( &p_input->stream.stream_lock );
938         vlc_mutex_unlock( &p_input->stream.stream_lock );
939     }
940 }
941
942 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
943 {
944         currentIndex = -1;
945         maxIndex = -1;
946         if ( p_input )
947         {
948                 vlc_mutex_lock( &p_input->stream.stream_lock );
949
950                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
951                 if ( maxIndex > 0)
952                         currentIndex = p_input->stream.p_selected_area->i_part;
953                 else
954                         maxIndex = -1;
955
956                 vlc_mutex_unlock( &p_input->stream.stream_lock );
957         }
958 }
959
960 /****************
961  * Miscellanous *
962  ****************/
963  
964 void VlcWrapper::LoadSubFile( const char * psz_file )
965 {
966     config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
967 }
968
969 void VlcWrapper::FilterChange()
970 {
971     if( !p_input )
972         return;
973     
974     vout_thread_t * p_vout;
975     vlc_mutex_lock( &p_input->stream.stream_lock );
976
977     // Warn the vout we are about to change the filter chain
978     p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
979                                               FIND_ANYWHERE );
980     if( p_vout )
981     {
982         p_vout->b_filter_change = VLC_TRUE;
983         vlc_object_release( p_vout );
984     }
985
986     // restart all video stream
987     for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
988     {
989         if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
990             ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
991         {
992             input_UnselectES( p_input, p_input->stream.pp_es[i] );
993             input_SelectES( p_input, p_input->stream.pp_es[i] );
994         }
995     }
996     vlc_mutex_unlock( &p_input->stream.stream_lock );
997 }