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