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.25 2003/02/09 11:51:36 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 <audio_output.h>
37 #include <aout_internal.h>
40 #include "VlcWrapper.h"
44 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
48 p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
53 VlcWrapper::~VlcWrapper()
57 vlc_object_release( p_input );
61 vlc_object_release( p_playlist );
65 /* UpdateInput: updates p_input, returns true if the interface needs to
67 bool VlcWrapper::UpdateInput()
71 p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
79 vlc_object_release( p_input );
88 /***************************
89 * input infos and control *
90 ***************************/
92 bool VlcWrapper::HasInput()
94 return ( p_input != NULL );
97 int VlcWrapper::InputStatus()
103 return p_input->stream.control.i_status;
106 int VlcWrapper::InputRate()
112 return p_input->stream.control.i_rate;
115 void VlcWrapper::InputSlower()
117 if( p_input != NULL )
119 input_SetStatus( p_input, INPUT_STATUS_SLOWER );
123 void VlcWrapper::InputFaster()
125 if( p_input != NULL )
127 input_SetStatus( p_input, INPUT_STATUS_FASTER );
131 BList * VlcWrapper::GetChannels( int i_cat )
137 const char* fieldName;
143 what = SELECT_CHANNEL;
144 fieldName = "channel";
149 what = SELECT_SUBTITLE;
150 fieldName = "subtitle";
157 vlc_mutex_lock( &p_input->stream.stream_lock );
159 /* find which track is currently playing */
160 es_descriptor_t *p_es = NULL;
161 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
163 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
164 p_es = p_input->stream.pp_selected_es[i];
167 /* build a list of all tracks */
168 BList *list = new BList( p_input->stream.i_es_number );
174 message = new BMessage( what );
175 message->AddInt32( fieldName, -1 );
176 menuItem = new BMenuItem( "None", message );
178 menuItem->SetMarked( true );
179 list->AddItem( menuItem );
181 for( i = 0; i < p_input->stream.i_es_number; i++ )
183 if( p_input->stream.pp_es[i]->i_cat == i_cat )
185 message = new BMessage( what );
186 message->AddInt32( fieldName, i );
187 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
188 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
190 trackName = "<unknown>";
191 menuItem = new BMenuItem( trackName, message );
192 if( p_input->stream.pp_es[i] == p_es )
193 menuItem->SetMarked( true );
194 list->AddItem( menuItem );
198 vlc_mutex_unlock( &p_input->stream.stream_lock );
205 void VlcWrapper::ToggleLanguage( int i_language )
207 es_descriptor_t * p_es = NULL;
208 es_descriptor_t * p_es_old = NULL;
210 vlc_mutex_lock( &p_input->stream.stream_lock );
211 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
213 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
215 p_es_old = p_input->stream.pp_selected_es[i];
219 vlc_mutex_unlock( &p_input->stream.stream_lock );
221 if( i_language != -1 )
223 p_es = p_input->stream.pp_es[i_language];
225 if( p_es == p_es_old )
231 input_ToggleES( p_input, p_es_old, VLC_FALSE );
235 input_ToggleES( p_input, p_es, VLC_TRUE );
239 void VlcWrapper::ToggleSubtitle( int i_subtitle )
241 es_descriptor_t * p_es = NULL;
242 es_descriptor_t * p_es_old = NULL;
244 vlc_mutex_lock( &p_input->stream.stream_lock );
245 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
247 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
249 p_es_old = p_input->stream.pp_selected_es[i];
253 vlc_mutex_unlock( &p_input->stream.stream_lock );
255 if( i_subtitle != -1 )
257 p_es = p_input->stream.pp_es[i_subtitle];
259 if( p_es == p_es_old )
265 input_ToggleES( p_input, p_es_old, VLC_FALSE );
269 input_ToggleES( p_input, p_es, VLC_TRUE );
273 const char * VlcWrapper::GetTimeAsString()
275 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
277 if( p_input == NULL )
282 input_OffsetToTime( p_input,
284 p_input->stream.p_selected_area->i_tell );
286 return(psz_currenttime);
289 float VlcWrapper::GetTimeAsFloat()
293 if( p_input != NULL )
295 f_time = (float)p_input->stream.p_selected_area->i_tell /
296 (float)p_input->stream.p_selected_area->i_size;
305 void VlcWrapper::SetTimeAsFloat( float f_position )
307 if( p_input != NULL )
310 (long long int)(p_input->stream.p_selected_area->i_size
311 * f_position / SEEKSLIDER_RANGE ),
316 bool VlcWrapper::IsPlaying()
319 bool playing = false;
322 switch ( p_input->stream.control.i_status )
345 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
347 if ( o_files && o_files->CountItems() > 0)
349 int size = PlaylistSize();
350 bool wasEmpty = ( size < 1 );
352 index = PLAYLIST_END;
353 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
355 /* delete current playlist */
358 for( int i = 0; i < size; i++ )
360 playlist_Delete( p_playlist, 0 );
365 int32 count = o_files->CountItems();
366 for ( int32 i = count - 1; i >= 0; i-- )
368 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
370 playlist_Add( p_playlist, o_file->String(),
372 if ( mode == PLAYLIST_INSERT )
377 // TODO: implement a user setting
378 // if to start automatically
379 /* eventually restart playing */
380 if( replace || wasEmpty )
382 playlist_Stop( p_playlist );
383 playlist_Play( p_playlist );
388 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
390 if( p_intf->p_sys->b_dvdmenus )
391 o_device.Prepend( "dvd:" );
393 o_device.Prepend( "dvdold:" );
394 playlist_Add( p_playlist, o_device.String(),
395 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
398 int VlcWrapper::PlaylistSize()
400 vlc_mutex_lock( &p_playlist->object_lock );
401 int i_size = p_playlist->i_size;
402 vlc_mutex_unlock( &p_playlist->object_lock );
406 char * VlcWrapper::PlaylistItemName( int i )
408 return p_playlist->pp_items[i]->psz_name;
411 int VlcWrapper::PlaylistCurrent()
413 return p_playlist->i_index;
416 bool VlcWrapper::PlaylistPlay()
420 playlist_Play( p_playlist );
425 void VlcWrapper::PlaylistPause()
429 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
433 void VlcWrapper::PlaylistStop()
435 playlist_Stop( p_playlist );
438 void VlcWrapper::PlaylistNext()
440 playlist_Next( p_playlist );
443 void VlcWrapper::PlaylistPrev()
445 playlist_Prev( p_playlist );
448 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
454 vlc_mutex_lock( &p_playlist->object_lock );
456 maxIndex = p_playlist->i_size;
458 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
462 vlc_mutex_unlock( &p_playlist->object_lock );
466 void VlcWrapper::PlaylistJumpTo( int pos )
468 playlist_Goto( p_playlist, pos );
471 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
473 if ( canSkipPrev && canSkipNext )
475 // init the parameters
476 *canSkipPrev = false;
477 *canSkipNext = false;
479 int pos = PlaylistCurrent();
480 int size = PlaylistSize();
482 // see if we have got a stream going
485 vlc_mutex_lock( &p_input->stream.stream_lock );
487 bool hasTitles = p_input->stream.i_area_nb > 1;
488 int numChapters = p_input->stream.p_selected_area->i_part_nb;
489 bool hasChapters = numChapters > 1;
490 // first, look for chapters
493 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
494 *canSkipNext = p_input->stream.p_selected_area->i_part <
495 p_input->stream.p_selected_area->i_part_nb - 1;
497 // if one of the skip capabilities is false,
498 // make it depend on titles instead
499 if ( !*canSkipPrev && hasTitles )
500 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
501 if ( !*canSkipNext && hasTitles )
502 *canSkipNext = p_input->stream.p_selected_area->i_id <
503 p_input->stream.i_area_nb - 1;
505 vlc_mutex_unlock( &p_input->stream.stream_lock );
507 // last but not least, make capabilities depend on playlist
509 *canSkipPrev = pos > 0;
511 *canSkipNext = pos < size - 1;
515 void VlcWrapper::NavigatePrev()
517 bool hasSkiped = false;
519 // see if we have got a stream going
522 // get information from stream (lock it while looking at it)
523 vlc_mutex_lock( &p_input->stream.stream_lock );
525 int currentTitle = p_input->stream.p_selected_area->i_id;
526 int currentChapter = p_input->stream.p_selected_area->i_part;
527 int numTitles = p_input->stream.i_area_nb;
528 bool hasTitles = numTitles > 1;
529 int numChapters = p_input->stream.p_selected_area->i_part_nb;
530 bool hasChapters = numChapters > 1;
532 vlc_mutex_unlock( &p_input->stream.stream_lock );
534 // first, look for chapters
537 // skip to the previous chapter
540 if ( currentChapter >= 0 )
542 ToggleChapter( currentChapter );
546 // if we couldn't skip chapters, try titles instead
547 if ( !hasSkiped && hasTitles )
549 // skip to the previous title
551 // disallow area 0 since it is used for video_ts.vob
552 if( currentTitle > 0 )
554 ToggleTitle(currentTitle);
560 // last but not least, skip to previous file
565 void VlcWrapper::NavigateNext()
567 bool hasSkiped = false;
569 // see if we have got a stream going
572 // get information from stream (lock it while looking at it)
573 vlc_mutex_lock( &p_input->stream.stream_lock );
575 int currentTitle = p_input->stream.p_selected_area->i_id;
576 int currentChapter = p_input->stream.p_selected_area->i_part;
577 int numTitles = p_input->stream.i_area_nb;
578 bool hasTitles = numTitles > 1;
579 int numChapters = p_input->stream.p_selected_area->i_part_nb;
580 bool hasChapters = numChapters > 1;
582 vlc_mutex_unlock( &p_input->stream.stream_lock );
584 // first, look for chapters
587 // skip to the next chapter
589 if ( currentChapter < numChapters )
591 ToggleChapter( currentChapter );
595 // if we couldn't skip chapters, try titles instead
596 if ( !hasSkiped && hasTitles )
598 // skip to the next title
600 // disallow area 0 since it is used for video_ts.vob
601 if ( currentTitle < numTitles - 1 )
603 ToggleTitle(currentTitle);
609 // last but not least, skip to next file
614 /*************************
615 * Playlist manipulation *
616 *************************/
620 VlcWrapper::PlaylistLock() const
622 // TODO: search and destroy -> deadlock!
626 vlc_mutex_lock( &p_playlist->object_lock );
634 VlcWrapper::PlaylistUnlock() const
636 // TODO: search and destroy -> deadlock!
638 vlc_mutex_unlock( &p_playlist->object_lock );
643 VlcWrapper::PlaylistItemAt( int index ) const
645 playlist_item_t* item = NULL;
646 if ( index >= 0 && index < p_playlist->i_size )
647 item = p_playlist->pp_items[index];
651 // PlaylistRemoveItem
653 VlcWrapper::PlaylistRemoveItem( int index ) const
655 playlist_item_t* copy = NULL;
656 // check if item exists at the provided index
657 if ( index >= 0 && index < p_playlist->i_size )
659 playlist_item_t* item = p_playlist->pp_items[index];
662 // make a copy of the removed item
663 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
664 // remove item from playlist (unfortunately, this frees it)
665 playlist_Delete( p_playlist, index );
671 // PlaylistRemoveItem
673 VlcWrapper::PlaylistRemoveItem( void* item ) const
675 playlist_item_t* copy = NULL;
676 for ( int32 i = 0; i < p_playlist->i_size; i++ )
678 if ( p_playlist->pp_items[i] == item )
680 copy = (playlist_item_t*)PlaylistRemoveItem( i );
689 VlcWrapper::PlaylistAddItem( void* item, int index ) const
693 playlist_AddItem( p_playlist, (playlist_item_t*)item,
694 PLAYLIST_INSERT, index );
696 // TODO: once playlist is returning useful info, return that instead
702 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
704 playlist_item_t* copy = NULL;
705 playlist_item_t* item = (playlist_item_t*)castToItem;
708 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
711 // make a copy of the item at index
712 copy->psz_name = strdup( item->psz_name );
713 copy->psz_uri = strdup( item->psz_uri );
714 copy->i_type = item->i_type;
715 copy->i_status = item->i_status;
716 copy->b_autodeletion = item->b_autodeletion;
722 // Careful! You need to know what you're doing here!
723 // The reason for having it, is to be able to deal with
724 // the rather lame list implementation of the playlist.
725 // It is meant to help manipulate the playlist with the above
726 // methods while keeping it valid.
728 // PlaylistSetPlaying
730 VlcWrapper::PlaylistSetPlaying( int index ) const
734 if ( index >= p_playlist->i_size )
735 index = p_playlist->i_size - 1;
736 p_playlist->i_index = index;
744 unsigned short VlcWrapper::GetVolume()
746 unsigned short i_volume;
747 aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
751 void VlcWrapper::SetVolume( int value )
753 if ( p_intf->p_sys->b_mute )
755 p_intf->p_sys->b_mute = 0;
757 aout_VolumeSet( p_intf, value );
760 void VlcWrapper::VolumeMute()
762 aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
763 aout_VolumeMute( p_intf, NULL );
764 p_intf->p_sys->b_mute = 1;
767 void VlcWrapper::VolumeRestore()
769 aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
770 p_intf->p_sys->b_mute = 0;
773 bool VlcWrapper::IsMuted()
775 return p_intf->p_sys->b_mute;
782 bool VlcWrapper::HasTitles()
788 return ( p_input->stream.i_area_nb > 1 );
791 BList * VlcWrapper::GetTitles()
795 vlc_mutex_lock( &p_input->stream.stream_lock );
797 BList *list = new BList( p_input->stream.i_area_nb );
801 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
803 message = new BMessage( TOGGLE_TITLE );
804 message->AddInt32( "index", i );
805 BString helper( "" );
807 menuItem = new BMenuItem( helper.String(), message );
808 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
809 list->AddItem( menuItem );
812 vlc_mutex_unlock( &p_input->stream.stream_lock );
819 void VlcWrapper::PrevTitle()
822 i_id = p_input->stream.p_selected_area->i_id - 1;
829 void VlcWrapper::NextTitle()
832 i_id = p_input->stream.p_selected_area->i_id + 1;
833 if( i_id < p_input->stream.i_area_nb )
839 void VlcWrapper::ToggleTitle(int i_title)
841 if( p_input != NULL )
843 input_ChangeArea( p_input,
844 p_input->stream.pp_areas[i_title] );
846 vlc_mutex_lock( &p_input->stream.stream_lock );
848 vlc_mutex_unlock( &p_input->stream.stream_lock );
852 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
858 vlc_mutex_lock( &p_input->stream.stream_lock );
860 maxIndex = p_input->stream.i_area_nb - 1;
862 currentIndex = p_input->stream.p_selected_area->i_id;
866 vlc_mutex_unlock( &p_input->stream.stream_lock );
870 bool VlcWrapper::HasChapters()
876 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
879 BList * VlcWrapper::GetChapters()
883 vlc_mutex_lock( &p_input->stream.stream_lock );
885 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
889 for( unsigned int i = 1;
890 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
892 message = new BMessage( TOGGLE_CHAPTER );
893 message->AddInt32( "index", i );
894 BString helper( "" );
896 menuItem = new BMenuItem( helper.String(), message );
897 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
898 list->AddItem( menuItem );
901 vlc_mutex_unlock( &p_input->stream.stream_lock );
908 void VlcWrapper::PrevChapter()
911 i_id = p_input->stream.p_selected_area->i_part - 1;
918 void VlcWrapper::NextChapter()
921 i_id = p_input->stream.p_selected_area->i_part + 1;
928 void VlcWrapper::ToggleChapter(int i_chapter)
930 if( p_input != NULL )
932 p_input->stream.p_selected_area->i_part = i_chapter;
933 input_ChangeArea( p_input,
934 p_input->stream.p_selected_area );
936 vlc_mutex_lock( &p_input->stream.stream_lock );
937 vlc_mutex_unlock( &p_input->stream.stream_lock );
941 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
947 vlc_mutex_lock( &p_input->stream.stream_lock );
949 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
951 currentIndex = p_input->stream.p_selected_area->i_part;
955 vlc_mutex_unlock( &p_input->stream.stream_lock );
963 void VlcWrapper::LoadSubFile( const char * psz_file )
965 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
968 void VlcWrapper::FilterChange()
973 vout_thread_t * p_vout;
974 vlc_mutex_lock( &p_input->stream.stream_lock );
976 /* Warn the vout we are about to change the filter chain */
977 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
981 p_vout->b_filter_change = VLC_TRUE;
982 vlc_object_release( p_vout );
985 /* restart all video stream */
986 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
988 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
989 ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
991 input_UnselectES( p_input, p_input->stream.pp_es[i] );
992 input_SelectES( p_input, p_input->stream.pp_es[i] );
995 vlc_mutex_unlock( &p_input->stream.stream_lock );