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