]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
* ALL: changed the prototype of input_AddES() to include enough information so we...
[vlc] / modules / gui / beos / VlcWrapper.cpp
1 /*****************************************************************************
2  * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port)
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: VlcWrapper.cpp,v 1.29 2003/05/05 22:23:38 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     {
66         vlc_object_release( p_input );
67     }
68     if( p_playlist )
69     {
70         vlc_object_release( p_playlist );
71     }
72 }
73
74 /* UpdateInput: updates p_input, returns true if the interface needs to
75    be updated */
76 bool VlcWrapper::UpdateInput()
77 {
78     if( p_input == NULL )
79     {
80         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
81                                                      FIND_ANYWHERE );
82     }
83         
84     if( p_input != NULL )
85     {
86         if( p_input->b_dead )
87         {
88             vlc_object_release( p_input );
89             p_input = NULL;
90         }
91         return true;
92     }
93     return false;
94 }
95
96
97 /***************************
98  * input infos and control *
99  ***************************/
100
101 bool VlcWrapper::HasInput()
102 {
103     return ( p_input != NULL );
104 }
105
106 int VlcWrapper::InputStatus()
107 {
108     if( !p_input )
109     {
110         return UNDEF_S;
111     }
112     return p_input->stream.control.i_status;
113 }
114
115 int VlcWrapper::InputRate()
116 {
117     if( !p_input )
118     {
119         return DEFAULT_RATE;
120     }
121     return p_input->stream.control.i_rate;
122 }
123
124 void VlcWrapper::InputSlower()
125 {
126     if( p_input != NULL )
127     {
128         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
129     }
130 }
131
132 void VlcWrapper::InputFaster()
133 {
134     if( p_input != NULL )
135     {
136         input_SetStatus( p_input, INPUT_STATUS_FASTER );
137     }
138 }
139
140 BList * VlcWrapper::GetChannels( int i_cat )
141 {
142     if( p_input )
143     {
144         unsigned int i;
145         uint32 what;
146         const char* fieldName;
147
148         switch( i_cat )
149         {
150             case AUDIO_ES:
151             {
152                 what = SELECT_CHANNEL;
153                 fieldName = "channel";
154                 break;
155             }
156             case SPU_ES:
157             {
158                 what = SELECT_SUBTITLE;
159                 fieldName = "subtitle";
160                 break;
161             }
162             default:
163             return NULL;
164        }
165
166         vlc_mutex_lock( &p_input->stream.stream_lock );
167       
168         /* find which track is currently playing */
169         es_descriptor_t *p_es = NULL;
170         for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
171         {
172             if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
173                 p_es = p_input->stream.pp_selected_es[i];
174         }
175         
176         /* build a list of all tracks */
177         BList *list = new BList( p_input->stream.i_es_number );
178         BMenuItem *menuItem;
179         BMessage *message;
180         char *trackName;
181         
182         /* "None" */
183         message = new BMessage( what );
184         message->AddInt32( fieldName, -1 );
185         menuItem = new BMenuItem( _("None"), message );
186         if( !p_es )
187             menuItem->SetMarked( true );
188         list->AddItem( menuItem );
189         
190         for( i = 0; i < p_input->stream.i_es_number; i++ )
191         {
192             if( p_input->stream.pp_es[i]->i_cat == i_cat )
193             {
194                 message = new BMessage( what );
195                 message->AddInt32( fieldName, i );
196                 if( !p_input->stream.pp_es[i]->psz_desc ||
197                     !*p_input->stream.pp_es[i]->psz_desc )
198                     trackName = _("<unknown>");
199                 else
200                     trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
201                 menuItem = new BMenuItem( trackName, message );
202                 if( p_input->stream.pp_es[i] == p_es )
203                     menuItem->SetMarked( true );
204                 list->AddItem( menuItem );
205             }
206         }
207         
208         vlc_mutex_unlock( &p_input->stream.stream_lock );
209
210         return list;
211     }
212     return NULL;
213 }
214
215 void VlcWrapper::ToggleLanguage( int i_language )
216 {
217     es_descriptor_t * p_es = NULL;
218     es_descriptor_t * p_es_old = NULL;
219
220     vlc_mutex_lock( &p_input->stream.stream_lock );
221     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
222     {
223         if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
224         {
225             p_es_old = p_input->stream.pp_selected_es[i];
226             break;
227         }
228     }
229     vlc_mutex_unlock( &p_input->stream.stream_lock );
230     
231     if( i_language != -1 )
232     {
233         p_es = p_input->stream.pp_es[i_language];
234     }
235     if( p_es == p_es_old )
236     {
237         return;
238     }
239     if( p_es_old )
240     {
241         input_ToggleES( p_input, p_es_old, VLC_FALSE );
242     }
243     if( p_es )
244     {
245         input_ToggleES( p_input, p_es, VLC_TRUE );
246     }
247 }
248
249 void VlcWrapper::ToggleSubtitle( int i_subtitle )
250 {
251     es_descriptor_t * p_es = NULL;
252     es_descriptor_t * p_es_old = NULL;
253
254     vlc_mutex_lock( &p_input->stream.stream_lock );
255     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
256     {
257         if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
258         {
259             p_es_old = p_input->stream.pp_selected_es[i];
260             break;
261         }
262     }
263     vlc_mutex_unlock( &p_input->stream.stream_lock );
264     
265     if( i_subtitle != -1 )
266     {
267         p_es = p_input->stream.pp_es[i_subtitle];
268     }
269     if( p_es == p_es_old )
270     {
271         return;
272     }
273     if( p_es_old )
274     {
275         input_ToggleES( p_input, p_es_old, VLC_FALSE );
276     }
277     if( p_es )
278     {
279         input_ToggleES( p_input, p_es, VLC_TRUE );
280     }
281 }
282
283 const char * VlcWrapper::GetTimeAsString()
284 {
285     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
286         
287     if( p_input == NULL )
288     {
289         return ("-:--:--");
290     }     
291    
292     input_OffsetToTime( p_input, 
293                         psz_currenttime, 
294                         p_input->stream.p_selected_area->i_tell );        
295
296     return(psz_currenttime);
297 }
298
299 float VlcWrapper::GetTimeAsFloat()
300 {
301     float f_time = 0.0;
302
303     if( p_input != NULL )
304     {
305         f_time = (float)p_input->stream.p_selected_area->i_tell / 
306                  (float)p_input->stream.p_selected_area->i_size;
307     }    
308     else
309     {
310         f_time = 0.0;
311     }
312     return( f_time );
313 }
314
315 void VlcWrapper::SetTimeAsFloat( float f_position )
316 {
317     if( p_input != NULL )
318     {
319         input_Seek( p_input, 
320                    (long long int)(p_input->stream.p_selected_area->i_size
321                        * f_position / SEEKSLIDER_RANGE ), 
322                    INPUT_SEEK_SET);
323     }
324 }
325
326 bool VlcWrapper::IsPlaying()
327 {
328
329         bool playing = false;
330         if ( p_input )
331         {
332                 switch ( p_input->stream.control.i_status )
333                 {
334                         case PLAYING_S:
335                         case FORWARD_S:
336                         case BACKWARD_S:
337                         case START_S:
338                                 playing = true;
339                     break;
340                         case PAUSE_S:
341                         case UNDEF_S:
342                         case NOT_STARTED_S:
343                         default:
344                                 break;
345                 }
346         }
347         return playing;
348
349 }
350
351 /************
352  * playlist *
353  ************/
354
355 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
356 {
357         if ( o_files && o_files->CountItems() > 0)
358         {
359             int size = PlaylistSize();
360                 bool wasEmpty = ( size < 1 );
361                 if ( index == -1 )
362                         index = PLAYLIST_END;
363                 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
364         
365             /* delete current playlist */
366             if( replace )
367             {
368                 for( int i = 0; i < size; i++ )
369                 {
370                     playlist_Delete( p_playlist, 0 );
371                 }
372             }
373         
374             /* insert files */
375             int32 count = o_files->CountItems();
376             for ( int32 i = count - 1; i >= 0; i-- )
377             {
378                 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
379                 {
380                         playlist_Add( p_playlist, o_file->String(),
381                                       mode, index );
382                         if ( mode == PLAYLIST_INSERT )
383                                 index++;
384                         delete o_file;
385                 }
386             }
387             // TODO: implement a user setting
388             // if to start automatically
389             /* eventually restart playing */
390             if( replace || wasEmpty )
391             {
392                 playlist_Stop( p_playlist );
393                 playlist_Play( p_playlist );
394             }
395         }
396 }
397  
398 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
399 {
400     if( p_intf->p_sys->b_dvdmenus )
401         o_device.Prepend( "dvd:" );
402     else
403         o_device.Prepend( "dvdold:" );
404     playlist_Add( p_playlist, o_device.String(),
405                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
406 }
407
408 int VlcWrapper::PlaylistSize()
409 {
410     vlc_mutex_lock( &p_playlist->object_lock );
411     int i_size = p_playlist->i_size;
412     vlc_mutex_unlock( &p_playlist->object_lock );
413     return i_size;
414 }
415
416 char * VlcWrapper::PlaylistItemName( int i )
417 {
418    return p_playlist->pp_items[i]->psz_name;
419 }
420
421 int VlcWrapper::PlaylistCurrent()
422 {
423     return p_playlist->i_index;
424 }
425
426 bool VlcWrapper::PlaylistPlay()
427 {
428     if( PlaylistSize() )
429     {
430         playlist_Play( p_playlist );
431     }
432     return( true );
433 }
434
435 void VlcWrapper::PlaylistPause()
436 {
437     if( p_input )
438     {
439         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
440     }
441 }
442
443 void VlcWrapper::PlaylistStop()
444 {
445     playlist_Stop( p_playlist );
446 }
447
448 void VlcWrapper::PlaylistNext()
449 {
450     playlist_Next( p_playlist );
451 }
452
453 void VlcWrapper::PlaylistPrev()
454 {
455     playlist_Prev( p_playlist );
456 }
457
458 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
459 {
460         currentIndex = -1;
461         maxIndex = -1;
462         if ( p_playlist )
463         {
464             vlc_mutex_lock( &p_playlist->object_lock );
465
466                 maxIndex = p_playlist->i_size;
467                 if ( maxIndex > 0 )
468                         currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
469                 else
470                         maxIndex = -1;
471
472             vlc_mutex_unlock( &p_playlist->object_lock );
473         }
474 }
475
476 void VlcWrapper::PlaylistJumpTo( int pos )
477 {
478     playlist_Goto( p_playlist, pos );
479 }
480
481 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
482 {
483         if ( canSkipPrev && canSkipNext )
484         {
485                 // init the parameters
486                 *canSkipPrev = false;
487                 *canSkipNext = false;
488                 // get playlist info
489                 int pos = PlaylistCurrent();
490                 int size = PlaylistSize();
491
492                 // see if we have got a stream going            
493                 if ( p_input )
494                 {
495                         vlc_mutex_lock( &p_input->stream.stream_lock );
496
497                         bool hasTitles = p_input->stream.i_area_nb > 1;
498                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
499                         bool hasChapters = numChapters > 1;
500                         // first, look for chapters
501                         if ( hasChapters )
502                         {
503                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
504                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
505                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
506                         }
507                         // if one of the skip capabilities is false,
508                         // make it depend on titles instead
509                         if ( !*canSkipPrev && hasTitles )
510                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
511                         if ( !*canSkipNext && hasTitles )
512                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
513                                                    p_input->stream.i_area_nb - 1;
514
515                         vlc_mutex_unlock( &p_input->stream.stream_lock );
516                 }
517                 // last but not least, make capabilities depend on playlist
518                 if ( !*canSkipPrev )
519                         *canSkipPrev = pos > 0;
520                 if ( !*canSkipNext )
521                         *canSkipNext = pos < size - 1;
522         }
523 }
524
525 void VlcWrapper::NavigatePrev()
526 {
527         bool hasSkiped = false;
528
529         // see if we have got a stream going            
530         if ( p_input )
531         {
532                 // get information from stream (lock it while looking at it)
533                 vlc_mutex_lock( &p_input->stream.stream_lock );
534
535                 int currentTitle = p_input->stream.p_selected_area->i_id;
536                 int currentChapter = p_input->stream.p_selected_area->i_part;
537                 int numTitles = p_input->stream.i_area_nb;
538                 bool hasTitles = numTitles > 1;
539                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
540                 bool hasChapters = numChapters > 1;
541
542                 vlc_mutex_unlock( &p_input->stream.stream_lock );
543
544                 // first, look for chapters
545                 if ( hasChapters )
546                 {
547                         // skip to the previous chapter
548                         currentChapter--;
549
550                         if ( currentChapter >= 0 )
551                         {
552                                 ToggleChapter( currentChapter );
553                                 hasSkiped = true;
554                         }
555                 }
556                 // if we couldn't skip chapters, try titles instead
557                 if ( !hasSkiped && hasTitles )
558                 {
559                         // skip to the previous title
560                         currentTitle--;
561                         // disallow area 0 since it is used for video_ts.vob
562                         if( currentTitle > 0 )
563                         {
564                                 ToggleTitle(currentTitle);
565                                 hasSkiped = true;
566                         }
567                 }
568
569         }
570         // last but not least, skip to previous file
571         if ( !hasSkiped )
572                 PlaylistPrev();
573 }
574
575 void VlcWrapper::NavigateNext()
576 {
577         bool hasSkiped = false;
578
579         // see if we have got a stream going            
580         if ( p_input )
581         {
582                 // get information from stream (lock it while looking at it)
583                 vlc_mutex_lock( &p_input->stream.stream_lock );
584
585                 int currentTitle = p_input->stream.p_selected_area->i_id;
586                 int currentChapter = p_input->stream.p_selected_area->i_part;
587                 int numTitles = p_input->stream.i_area_nb;
588                 bool hasTitles = numTitles > 1;
589                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
590                 bool hasChapters = numChapters > 1;
591
592                 vlc_mutex_unlock( &p_input->stream.stream_lock );
593
594                 // first, look for chapters
595                 if ( hasChapters )
596                 {
597                         // skip to the next chapter
598                         currentChapter++;
599                         if ( currentChapter < numChapters )
600                         {
601                                 ToggleChapter( currentChapter );
602                                 hasSkiped = true;
603                         }
604                 }
605                 // if we couldn't skip chapters, try titles instead
606                 if ( !hasSkiped && hasTitles )
607                 {
608                         // skip to the next title
609                         currentTitle++;
610                         // disallow area 0 since it is used for video_ts.vob
611                         if ( currentTitle < numTitles - 1 )
612                         {
613                                 ToggleTitle(currentTitle);
614                                 hasSkiped = true;
615                         }
616                 }
617
618         }
619         // last but not least, skip to next file
620         if ( !hasSkiped )
621                 PlaylistNext();
622 }
623
624 /*************************
625  * Playlist manipulation *
626  *************************/
627
628 // PlaylistLock
629 bool
630 VlcWrapper::PlaylistLock() const
631 {
632 // TODO: search and destroy -> deadlock!
633 return true;
634         if ( p_playlist )
635         {
636                 vlc_mutex_lock( &p_playlist->object_lock );
637                 return true;
638         }
639         return false;
640 }
641
642 // PlaylistUnlock
643 void
644 VlcWrapper::PlaylistUnlock() const
645 {
646 // TODO: search and destroy -> deadlock!
647 return;
648         vlc_mutex_unlock( &p_playlist->object_lock );
649 }
650
651 // PlaylistItemAt
652 void*
653 VlcWrapper::PlaylistItemAt( int index ) const
654 {
655         playlist_item_t* item = NULL;
656         if ( index >= 0 && index < p_playlist->i_size )
657                 item = p_playlist->pp_items[index];
658         return (void*)item;
659 }
660
661 // PlaylistRemoveItem
662 void*
663 VlcWrapper::PlaylistRemoveItem( int index ) const
664 {
665         playlist_item_t* copy = NULL;
666         // check if item exists at the provided index
667         if ( index >= 0 && index < p_playlist->i_size )
668         {
669                 playlist_item_t* item = p_playlist->pp_items[index];
670                 if ( item )
671                 {
672                         // make a copy of the removed item
673                         copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
674                         // remove item from playlist (unfortunately, this frees it)
675                         playlist_Delete( p_playlist, index );
676                 }
677         }
678         return (void*)copy;
679 }
680
681 // PlaylistRemoveItem
682 void*
683 VlcWrapper::PlaylistRemoveItem( void* item ) const
684 {
685         playlist_item_t* copy = NULL;
686         for ( int32 i = 0; i < p_playlist->i_size; i++ )
687         {
688                 if ( p_playlist->pp_items[i] == item )
689                 {
690                         copy = (playlist_item_t*)PlaylistRemoveItem( i );
691                         break;
692                 }
693         }
694         return (void*)copy;
695 }
696
697 // PlaylistAddItem
698 bool
699 VlcWrapper::PlaylistAddItem( void* item, int index ) const
700 {
701         if ( item )
702         {
703                 playlist_AddItem( p_playlist, (playlist_item_t*)item,
704                                                   PLAYLIST_INSERT, index );
705         }
706         // TODO: once playlist is returning useful info, return that instead
707         return true;
708 }
709
710 // PlaylistCloneItem
711 void*
712 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
713 {
714         playlist_item_t* copy = NULL;
715         playlist_item_t* item = (playlist_item_t*)castToItem;
716         if ( item )
717         {
718                 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
719                 if ( copy )
720                 {
721                         // make a copy of the item at index
722                         copy->psz_name = strdup( item->psz_name );
723                         copy->psz_uri  = strdup( item->psz_uri );
724                         copy->i_type = item->i_type;
725                         copy->i_status = item->i_status;
726                         copy->b_autodeletion = item->b_autodeletion;
727                 }
728         }
729         return (void*)copy;
730 }
731
732 // Careful! You need to know what you're doing here!
733 // The reason for having it, is to be able to deal with
734 // the rather lame list implementation of the playlist.
735 // It is meant to help manipulate the playlist with the above
736 // methods while keeping it valid.
737 //
738 // PlaylistSetPlaying
739 void
740 VlcWrapper::PlaylistSetPlaying( int index ) const
741 {
742         if ( index < 0 )
743                 index = 0;
744         if ( index >= p_playlist->i_size )
745                 index = p_playlist->i_size - 1;
746         p_playlist->i_index = index;
747 }
748
749
750 /*********
751  * audio *
752  *********/
753
754 unsigned short VlcWrapper::GetVolume()
755 {
756     unsigned short i_volume;
757     aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
758     return i_volume;
759 }
760
761 void VlcWrapper::SetVolume( int value )
762 {
763     if ( p_intf->p_sys->b_mute )
764     {
765         p_intf->p_sys->b_mute = 0;
766     }
767     aout_VolumeSet( p_intf, value );
768 }
769
770 void VlcWrapper::VolumeMute()
771 {
772         aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
773     aout_VolumeMute( p_intf, NULL );
774     p_intf->p_sys->b_mute = 1;
775 }
776
777 void VlcWrapper::VolumeRestore()
778 {
779     aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
780     p_intf->p_sys->b_mute = 0;
781 }
782
783 bool VlcWrapper::IsMuted()
784 {
785     return p_intf->p_sys->b_mute;
786 }
787
788 /*******
789  * DVD *
790  *******/
791
792 bool VlcWrapper::HasTitles()
793 {
794     if( !p_input )
795     {
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 }