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