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.34 2003/06/08 16:04:30 titer 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"
44 const char * _AddEllipsis( char * string )
47 temp = (char*) calloc( strlen( string ) + 4, 1 );
48 sprintf( temp, "%s%s", string, B_UTF8_ELLIPSIS );
53 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
57 p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
62 VlcWrapper::~VlcWrapper()
65 vlc_object_release( p_input );
68 vlc_object_release( p_playlist );
71 /* UpdateInput: updates p_input */
72 void VlcWrapper::UpdateInput()
75 p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
81 vlc_object_release( p_input );
87 /***************************
88 * input infos and control *
89 ***************************/
91 bool VlcWrapper::HasInput()
93 return ( p_input != NULL );
96 int VlcWrapper::InputStatus()
101 return p_input->stream.control.i_status;
104 int VlcWrapper::InputRate()
109 return p_input->stream.control.i_rate;
112 void VlcWrapper::InputSetRate( int rate )
117 input_SetRate( p_input, rate );
120 BList * VlcWrapper::GetChannels( int i_cat )
126 const char* fieldName;
132 what = SELECT_CHANNEL;
133 fieldName = "channel";
138 what = SELECT_SUBTITLE;
139 fieldName = "subtitle";
146 vlc_mutex_lock( &p_input->stream.stream_lock );
148 /* find which track is currently playing */
149 es_descriptor_t *p_es = NULL;
150 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
152 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
153 p_es = p_input->stream.pp_selected_es[i];
156 /* build a list of all tracks */
157 BList *list = new BList( p_input->stream.i_es_number );
163 message = new BMessage( what );
164 message->AddInt32( fieldName, -1 );
165 menuItem = new BMenuItem( _("None"), message );
167 menuItem->SetMarked( true );
168 list->AddItem( menuItem );
170 for( i = 0; i < p_input->stream.i_es_number; i++ )
172 if( p_input->stream.pp_es[i]->i_cat == i_cat )
174 message = new BMessage( what );
175 message->AddInt32( fieldName, i );
176 if( !p_input->stream.pp_es[i]->psz_desc ||
177 !*p_input->stream.pp_es[i]->psz_desc )
178 trackName = _("<unknown>");
180 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
181 menuItem = new BMenuItem( trackName, message );
182 if( p_input->stream.pp_es[i] == p_es )
183 menuItem->SetMarked( true );
184 list->AddItem( menuItem );
188 vlc_mutex_unlock( &p_input->stream.stream_lock );
195 void VlcWrapper::ToggleLanguage( int i_language )
197 es_descriptor_t * p_es = NULL;
198 es_descriptor_t * p_es_old = NULL;
200 vlc_mutex_lock( &p_input->stream.stream_lock );
201 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
203 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
205 p_es_old = p_input->stream.pp_selected_es[i];
209 vlc_mutex_unlock( &p_input->stream.stream_lock );
211 if( i_language != -1 )
213 p_es = p_input->stream.pp_es[i_language];
215 if( p_es == p_es_old )
221 input_ToggleES( p_input, p_es_old, VLC_FALSE );
225 input_ToggleES( p_input, p_es, VLC_TRUE );
229 void VlcWrapper::ToggleSubtitle( int i_subtitle )
231 es_descriptor_t * p_es = NULL;
232 es_descriptor_t * p_es_old = NULL;
234 vlc_mutex_lock( &p_input->stream.stream_lock );
235 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
237 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
239 p_es_old = p_input->stream.pp_selected_es[i];
243 vlc_mutex_unlock( &p_input->stream.stream_lock );
245 if( i_subtitle != -1 )
247 p_es = p_input->stream.pp_es[i_subtitle];
249 if( p_es == p_es_old )
255 input_ToggleES( p_input, p_es_old, VLC_FALSE );
259 input_ToggleES( p_input, p_es, VLC_TRUE );
263 const char * VlcWrapper::GetTimeAsString()
265 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
267 if( p_input == NULL )
272 input_OffsetToTime( p_input,
274 p_input->stream.p_selected_area->i_tell );
276 return(psz_currenttime);
279 float VlcWrapper::GetTimeAsFloat()
283 if( p_input != NULL )
285 f_time = (float)p_input->stream.p_selected_area->i_tell /
286 (float)p_input->stream.p_selected_area->i_size;
295 void VlcWrapper::SetTimeAsFloat( float f_position )
297 if( p_input != NULL )
300 (long long)(p_input->stream.p_selected_area->i_size
301 * f_position / SEEKSLIDER_RANGE ),
306 bool VlcWrapper::IsPlaying()
309 bool playing = false;
312 switch ( p_input->stream.control.i_status )
335 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
337 if ( o_files && o_files->CountItems() > 0)
339 int size = PlaylistSize();
340 bool wasEmpty = ( size < 1 );
342 index = PLAYLIST_END;
343 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
345 /* delete current playlist */
348 for( int i = 0; i < size; i++ )
350 playlist_Delete( p_playlist, 0 );
355 int32 count = o_files->CountItems();
356 for ( int32 i = count - 1; i >= 0; i-- )
358 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
360 playlist_Add( p_playlist, o_file->String(),
362 if ( mode == PLAYLIST_INSERT )
367 // TODO: implement a user setting
368 // if to start automatically
369 /* eventually restart playing */
370 if( replace || wasEmpty )
372 playlist_Stop( p_playlist );
373 playlist_Play( p_playlist );
378 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
380 if( config_GetInt( p_intf, "beos-dvdmenus" ) )
381 o_device.Prepend( "dvdplay:" );
383 o_device.Prepend( "dvdold:" );
384 playlist_Add( p_playlist, o_device.String(),
385 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
388 int VlcWrapper::PlaylistSize()
390 vlc_mutex_lock( &p_playlist->object_lock );
391 int i_size = p_playlist->i_size;
392 vlc_mutex_unlock( &p_playlist->object_lock );
396 char * VlcWrapper::PlaylistItemName( int i )
398 return p_playlist->pp_items[i]->psz_name;
401 int VlcWrapper::PlaylistCurrent()
403 return p_playlist->i_index;
406 bool VlcWrapper::PlaylistPlay()
410 playlist_Play( p_playlist );
415 void VlcWrapper::PlaylistPause()
419 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
423 void VlcWrapper::PlaylistStop()
425 playlist_Stop( p_playlist );
428 void VlcWrapper::PlaylistNext()
430 playlist_Next( p_playlist );
433 void VlcWrapper::PlaylistPrev()
435 playlist_Prev( p_playlist );
438 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
444 vlc_mutex_lock( &p_playlist->object_lock );
446 maxIndex = p_playlist->i_size;
448 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
452 vlc_mutex_unlock( &p_playlist->object_lock );
456 void VlcWrapper::PlaylistJumpTo( int pos )
458 playlist_Goto( p_playlist, pos );
461 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
463 if ( canSkipPrev && canSkipNext )
465 // init the parameters
466 *canSkipPrev = false;
467 *canSkipNext = false;
469 int pos = PlaylistCurrent();
470 int size = PlaylistSize();
472 // see if we have got a stream going
475 vlc_mutex_lock( &p_input->stream.stream_lock );
477 bool hasTitles = p_input->stream.i_area_nb > 1;
478 int numChapters = p_input->stream.p_selected_area->i_part_nb;
479 bool hasChapters = numChapters > 1;
480 // first, look for chapters
483 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
484 *canSkipNext = p_input->stream.p_selected_area->i_part <
485 p_input->stream.p_selected_area->i_part_nb - 1;
487 // if one of the skip capabilities is false,
488 // make it depend on titles instead
489 if ( !*canSkipPrev && hasTitles )
490 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
491 if ( !*canSkipNext && hasTitles )
492 *canSkipNext = p_input->stream.p_selected_area->i_id <
493 p_input->stream.i_area_nb - 1;
495 vlc_mutex_unlock( &p_input->stream.stream_lock );
497 // last but not least, make capabilities depend on playlist
499 *canSkipPrev = pos > 0;
501 *canSkipNext = pos < size - 1;
505 void VlcWrapper::NavigatePrev()
507 bool hasSkiped = false;
509 // see if we have got a stream going
512 // get information from stream (lock it while looking at it)
513 vlc_mutex_lock( &p_input->stream.stream_lock );
515 int currentTitle = p_input->stream.p_selected_area->i_id;
516 int currentChapter = p_input->stream.p_selected_area->i_part;
517 int numTitles = p_input->stream.i_area_nb;
518 bool hasTitles = numTitles > 1;
519 int numChapters = p_input->stream.p_selected_area->i_part_nb;
520 bool hasChapters = numChapters > 1;
522 vlc_mutex_unlock( &p_input->stream.stream_lock );
524 // first, look for chapters
527 // skip to the previous chapter
530 if ( currentChapter >= 0 )
532 ToggleChapter( currentChapter );
536 // if we couldn't skip chapters, try titles instead
537 if ( !hasSkiped && hasTitles )
539 // skip to the previous title
541 // disallow area 0 since it is used for video_ts.vob
542 if( currentTitle > 0 )
544 ToggleTitle(currentTitle);
550 // last but not least, skip to previous file
555 void VlcWrapper::NavigateNext()
557 bool hasSkiped = false;
559 // see if we have got a stream going
562 // get information from stream (lock it while looking at it)
563 vlc_mutex_lock( &p_input->stream.stream_lock );
565 int currentTitle = p_input->stream.p_selected_area->i_id;
566 int currentChapter = p_input->stream.p_selected_area->i_part;
567 int numTitles = p_input->stream.i_area_nb;
568 bool hasTitles = numTitles > 1;
569 int numChapters = p_input->stream.p_selected_area->i_part_nb;
570 bool hasChapters = numChapters > 1;
572 vlc_mutex_unlock( &p_input->stream.stream_lock );
574 // first, look for chapters
577 // skip to the next chapter
579 if ( currentChapter < numChapters )
581 ToggleChapter( currentChapter );
585 // if we couldn't skip chapters, try titles instead
586 if ( !hasSkiped && hasTitles )
588 // skip to the next title
590 // disallow area 0 since it is used for video_ts.vob
591 if ( currentTitle < numTitles - 1 )
593 ToggleTitle(currentTitle);
599 // last but not least, skip to next file
604 /*************************
605 * Playlist manipulation *
606 *************************/
610 VlcWrapper::PlaylistLock() const
612 // TODO: search and destroy -> deadlock!
616 vlc_mutex_lock( &p_playlist->object_lock );
624 VlcWrapper::PlaylistUnlock() const
626 // TODO: search and destroy -> deadlock!
628 vlc_mutex_unlock( &p_playlist->object_lock );
633 VlcWrapper::PlaylistItemAt( int index ) const
635 playlist_item_t* item = NULL;
636 if ( index >= 0 && index < p_playlist->i_size )
637 item = p_playlist->pp_items[index];
641 // PlaylistRemoveItem
643 VlcWrapper::PlaylistRemoveItem( int index ) const
645 playlist_item_t* copy = NULL;
646 // check if item exists at the provided index
647 if ( index >= 0 && index < p_playlist->i_size )
649 playlist_item_t* item = p_playlist->pp_items[index];
652 // make a copy of the removed item
653 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
654 // remove item from playlist (unfortunately, this frees it)
655 playlist_Delete( p_playlist, index );
661 // PlaylistRemoveItem
663 VlcWrapper::PlaylistRemoveItem( void* item ) const
665 playlist_item_t* copy = NULL;
666 for ( int32 i = 0; i < p_playlist->i_size; i++ )
668 if ( p_playlist->pp_items[i] == item )
670 copy = (playlist_item_t*)PlaylistRemoveItem( i );
679 VlcWrapper::PlaylistAddItem( void* item, int index ) const
683 playlist_AddItem( p_playlist, (playlist_item_t*)item,
684 PLAYLIST_INSERT, index );
686 // TODO: once playlist is returning useful info, return that instead
692 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
694 playlist_item_t* copy = NULL;
695 playlist_item_t* item = (playlist_item_t*)castToItem;
698 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
701 // make a copy of the item at index
702 copy->psz_name = strdup( item->psz_name );
703 copy->psz_uri = strdup( item->psz_uri );
704 copy->i_type = item->i_type;
705 copy->i_status = item->i_status;
706 copy->b_autodeletion = item->b_autodeletion;
712 // Careful! You need to know what you're doing here!
713 // The reason for having it, is to be able to deal with
714 // the rather lame list implementation of the playlist.
715 // It is meant to help manipulate the playlist with the above
716 // methods while keeping it valid.
718 // PlaylistSetPlaying
720 VlcWrapper::PlaylistSetPlaying( int index ) const
724 if ( index >= p_playlist->i_size )
725 index = p_playlist->i_size - 1;
726 p_playlist->i_index = index;
734 unsigned short VlcWrapper::GetVolume()
736 unsigned short i_volume;
737 aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
741 void VlcWrapper::SetVolume( int value )
743 if ( p_intf->p_sys->b_mute )
745 p_intf->p_sys->b_mute = 0;
747 aout_VolumeSet( p_intf, value );
750 void VlcWrapper::VolumeMute()
752 aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
753 aout_VolumeMute( p_intf, NULL );
754 p_intf->p_sys->b_mute = 1;
757 void VlcWrapper::VolumeRestore()
759 aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
760 p_intf->p_sys->b_mute = 0;
763 bool VlcWrapper::IsMuted()
765 return p_intf->p_sys->b_mute;
772 bool VlcWrapper::IsUsingMenus()
777 vlc_mutex_lock( &p_playlist->object_lock );
778 if( p_playlist->i_index < 0 )
780 vlc_mutex_unlock( &p_playlist->object_lock );
784 char * psz_name = p_playlist->pp_items[p_playlist->i_index]->psz_name;
785 if( !strncmp( psz_name, "dvdplay:", 8 ) )
787 vlc_mutex_unlock( &p_playlist->object_lock );
790 vlc_mutex_unlock( &p_playlist->object_lock );
795 bool VlcWrapper::HasTitles()
800 return ( p_input->stream.i_area_nb > 1 );
803 BList * VlcWrapper::GetTitles()
807 vlc_mutex_lock( &p_input->stream.stream_lock );
809 BList *list = new BList( p_input->stream.i_area_nb );
813 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
815 message = new BMessage( TOGGLE_TITLE );
816 message->AddInt32( "index", i );
817 BString helper( "" );
819 menuItem = new BMenuItem( helper.String(), message );
820 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
821 list->AddItem( menuItem );
824 vlc_mutex_unlock( &p_input->stream.stream_lock );
831 void VlcWrapper::PrevTitle()
834 i_id = p_input->stream.p_selected_area->i_id - 1;
841 void VlcWrapper::NextTitle()
844 i_id = p_input->stream.p_selected_area->i_id + 1;
845 if( i_id < p_input->stream.i_area_nb )
851 void VlcWrapper::ToggleTitle(int i_title)
853 if( p_input != NULL )
855 input_ChangeArea( p_input,
856 p_input->stream.pp_areas[i_title] );
858 vlc_mutex_lock( &p_input->stream.stream_lock );
860 vlc_mutex_unlock( &p_input->stream.stream_lock );
864 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
870 vlc_mutex_lock( &p_input->stream.stream_lock );
872 maxIndex = p_input->stream.i_area_nb - 1;
874 currentIndex = p_input->stream.p_selected_area->i_id;
878 vlc_mutex_unlock( &p_input->stream.stream_lock );
882 bool VlcWrapper::HasChapters()
888 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
891 BList * VlcWrapper::GetChapters()
895 vlc_mutex_lock( &p_input->stream.stream_lock );
897 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
901 for( unsigned int i = 1;
902 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
904 message = new BMessage( TOGGLE_CHAPTER );
905 message->AddInt32( "index", i );
906 BString helper( "" );
908 menuItem = new BMenuItem( helper.String(), message );
909 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
910 list->AddItem( menuItem );
913 vlc_mutex_unlock( &p_input->stream.stream_lock );
920 void VlcWrapper::PrevChapter()
923 i_id = p_input->stream.p_selected_area->i_part - 1;
930 void VlcWrapper::NextChapter()
933 i_id = p_input->stream.p_selected_area->i_part + 1;
940 void VlcWrapper::ToggleChapter(int i_chapter)
942 if( p_input != NULL )
944 p_input->stream.p_selected_area->i_part = i_chapter;
945 input_ChangeArea( p_input,
946 p_input->stream.p_selected_area );
948 vlc_mutex_lock( &p_input->stream.stream_lock );
949 vlc_mutex_unlock( &p_input->stream.stream_lock );
953 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
959 vlc_mutex_lock( &p_input->stream.stream_lock );
961 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
963 currentIndex = p_input->stream.p_selected_area->i_part;
967 vlc_mutex_unlock( &p_input->stream.stream_lock );
975 void VlcWrapper::LoadSubFile( const char * psz_file )
977 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
980 void VlcWrapper::FilterChange()
985 vout_thread_t * p_vout;
986 vlc_mutex_lock( &p_input->stream.stream_lock );
988 // Warn the vout we are about to change the filter chain
989 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
993 p_vout->b_filter_change = VLC_TRUE;
994 vlc_object_release( p_vout );
997 // restart all video stream
998 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
1000 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
1001 ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
1003 input_UnselectES( p_input, p_input->stream.pp_es[i] );
1004 input_SelectES( p_input, p_input->stream.pp_es[i] );
1007 vlc_mutex_unlock( &p_input->stream.stream_lock );