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.28 2003/04/23 15:18:24 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()
66 vlc_object_release( p_input );
70 vlc_object_release( p_playlist );
74 /* UpdateInput: updates p_input, returns true if the interface needs to
76 bool VlcWrapper::UpdateInput()
80 p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
88 vlc_object_release( p_input );
97 /***************************
98 * input infos and control *
99 ***************************/
101 bool VlcWrapper::HasInput()
103 return ( p_input != NULL );
106 int VlcWrapper::InputStatus()
112 return p_input->stream.control.i_status;
115 int VlcWrapper::InputRate()
121 return p_input->stream.control.i_rate;
124 void VlcWrapper::InputSlower()
126 if( p_input != NULL )
128 input_SetStatus( p_input, INPUT_STATUS_SLOWER );
132 void VlcWrapper::InputFaster()
134 if( p_input != NULL )
136 input_SetStatus( p_input, INPUT_STATUS_FASTER );
140 BList * VlcWrapper::GetChannels( int i_cat )
146 const char* fieldName;
152 what = SELECT_CHANNEL;
153 fieldName = "channel";
158 what = SELECT_SUBTITLE;
159 fieldName = "subtitle";
166 vlc_mutex_lock( &p_input->stream.stream_lock );
168 /* find which track is currently playing */
169 es_descriptor_t *p_es = NULL;
170 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
172 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
173 p_es = p_input->stream.pp_selected_es[i];
176 /* build a list of all tracks */
177 BList *list = new BList( p_input->stream.i_es_number );
183 message = new BMessage( what );
184 message->AddInt32( fieldName, -1 );
185 menuItem = new BMenuItem( _("None"), message );
187 menuItem->SetMarked( true );
188 list->AddItem( menuItem );
190 for( i = 0; i < p_input->stream.i_es_number; i++ )
192 if( p_input->stream.pp_es[i]->i_cat == i_cat )
194 message = new BMessage( what );
195 message->AddInt32( fieldName, i );
196 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
197 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
199 trackName = _("<unknown>");
200 menuItem = new BMenuItem( trackName, message );
201 if( p_input->stream.pp_es[i] == p_es )
202 menuItem->SetMarked( true );
203 list->AddItem( menuItem );
207 vlc_mutex_unlock( &p_input->stream.stream_lock );
214 void VlcWrapper::ToggleLanguage( int i_language )
216 es_descriptor_t * p_es = NULL;
217 es_descriptor_t * p_es_old = NULL;
219 vlc_mutex_lock( &p_input->stream.stream_lock );
220 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
222 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
224 p_es_old = p_input->stream.pp_selected_es[i];
228 vlc_mutex_unlock( &p_input->stream.stream_lock );
230 if( i_language != -1 )
232 p_es = p_input->stream.pp_es[i_language];
234 if( p_es == p_es_old )
240 input_ToggleES( p_input, p_es_old, VLC_FALSE );
244 input_ToggleES( p_input, p_es, VLC_TRUE );
248 void VlcWrapper::ToggleSubtitle( int i_subtitle )
250 es_descriptor_t * p_es = NULL;
251 es_descriptor_t * p_es_old = NULL;
253 vlc_mutex_lock( &p_input->stream.stream_lock );
254 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
256 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
258 p_es_old = p_input->stream.pp_selected_es[i];
262 vlc_mutex_unlock( &p_input->stream.stream_lock );
264 if( i_subtitle != -1 )
266 p_es = p_input->stream.pp_es[i_subtitle];
268 if( p_es == p_es_old )
274 input_ToggleES( p_input, p_es_old, VLC_FALSE );
278 input_ToggleES( p_input, p_es, VLC_TRUE );
282 const char * VlcWrapper::GetTimeAsString()
284 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
286 if( p_input == NULL )
291 input_OffsetToTime( p_input,
293 p_input->stream.p_selected_area->i_tell );
295 return(psz_currenttime);
298 float VlcWrapper::GetTimeAsFloat()
302 if( p_input != NULL )
304 f_time = (float)p_input->stream.p_selected_area->i_tell /
305 (float)p_input->stream.p_selected_area->i_size;
314 void VlcWrapper::SetTimeAsFloat( float f_position )
316 if( p_input != NULL )
319 (long long int)(p_input->stream.p_selected_area->i_size
320 * f_position / SEEKSLIDER_RANGE ),
325 bool VlcWrapper::IsPlaying()
328 bool playing = false;
331 switch ( p_input->stream.control.i_status )
354 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
356 if ( o_files && o_files->CountItems() > 0)
358 int size = PlaylistSize();
359 bool wasEmpty = ( size < 1 );
361 index = PLAYLIST_END;
362 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
364 /* delete current playlist */
367 for( int i = 0; i < size; i++ )
369 playlist_Delete( p_playlist, 0 );
374 int32 count = o_files->CountItems();
375 for ( int32 i = count - 1; i >= 0; i-- )
377 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
379 playlist_Add( p_playlist, o_file->String(),
381 if ( mode == PLAYLIST_INSERT )
386 // TODO: implement a user setting
387 // if to start automatically
388 /* eventually restart playing */
389 if( replace || wasEmpty )
391 playlist_Stop( p_playlist );
392 playlist_Play( p_playlist );
397 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
399 if( p_intf->p_sys->b_dvdmenus )
400 o_device.Prepend( "dvd:" );
402 o_device.Prepend( "dvdold:" );
403 playlist_Add( p_playlist, o_device.String(),
404 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
407 int VlcWrapper::PlaylistSize()
409 vlc_mutex_lock( &p_playlist->object_lock );
410 int i_size = p_playlist->i_size;
411 vlc_mutex_unlock( &p_playlist->object_lock );
415 char * VlcWrapper::PlaylistItemName( int i )
417 return p_playlist->pp_items[i]->psz_name;
420 int VlcWrapper::PlaylistCurrent()
422 return p_playlist->i_index;
425 bool VlcWrapper::PlaylistPlay()
429 playlist_Play( p_playlist );
434 void VlcWrapper::PlaylistPause()
438 input_SetStatus( p_input, INPUT_STATUS_PAUSE );
442 void VlcWrapper::PlaylistStop()
444 playlist_Stop( p_playlist );
447 void VlcWrapper::PlaylistNext()
449 playlist_Next( p_playlist );
452 void VlcWrapper::PlaylistPrev()
454 playlist_Prev( p_playlist );
457 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
463 vlc_mutex_lock( &p_playlist->object_lock );
465 maxIndex = p_playlist->i_size;
467 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
471 vlc_mutex_unlock( &p_playlist->object_lock );
475 void VlcWrapper::PlaylistJumpTo( int pos )
477 playlist_Goto( p_playlist, pos );
480 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
482 if ( canSkipPrev && canSkipNext )
484 // init the parameters
485 *canSkipPrev = false;
486 *canSkipNext = false;
488 int pos = PlaylistCurrent();
489 int size = PlaylistSize();
491 // see if we have got a stream going
494 vlc_mutex_lock( &p_input->stream.stream_lock );
496 bool hasTitles = p_input->stream.i_area_nb > 1;
497 int numChapters = p_input->stream.p_selected_area->i_part_nb;
498 bool hasChapters = numChapters > 1;
499 // first, look for chapters
502 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
503 *canSkipNext = p_input->stream.p_selected_area->i_part <
504 p_input->stream.p_selected_area->i_part_nb - 1;
506 // if one of the skip capabilities is false,
507 // make it depend on titles instead
508 if ( !*canSkipPrev && hasTitles )
509 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
510 if ( !*canSkipNext && hasTitles )
511 *canSkipNext = p_input->stream.p_selected_area->i_id <
512 p_input->stream.i_area_nb - 1;
514 vlc_mutex_unlock( &p_input->stream.stream_lock );
516 // last but not least, make capabilities depend on playlist
518 *canSkipPrev = pos > 0;
520 *canSkipNext = pos < size - 1;
524 void VlcWrapper::NavigatePrev()
526 bool hasSkiped = false;
528 // see if we have got a stream going
531 // get information from stream (lock it while looking at it)
532 vlc_mutex_lock( &p_input->stream.stream_lock );
534 int currentTitle = p_input->stream.p_selected_area->i_id;
535 int currentChapter = p_input->stream.p_selected_area->i_part;
536 int numTitles = p_input->stream.i_area_nb;
537 bool hasTitles = numTitles > 1;
538 int numChapters = p_input->stream.p_selected_area->i_part_nb;
539 bool hasChapters = numChapters > 1;
541 vlc_mutex_unlock( &p_input->stream.stream_lock );
543 // first, look for chapters
546 // skip to the previous chapter
549 if ( currentChapter >= 0 )
551 ToggleChapter( currentChapter );
555 // if we couldn't skip chapters, try titles instead
556 if ( !hasSkiped && hasTitles )
558 // skip to the previous title
560 // disallow area 0 since it is used for video_ts.vob
561 if( currentTitle > 0 )
563 ToggleTitle(currentTitle);
569 // last but not least, skip to previous file
574 void VlcWrapper::NavigateNext()
576 bool hasSkiped = false;
578 // see if we have got a stream going
581 // get information from stream (lock it while looking at it)
582 vlc_mutex_lock( &p_input->stream.stream_lock );
584 int currentTitle = p_input->stream.p_selected_area->i_id;
585 int currentChapter = p_input->stream.p_selected_area->i_part;
586 int numTitles = p_input->stream.i_area_nb;
587 bool hasTitles = numTitles > 1;
588 int numChapters = p_input->stream.p_selected_area->i_part_nb;
589 bool hasChapters = numChapters > 1;
591 vlc_mutex_unlock( &p_input->stream.stream_lock );
593 // first, look for chapters
596 // skip to the next chapter
598 if ( currentChapter < numChapters )
600 ToggleChapter( currentChapter );
604 // if we couldn't skip chapters, try titles instead
605 if ( !hasSkiped && hasTitles )
607 // skip to the next title
609 // disallow area 0 since it is used for video_ts.vob
610 if ( currentTitle < numTitles - 1 )
612 ToggleTitle(currentTitle);
618 // last but not least, skip to next file
623 /*************************
624 * Playlist manipulation *
625 *************************/
629 VlcWrapper::PlaylistLock() const
631 // TODO: search and destroy -> deadlock!
635 vlc_mutex_lock( &p_playlist->object_lock );
643 VlcWrapper::PlaylistUnlock() const
645 // TODO: search and destroy -> deadlock!
647 vlc_mutex_unlock( &p_playlist->object_lock );
652 VlcWrapper::PlaylistItemAt( int index ) const
654 playlist_item_t* item = NULL;
655 if ( index >= 0 && index < p_playlist->i_size )
656 item = p_playlist->pp_items[index];
660 // PlaylistRemoveItem
662 VlcWrapper::PlaylistRemoveItem( int index ) const
664 playlist_item_t* copy = NULL;
665 // check if item exists at the provided index
666 if ( index >= 0 && index < p_playlist->i_size )
668 playlist_item_t* item = p_playlist->pp_items[index];
671 // make a copy of the removed item
672 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
673 // remove item from playlist (unfortunately, this frees it)
674 playlist_Delete( p_playlist, index );
680 // PlaylistRemoveItem
682 VlcWrapper::PlaylistRemoveItem( void* item ) const
684 playlist_item_t* copy = NULL;
685 for ( int32 i = 0; i < p_playlist->i_size; i++ )
687 if ( p_playlist->pp_items[i] == item )
689 copy = (playlist_item_t*)PlaylistRemoveItem( i );
698 VlcWrapper::PlaylistAddItem( void* item, int index ) const
702 playlist_AddItem( p_playlist, (playlist_item_t*)item,
703 PLAYLIST_INSERT, index );
705 // TODO: once playlist is returning useful info, return that instead
711 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
713 playlist_item_t* copy = NULL;
714 playlist_item_t* item = (playlist_item_t*)castToItem;
717 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
720 // make a copy of the item at index
721 copy->psz_name = strdup( item->psz_name );
722 copy->psz_uri = strdup( item->psz_uri );
723 copy->i_type = item->i_type;
724 copy->i_status = item->i_status;
725 copy->b_autodeletion = item->b_autodeletion;
731 // Careful! You need to know what you're doing here!
732 // The reason for having it, is to be able to deal with
733 // the rather lame list implementation of the playlist.
734 // It is meant to help manipulate the playlist with the above
735 // methods while keeping it valid.
737 // PlaylistSetPlaying
739 VlcWrapper::PlaylistSetPlaying( int index ) const
743 if ( index >= p_playlist->i_size )
744 index = p_playlist->i_size - 1;
745 p_playlist->i_index = index;
753 unsigned short VlcWrapper::GetVolume()
755 unsigned short i_volume;
756 aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
760 void VlcWrapper::SetVolume( int value )
762 if ( p_intf->p_sys->b_mute )
764 p_intf->p_sys->b_mute = 0;
766 aout_VolumeSet( p_intf, value );
769 void VlcWrapper::VolumeMute()
771 aout_VolumeGet( p_intf, &p_intf->p_sys->i_saved_volume );
772 aout_VolumeMute( p_intf, NULL );
773 p_intf->p_sys->b_mute = 1;
776 void VlcWrapper::VolumeRestore()
778 aout_VolumeSet( p_intf, p_intf->p_sys->i_saved_volume );
779 p_intf->p_sys->b_mute = 0;
782 bool VlcWrapper::IsMuted()
784 return p_intf->p_sys->b_mute;
791 bool VlcWrapper::HasTitles()
797 return ( p_input->stream.i_area_nb > 1 );
800 BList * VlcWrapper::GetTitles()
804 vlc_mutex_lock( &p_input->stream.stream_lock );
806 BList *list = new BList( p_input->stream.i_area_nb );
810 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
812 message = new BMessage( TOGGLE_TITLE );
813 message->AddInt32( "index", i );
814 BString helper( "" );
816 menuItem = new BMenuItem( helper.String(), message );
817 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
818 list->AddItem( menuItem );
821 vlc_mutex_unlock( &p_input->stream.stream_lock );
828 void VlcWrapper::PrevTitle()
831 i_id = p_input->stream.p_selected_area->i_id - 1;
838 void VlcWrapper::NextTitle()
841 i_id = p_input->stream.p_selected_area->i_id + 1;
842 if( i_id < p_input->stream.i_area_nb )
848 void VlcWrapper::ToggleTitle(int i_title)
850 if( p_input != NULL )
852 input_ChangeArea( p_input,
853 p_input->stream.pp_areas[i_title] );
855 vlc_mutex_lock( &p_input->stream.stream_lock );
857 vlc_mutex_unlock( &p_input->stream.stream_lock );
861 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
867 vlc_mutex_lock( &p_input->stream.stream_lock );
869 maxIndex = p_input->stream.i_area_nb - 1;
871 currentIndex = p_input->stream.p_selected_area->i_id;
875 vlc_mutex_unlock( &p_input->stream.stream_lock );
879 bool VlcWrapper::HasChapters()
885 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
888 BList * VlcWrapper::GetChapters()
892 vlc_mutex_lock( &p_input->stream.stream_lock );
894 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
898 for( unsigned int i = 1;
899 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
901 message = new BMessage( TOGGLE_CHAPTER );
902 message->AddInt32( "index", i );
903 BString helper( "" );
905 menuItem = new BMenuItem( helper.String(), message );
906 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
907 list->AddItem( menuItem );
910 vlc_mutex_unlock( &p_input->stream.stream_lock );
917 void VlcWrapper::PrevChapter()
920 i_id = p_input->stream.p_selected_area->i_part - 1;
927 void VlcWrapper::NextChapter()
930 i_id = p_input->stream.p_selected_area->i_part + 1;
937 void VlcWrapper::ToggleChapter(int i_chapter)
939 if( p_input != NULL )
941 p_input->stream.p_selected_area->i_part = i_chapter;
942 input_ChangeArea( p_input,
943 p_input->stream.p_selected_area );
945 vlc_mutex_lock( &p_input->stream.stream_lock );
946 vlc_mutex_unlock( &p_input->stream.stream_lock );
950 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
956 vlc_mutex_lock( &p_input->stream.stream_lock );
958 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
960 currentIndex = p_input->stream.p_selected_area->i_part;
964 vlc_mutex_unlock( &p_input->stream.stream_lock );
972 void VlcWrapper::LoadSubFile( const char * psz_file )
974 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
977 void VlcWrapper::FilterChange()
982 vout_thread_t * p_vout;
983 vlc_mutex_lock( &p_input->stream.stream_lock );
985 // Warn the vout we are about to change the filter chain
986 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
990 p_vout->b_filter_change = VLC_TRUE;
991 vlc_object_release( p_vout );
994 // restart all video stream
995 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
997 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
998 ( p_input->stream.pp_es[i]->p_decoder_fifo != NULL ) )
1000 input_UnselectES( p_input, p_input->stream.pp_es[i] );
1001 input_SelectES( p_input, p_input->stream.pp_es[i] );
1004 vlc_mutex_unlock( &p_input->stream.stream_lock );