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