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.24 2003/02/01 12:01:11 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 <audio_output.h>
37 #include <aout_internal.h>
40 #include "VlcWrapper.h"
44 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 vlc_object_release( p_aout );
70 /* UpdateInputAndAOut: updates p_input and p_aout, returns true if the
71 interface needs to be updated */
72 bool VlcWrapper::UpdateInputAndAOut()
76 p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
81 p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
89 vlc_object_release( p_input );
94 vlc_object_release( p_aout );
104 /***************************
105 * input infos and control *
106 ***************************/
108 bool VlcWrapper::HasInput()
110 return ( p_input != NULL );
113 int VlcWrapper::InputStatus()
119 return p_input->stream.control.i_status;
122 int VlcWrapper::InputRate()
128 return p_input->stream.control.i_rate;
131 void VlcWrapper::InputSlower()
133 if( p_input != NULL )
135 input_SetStatus( p_input, INPUT_STATUS_SLOWER );
139 void VlcWrapper::InputFaster()
141 if( p_input != NULL )
143 input_SetStatus( p_input, INPUT_STATUS_FASTER );
147 BList * VlcWrapper::GetChannels( int i_cat )
153 const char* fieldName;
159 what = SELECT_CHANNEL;
160 fieldName = "channel";
165 what = SELECT_SUBTITLE;
166 fieldName = "subtitle";
173 vlc_mutex_lock( &p_input->stream.stream_lock );
175 /* find which track is currently playing */
176 es_descriptor_t *p_es = NULL;
177 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
179 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
180 p_es = p_input->stream.pp_selected_es[i];
183 /* build a list of all tracks */
184 BList *list = new BList( p_input->stream.i_es_number );
190 message = new BMessage( what );
191 message->AddInt32( fieldName, -1 );
192 menuItem = new BMenuItem( "None", message );
194 menuItem->SetMarked( true );
195 list->AddItem( menuItem );
197 for( i = 0; i < p_input->stream.i_es_number; i++ )
199 if( p_input->stream.pp_es[i]->i_cat == i_cat )
201 message = new BMessage( what );
202 message->AddInt32( fieldName, i );
203 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
204 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
206 trackName = "<unknown>";
207 menuItem = new BMenuItem( trackName, message );
208 if( p_input->stream.pp_es[i] == p_es )
209 menuItem->SetMarked( true );
210 list->AddItem( menuItem );
214 vlc_mutex_unlock( &p_input->stream.stream_lock );
221 void VlcWrapper::ToggleLanguage( int i_language )
223 es_descriptor_t * p_es = NULL;
224 es_descriptor_t * p_es_old = NULL;
226 vlc_mutex_lock( &p_input->stream.stream_lock );
227 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
229 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
231 p_es_old = p_input->stream.pp_selected_es[i];
235 vlc_mutex_unlock( &p_input->stream.stream_lock );
237 if( i_language != -1 )
239 p_es = p_input->stream.pp_es[i_language];
241 if( p_es == p_es_old )
247 input_ToggleES( p_input, p_es_old, VLC_FALSE );
251 input_ToggleES( p_input, p_es, VLC_TRUE );
255 void VlcWrapper::ToggleSubtitle( int i_subtitle )
257 es_descriptor_t * p_es = NULL;
258 es_descriptor_t * p_es_old = NULL;
260 vlc_mutex_lock( &p_input->stream.stream_lock );
261 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
263 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
265 p_es_old = p_input->stream.pp_selected_es[i];
269 vlc_mutex_unlock( &p_input->stream.stream_lock );
271 if( i_subtitle != -1 )
273 p_es = p_input->stream.pp_es[i_subtitle];
275 if( p_es == p_es_old )
281 input_ToggleES( p_input, p_es_old, VLC_FALSE );
285 input_ToggleES( p_input, p_es, VLC_TRUE );
289 const char * VlcWrapper::GetTimeAsString()
291 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
293 if( p_input == NULL )
298 input_OffsetToTime( p_input,
300 p_input->stream.p_selected_area->i_tell );
302 return(psz_currenttime);
305 float VlcWrapper::GetTimeAsFloat()
309 if( p_input != NULL )
311 f_time = (float)p_input->stream.p_selected_area->i_tell /
312 (float)p_input->stream.p_selected_area->i_size;
321 void VlcWrapper::SetTimeAsFloat( float f_position )
323 if( p_input != NULL )
326 (long long int)(p_input->stream.p_selected_area->i_size
327 * f_position / SEEKSLIDER_RANGE ),
332 bool VlcWrapper::IsPlaying()
335 bool playing = false;
338 switch ( p_input->stream.control.i_status )
361 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
363 if ( o_files && o_files->CountItems() > 0)
365 int size = PlaylistSize();
366 bool wasEmpty = ( size < 1 );
368 index = PLAYLIST_END;
369 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
371 /* delete current playlist */
374 for( int i = 0; i < size; i++ )
376 playlist_Delete( p_playlist, 0 );
381 int32 count = o_files->CountItems();
382 for ( int32 i = count - 1; i >= 0; i-- )
384 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
386 playlist_Add( p_playlist, o_file->String(),
388 if ( mode == PLAYLIST_INSERT )
393 // TODO: implement a user setting
394 // if to start automatically
395 /* eventually restart playing */
396 if( replace || wasEmpty )
398 playlist_Stop( p_playlist );
399 playlist_Play( p_playlist );
404 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
406 if( p_intf->p_sys->b_dvdmenus )
407 o_device.Prepend( "dvd:" );
409 o_device.Prepend( "dvdold:" );
410 playlist_Add( p_playlist, o_device.String(),
411 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
414 int VlcWrapper::PlaylistSize()
416 vlc_mutex_lock( &p_playlist->object_lock );
417 int i_size = p_playlist->i_size;
418 vlc_mutex_unlock( &p_playlist->object_lock );
422 char * VlcWrapper::PlaylistItemName( int i )
424 return p_playlist->pp_items[i]->psz_name;
427 int VlcWrapper::PlaylistCurrent()
429 return p_playlist->i_index;
432 bool VlcWrapper::PlaylistPlay()
436 playlist_Play( p_playlist );
441 void VlcWrapper::PlaylistPause()
445 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
449 void VlcWrapper::PlaylistStop()
451 playlist_Stop( p_playlist );
454 void VlcWrapper::PlaylistNext()
456 playlist_Next( p_playlist );
459 void VlcWrapper::PlaylistPrev()
461 playlist_Prev( p_playlist );
464 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
470 vlc_mutex_lock( &p_playlist->object_lock );
472 maxIndex = p_playlist->i_size;
474 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
478 vlc_mutex_unlock( &p_playlist->object_lock );
482 void VlcWrapper::PlaylistJumpTo( int pos )
484 playlist_Goto( p_playlist, pos );
487 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
489 if ( canSkipPrev && canSkipNext )
491 // init the parameters
492 *canSkipPrev = false;
493 *canSkipNext = false;
495 int pos = PlaylistCurrent();
496 int size = PlaylistSize();
498 // see if we have got a stream going
501 vlc_mutex_lock( &p_input->stream.stream_lock );
503 bool hasTitles = p_input->stream.i_area_nb > 1;
504 int numChapters = p_input->stream.p_selected_area->i_part_nb;
505 bool hasChapters = numChapters > 1;
506 // first, look for chapters
509 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
510 *canSkipNext = p_input->stream.p_selected_area->i_part <
511 p_input->stream.p_selected_area->i_part_nb - 1;
513 // if one of the skip capabilities is false,
514 // make it depend on titles instead
515 if ( !*canSkipPrev && hasTitles )
516 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
517 if ( !*canSkipNext && hasTitles )
518 *canSkipNext = p_input->stream.p_selected_area->i_id <
519 p_input->stream.i_area_nb - 1;
521 vlc_mutex_unlock( &p_input->stream.stream_lock );
523 // last but not least, make capabilities depend on playlist
525 *canSkipPrev = pos > 0;
527 *canSkipNext = pos < size - 1;
531 void VlcWrapper::NavigatePrev()
533 bool hasSkiped = false;
535 // see if we have got a stream going
538 // get information from stream (lock it while looking at it)
539 vlc_mutex_lock( &p_input->stream.stream_lock );
541 int currentTitle = p_input->stream.p_selected_area->i_id;
542 int currentChapter = p_input->stream.p_selected_area->i_part;
543 int numTitles = p_input->stream.i_area_nb;
544 bool hasTitles = numTitles > 1;
545 int numChapters = p_input->stream.p_selected_area->i_part_nb;
546 bool hasChapters = numChapters > 1;
548 vlc_mutex_unlock( &p_input->stream.stream_lock );
550 // first, look for chapters
553 // skip to the previous chapter
556 if ( currentChapter >= 0 )
558 ToggleChapter( currentChapter );
562 // if we couldn't skip chapters, try titles instead
563 if ( !hasSkiped && hasTitles )
565 // skip to the previous title
567 // disallow area 0 since it is used for video_ts.vob
568 if( currentTitle > 0 )
570 ToggleTitle(currentTitle);
576 // last but not least, skip to previous file
581 void VlcWrapper::NavigateNext()
583 bool hasSkiped = false;
585 // see if we have got a stream going
588 // get information from stream (lock it while looking at it)
589 vlc_mutex_lock( &p_input->stream.stream_lock );
591 int currentTitle = p_input->stream.p_selected_area->i_id;
592 int currentChapter = p_input->stream.p_selected_area->i_part;
593 int numTitles = p_input->stream.i_area_nb;
594 bool hasTitles = numTitles > 1;
595 int numChapters = p_input->stream.p_selected_area->i_part_nb;
596 bool hasChapters = numChapters > 1;
598 vlc_mutex_unlock( &p_input->stream.stream_lock );
600 // first, look for chapters
603 // skip to the next chapter
605 if ( currentChapter < numChapters )
607 ToggleChapter( currentChapter );
611 // if we couldn't skip chapters, try titles instead
612 if ( !hasSkiped && hasTitles )
614 // skip to the next title
616 // disallow area 0 since it is used for video_ts.vob
617 if ( currentTitle < numTitles - 1 )
619 ToggleTitle(currentTitle);
625 // last but not least, skip to next file
630 /*************************
631 * Playlist manipulation *
632 *************************/
636 VlcWrapper::PlaylistLock() const
638 // TODO: search and destroy -> deadlock!
642 vlc_mutex_lock( &p_playlist->object_lock );
650 VlcWrapper::PlaylistUnlock() const
652 // TODO: search and destroy -> deadlock!
654 vlc_mutex_unlock( &p_playlist->object_lock );
659 VlcWrapper::PlaylistItemAt( int index ) const
661 playlist_item_t* item = NULL;
662 if ( index >= 0 && index < p_playlist->i_size )
663 item = p_playlist->pp_items[index];
667 // PlaylistRemoveItem
669 VlcWrapper::PlaylistRemoveItem( int index ) const
671 playlist_item_t* copy = NULL;
672 // check if item exists at the provided index
673 if ( index >= 0 && index < p_playlist->i_size )
675 playlist_item_t* item = p_playlist->pp_items[index];
678 // make a copy of the removed item
679 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
680 // remove item from playlist (unfortunately, this frees it)
681 playlist_Delete( p_playlist, index );
687 // PlaylistRemoveItem
689 VlcWrapper::PlaylistRemoveItem( void* item ) const
691 playlist_item_t* copy = NULL;
692 for ( int32 i = 0; i < p_playlist->i_size; i++ )
694 if ( p_playlist->pp_items[i] == item )
696 copy = (playlist_item_t*)PlaylistRemoveItem( i );
705 VlcWrapper::PlaylistAddItem( void* item, int index ) const
709 playlist_AddItem( p_playlist, (playlist_item_t*)item,
710 PLAYLIST_INSERT, index );
712 // TODO: once playlist is returning useful info, return that instead
718 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
720 playlist_item_t* copy = NULL;
721 playlist_item_t* item = (playlist_item_t*)castToItem;
724 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
727 // make a copy of the item at index
728 copy->psz_name = strdup( item->psz_name );
729 copy->psz_uri = strdup( item->psz_uri );
730 copy->i_type = item->i_type;
731 copy->i_status = item->i_status;
732 copy->b_autodeletion = item->b_autodeletion;
738 // Careful! You need to know what you're doing here!
739 // The reason for having it, is to be able to deal with
740 // the rather lame list implementation of the playlist.
741 // It is meant to help manipulate the playlist with the above
742 // methods while keeping it valid.
744 // PlaylistSetPlaying
746 VlcWrapper::PlaylistSetPlaying( int index ) const
750 if ( index >= p_playlist->i_size )
751 index = p_playlist->i_size - 1;
752 p_playlist->i_index = index;
760 bool VlcWrapper::HasAudio()
762 return( p_aout != NULL );
765 unsigned short VlcWrapper::GetVolume()
769 unsigned short i_volume;
770 aout_VolumeGet( p_aout, (audio_volume_t*)&i_volume );
776 void VlcWrapper::SetVolume(int value)
780 if ( p_intf->p_sys->b_mute )
782 p_intf->p_sys->b_mute = 0;
784 aout_VolumeSet( p_aout, value );
788 void VlcWrapper::VolumeMute()
792 aout_VolumeGet( p_aout, &p_intf->p_sys->i_saved_volume );
793 aout_VolumeMute( p_aout, NULL );
794 p_intf->p_sys->b_mute = 1;
798 void VlcWrapper::VolumeRestore()
802 aout_VolumeSet( p_aout, p_intf->p_sys->i_saved_volume );
803 p_intf->p_sys->b_mute = 0;
807 bool VlcWrapper::IsMuted()
809 return p_intf->p_sys->b_mute;
816 bool VlcWrapper::HasTitles()
822 return ( p_input->stream.i_area_nb > 1 );
825 BList * VlcWrapper::GetTitles()
829 vlc_mutex_lock( &p_input->stream.stream_lock );
831 BList *list = new BList( p_input->stream.i_area_nb );
835 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
837 message = new BMessage( TOGGLE_TITLE );
838 message->AddInt32( "index", i );
839 BString helper( "" );
841 menuItem = new BMenuItem( helper.String(), message );
842 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
843 list->AddItem( menuItem );
846 vlc_mutex_unlock( &p_input->stream.stream_lock );
853 void VlcWrapper::PrevTitle()
856 i_id = p_input->stream.p_selected_area->i_id - 1;
863 void VlcWrapper::NextTitle()
866 i_id = p_input->stream.p_selected_area->i_id + 1;
867 if( i_id < p_input->stream.i_area_nb )
873 void VlcWrapper::ToggleTitle(int i_title)
875 if( p_input != NULL )
877 input_ChangeArea( p_input,
878 p_input->stream.pp_areas[i_title] );
880 vlc_mutex_lock( &p_input->stream.stream_lock );
882 vlc_mutex_unlock( &p_input->stream.stream_lock );
886 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
892 vlc_mutex_lock( &p_input->stream.stream_lock );
894 maxIndex = p_input->stream.i_area_nb - 1;
896 currentIndex = p_input->stream.p_selected_area->i_id;
900 vlc_mutex_unlock( &p_input->stream.stream_lock );
904 bool VlcWrapper::HasChapters()
910 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
913 BList * VlcWrapper::GetChapters()
917 vlc_mutex_lock( &p_input->stream.stream_lock );
919 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
923 for( unsigned int i = 1;
924 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
926 message = new BMessage( TOGGLE_CHAPTER );
927 message->AddInt32( "index", i );
928 BString helper( "" );
930 menuItem = new BMenuItem( helper.String(), message );
931 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
932 list->AddItem( menuItem );
935 vlc_mutex_unlock( &p_input->stream.stream_lock );
942 void VlcWrapper::PrevChapter()
945 i_id = p_input->stream.p_selected_area->i_part - 1;
952 void VlcWrapper::NextChapter()
955 i_id = p_input->stream.p_selected_area->i_part + 1;
962 void VlcWrapper::ToggleChapter(int i_chapter)
964 if( p_input != NULL )
966 p_input->stream.p_selected_area->i_part = i_chapter;
967 input_ChangeArea( p_input,
968 p_input->stream.p_selected_area );
970 vlc_mutex_lock( &p_input->stream.stream_lock );
971 vlc_mutex_unlock( &p_input->stream.stream_lock );
975 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
981 vlc_mutex_lock( &p_input->stream.stream_lock );
983 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
985 currentIndex = p_input->stream.p_selected_area->i_part;
989 vlc_mutex_unlock( &p_input->stream.stream_lock );
997 void VlcWrapper::LoadSubFile( const char * psz_file )
999 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
1002 void VlcWrapper::FilterChange()
1007 vout_thread_t * p_vout;
1008 vlc_mutex_lock( &p_input->stream.stream_lock );
1010 /* Warn the vout we are about to change the filter chain */
1011 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
1015 p_vout->b_filter_change = VLC_TRUE;
1016 vlc_object_release( p_vout );
1019 /* restart all video stream */
1020 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
1022 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
1023 ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
1025 input_UnselectES( p_input, p_input->stream.pp_es[i] );
1026 input_SelectES( p_input, p_input->stream.pp_es[i] );
1029 vlc_mutex_unlock( &p_input->stream.stream_lock );