1 /*****************************************************************************
2 * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port)
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
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()
104 var_Get( p_input, "state", &state );
108 int VlcWrapper::InputRate()
115 return p_input->stream.control.i_rate;
118 void VlcWrapper::InputSetRate( int rate )
124 var_SetInteger( p_input, "rate", rate );
127 BList * VlcWrapper::GetChannels( int i_cat )
133 const char* fieldName;
139 what = SELECT_CHANNEL;
140 fieldName = "channel";
145 what = SELECT_SUBTITLE;
146 fieldName = "subtitle";
153 vlc_mutex_lock( &p_input->stream.stream_lock );
155 /* find which track is currently playing */
156 es_descriptor_t *p_es = NULL;
157 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
159 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
160 p_es = p_input->stream.pp_selected_es[i];
163 /* build a list of all tracks */
164 BList *list = new BList( p_input->stream.i_es_number );
170 message = new BMessage( what );
171 message->AddInt32( fieldName, -1 );
172 menuItem = new BMenuItem( _("None"), message );
174 menuItem->SetMarked( true );
175 list->AddItem( menuItem );
177 for( i = 0; i < p_input->stream.i_es_number; i++ )
179 if( p_input->stream.pp_es[i]->i_cat == i_cat )
181 message = new BMessage( what );
182 message->AddInt32( fieldName, i );
183 if( !p_input->stream.pp_es[i]->psz_desc ||
184 !*p_input->stream.pp_es[i]->psz_desc )
185 trackName = _("<unknown>");
187 trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
188 menuItem = new BMenuItem( trackName, message );
189 if( p_input->stream.pp_es[i] == p_es )
190 menuItem->SetMarked( true );
191 list->AddItem( menuItem );
195 vlc_mutex_unlock( &p_input->stream.stream_lock );
202 void VlcWrapper::ToggleLanguage( int i_language )
205 var_SetInteger( p_input, "audio-es", -1 ); /* Disable audio */
207 var_SetInteger( p_input, "audio-es", i_language );
210 void VlcWrapper::ToggleSubtitle( int i_subtitle )
213 var_SetInteger( p_input, "spu-es", -1 ); /* Disable SPU */
215 var_SetInteger( p_input, "spu-es", i_subtitle );
218 const char * VlcWrapper::GetTimeAsString()
220 static char psz_time[ MSTRTIME_MAX_SIZE ];
228 var_Get( p_input, "time", &time );
230 mtime_t seconds = time.i_time / 1000000;
231 sprintf( psz_time, "%d:%02d:%02d",
232 (int) ( seconds / (60 * 60 ) ),
233 (int) ( ( seconds / 60 ) % 60 ),
234 (int) ( seconds % 60 ) );
239 float VlcWrapper::GetTimeAsFloat()
247 var_Get( p_input, "position", &pos );
251 void VlcWrapper::SetTimeAsFloat( float f_position )
259 pos.f_float = f_position / SEEKSLIDER_RANGE;
260 var_Set( p_input, "position", pos );
263 bool VlcWrapper::IsPlaying()
265 bool playing = false;
268 switch( p_input->stream.control.i_status )
289 void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
291 if ( o_files && o_files->CountItems() > 0)
293 int size = PlaylistSize();
294 bool wasEmpty = ( size < 1 );
296 index = PLAYLIST_END;
297 int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
299 /* delete current playlist */
302 for( int i = 0; i < size; i++ )
304 playlist_Delete( p_playlist, 0 );
309 int32 count = o_files->CountItems();
310 for ( int32 i = count - 1; i >= 0; i-- )
312 if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
314 playlist_Add( p_playlist, o_file->String(),
315 o_file->String(), mode, index );
316 if ( mode == PLAYLIST_INSERT )
321 // TODO: implement a user setting
322 // if to start automatically
323 /* eventually restart playing */
324 if( replace || wasEmpty )
326 playlist_Stop( p_playlist );
327 playlist_Play( p_playlist );
332 void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
334 if( config_GetInt( p_intf, "beos-dvdmenus" ) )
335 o_device.Prepend( "dvdplay:" );
337 o_device.Prepend( "dvdold:" );
338 playlist_Add( p_playlist, o_device.String(), o_device.String(),
339 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
342 int VlcWrapper::PlaylistSize()
344 vlc_mutex_lock( &p_playlist->object_lock );
345 int i_size = p_playlist->i_size;
346 vlc_mutex_unlock( &p_playlist->object_lock );
350 char * VlcWrapper::PlaylistItemName( int i )
352 return p_playlist->pp_items[i]->input.psz_name;
355 int VlcWrapper::PlaylistCurrent()
357 return p_playlist->i_index;
360 bool VlcWrapper::PlaylistPlay()
364 playlist_Play( p_playlist );
369 void VlcWrapper::PlaylistPause()
373 var_SetInteger( p_input, "state", PAUSE_S );
377 void VlcWrapper::PlaylistStop()
379 playlist_Stop( p_playlist );
382 void VlcWrapper::PlaylistNext()
384 playlist_Next( p_playlist );
387 void VlcWrapper::PlaylistPrev()
389 playlist_Prev( p_playlist );
392 void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
398 vlc_mutex_lock( &p_playlist->object_lock );
400 maxIndex = p_playlist->i_size;
402 currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
406 vlc_mutex_unlock( &p_playlist->object_lock );
410 void VlcWrapper::PlaylistJumpTo( int pos )
412 playlist_Goto( p_playlist, pos );
415 void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
417 if ( canSkipPrev && canSkipNext )
419 // init the parameters
420 *canSkipPrev = false;
421 *canSkipNext = false;
423 int pos = PlaylistCurrent();
424 int size = PlaylistSize();
426 // see if we have got a stream going
429 vlc_mutex_lock( &p_input->stream.stream_lock );
431 bool hasTitles = p_input->stream.i_area_nb > 1;
432 int numChapters = p_input->stream.p_selected_area->i_part_nb;
433 bool hasChapters = numChapters > 1;
434 // first, look for chapters
437 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
438 *canSkipNext = p_input->stream.p_selected_area->i_part <
439 p_input->stream.p_selected_area->i_part_nb - 1;
441 // if one of the skip capabilities is false,
442 // make it depend on titles instead
443 if ( !*canSkipPrev && hasTitles )
444 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
445 if ( !*canSkipNext && hasTitles )
446 *canSkipNext = p_input->stream.p_selected_area->i_id <
447 p_input->stream.i_area_nb - 1;
449 vlc_mutex_unlock( &p_input->stream.stream_lock );
451 // last but not least, make capabilities depend on playlist
453 *canSkipPrev = pos > 0;
455 *canSkipNext = pos < size - 1;
459 void VlcWrapper::NavigatePrev()
461 bool hasSkiped = false;
463 // see if we have got a stream going
466 // get information from stream (lock it while looking at it)
467 vlc_mutex_lock( &p_input->stream.stream_lock );
469 int currentTitle = p_input->stream.p_selected_area->i_id;
470 int currentChapter = p_input->stream.p_selected_area->i_part;
471 int numTitles = p_input->stream.i_area_nb;
472 bool hasTitles = numTitles > 1;
473 int numChapters = p_input->stream.p_selected_area->i_part_nb;
474 bool hasChapters = numChapters > 1;
476 vlc_mutex_unlock( &p_input->stream.stream_lock );
478 // first, look for chapters
481 // skip to the previous chapter
484 if ( currentChapter >= 0 )
486 ToggleChapter( currentChapter );
490 // if we couldn't skip chapters, try titles instead
491 if ( !hasSkiped && hasTitles )
493 // skip to the previous title
495 // disallow area 0 since it is used for video_ts.vob
496 if( currentTitle > 0 )
498 ToggleTitle(currentTitle);
504 // last but not least, skip to previous file
509 void VlcWrapper::NavigateNext()
511 bool hasSkiped = false;
513 // see if we have got a stream going
516 // get information from stream (lock it while looking at it)
517 vlc_mutex_lock( &p_input->stream.stream_lock );
519 int currentTitle = p_input->stream.p_selected_area->i_id;
520 int currentChapter = p_input->stream.p_selected_area->i_part;
521 int numTitles = p_input->stream.i_area_nb;
522 bool hasTitles = numTitles > 1;
523 int numChapters = p_input->stream.p_selected_area->i_part_nb;
524 bool hasChapters = numChapters > 1;
526 vlc_mutex_unlock( &p_input->stream.stream_lock );
528 // first, look for chapters
531 // skip to the next chapter
533 if ( currentChapter < numChapters )
535 ToggleChapter( currentChapter );
539 // if we couldn't skip chapters, try titles instead
540 if ( !hasSkiped && hasTitles )
542 // skip to the next title
544 // disallow area 0 since it is used for video_ts.vob
545 if ( currentTitle < numTitles - 1 )
547 ToggleTitle(currentTitle);
553 // last but not least, skip to next file
558 /*************************
559 * Playlist manipulation *
560 *************************/
564 VlcWrapper::PlaylistLock() const
566 // TODO: search and destroy -> deadlock!
570 vlc_mutex_lock( &p_playlist->object_lock );
578 VlcWrapper::PlaylistUnlock() const
580 // TODO: search and destroy -> deadlock!
582 vlc_mutex_unlock( &p_playlist->object_lock );
587 VlcWrapper::PlaylistItemAt( int index ) const
589 playlist_item_t* item = NULL;
590 if ( index >= 0 && index < p_playlist->i_size )
591 item = p_playlist->pp_items[index];
595 // PlaylistRemoveItem
597 VlcWrapper::PlaylistRemoveItem( int index ) const
599 playlist_item_t* copy = NULL;
600 // check if item exists at the provided index
601 if ( index >= 0 && index < p_playlist->i_size )
603 playlist_item_t* item = p_playlist->pp_items[index];
606 // make a copy of the removed item
607 copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
608 // remove item from playlist (unfortunately, this frees it)
609 playlist_Delete( p_playlist, index );
615 // PlaylistRemoveItem
617 VlcWrapper::PlaylistRemoveItem( void* item ) const
619 playlist_item_t* copy = NULL;
620 for ( int32 i = 0; i < p_playlist->i_size; i++ )
622 if ( p_playlist->pp_items[i] == item )
624 copy = (playlist_item_t*)PlaylistRemoveItem( i );
633 VlcWrapper::PlaylistAddItem( void* item, int index ) const
637 playlist_AddItem( p_playlist, (playlist_item_t*)item,
638 PLAYLIST_INSERT, index );
640 // TODO: once playlist is returning useful info, return that instead
646 VlcWrapper::PlaylistCloneItem( void* castToItem ) const
648 playlist_item_t* copy = NULL;
649 playlist_item_t* item = (playlist_item_t*)castToItem;
652 copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
655 // make a copy of the item at index
657 copy->input.psz_name = strdup( item->input.psz_name );
658 copy->input.psz_uri = strdup( item->input.psz_uri );
664 // Careful! You need to know what you're doing here!
665 // The reason for having it, is to be able to deal with
666 // the rather lame list implementation of the playlist.
667 // It is meant to help manipulate the playlist with the above
668 // methods while keeping it valid.
670 // PlaylistSetPlaying
672 VlcWrapper::PlaylistSetPlaying( int index ) const
676 if ( index >= p_playlist->i_size )
677 index = p_playlist->i_size - 1;
678 p_playlist->i_index = index;
686 unsigned short VlcWrapper::GetVolume()
688 unsigned short i_volume;
689 aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
693 void VlcWrapper::SetVolume( int value )
695 if ( p_intf->p_sys->b_mute )
697 p_intf->p_sys->b_mute = 0;
699 aout_VolumeSet( p_intf, value );
702 void VlcWrapper::VolumeMute()
704 aout_VolumeMute( p_intf, NULL );
705 p_intf->p_sys->b_mute = 1;
708 void VlcWrapper::VolumeRestore()
710 audio_volume_t dummy;
711 aout_VolumeMute( p_intf, &dummy );
712 p_intf->p_sys->b_mute = 0;
715 bool VlcWrapper::IsMuted()
717 return p_intf->p_sys->b_mute;
724 bool VlcWrapper::IsUsingMenus()
729 vlc_mutex_lock( &p_playlist->object_lock );
730 if( p_playlist->i_index < 0 )
732 vlc_mutex_unlock( &p_playlist->object_lock );
736 char * psz_name = p_playlist->pp_items[p_playlist->i_index]->input.psz_name;
737 if( !strncmp( psz_name, "dvdplay:", 8 ) )
739 vlc_mutex_unlock( &p_playlist->object_lock );
742 vlc_mutex_unlock( &p_playlist->object_lock );
747 bool VlcWrapper::HasTitles()
752 return ( p_input->stream.i_area_nb > 1 );
755 BList * VlcWrapper::GetTitles()
759 vlc_mutex_lock( &p_input->stream.stream_lock );
761 BList *list = new BList( p_input->stream.i_area_nb );
765 for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
767 message = new BMessage( TOGGLE_TITLE );
768 message->AddInt32( "index", i );
769 BString helper( "" );
771 menuItem = new BMenuItem( helper.String(), message );
772 menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
773 list->AddItem( menuItem );
776 vlc_mutex_unlock( &p_input->stream.stream_lock );
783 void VlcWrapper::PrevTitle()
786 i_id = p_input->stream.p_selected_area->i_id - 1;
793 void VlcWrapper::NextTitle()
796 i_id = p_input->stream.p_selected_area->i_id + 1;
797 if( i_id < p_input->stream.i_area_nb )
803 void VlcWrapper::ToggleTitle(int i_title)
805 if( p_input != NULL )
807 var_SetInteger( p_input, "title", i_title );
811 void VlcWrapper::TitleInfo( int32 ¤tIndex, int32 &maxIndex )
817 vlc_mutex_lock( &p_input->stream.stream_lock );
819 maxIndex = p_input->stream.i_area_nb - 1;
821 currentIndex = p_input->stream.p_selected_area->i_id;
825 vlc_mutex_unlock( &p_input->stream.stream_lock );
829 bool VlcWrapper::HasChapters()
835 return ( p_input->stream.p_selected_area->i_part_nb > 1 );
838 BList * VlcWrapper::GetChapters()
842 vlc_mutex_lock( &p_input->stream.stream_lock );
844 BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
848 for( unsigned int i = 1;
849 i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
851 message = new BMessage( TOGGLE_CHAPTER );
852 message->AddInt32( "index", i );
853 BString helper( "" );
855 menuItem = new BMenuItem( helper.String(), message );
856 menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
857 list->AddItem( menuItem );
860 vlc_mutex_unlock( &p_input->stream.stream_lock );
867 void VlcWrapper::PrevChapter()
870 i_id = p_input->stream.p_selected_area->i_part - 1;
877 void VlcWrapper::NextChapter()
880 i_id = p_input->stream.p_selected_area->i_part + 1;
887 void VlcWrapper::ToggleChapter(int i_chapter)
889 if( p_input != NULL )
891 var_SetInteger( p_input, "chapter", i_chapter );
895 void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex )
901 vlc_mutex_lock( &p_input->stream.stream_lock );
903 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
905 currentIndex = p_input->stream.p_selected_area->i_part;
909 vlc_mutex_unlock( &p_input->stream.stream_lock );
917 void VlcWrapper::LoadSubFile( const char * psz_file )
919 config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
922 void VlcWrapper::FilterChange()
927 vout_thread_t * p_vout;
928 vlc_mutex_lock( &p_input->stream.stream_lock );
930 // Warn the vout we are about to change the filter chain
931 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
935 p_vout->b_filter_change = VLC_TRUE;
936 vlc_object_release( p_vout );
939 // restart all video stream
940 for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
942 if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
943 ( p_input->stream.pp_es[i]->p_dec != NULL ) )
945 input_UnselectES( p_input, p_input->stream.pp_es[i] );
946 input_SelectES( p_input, p_input->stream.pp_es[i] );
949 vlc_mutex_unlock( &p_input->stream.stream_lock );