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