8accd59383a2b9440cb7a631684f4bd2e9ebd519
[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.36 2003/07/23 01:13:47 gbazin 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                         case START_S:
318                                 playing = true;
319                     break;
320                         case PAUSE_S:
321                         case UNDEF_S:
322                         case NOT_STARTED_S:
323                         default:
324                                 break;
325                 }
326         }
327         return playing;
328
329 }
330
331 /************
332  * playlist *
333  ************/
334
335 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
336 {
337         if ( o_files && o_files->CountItems() > 0)
338         {
339             int size = PlaylistSize();
340                 bool wasEmpty = ( size < 1 );
341                 if ( index == -1 )
342                         index = PLAYLIST_END;
343                 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
344         
345             /* delete current playlist */
346             if( replace )
347             {
348                 for( int i = 0; i < size; i++ )
349                 {
350                     playlist_Delete( p_playlist, 0 );
351                 }
352             }
353         
354             /* insert files */
355             int32 count = o_files->CountItems();
356             for ( int32 i = count - 1; i >= 0; i-- )
357             {
358                 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
359                 {
360                         playlist_Add( p_playlist, o_file->String(),
361                                       0, 0, mode, index );
362                         if ( mode == PLAYLIST_INSERT )
363                                 index++;
364                         delete o_file;
365                 }
366             }
367             // TODO: implement a user setting
368             // if to start automatically
369             /* eventually restart playing */
370             if( replace || wasEmpty )
371             {
372                 playlist_Stop( p_playlist );
373                 playlist_Play( p_playlist );
374             }
375         }
376 }
377  
378 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
379 {
380     if( config_GetInt( p_intf, "beos-dvdmenus" ) )
381         o_device.Prepend( "dvdplay:" );
382     else
383         o_device.Prepend( "dvdold:" );
384     playlist_Add( p_playlist, o_device.String(), 0, 0,
385                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
386 }
387
388 int VlcWrapper::PlaylistSize()
389 {
390     vlc_mutex_lock( &p_playlist->object_lock );
391     int i_size = p_playlist->i_size;
392     vlc_mutex_unlock( &p_playlist->object_lock );
393     return i_size;
394 }
395
396 char * VlcWrapper::PlaylistItemName( int i )
397 {
398    return p_playlist->pp_items[i]->psz_name;
399 }
400
401 int VlcWrapper::PlaylistCurrent()
402 {
403     return p_playlist->i_index;
404 }
405
406 bool VlcWrapper::PlaylistPlay()
407 {
408     if( PlaylistSize() )
409     {
410         playlist_Play( p_playlist );
411     }
412     return( true );
413 }
414
415 void VlcWrapper::PlaylistPause()
416 {
417     if( p_input )
418     {
419         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
420     }
421 }
422
423 void VlcWrapper::PlaylistStop()
424 {
425     playlist_Stop( p_playlist );
426 }
427
428 void VlcWrapper::PlaylistNext()
429 {
430     playlist_Next( p_playlist );
431 }
432
433 void VlcWrapper::PlaylistPrev()
434 {
435     playlist_Prev( p_playlist );
436 }
437
438 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
439 {
440         currentIndex = -1;
441         maxIndex = -1;
442         if ( p_playlist )
443         {
444             vlc_mutex_lock( &p_playlist->object_lock );
445
446                 maxIndex = p_playlist->i_size;
447                 if ( maxIndex > 0 )
448                         currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
449                 else
450                         maxIndex = -1;
451
452             vlc_mutex_unlock( &p_playlist->object_lock );
453         }
454 }
455
456 void VlcWrapper::PlaylistJumpTo( int pos )
457 {
458     playlist_Goto( p_playlist, pos );
459 }
460
461 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
462 {
463         if ( canSkipPrev && canSkipNext )
464         {
465                 // init the parameters
466                 *canSkipPrev = false;
467                 *canSkipNext = false;
468                 // get playlist info
469                 int pos = PlaylistCurrent();
470                 int size = PlaylistSize();
471
472                 // see if we have got a stream going            
473                 if ( p_input )
474                 {
475                         vlc_mutex_lock( &p_input->stream.stream_lock );
476
477                         bool hasTitles = p_input->stream.i_area_nb > 1;
478                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
479                         bool hasChapters = numChapters > 1;
480                         // first, look for chapters
481                         if ( hasChapters )
482                         {
483                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
484                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
485                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
486                         }
487                         // if one of the skip capabilities is false,
488                         // make it depend on titles instead
489                         if ( !*canSkipPrev && hasTitles )
490                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
491                         if ( !*canSkipNext && hasTitles )
492                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
493                                                    p_input->stream.i_area_nb - 1;
494
495                         vlc_mutex_unlock( &p_input->stream.stream_lock );
496                 }
497                 // last but not least, make capabilities depend on playlist
498                 if ( !*canSkipPrev )
499                         *canSkipPrev = pos > 0;
500                 if ( !*canSkipNext )
501                         *canSkipNext = pos < size - 1;
502         }
503 }
504
505 void VlcWrapper::NavigatePrev()
506 {
507         bool hasSkiped = false;
508
509         // see if we have got a stream going            
510         if ( p_input )
511         {
512                 // get information from stream (lock it while looking at it)
513                 vlc_mutex_lock( &p_input->stream.stream_lock );
514
515                 int currentTitle = p_input->stream.p_selected_area->i_id;
516                 int currentChapter = p_input->stream.p_selected_area->i_part;
517                 int numTitles = p_input->stream.i_area_nb;
518                 bool hasTitles = numTitles > 1;
519                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
520                 bool hasChapters = numChapters > 1;
521
522                 vlc_mutex_unlock( &p_input->stream.stream_lock );
523
524                 // first, look for chapters
525                 if ( hasChapters )
526                 {
527                         // skip to the previous chapter
528                         currentChapter--;
529
530                         if ( currentChapter >= 0 )
531                         {
532                                 ToggleChapter( currentChapter );
533                                 hasSkiped = true;
534                         }
535                 }
536                 // if we couldn't skip chapters, try titles instead
537                 if ( !hasSkiped && hasTitles )
538                 {
539                         // skip to the previous title
540                         currentTitle--;
541                         // disallow area 0 since it is used for video_ts.vob
542                         if( currentTitle > 0 )
543                         {
544                                 ToggleTitle(currentTitle);
545                                 hasSkiped = true;
546                         }
547                 }
548
549         }
550         // last but not least, skip to previous file
551         if ( !hasSkiped )
552                 PlaylistPrev();
553 }
554
555 void VlcWrapper::NavigateNext()
556 {
557         bool hasSkiped = false;
558
559         // see if we have got a stream going            
560         if ( p_input )
561         {
562                 // get information from stream (lock it while looking at it)
563                 vlc_mutex_lock( &p_input->stream.stream_lock );
564
565                 int currentTitle = p_input->stream.p_selected_area->i_id;
566                 int currentChapter = p_input->stream.p_selected_area->i_part;
567                 int numTitles = p_input->stream.i_area_nb;
568                 bool hasTitles = numTitles > 1;
569                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
570                 bool hasChapters = numChapters > 1;
571
572                 vlc_mutex_unlock( &p_input->stream.stream_lock );
573
574                 // first, look for chapters
575                 if ( hasChapters )
576                 {
577                         // skip to the next chapter
578                         currentChapter++;
579                         if ( currentChapter < numChapters )
580                         {
581                                 ToggleChapter( currentChapter );
582                                 hasSkiped = true;
583                         }
584                 }
585                 // if we couldn't skip chapters, try titles instead
586                 if ( !hasSkiped && hasTitles )
587                 {
588                         // skip to the next title
589                         currentTitle++;
590                         // disallow area 0 since it is used for video_ts.vob
591                         if ( currentTitle < numTitles - 1 )
592                         {
593                                 ToggleTitle(currentTitle);
594                                 hasSkiped = true;
595                         }
596                 }
597
598         }
599         // last but not least, skip to next file
600         if ( !hasSkiped )
601                 PlaylistNext();
602 }
603
604 /*************************
605  * Playlist manipulation *
606  *************************/
607
608 // PlaylistLock
609 bool
610 VlcWrapper::PlaylistLock() const
611 {
612 // TODO: search and destroy -> deadlock!
613 return true;
614         if ( p_playlist )
615         {
616                 vlc_mutex_lock( &p_playlist->object_lock );
617                 return true;
618         }
619         return false;
620 }
621
622 // PlaylistUnlock
623 void
624 VlcWrapper::PlaylistUnlock() const
625 {
626 // TODO: search and destroy -> deadlock!
627 return;
628         vlc_mutex_unlock( &p_playlist->object_lock );
629 }
630
631 // PlaylistItemAt
632 void*
633 VlcWrapper::PlaylistItemAt( int index ) const
634 {
635         playlist_item_t* item = NULL;
636         if ( index >= 0 && index < p_playlist->i_size )
637                 item = p_playlist->pp_items[index];
638         return (void*)item;
639 }
640
641 // PlaylistRemoveItem
642 void*
643 VlcWrapper::PlaylistRemoveItem( int index ) const
644 {
645         playlist_item_t* copy = NULL;
646         // check if item exists at the provided index
647         if ( index >= 0 && index < p_playlist->i_size )
648         {
649                 playlist_item_t* item = p_playlist->pp_items[index];
650                 if ( item )
651                 {
652                         // make a copy of the removed item
653                         copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
654                         // remove item from playlist (unfortunately, this frees it)
655                         playlist_Delete( p_playlist, index );
656                 }
657         }
658         return (void*)copy;
659 }
660
661 // PlaylistRemoveItem
662 void*
663 VlcWrapper::PlaylistRemoveItem( void* item ) const
664 {
665         playlist_item_t* copy = NULL;
666         for ( int32 i = 0; i < p_playlist->i_size; i++ )
667         {
668                 if ( p_playlist->pp_items[i] == item )
669                 {
670                         copy = (playlist_item_t*)PlaylistRemoveItem( i );
671                         break;
672                 }
673         }
674         return (void*)copy;
675 }
676
677 // PlaylistAddItem
678 bool
679 VlcWrapper::PlaylistAddItem( void* item, int index ) const
680 {
681         if ( item )
682         {
683                 playlist_AddItem( p_playlist, (playlist_item_t*)item,
684                                                   PLAYLIST_INSERT, index );
685         }
686         // TODO: once playlist is returning useful info, return that instead
687         return true;
688 }
689
690 // PlaylistCloneItem
691 void*
692 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
693 {
694         playlist_item_t* copy = NULL;
695         playlist_item_t* item = (playlist_item_t*)castToItem;
696         if ( item )
697         {
698                 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
699                 if ( copy )
700                 {
701                         // make a copy of the item at index
702                         copy->psz_name = strdup( item->psz_name );
703                         copy->psz_uri  = strdup( item->psz_uri );
704                         copy->i_type = item->i_type;
705                         copy->i_status = item->i_status;
706                         copy->b_autodeletion = item->b_autodeletion;
707                 }
708         }
709         return (void*)copy;
710 }
711
712 // Careful! You need to know what you're doing here!
713 // The reason for having it, is to be able to deal with
714 // the rather lame list implementation of the playlist.
715 // It is meant to help manipulate the playlist with the above
716 // methods while keeping it valid.
717 //
718 // PlaylistSetPlaying
719 void
720 VlcWrapper::PlaylistSetPlaying( int index ) const
721 {
722         if ( index < 0 )
723                 index = 0;
724         if ( index >= p_playlist->i_size )
725                 index = p_playlist->i_size - 1;
726         p_playlist->i_index = index;
727 }
728
729
730 /*********
731  * audio *
732  *********/
733
734 unsigned short VlcWrapper::GetVolume()
735 {
736     unsigned short i_volume;
737     aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
738     return i_volume;
739 }
740
741 void VlcWrapper::SetVolume( int value )
742 {
743     if ( p_intf->p_sys->b_mute )
744     {
745         p_intf->p_sys->b_mute = 0;
746     }
747     aout_VolumeSet( p_intf, value );
748 }
749
750 void VlcWrapper::VolumeMute()
751 {
752     aout_VolumeMute( p_intf, NULL );
753     p_intf->p_sys->b_mute = 1;
754 }
755
756 void VlcWrapper::VolumeRestore()
757 {
758     audio_volume_t dummy;
759     aout_VolumeMute( p_intf, &dummy );
760     p_intf->p_sys->b_mute = 0;
761 }
762
763 bool VlcWrapper::IsMuted()
764 {
765     return p_intf->p_sys->b_mute;
766 }
767
768 /*******
769  * DVD *
770  *******/
771
772 bool VlcWrapper::IsUsingMenus()
773 {
774     if( !p_input )
775         return false;
776
777     vlc_mutex_lock( &p_playlist->object_lock );
778     if( p_playlist->i_index < 0 )
779     {
780         vlc_mutex_unlock( &p_playlist->object_lock );
781         return false;
782     }
783     
784     char * psz_name = p_playlist->pp_items[p_playlist->i_index]->psz_name;
785     if( !strncmp( psz_name, "dvdplay:", 8 ) )
786     {
787         vlc_mutex_unlock( &p_playlist->object_lock );
788         return true;
789     }
790     vlc_mutex_unlock( &p_playlist->object_lock );
791
792     return false;
793 }
794
795 bool VlcWrapper::HasTitles()
796 {
797     if( !p_input )
798         return false;
799
800     return ( p_input->stream.i_area_nb > 1 );
801 }
802
803 BList * VlcWrapper::GetTitles()
804 {
805     if( p_input )
806     {
807         vlc_mutex_lock( &p_input->stream.stream_lock );
808       
809         BList *list = new BList( p_input->stream.i_area_nb );
810         BMenuItem *menuItem;
811         BMessage *message;
812         
813         for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
814         {
815             message = new BMessage( TOGGLE_TITLE );
816             message->AddInt32( "index", i );
817             BString helper( "" );
818             helper << i;
819             menuItem = new BMenuItem( helper.String(), message );
820             menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
821             list->AddItem( menuItem );
822         }
823         
824         vlc_mutex_unlock( &p_input->stream.stream_lock );
825
826         return list;
827     }
828     return NULL;
829 }
830
831 void VlcWrapper::PrevTitle()
832 {
833     int i_id;
834     i_id = p_input->stream.p_selected_area->i_id - 1;
835     if( i_id > 0 )
836     {
837         ToggleTitle(i_id);
838     }
839 }
840
841 void VlcWrapper::NextTitle()
842 {
843     unsigned int i_id;
844     i_id = p_input->stream.p_selected_area->i_id + 1;
845     if( i_id < p_input->stream.i_area_nb )
846     {
847         ToggleTitle(i_id);
848     }
849 }
850
851 void VlcWrapper::ToggleTitle(int i_title)
852 {
853     if( p_input != NULL )
854     {
855         input_ChangeArea( p_input,
856                           p_input->stream.pp_areas[i_title] );
857
858         vlc_mutex_lock( &p_input->stream.stream_lock );
859
860         vlc_mutex_unlock( &p_input->stream.stream_lock );
861     }
862 }
863
864 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
865 {
866         currentIndex = -1;
867         maxIndex = -1;
868         if ( p_input )
869         {
870                 vlc_mutex_lock( &p_input->stream.stream_lock );
871
872                 maxIndex = p_input->stream.i_area_nb - 1;
873                 if ( maxIndex > 0)
874                         currentIndex = p_input->stream.p_selected_area->i_id;
875                 else
876                         maxIndex = -1;
877
878                 vlc_mutex_unlock( &p_input->stream.stream_lock );
879         }
880 }
881
882 bool VlcWrapper::HasChapters()
883 {
884     if( !p_input )
885     {
886         return false;
887     }
888     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
889 }
890
891 BList * VlcWrapper::GetChapters()
892 {
893     if( p_input )
894     {
895         vlc_mutex_lock( &p_input->stream.stream_lock );
896       
897         BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
898         BMenuItem *menuItem;
899         BMessage *message;
900         
901         for( unsigned int i = 1;
902              i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
903         {
904             message = new BMessage( TOGGLE_CHAPTER );
905             message->AddInt32( "index", i );
906             BString helper( "" );
907             helper << i;
908             menuItem = new BMenuItem( helper.String(), message );
909             menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
910             list->AddItem( menuItem );
911         }
912         
913         vlc_mutex_unlock( &p_input->stream.stream_lock );
914
915         return list;
916     }
917     return NULL;
918 }
919
920 void VlcWrapper::PrevChapter()
921 {
922     int i_id;
923     i_id = p_input->stream.p_selected_area->i_part - 1;
924     if( i_id >= 0 )
925     {
926         ToggleChapter(i_id);
927     }
928 }
929
930 void VlcWrapper::NextChapter()
931 {
932     int i_id;
933     i_id = p_input->stream.p_selected_area->i_part + 1;
934     if( i_id >= 0 )
935     {
936         ToggleChapter(i_id);
937     }
938 }
939
940 void VlcWrapper::ToggleChapter(int i_chapter)
941 {
942     if( p_input != NULL )
943     {
944         p_input->stream.p_selected_area->i_part = i_chapter;
945         input_ChangeArea( p_input,
946                           p_input->stream.p_selected_area );
947
948         vlc_mutex_lock( &p_input->stream.stream_lock );
949         vlc_mutex_unlock( &p_input->stream.stream_lock );
950     }
951 }
952
953 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
954 {
955         currentIndex = -1;
956         maxIndex = -1;
957         if ( p_input )
958         {
959                 vlc_mutex_lock( &p_input->stream.stream_lock );
960
961                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
962                 if ( maxIndex > 0)
963                         currentIndex = p_input->stream.p_selected_area->i_part;
964                 else
965                         maxIndex = -1;
966
967                 vlc_mutex_unlock( &p_input->stream.stream_lock );
968         }
969 }
970
971 /****************
972  * Miscellanous *
973  ****************/
974  
975 void VlcWrapper::LoadSubFile( const char * psz_file )
976 {
977     config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
978 }
979
980 void VlcWrapper::FilterChange()
981 {
982     if( !p_input )
983         return;
984     
985     vout_thread_t * p_vout;
986     vlc_mutex_lock( &p_input->stream.stream_lock );
987
988     // Warn the vout we are about to change the filter chain
989     p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
990                                               FIND_ANYWHERE );
991     if( p_vout )
992     {
993         p_vout->b_filter_change = VLC_TRUE;
994         vlc_object_release( p_vout );
995     }
996
997     // restart all video stream
998     for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
999     {
1000         if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
1001             ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
1002         {
1003             input_UnselectES( p_input, p_input->stream.pp_es[i] );
1004             input_SelectES( p_input, p_input->stream.pp_es[i] );
1005         }
1006     }
1007     vlc_mutex_unlock( &p_input->stream.stream_lock );
1008 }