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