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.26 2003/02/09 17:10:52 stippi Exp $
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>
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.
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.
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 *****************************************************************************/
28 #include <InterfaceKit.h>
29 #include <SupportKit.h>
36 #include <input_ext-plugins.h> // needed here when compiling without plugins
37 #include <audio_output.h>
38 #include <aout_internal.h>
41 #include "VlcWrapper.h"
45 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
49 p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
54 VlcWrapper::~VlcWrapper()
58 vlc_object_release( p_input );
62 vlc_object_release( p_playlist );
66 /* UpdateInput: updates p_input, returns true if the interface needs to
68 bool VlcWrapper::UpdateInput()
72 p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
80 vlc_object_release( p_input );
89 /***************************
90 * input infos and control *
91 ***************************/
93 bool VlcWrapper::HasInput()
95 return ( p_input != NULL );
98 int VlcWrapper::InputStatus()
104 return p_input->stream.control.i_status;
107 int VlcWrapper::InputRate()
113 return p_input->stream.control.i_rate;
116 void VlcWrapper::InputSlower()
118 if( p_input != NULL )
120 input_SetStatus( p_input, INPUT_STATUS_SLOWER );
124 void VlcWrapper::InputFaster()
126 if( p_input != NULL )
128 input_SetStatus( p_input, INPUT_STATUS_FASTER );
132 BList * VlcWrapper::GetChannels( int i_cat )
138 const char* fieldName;
144 what = SELECT_CHANNEL;
145 fieldName = "channel";
150 what = SELECT_SUBTITLE;
151 fieldName = "subtitle";
158 vlc_mutex_lock( &p_input->stream.stream_lock );
160 /* find which track is currently playing */
161 es_descriptor_t *p_es = NULL;
162 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
164 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
165 p_es = p_input->stream.pp_selected_es[i];
168 /* build a list of all tracks */
169 BList *list = new BList( p_input->stream.i_es_number );
175 message = new BMessage( what );
176 message->AddInt32( fieldName, -1 );
177 menuItem = new BMenuItem( "None", message );
179 menuItem->SetMarked( true );
180 list->AddItem( menuItem );
182 for( i = 0; i < p_input->stream.i_es_number; i++ )
184 if( p_input->stream.pp_es[i]->i_cat == i_cat )
186 message = new BMessage( what );
187 message->AddInt32( fieldName, i );
188 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
189 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
191 trackName = "<unknown>";
192 menuItem = new BMenuItem( trackName, message );
193 if( p_input->stream.pp_es[i] == p_es )
194 menuItem->SetMarked( true );
195 list->AddItem( menuItem );
199 vlc_mutex_unlock( &p_input->stream.stream_lock );
206 void VlcWrapper::ToggleLanguage( int i_language )
208 es_descriptor_t * p_es = NULL;
209 es_descriptor_t * p_es_old = NULL;
211 vlc_mutex_lock( &p_input->stream.stream_lock );
212 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
214 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
216 p_es_old = p_input->stream.pp_selected_es[i];
220 vlc_mutex_unlock( &p_input->stream.stream_lock );
222 if( i_language != -1 )
224 p_es = p_input->stream.pp_es[i_language];
226 if( p_es == p_es_old )
232 input_ToggleES( p_input, p_es_old, VLC_FALSE );
236 input_ToggleES( p_input, p_es, VLC_TRUE );
240 void VlcWrapper::ToggleSubtitle( int i_subtitle )
242 es_descriptor_t * p_es = NULL;
243 es_descriptor_t * p_es_old = NULL;
245 vlc_mutex_lock( &p_input->stream.stream_lock );
246 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
248 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
250 p_es_old = p_input->stream.pp_selected_es[i];
254 vlc_mutex_unlock( &p_input->stream.stream_lock );
256 if( i_subtitle != -1 )
258 p_es = p_input->stream.pp_es[i_subtitle];
260 if( p_es == p_es_old )
266 input_ToggleES( p_input, p_es_old, VLC_FALSE );
270 input_ToggleES( p_input, p_es, VLC_TRUE );
274 const char * VlcWrapper::GetTimeAsString()
276 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
278 if( p_input == NULL )
283 input_OffsetToTime( p_input,
285 p_input->stream.p_selected_area->i_tell );
287 return(psz_currenttime);
290 float VlcWrapper::GetTimeAsFloat()
294 if( p_input != NULL )
296 f_time = (float)p_input->stream.p_selected_area->i_tell /
297 (float)p_input->stream.p_selected_area->i_size;
306 void VlcWrapper::SetTimeAsFloat( float f_position )
308 if( p_input != NULL )
311 (long long int)(p_input->stream.p_selected_area->i_size
312 * f_position / SEEKSLIDER_RANGE ),
317 bool VlcWrapper::IsPlaying()
320 bool playing = false;
323 switch ( p_input->stream.control.i_status )
346 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
348 if ( o_files && o_files->CountItems() > 0)
350 int size = PlaylistSize();
351 bool wasEmpty = ( size < 1 );
353 index = PLAYLIST_END;
354 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
356 /* delete current playlist */
359 for( int i = 0; i < size; i++ )
361 playlist_Delete( p_playlist, 0 );
366 int32 count = o_files->CountItems();
367 for ( int32 i = count - 1; i >= 0; i-- )
369 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
371 playlist_Add( p_playlist, o_file->String(),
373 if ( mode == PLAYLIST_INSERT )
378 // TODO: implement a user setting
379 // if to start automatically
380 /* eventually restart playing */
381 if( replace || wasEmpty )
383 playlist_Stop( p_playlist );
384 playlist_Play( p_playlist );
389 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
391 if( p_intf->p_sys->b_dvdmenus )
392 o_device.Prepend( "dvd:" );
394 o_device.Prepend( "dvdold:" );
395 playlist_Add( p_playlist, o_device.String(),
396 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
399 int VlcWrapper::PlaylistSize()
401 vlc_mutex_lock( &p_playlist->object_lock );
402 int i_size = p_playlist->i_size;
403 vlc_mutex_unlock( &p_playlist->object_lock );
407 char * VlcWrapper::PlaylistItemName( int i )
409 return p_playlist->pp_items[i]->psz_name;
412 int VlcWrapper::PlaylistCurrent()
414 return p_playlist->i_index;
417 bool VlcWrapper::PlaylistPlay()
421 playlist_Play( p_playlist );
426 void VlcWrapper::PlaylistPause()
430 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
434 void VlcWrapper::PlaylistStop()
436 playlist_Stop( p_playlist );
439 void VlcWrapper::PlaylistNext()
441 playlist_Next( p_playlist );
444 void VlcWrapper::PlaylistPrev()
446 playlist_Prev( p_playlist );
449 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
455 vlc_mutex_lock( &p_playlist->object_lock );
457 maxIndex = p_playlist->i_size;
459 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
463 vlc_mutex_unlock( &p_playlist->object_lock );
467 void VlcWrapper::PlaylistJumpTo( int pos )
469 playlist_Goto( p_playlist, pos );
472 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
474 if ( canSkipPrev && canSkipNext )
476 // init the parameters
477 *canSkipPrev = false;
478 *canSkipNext = false;
480 int pos = PlaylistCurrent();
481 int size = PlaylistSize();
483 // see if we have got a stream going
486 vlc_mutex_lock( &p_input->stream.stream_lock );
488 bool hasTitles = p_input->stream.i_area_nb > 1;
489 int numChapters = p_input->stream.p_selected_area->i_part_nb;
490 bool hasChapters = numChapters > 1;
491 // first, look for chapters
494 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
495 *canSkipNext = p_input->stream.p_selected_area->i_part <
496 p_input->stream.p_selected_area->i_part_nb - 1;
498 // if one of the skip capabilities is false,
499 // make it depend on titles instead
500 if ( !*canSkipPrev && hasTitles )
501 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
502 if ( !*canSkipNext && hasTitles )
503 *canSkipNext = p_input->stream.p_selected_area->i_id <
504 p_input->stream.i_area_nb - 1;
506 vlc_mutex_unlock( &p_input->stream.stream_lock );
508 // last but not least, make capabilities depend on playlist
510 *canSkipPrev = pos > 0;
512 *canSkipNext = pos < size - 1;
516 void VlcWrapper::NavigatePrev()
518 bool hasSkiped = false;
520 // see if we have got a stream going
523 // get information from stream (lock it while looking at it)
524 vlc_mutex_lock( &p_input->stream.stream_lock );
526 int currentTitle = p_input->stream.p_selected_area->i_id;
527 int currentChapter = p_input->stream.p_selected_area->i_part;
528 int numTitles = p_input->stream.i_area_nb;
529 bool hasTitles = numTitles > 1;
530 int numChapters = p_input->stream.p_selected_area->i_part_nb;
531 bool hasChapters = numChapters > 1;
533 vlc_mutex_unlock( &p_input->stream.stream_lock );
535 // first, look for chapters
538 // skip to the previous chapter
541 if ( currentChapter >= 0 )
543 ToggleChapter( currentChapter );
547 // if we couldn't skip chapters, try titles instead
548 if ( !hasSkiped && hasTitles )
550 // skip to the previous title
552 // disallow area 0 since it is used for video_ts.vob
553 if( currentTitle > 0 )
555 ToggleTitle(currentTitle);
561 // last but not least, skip to previous file
566 void VlcWrapper::NavigateNext()
568 bool hasSkiped = false;
570 // see if we have got a stream going
573 // get information from stream (lock it while looking at it)
574 vlc_mutex_lock( &p_input->stream.stream_lock );
576 int currentTitle = p_input->stream.p_selected_area->i_id;
577 int currentChapter = p_input->stream.p_selected_area->i_part;
578 int numTitles = p_input->stream.i_area_nb;
579 bool hasTitles = numTitles > 1;
580 int numChapters = p_input->stream.p_selected_area->i_part_nb;
581 bool hasChapters = numChapters > 1;
583 vlc_mutex_unlock( &p_input->stream.stream_lock );
585 // first, look for chapters
588 // skip to the next chapter
590 if ( currentChapter < numChapters )
592 ToggleChapter( currentChapter );
596 // if we couldn't skip chapters, try titles instead
597 if ( !hasSkiped && hasTitles )
599 // skip to the next title
601 // disallow area 0 since it is used for video_ts.vob
602 if ( currentTitle < numTitles - 1 )
604 ToggleTitle(currentTitle);
610 // last but not least, skip to next file
615 /*************************
616 * Playlist manipulation *
617 *************************/
621 VlcWrapper::PlaylistLock() const
623 // TODO: search and destroy -> deadlock!
627 vlc_mutex_lock( &p_playlist->object_lock );
635 VlcWrapper::PlaylistUnlock() const
637 // TODO: search and destroy -> deadlock!
639 vlc_mutex_unlock( &p_playlist->object_lock );
644 VlcWrapper::PlaylistItemAt( int index ) const
646 playlist_item_t* item = NULL;
647 if ( index >= 0 && index < p_playlist->i_size )
648 item = p_playlist->pp_items[index];
652 // PlaylistRemoveItem
654 VlcWrapper::PlaylistRemoveItem( int index ) const
656 playlist_item_t* copy = NULL;
657 // check if item exists at the provided index
658 if ( index >= 0 && index < p_playlist->i_size )
660 playlist_item_t* item = p_playlist->pp_items[index];
663 // make a copy of the removed item
664 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
665 // remove item from playlist (unfortunately, this frees it)
666 playlist_Delete( p_playlist, index );
672 // PlaylistRemoveItem
674 VlcWrapper::PlaylistRemoveItem( void* item ) const
676 playlist_item_t* copy = NULL;
677 for ( int32 i = 0; i < p_playlist->i_size; i++ )
679 if ( p_playlist->pp_items[i] == item )
681 copy = (playlist_item_t*)PlaylistRemoveItem( i );
690 VlcWrapper::PlaylistAddItem( void* item, int index ) const
694 playlist_AddItem( p_playlist, (playlist_item_t*)item,
695 PLAYLIST_INSERT, index );
697 // TODO: once playlist is returning useful info, return that instead
703 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
705 playlist_item_t* copy = NULL;
706 playlist_item_t* item = (playlist_item_t*)castToItem;
709 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
712 // make a copy of the item at index
713 copy->psz_name = strdup( item->psz_name );
714 copy->psz_uri = strdup( item->psz_uri );
715 copy->i_type = item->i_type;
716 copy->i_status = item->i_status;
717 copy->b_autodeletion = item->b_autodeletion;
723 // Careful! You need to know what you're doing here!
724 // The reason for having it, is to be able to deal with
725 // the rather lame list implementation of the playlist.
726 // It is meant to help manipulate the playlist with the above
727 // methods while keeping it valid.
729 // PlaylistSetPlaying
731 VlcWrapper::PlaylistSetPlaying( int index ) const
735 if ( index >= p_playlist->i_size )
736 index = p_playlist->i_size - 1;
737 p_playlist->i_index = index;
745 unsigned short VlcWrapper::GetVolume()
747 unsigned short i_volume;
748 aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
752 void VlcWrapper::SetVolume( int value )
754 if ( p_intf->p_sys->b_mute )
756 p_intf->p_sys->b_mute = 0;
758 aout_VolumeSet( p_intf, value );
761 void VlcWrapper::VolumeMute()
763 aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
764 aout_VolumeMute( p_intf, NULL );
765 p_intf->p_sys->b_mute = 1;
768 void VlcWrapper::VolumeRestore()
770 aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
771 p_intf->p_sys->b_mute = 0;
774 bool VlcWrapper::IsMuted()
776 return p_intf->p_sys->b_mute;
783 bool VlcWrapper::HasTitles()
789 return ( p_input->stream.i_area_nb > 1 );
792 BList * VlcWrapper::GetTitles()
796 vlc_mutex_lock( &p_input->stream.stream_lock );
798 BList *list = new BList( p_input->stream.i_area_nb );
802 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
804 message = new BMessage( TOGGLE_TITLE );
805 message->AddInt32( "index", i );
806 BString helper( "" );
808 menuItem = new BMenuItem( helper.String(), message );
809 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
810 list->AddItem( menuItem );
813 vlc_mutex_unlock( &p_input->stream.stream_lock );
820 void VlcWrapper::PrevTitle()
823 i_id = p_input->stream.p_selected_area->i_id - 1;
830 void VlcWrapper::NextTitle()
833 i_id = p_input->stream.p_selected_area->i_id + 1;
834 if( i_id < p_input->stream.i_area_nb )
840 void VlcWrapper::ToggleTitle(int i_title)
842 if( p_input != NULL )
844 input_ChangeArea( p_input,
845 p_input->stream.pp_areas[i_title] );
847 vlc_mutex_lock( &p_input->stream.stream_lock );
849 vlc_mutex_unlock( &p_input->stream.stream_lock );
853 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
859 vlc_mutex_lock( &p_input->stream.stream_lock );
861 maxIndex = p_input->stream.i_area_nb - 1;
863 currentIndex = p_input->stream.p_selected_area->i_id;
867 vlc_mutex_unlock( &p_input->stream.stream_lock );
871 bool VlcWrapper::HasChapters()
877 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
880 BList * VlcWrapper::GetChapters()
884 vlc_mutex_lock( &p_input->stream.stream_lock );
886 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
890 for( unsigned int i = 1;
891 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
893 message = new BMessage( TOGGLE_CHAPTER );
894 message->AddInt32( "index", i );
895 BString helper( "" );
897 menuItem = new BMenuItem( helper.String(), message );
898 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
899 list->AddItem( menuItem );
902 vlc_mutex_unlock( &p_input->stream.stream_lock );
909 void VlcWrapper::PrevChapter()
912 i_id = p_input->stream.p_selected_area->i_part - 1;
919 void VlcWrapper::NextChapter()
922 i_id = p_input->stream.p_selected_area->i_part + 1;
929 void VlcWrapper::ToggleChapter(int i_chapter)
931 if( p_input != NULL )
933 p_input->stream.p_selected_area->i_part = i_chapter;
934 input_ChangeArea( p_input,
935 p_input->stream.p_selected_area );
937 vlc_mutex_lock( &p_input->stream.stream_lock );
938 vlc_mutex_unlock( &p_input->stream.stream_lock );
942 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
948 vlc_mutex_lock( &p_input->stream.stream_lock );
950 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
952 currentIndex = p_input->stream.p_selected_area->i_part;
956 vlc_mutex_unlock( &p_input->stream.stream_lock );
964 void VlcWrapper::LoadSubFile( const char * psz_file )
966 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
969 void VlcWrapper::FilterChange()
974 vout_thread_t * p_vout;
975 vlc_mutex_lock( &p_input->stream.stream_lock );
977 // Warn the vout we are about to change the filter chain
978 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
982 p_vout->b_filter_change = VLC_TRUE;
983 vlc_object_release( p_vout );
986 // restart all video stream
987 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
989 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
990 ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
992 input_UnselectES( p_input, p_input->stream.pp_es[i] );
993 input_SelectES( p_input, p_input->stream.pp_es[i] );
996 vlc_mutex_unlock( &p_input->stream.stream_lock );