]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
* modules/gui/*: use MSTRTIME_MAX_SIZE instead of OFFSETTOTIME_MAX_SIZE.
[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.40 2003/12/04 10:25:47 gbazin Exp $
6  *
7  * Authors: Florian G. Pflug <fgp@phlo.org>
8  *          Jon Lech Johansen <jon-vl@nanocrew.net>
9  *          Tony Casltey <tony@castley.net>
10  *          Stephan Aßmus <stippi@yellowbites.com>
11  *          Eric Petit <titer@videolan.org>
12  *
13  * This program is free software{} you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation{} either version 2 of the License, or
16  * (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY{} without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program{} if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27 #include <AppKit.h>
28 #include <InterfaceKit.h>
29 #include <SupportKit.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33 #include <vlc/vout.h>
34 extern "C"
35 {
36   #include <input_ext-plugins.h> // needed here when compiling without plugins
37   #include <audio_output.h>
38   #include <aout_internal.h>
39 }
40
41 #include "VlcWrapper.h"
42 #include "MsgVals.h"
43
44 const char * _AddEllipsis( char * string )
45 {
46     char * temp;
47     temp = (char*) calloc( strlen( string ) + 4, 1 );
48     sprintf( temp, "%s%s", string, B_UTF8_ELLIPSIS );
49     return temp;
50 }
51
52 /* constructor */
53 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
54 {
55     p_intf = p_interface;
56     p_input = NULL;
57     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
58                                                 FIND_ANYWHERE );
59 }
60
61 /* destructor */
62 VlcWrapper::~VlcWrapper()
63 {
64     if( p_input )
65         vlc_object_release( p_input );
66
67     if( p_playlist )
68         vlc_object_release( p_playlist );
69 }
70
71 /* UpdateInput: updates p_input */
72 void VlcWrapper::UpdateInput()
73 {
74     if( !p_input )
75         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
76                                                      FIND_ANYWHERE );
77         
78     if( p_input )
79         if( p_input->b_dead )
80         {
81             vlc_object_release( p_input );
82             p_input = NULL;
83         }
84 }
85
86
87 /***************************
88  * input infos and control *
89  ***************************/
90
91 bool VlcWrapper::HasInput()
92 {
93     return ( p_input != NULL );
94 }
95
96 int VlcWrapper::InputStatus()
97 {
98     if( !p_input )
99     {
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                                       0, 0, 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(), 0, 0,
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->psz_name = strdup( item->psz_name );
710                         copy->psz_uri  = strdup( item->psz_uri );
711                         copy->i_type = item->i_type;
712                         copy->i_status = item->i_status;
713                         copy->b_autodeletion = item->b_autodeletion;
714                 }
715         }
716         return (void*)copy;
717 }
718
719 // Careful! You need to know what you're doing here!
720 // The reason for having it, is to be able to deal with
721 // the rather lame list implementation of the playlist.
722 // It is meant to help manipulate the playlist with the above
723 // methods while keeping it valid.
724 //
725 // PlaylistSetPlaying
726 void
727 VlcWrapper::PlaylistSetPlaying( int index ) const
728 {
729         if ( index < 0 )
730                 index = 0;
731         if ( index >= p_playlist->i_size )
732                 index = p_playlist->i_size - 1;
733         p_playlist->i_index = index;
734 }
735
736
737 /*********
738  * audio *
739  *********/
740
741 unsigned short VlcWrapper::GetVolume()
742 {
743     unsigned short i_volume;
744     aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
745     return i_volume;
746 }
747
748 void VlcWrapper::SetVolume( int value )
749 {
750     if ( p_intf->p_sys->b_mute )
751     {
752         p_intf->p_sys->b_mute = 0;
753     }
754     aout_VolumeSet( p_intf, value );
755 }
756
757 void VlcWrapper::VolumeMute()
758 {
759     aout_VolumeMute( p_intf, NULL );
760     p_intf->p_sys->b_mute = 1;
761 }
762
763 void VlcWrapper::VolumeRestore()
764 {
765     audio_volume_t dummy;
766     aout_VolumeMute( p_intf, &dummy );
767     p_intf->p_sys->b_mute = 0;
768 }
769
770 bool VlcWrapper::IsMuted()
771 {
772     return p_intf->p_sys->b_mute;
773 }
774
775 /*******
776  * DVD *
777  *******/
778
779 bool VlcWrapper::IsUsingMenus()
780 {
781     if( !p_input )
782         return false;
783
784     vlc_mutex_lock( &p_playlist->object_lock );
785     if( p_playlist->i_index < 0 )
786     {
787         vlc_mutex_unlock( &p_playlist->object_lock );
788         return false;
789     }
790     
791     char * psz_name = p_playlist->pp_items[p_playlist->i_index]->psz_name;
792     if( !strncmp( psz_name, "dvdplay:", 8 ) )
793     {
794         vlc_mutex_unlock( &p_playlist->object_lock );
795         return true;
796     }
797     vlc_mutex_unlock( &p_playlist->object_lock );
798
799     return false;
800 }
801
802 bool VlcWrapper::HasTitles()
803 {
804     if( !p_input )
805         return false;
806
807     return ( p_input->stream.i_area_nb > 1 );
808 }
809
810 BList * VlcWrapper::GetTitles()
811 {
812     if( p_input )
813     {
814         vlc_mutex_lock( &p_input->stream.stream_lock );
815       
816         BList *list = new BList( p_input->stream.i_area_nb );
817         BMenuItem *menuItem;
818         BMessage *message;
819         
820         for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
821         {
822             message = new BMessage( TOGGLE_TITLE );
823             message->AddInt32( "index", i );
824             BString helper( "" );
825             helper << i;
826             menuItem = new BMenuItem( helper.String(), message );
827             menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
828             list->AddItem( menuItem );
829         }
830         
831         vlc_mutex_unlock( &p_input->stream.stream_lock );
832
833         return list;
834     }
835     return NULL;
836 }
837
838 void VlcWrapper::PrevTitle()
839 {
840     int i_id;
841     i_id = p_input->stream.p_selected_area->i_id - 1;
842     if( i_id > 0 )
843     {
844         ToggleTitle(i_id);
845     }
846 }
847
848 void VlcWrapper::NextTitle()
849 {
850     unsigned int i_id;
851     i_id = p_input->stream.p_selected_area->i_id + 1;
852     if( i_id < p_input->stream.i_area_nb )
853     {
854         ToggleTitle(i_id);
855     }
856 }
857
858 void VlcWrapper::ToggleTitle(int i_title)
859 {
860     if( p_input != NULL )
861     {
862         input_ChangeArea( p_input,
863                           p_input->stream.pp_areas[i_title] );
864
865         vlc_mutex_lock( &p_input->stream.stream_lock );
866
867         vlc_mutex_unlock( &p_input->stream.stream_lock );
868     }
869 }
870
871 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
872 {
873         currentIndex = -1;
874         maxIndex = -1;
875         if ( p_input )
876         {
877                 vlc_mutex_lock( &p_input->stream.stream_lock );
878
879                 maxIndex = p_input->stream.i_area_nb - 1;
880                 if ( maxIndex > 0)
881                         currentIndex = p_input->stream.p_selected_area->i_id;
882                 else
883                         maxIndex = -1;
884
885                 vlc_mutex_unlock( &p_input->stream.stream_lock );
886         }
887 }
888
889 bool VlcWrapper::HasChapters()
890 {
891     if( !p_input )
892     {
893         return false;
894     }
895     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
896 }
897
898 BList * VlcWrapper::GetChapters()
899 {
900     if( p_input )
901     {
902         vlc_mutex_lock( &p_input->stream.stream_lock );
903       
904         BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
905         BMenuItem *menuItem;
906         BMessage *message;
907         
908         for( unsigned int i = 1;
909              i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
910         {
911             message = new BMessage( TOGGLE_CHAPTER );
912             message->AddInt32( "index", i );
913             BString helper( "" );
914             helper << i;
915             menuItem = new BMenuItem( helper.String(), message );
916             menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
917             list->AddItem( menuItem );
918         }
919         
920         vlc_mutex_unlock( &p_input->stream.stream_lock );
921
922         return list;
923     }
924     return NULL;
925 }
926
927 void VlcWrapper::PrevChapter()
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::NextChapter()
938 {
939     int i_id;
940     i_id = p_input->stream.p_selected_area->i_part + 1;
941     if( i_id >= 0 )
942     {
943         ToggleChapter(i_id);
944     }
945 }
946
947 void VlcWrapper::ToggleChapter(int i_chapter)
948 {
949     if( p_input != NULL )
950     {
951         p_input->stream.p_selected_area->i_part = i_chapter;
952         input_ChangeArea( p_input,
953                           p_input->stream.p_selected_area );
954
955         vlc_mutex_lock( &p_input->stream.stream_lock );
956         vlc_mutex_unlock( &p_input->stream.stream_lock );
957     }
958 }
959
960 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
961 {
962         currentIndex = -1;
963         maxIndex = -1;
964         if ( p_input )
965         {
966                 vlc_mutex_lock( &p_input->stream.stream_lock );
967
968                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
969                 if ( maxIndex > 0)
970                         currentIndex = p_input->stream.p_selected_area->i_part;
971                 else
972                         maxIndex = -1;
973
974                 vlc_mutex_unlock( &p_input->stream.stream_lock );
975         }
976 }
977
978 /****************
979  * Miscellanous *
980  ****************/
981  
982 void VlcWrapper::LoadSubFile( const char * psz_file )
983 {
984     config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
985 }
986
987 void VlcWrapper::FilterChange()
988 {
989     if( !p_input )
990         return;
991     
992     vout_thread_t * p_vout;
993     vlc_mutex_lock( &p_input->stream.stream_lock );
994
995     // Warn the vout we are about to change the filter chain
996     p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
997                                               FIND_ANYWHERE );
998     if( p_vout )
999     {
1000         p_vout->b_filter_change = VLC_TRUE;
1001         vlc_object_release( p_vout );
1002     }
1003
1004     // restart all video stream
1005     for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
1006     {
1007         if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
1008             ( p_input->stream.pp_es[i]->p_dec != NULL ) )
1009         {
1010             input_UnselectES( p_input, p_input->stream.pp_es[i] );
1011             input_SelectES( p_input, p_input->stream.pp_es[i] );
1012         }
1013     }
1014     vlc_mutex_unlock( &p_input->stream.stream_lock );
1015 }