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