]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
* AudioOutput.cpp: fixed a segfault
[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.12 2002/11/27 05:36:41 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 <SupportKit.h>
28
29 #include <vlc/vlc.h>
30 #include <vlc/intf.h>
31 #include <audio_output.h>
32 #include <aout_internal.h>
33
34 #include "VlcWrapper.h"
35
36 /* constructor */
37 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
38 {
39     p_intf = p_interface;
40     p_input = NULL;
41     p_aout = NULL;
42     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
43                                                 FIND_ANYWHERE );
44 }
45
46 /* destructor */
47 VlcWrapper::~VlcWrapper()
48 {
49     if( p_input )
50     {
51         vlc_object_release( p_input );
52     }
53     if( p_playlist )
54     {
55         vlc_object_release( p_playlist );
56     }
57     if( p_aout )
58     {
59         vlc_object_release( p_aout );
60     }
61 }
62
63 /* UpdateInputAndAOut: updates p_input and p_aout, returns true if the
64    interface needs to be updated */
65 bool VlcWrapper::UpdateInputAndAOut()
66 {
67     if( p_input == NULL )
68     {
69         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
70                                                      FIND_ANYWHERE );
71     }
72     if( p_aout == NULL )
73     {
74         p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
75                                                     FIND_ANYWHERE );
76     }
77         
78     if( p_input != NULL )
79     {
80         if( p_input->b_dead )
81         {
82             vlc_object_release( p_input );
83             p_input = NULL;
84             
85             if( p_aout )
86             {
87                 vlc_object_release( p_aout );
88                 p_aout = NULL;
89             }
90         }
91         return true;
92     }
93     return false;
94 }
95
96
97 /***************************
98  * input infos and control *
99  ***************************/
100
101 /* status (UNDEF_S, PLAYING_S, PAUSE_S, FORWARD_S, BACKWARD_S,
102    REWIND_S, NOT_STARTED_S, START_S) */
103 int VlcWrapper::InputStatus()
104 {
105     if( !p_input )
106     {
107         return UNDEF_S;
108     }
109     return p_input->stream.control.i_status;
110 }
111
112 int VlcWrapper::InputRate()
113 {
114     if( !p_input )
115     {
116         return DEFAULT_RATE;
117     }
118     return p_input->stream.control.i_rate;
119 }
120
121 /* tell: location in the current stream (in arbitrary units) */
122 int VlcWrapper::InputTell()
123 {
124     if( !p_input )
125     {
126         return -1;
127     }
128     return p_input->stream.p_selected_area->i_tell;
129 }
130
131 /* size: total size of the current stream (in arbitrary units) */
132 int VlcWrapper::InputSize()
133 {
134     if( !p_input )
135     {
136         return -1;
137     }
138     return p_input->stream.p_selected_area->i_size;
139 }
140
141 void VlcWrapper::InputSlower()
142 {
143     if( p_input != NULL )
144     {
145         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
146     }
147     if( p_input->stream.control.i_rate == DEFAULT_RATE)
148     {
149         toggle_mute();
150     }
151     else
152     {
153         toggle_mute();
154     }
155 }
156
157 void VlcWrapper::InputFaster()
158 {
159     if( p_input != NULL )
160     {
161         input_SetStatus( p_input, INPUT_STATUS_FASTER );
162     }
163     if( p_input->stream.control.i_rate == DEFAULT_RATE)
164     {
165         toggle_mute();
166     }
167     else
168     {
169         toggle_mute();
170     }
171 }
172
173 void VlcWrapper::openFiles( BList* o_files, bool replace )
174 {
175     BString *o_file;
176
177     while( ( o_file = (BString *)o_files->LastItem() ) )
178     {
179         o_files->RemoveItem(o_files->CountItems() - 1);
180         playlist_Add( p_playlist, o_file->String(),
181                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
182         delete o_file;
183     }
184 }
185
186 void VlcWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
187 {
188     BString o_source("");
189     o_source << o_type << ":" << o_device ;
190
191     playlist_Add( p_playlist, o_source.String(),
192                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
193 }
194
195
196
197 void VlcWrapper::toggleLanguage(int i_language)
198 {
199
200     int32 i_old = -1;
201     int i_cat = AUDIO_ES;
202
203     vlc_mutex_lock( &p_input->stream.stream_lock );
204     for( int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
205     {
206         if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
207         {
208             i_old = i;
209             break;
210         }
211     }
212     vlc_mutex_unlock( &p_input->stream.stream_lock );
213
214     msg_Info( p_intf, "Old: %d,  New: %d", i_old, i_language);
215     if( i_language != -1 )
216     {
217         input_ToggleES( p_input, 
218                         p_input->stream.pp_selected_es[i_language],
219                         VLC_TRUE );
220     }
221
222     if( (i_old != -1) && (i_old != i_language) )
223     {
224         input_ToggleES( p_input, 
225                         p_input->stream.pp_selected_es[i_old],
226                         VLC_FALSE );
227     }
228 }
229
230 void VlcWrapper::toggleSubtitle(int i_subtitle)
231 {
232     int32 i_old = -1;
233     int i_cat = SPU_ES;
234
235     vlc_mutex_lock( &p_input->stream.stream_lock );
236     for( int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
237     {
238         if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
239         {
240             i_old = i;
241             break;
242         }
243     }
244     vlc_mutex_unlock( &p_input->stream.stream_lock );
245     
246     msg_Info( p_intf, "Old: %d,  New: %d", i_old, i_subtitle);
247     if( i_subtitle != -1 )
248     {
249         input_ToggleES( p_input, 
250                         p_input->stream.pp_selected_es[i_subtitle],
251                         VLC_TRUE );
252     }
253
254     if( (i_old != -1) && (i_old != i_subtitle) )
255     {
256         input_ToggleES( p_input, 
257                         p_input->stream.pp_selected_es[i_old],
258                         VLC_FALSE );
259     }
260 }
261
262 const char*  VlcWrapper::getTimeAsString()
263 {
264     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
265         
266     if( p_input == NULL )
267     {
268         return ("-:--:--");
269     }     
270    
271     input_OffsetToTime( p_input, 
272                         psz_currenttime, 
273                         p_input->stream.p_selected_area->i_tell );        
274
275     return(psz_currenttime);
276 }
277
278 float  VlcWrapper::getTimeAsFloat()
279 {
280     float f_time = 0.0;
281
282     if( p_input != NULL )
283     {
284         f_time = (float)p_input->stream.p_selected_area->i_tell / 
285                  (float)p_input->stream.p_selected_area->i_size;
286     }    
287     else
288     {
289         f_time = 0.0;
290     }
291     return( f_time );
292 }
293
294 void VlcWrapper::setTimeAsFloat(float f_position)
295 {
296     if( p_input != NULL )
297     {
298         input_Seek( p_input, 
299                    (long long int)(p_input->stream.p_selected_area->i_size
300                        * f_position / SEEKSLIDER_RANGE ), 
301                    INPUT_SEEK_SET);
302     }
303 }
304
305
306 /******************************
307  * playlist infos and control *
308  ******************************/
309 int VlcWrapper::PlaylistSize()
310 {
311     vlc_mutex_lock( &p_playlist->object_lock );
312     int i_size = p_playlist->i_size;
313     vlc_mutex_unlock( &p_playlist->object_lock );
314     return i_size;
315 }
316
317 char *VlcWrapper::PlaylistItemName( int i )
318 {
319    return p_playlist->pp_items[i]->psz_name;
320 }
321
322 int VlcWrapper::PlaylistCurrent()
323 {
324     return p_playlist->i_index;
325 }
326
327 int  VlcWrapper::PlaylistStatus()
328 {
329     return p_playlist->i_status;
330 }
331
332 bool VlcWrapper::PlaylistPlay()
333 {
334     if( PlaylistSize() )
335     {
336         playlist_Play( p_playlist );
337     }
338     return( true );
339 }
340
341 void VlcWrapper::PlaylistPause()
342 {
343     toggle_mute();
344     if( p_input )
345     {
346         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
347     }
348 }
349
350 void VlcWrapper::PlaylistStop()
351 {
352     volume_mute();
353     playlist_Stop( p_playlist );
354 }
355
356 void VlcWrapper::PlaylistNext()
357 {
358     playlist_Next( p_playlist );
359 }
360
361 void VlcWrapper::PlaylistPrev()
362 {
363     playlist_Prev( p_playlist );
364 }
365
366 void VlcWrapper::PlaylistSkip( int i )
367 {
368     playlist_Skip( p_playlist, i );
369 }
370
371 void VlcWrapper::PlaylistGoto( int i )
372 {
373     playlist_Goto( p_playlist, i );
374 }
375
376 void VlcWrapper::PlaylistLoop()
377 {
378     if ( p_intf->p_sys->b_loop )
379     {
380         playlist_Delete( p_playlist, p_playlist->i_size - 1 );
381     }
382     else
383     {
384         playlist_Add( p_playlist, "vlc:loop",
385                       PLAYLIST_APPEND | PLAYLIST_GO,
386                       PLAYLIST_END );
387     }
388     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
389 }
390
391 BList * VlcWrapper::PlaylistAsArray()
392
393     int i;
394     BList* p_list = new BList(p_playlist->i_size);
395     
396     vlc_mutex_lock( &p_playlist->object_lock );
397
398     for( i = 0; i < p_playlist->i_size; i++ )
399     {
400         p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
401     }
402
403     vlc_mutex_unlock( &p_playlist->object_lock );
404     return( p_list );
405 }
406
407 void VlcWrapper::getPlaylistInfo( int32& currentIndex, int32& maxIndex )
408 {
409         currentIndex = -1;
410         maxIndex = -1;
411         if ( p_playlist )
412         {
413                 maxIndex = p_playlist->i_size;
414                 if ( maxIndex > 0 )
415                         currentIndex = p_playlist->i_index + 1;
416                 else
417                         maxIndex = -1;
418         }
419 }
420
421
422 void VlcWrapper::PlaylistJumpTo( int pos )
423 {
424 #if 0
425         // sanity checks
426         if ( pos < 0 )
427                 pos = 0;
428         int size = playlistSize();
429         if (pos >= size)
430                 pos = size - 1;
431         // weird hack
432     if( p_input_bank->pp_input[0] != NULL )
433                 pos--;
434         // stop current stream
435         playlistStop();
436         // modify current position in playlist
437         playlistLock();
438         p_main->p_playlist->i_index = pos;
439         playlistUnlock();
440         // start playing
441         playlistPlay();
442 #endif
443 }
444
445 void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
446 {
447         if ( canSkipPrev && canSkipNext )
448         {
449                 // init the parameters
450                 *canSkipPrev = false;
451                 *canSkipNext = false;
452                 // get playlist info
453                 int pos = PlaylistCurrent();
454                 int size = PlaylistSize();
455
456                 // see if we have got a stream going            
457                 if ( p_input )
458                 {
459                         vlc_mutex_lock( &p_input->stream.stream_lock );
460
461                         bool hasTitles = p_input->stream.i_area_nb > 1;
462                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
463                         bool hasChapters = numChapters > 1;
464                         // first, look for chapters
465                         if ( hasChapters )
466                         {
467                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
468                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
469                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
470                         }
471                         // if one of the skip capabilities is false,
472                         // make it depend on titles instead
473                         if ( !*canSkipPrev && hasTitles )
474                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
475                         if ( !*canSkipNext && hasTitles )
476                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
477                                                    p_input->stream.i_area_nb - 1;
478
479                         vlc_mutex_unlock( &p_input->stream.stream_lock );
480                 }
481                 // last but not least, make capabilities depend on playlist
482                 if ( !*canSkipPrev )
483                         *canSkipPrev = pos > 0;
484                 if ( !*canSkipNext )
485                         *canSkipNext = pos < size - 1;
486         }
487 }
488
489 void VlcWrapper::navigatePrev()
490 {
491         bool hasSkiped = false;
492
493         // see if we have got a stream going            
494         if ( p_input )
495         {
496                 // get information from stream (lock it while looking at it)
497                 vlc_mutex_lock( &p_input->stream.stream_lock );
498
499                 int currentTitle = p_input->stream.p_selected_area->i_id;
500                 int currentChapter = p_input->stream.p_selected_area->i_part;
501                 int numTitles = p_input->stream.i_area_nb;
502                 bool hasTitles = numTitles > 1;
503                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
504                 bool hasChapters = numChapters > 1;
505
506                 vlc_mutex_unlock( &p_input->stream.stream_lock );
507
508                 // first, look for chapters
509                 if ( hasChapters )
510                 {
511                         // skip to the previous chapter
512                         currentChapter--;
513
514                         if ( currentChapter >= 0 )
515                         {
516                                 toggleChapter( currentChapter );
517                                 hasSkiped = true;
518                         }
519                 }
520                 // if we couldn't skip chapters, try titles instead
521                 if ( !hasSkiped && hasTitles )
522                 {
523                         // skip to the previous title
524                         currentTitle--;
525                         // disallow area 0 since it is used for video_ts.vob
526                         if( currentTitle > 0 )
527                         {
528                                 toggleTitle(currentTitle);
529                                 hasSkiped = true;
530                         }
531                 }
532
533         }
534         // last but not least, skip to previous file
535         if ( !hasSkiped )
536                 PlaylistPrev();
537 }
538
539 void VlcWrapper::navigateNext()
540 {
541         bool hasSkiped = false;
542
543         // see if we have got a stream going            
544         if ( p_input )
545         {
546                 // get information from stream (lock it while looking at it)
547                 vlc_mutex_lock( &p_input->stream.stream_lock );
548
549                 int currentTitle = p_input->stream.p_selected_area->i_id;
550                 int currentChapter = p_input->stream.p_selected_area->i_part;
551                 int numTitles = p_input->stream.i_area_nb;
552                 bool hasTitles = numTitles > 1;
553                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
554                 bool hasChapters = numChapters > 1;
555
556                 vlc_mutex_unlock( &p_input->stream.stream_lock );
557
558                 // first, look for chapters
559                 if ( hasChapters )
560                 {
561                         // skip to the next chapter
562                         currentChapter++;
563                         if ( currentChapter < numChapters )
564                         {
565                                 toggleChapter( currentChapter );
566                                 hasSkiped = true;
567                         }
568                 }
569                 // if we couldn't skip chapters, try titles instead
570                 if ( !hasSkiped && hasTitles )
571                 {
572                         // skip to the next title
573                         currentTitle++;
574                         // disallow area 0 since it is used for video_ts.vob
575                         if ( currentTitle < numTitles - 1 )
576                         {
577                                 toggleTitle(currentTitle);
578                                 hasSkiped = true;
579                         }
580                 }
581
582         }
583         // last but not least, skip to next file
584         if ( !hasSkiped )
585                 PlaylistNext();
586 }
587
588
589 /***************************
590  * audio infos and control *
591  ***************************/
592
593 void VlcWrapper::volume_mute()
594 {
595     if( p_aout != NULL )
596     {
597             if( !p_intf->p_sys->b_mute )
598                 {
599                     p_intf->p_sys->i_saved_volume = p_aout->output.i_volume;
600                     p_aout->output.i_volume = 0;
601                     p_intf->p_sys->b_mute = 1;
602                 }
603     }
604
605 }
606
607 void VlcWrapper::volume_restore()
608 {
609     if( p_aout != NULL )
610     {
611             p_aout->output.i_volume = p_intf->p_sys->i_saved_volume;
612                 p_intf->p_sys->i_saved_volume = 0;
613             p_intf->p_sys->b_mute = 0;
614     }
615
616 }
617
618 void VlcWrapper::set_volume(int value)
619 {
620     if( p_aout != NULL )
621     {
622                 // make sure value is within bounds
623                 if (value < 0)
624                         value = 0;
625                 if (value > AOUT_VOLUME_MAX)
626                         value = AOUT_VOLUME_MAX;
627                 vlc_mutex_lock( &p_aout->mixer_lock );
628                 // unmute volume if muted
629                 if ( p_intf->p_sys->b_mute )
630                 {
631                         p_intf->p_sys->b_mute = 0;
632             p_aout->output.i_volume = value;
633                 }
634                 vlc_mutex_unlock( &p_aout->mixer_lock );
635     }
636 }
637
638 void VlcWrapper::toggle_mute()
639 {
640     if( p_aout != NULL )
641         {
642             if ( p_intf->p_sys->b_mute )
643             {
644                 volume_restore();
645             }
646             else
647             {
648                 volume_mute();
649             }
650         }
651 }
652
653 bool VlcWrapper::is_muted()
654 {
655         bool muted = true;
656         
657     if( p_aout != NULL )
658         {
659                 vlc_mutex_lock( &p_aout->mixer_lock );
660                 if( p_aout->output.i_volume > 0 )
661                 {
662                         muted = false;
663                 }
664                 vlc_mutex_unlock( &p_aout->mixer_lock );
665 // unfortunately, this is not reliable!
666 //              return p_main->p_intf->p_sys->b_mute;
667         }
668         return muted;
669 }
670
671 bool VlcWrapper::is_playing()
672 {
673
674         bool playing = false;
675         if ( p_input )
676         {
677                 switch ( p_input->stream.control.i_status )
678                 {
679                         case PLAYING_S:
680                         case FORWARD_S:
681                         case BACKWARD_S:
682                         case START_S:
683                                 playing = true;
684                     break;
685                         case PAUSE_S:
686                         case UNDEF_S:
687                         case NOT_STARTED_S:
688                         default:
689                                 break;
690                 }
691         }
692         return playing;
693
694 }
695
696 void VlcWrapper::maxvolume()
697 {
698     if( p_aout != NULL )
699     {
700             if( p_intf->p_sys->b_mute )
701             {
702                 p_intf->p_sys->i_saved_volume = AOUT_VOLUME_MAX;
703             }
704             else
705             {
706                 p_aout->output.i_volume = AOUT_VOLUME_MAX;
707             }
708     }
709 }
710
711 bool VlcWrapper::has_audio()
712 {
713     return( p_aout != NULL );
714 }
715
716 /*******
717  * DVD *
718  *******/
719 bool VlcWrapper::HasTitles()
720 {
721     if( !p_input )
722     {
723         return false;
724     }
725     return ( p_input->stream.i_area_nb > 1 );
726 }
727
728 void VlcWrapper::PrevTitle()
729 {
730     int i_id;
731     i_id = p_input->stream.p_selected_area->i_id - 1;
732     if( i_id > 0 )
733     {
734         toggleTitle(i_id);
735     }
736 }
737
738 void VlcWrapper::NextTitle()
739 {
740     int i_id;
741     i_id = p_input->stream.p_selected_area->i_id + 1;
742     if( i_id < p_input->stream.i_area_nb )
743     {
744         toggleTitle(i_id);
745     }
746 }
747
748 bool VlcWrapper::HasChapters()
749 {
750     if( !p_input )
751     {
752         return false;
753     }
754     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
755 }
756
757 void VlcWrapper::PrevChapter()
758 {
759     int i_id;
760     i_id = p_input->stream.p_selected_area->i_part - 1;
761     if( i_id >= 0 )
762     {
763         toggleChapter(i_id);
764     }
765 }
766
767 void VlcWrapper::NextChapter()
768 {
769     int i_id;
770     i_id = p_input->stream.p_selected_area->i_part + 1;
771     if( i_id >= 0 )
772     {
773         toggleChapter(i_id);
774     }
775 }
776
777 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
778 {
779         currentIndex = -1;
780         maxIndex = -1;
781         if ( p_input )
782         {
783                 vlc_mutex_lock( &p_input->stream.stream_lock );
784
785                 maxIndex = p_input->stream.i_area_nb - 1;
786                 if ( maxIndex > 0)
787                         currentIndex = p_input->stream.p_selected_area->i_id;
788                 else
789                         maxIndex = -1;
790
791                 vlc_mutex_unlock( &p_input->stream.stream_lock );
792         }
793 }
794
795 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
796 {
797         currentIndex = -1;
798         maxIndex = -1;
799         if ( p_input )
800         {
801                 vlc_mutex_lock( &p_input->stream.stream_lock );
802
803                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
804                 if ( maxIndex > 0)
805                         currentIndex = p_input->stream.p_selected_area->i_part;
806                 else
807                         maxIndex = -1;
808
809                 vlc_mutex_unlock( &p_input->stream.stream_lock );
810         }
811 }
812
813 void VlcWrapper::toggleTitle(int i_title)
814 {
815     if( p_input != NULL )
816     {
817         input_ChangeArea( p_input,
818                           p_input->stream.pp_areas[i_title] );
819
820         vlc_mutex_lock( &p_input->stream.stream_lock );
821
822         vlc_mutex_unlock( &p_input->stream.stream_lock );
823     }
824 }
825
826 void VlcWrapper::toggleChapter(int i_chapter)
827 {
828     if( p_input != NULL )
829     {
830         p_input->stream.p_selected_area->i_part = i_chapter;
831         input_ChangeArea( p_input,
832                           p_input->stream.p_selected_area );
833
834         vlc_mutex_lock( &p_input->stream.stream_lock );
835         vlc_mutex_unlock( &p_input->stream.stream_lock );
836     }
837 }