1 /*****************************************************************************
2 * InterfaceWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: InterfaceWindow.cpp,v 1.11 2001/12/30 07:09:54 sam Exp $
7 * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8 * Samuel Hocevar <sam@zoy.org>
9 * Tony Castley <tony@castley.net>
10 * Richard Shepherd <richard@rshepherd.demon.co.uk>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
28 #include <kernel/OS.h>
29 #include <InterfaceKit.h>
31 #include <StorageKit.h>
34 #include <scsiprobe_driver.h>
42 #include <videolan/vlc.h>
44 #include "stream_control.h"
45 #include "input_ext-intf.h"
47 #include "interface.h"
48 #include "intf_playlist.h"
50 #include "audio_output.h"
53 /* BeOS interface headers */
55 #include "MediaControlView.h"
56 #include "InterfaceWindow.h"
57 #include "PlayListWindow.h"
59 /*****************************************************************************
61 *****************************************************************************/
63 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
64 intf_thread_t *p_interface )
65 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
66 B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
67 | B_ASYNCHRONOUS_CONTROLS )
71 BRect controlRect(0,0,0,0);
72 b_empty_playlist = (p_main->p_playlist->i_size < 0);
74 /* set the title bar */
75 SetName( "interface" );
78 /* set up the main menu */
80 menu_bar = new BMenuBar(controlRect, "main menu");
88 /* Add the file Menu */
90 menu_bar->AddItem( mFile = new BMenu( "File" ) );
91 menu_bar->ResizeToPreferred();
92 mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
93 new BMessage(OPEN_FILE), 'O') );
95 cd_menu = new CDMenu( "Open Disc" );
96 mFile->AddItem( cd_menu );
98 mFile->AddSeparatorItem();
99 mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
100 new BMessage(OPEN_PLAYLIST), 'P') );
102 mFile->AddSeparatorItem();
103 mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
104 new BMessage(B_ABOUT_REQUESTED), 'A') );
105 mItem->SetTarget( be_app );
106 mFile->AddItem(mItem = new BMenuItem( "Quit",
107 new BMessage(B_QUIT_REQUESTED), 'Q') );
109 /* Add the Audio menu */
110 menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
111 menu_bar->ResizeToPreferred();
112 mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
113 mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
115 /* Add the Navigation menu */
116 menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
117 menu_bar->ResizeToPreferred();
118 mNavigation->AddItem( new BMenuItem( "Prev Title",
119 new BMessage(PREV_TITLE)) );
120 mNavigation->AddItem( new BMenuItem( "Next Title",
121 new BMessage(NEXT_TITLE)) );
122 mNavigation->AddItem( new BMenuItem( "Prev Chapter",
123 new BMessage(PREV_CHAPTER)) );
124 mNavigation->AddItem( new BMenuItem( "Next Chapter",
125 new BMessage(NEXT_CHAPTER)) );
128 ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
129 controlRect = Bounds();
130 controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
132 p_mediaControl = new MediaControlView( controlRect );
133 p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
136 AddChild( p_mediaControl );
141 InterfaceWindow::~InterfaceWindow()
145 /*****************************************************************************
146 * InterfaceWindow::MessageReceived
147 *****************************************************************************/
148 void InterfaceWindow::MessageReceived( BMessage * p_message )
150 int vol_val = p_mediaControl->GetVolume(); // remember the current volume
151 int playback_status; // remember playback state
158 playback_status = p_intf->p_input->stream.control.i_status;
162 playback_status = UNDEF_S;
165 switch( p_message->what )
167 case B_ABOUT_REQUESTED:
168 alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
178 file_panel = new BFilePanel();
179 file_panel->SetTarget( this );
185 BRect rect(20,20,320,420);
186 PlayListWindow* playlist_window = new PlayListWindow(rect,
187 "Playlist", (playlist_t *)p_main->p_playlist);
188 playlist_window->Show();
192 const char *psz_device;
193 char psz_source[ B_FILE_NAME_LENGTH + 4 ];
194 if( p_message->FindString("device", &psz_device) != B_ERROR )
196 snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
197 "dvd:%s", psz_device );
198 psz_source[ strlen(psz_source) ] = '\0';
199 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, (char*)psz_source );
200 if( p_intf->p_input != NULL )
202 p_intf->p_input->b_eof = 1;
204 intf_PlaylistJumpto( p_main->p_playlist,
205 p_main->p_playlist->i_size - 1 );
210 // this currently stops playback not nicely
211 if( p_intf->p_input != NULL )
213 // silence the sound, otherwise very horrible
214 vlc_mutex_lock( &p_aout_bank->lock );
215 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
217 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
218 p_aout_bank->pp_aout[i_index]->i_volume = 0;
220 vlc_mutex_unlock( &p_aout_bank->lock );
223 /* end playing item */
224 p_intf->p_input->b_eof = 1;
226 /* update playlist */
227 vlc_mutex_lock( &p_main->p_playlist->change_lock );
228 p_main->p_playlist->i_index--;
229 p_main->p_playlist->b_stopped = 1;
230 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
232 p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
236 /* starts playing in normal mode */
239 /* toggle between pause and play */
240 if( p_intf->p_input != NULL )
242 /* pause if currently playing */
243 if( playback_status == PLAYING_S )
246 vlc_mutex_lock( &p_aout_bank->lock );
247 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
249 p_aout_bank->pp_aout[i_index]->i_savedvolume =
250 p_aout_bank->pp_aout[i_index]->i_volume;
251 p_aout_bank->pp_aout[i_index]->i_volume = 0;
253 vlc_mutex_unlock( &p_aout_bank->lock );
256 /* pause the movie */
257 input_SetStatus( p_intf->p_input, INPUT_STATUS_PAUSE );
258 vlc_mutex_lock( &p_main->p_playlist->change_lock );
259 p_main->p_playlist->b_stopped = 0;
260 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
264 /* Play after pausing */
265 /* Restore the volume */
266 vlc_mutex_lock( &p_aout_bank->lock );
267 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
269 p_aout_bank->pp_aout[i_index]->i_volume =
270 p_aout_bank->pp_aout[i_index]->i_savedvolume;
271 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
273 vlc_mutex_unlock( &p_aout_bank->lock );
277 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
278 p_main->p_playlist->b_stopped = 0;
283 /* Play a new file */
284 vlc_mutex_lock( &p_main->p_playlist->change_lock );
285 if( p_main->p_playlist->b_stopped )
287 if( p_main->p_playlist->i_size )
289 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
290 intf_PlaylistJumpto( p_main->p_playlist,
291 p_main->p_playlist->i_index );
292 p_main->p_playlist->b_stopped = 0;
296 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
303 /* cycle the fast playback modes */
304 if( p_intf->p_input != NULL )
307 vlc_mutex_lock( &p_aout_bank->lock );
308 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
310 p_aout_bank->pp_aout[i_index]->i_savedvolume =
311 p_aout_bank->pp_aout[i_index]->i_volume;
312 p_aout_bank->pp_aout[i_index]->i_volume = 0;
314 vlc_mutex_unlock( &p_aout_bank->lock );
317 /* change the fast play mode */
318 input_SetStatus( p_intf->p_input, INPUT_STATUS_FASTER );
319 vlc_mutex_lock( &p_main->p_playlist->change_lock );
320 p_main->p_playlist->b_stopped = 0;
321 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
326 /* cycle the slow playback modes */
327 if (p_intf->p_input != NULL )
330 vlc_mutex_lock( &p_aout_bank->lock );
331 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
333 p_aout_bank->pp_aout[i_index]->i_savedvolume =
334 p_aout_bank->pp_aout[i_index]->i_volume;
335 p_aout_bank->pp_aout[i_index]->i_volume = 0;
337 vlc_mutex_unlock( &p_aout_bank->lock );
340 /* change the slower play */
341 input_SetStatus( p_intf->p_input, INPUT_STATUS_SLOWER );
342 vlc_mutex_lock( &p_main->p_playlist->change_lock );
343 p_main->p_playlist->b_stopped = 0;
344 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
349 /* handled by semaphores */
353 /* adjust the volume */
354 vlc_mutex_lock( &p_aout_bank->lock );
355 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
357 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
359 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
363 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
366 vlc_mutex_unlock( &p_aout_bank->lock );
371 vlc_mutex_lock( &p_aout_bank->lock );
372 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
374 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
376 p_aout_bank->pp_aout[i_index]->i_volume =
377 p_aout_bank->pp_aout[i_index]->i_savedvolume;
378 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
382 p_aout_bank->pp_aout[i_index]->i_savedvolume =
383 p_aout_bank->pp_aout[i_index]->i_volume;
384 p_aout_bank->pp_aout[i_index]->i_volume = 0;
387 vlc_mutex_unlock( &p_aout_bank->lock );
392 int32 i = p_message->FindInt32( "channel" );
395 input_ChangeES( p_intf->p_input, NULL, AUDIO_ES );
399 input_ChangeES( p_intf->p_input,
400 p_intf->p_input->stream.pp_es[i], AUDIO_ES );
405 case SELECT_SUBTITLE:
407 int32 i = p_message->FindInt32( "subtitle" );
410 input_ChangeES( p_intf->p_input, NULL, SPU_ES);
414 input_ChangeES( p_intf->p_input,
415 p_intf->p_input->stream.pp_es[i], SPU_ES );
421 input_area_t * p_area;
424 i_id = p_intf->p_input->stream.p_selected_area->i_id - 1;
426 /* Disallow area 0 since it is used for video_ts.vob */
429 p_area = p_intf->p_input->stream.pp_areas[i_id];
430 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
431 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
437 input_area_t * p_area;
440 i_id = p_intf->p_input->stream.p_selected_area->i_id + 1;
442 if( i_id < p_intf->p_input->stream.i_area_nb )
444 p_area = p_intf->p_input->stream.pp_areas[i_id];
445 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
446 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
452 input_area_t * p_area;
454 p_area = p_intf->p_input->stream.p_selected_area;
456 if( p_area->i_part > 0 )
459 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
460 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
466 input_area_t * p_area;
468 p_area = p_intf->p_input->stream.p_selected_area;
470 if( p_area->i_part > 0 )
473 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
474 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
478 case B_REFS_RECEIVED:
482 if( p_message->FindRef( "refs", &ref ) == B_OK )
485 intf_PlaylistAdd( p_main->p_playlist,
486 PLAYLIST_END, (char*)path.Path() );
487 if( p_intf->p_input != NULL )
489 p_intf->p_input->b_eof = 1;
491 intf_PlaylistJumpto( p_main->p_playlist,
492 p_main->p_playlist->i_size - 1 );
499 BWindow::MessageReceived( p_message );
505 /*****************************************************************************
506 * InterfaceWindow::updateInterface
507 *****************************************************************************/
508 void InterfaceWindow::updateInterface()
510 if ( p_intf->p_input )
512 if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
514 uint64 seekTo = (p_mediaControl->GetSeekTo() *
515 p_intf->p_input->stream.p_selected_area->i_size) / 100;
516 input_Seek( p_intf->p_input, seekTo);
520 p_mediaControl->SetStatus(p_intf->p_input->stream.control.i_status,
521 p_intf->p_input->stream.control.i_rate);
522 p_mediaControl->SetProgress(p_intf->p_input->stream.p_selected_area->i_tell,
523 p_intf->p_input->stream.p_selected_area->i_size);
527 if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) )
531 b_empty_playlist = !b_empty_playlist;
532 p_mediaControl->SetEnabled( !b_empty_playlist );
538 /*****************************************************************************
539 * InterfaceWindow::QuitRequested
540 *****************************************************************************/
541 bool InterfaceWindow::QuitRequested()
548 /*****************************************************************************
550 *****************************************************************************/
551 CDMenu::CDMenu(const char *name)
556 /*****************************************************************************
558 *****************************************************************************/
563 /*****************************************************************************
564 * CDMenu::AttachedToWindow
565 *****************************************************************************/
566 void CDMenu::AttachedToWindow(void)
568 while (RemoveItem((long int)0) != NULL); // remove all items
570 BMenu::AttachedToWindow();
573 /*****************************************************************************
575 *****************************************************************************/
576 int CDMenu::GetCD( const char *directory )
578 BVolumeRoster *volRoster;
583 char name[B_FILE_NAME_LENGTH];
587 volRoster = new BVolumeRoster();
589 dir = new BDirectory();
590 status = volRoster->GetNextVolume(vol);
591 status = vol->GetRootDirectory(dir);
592 while (status == B_NO_ERROR)
594 mounted = vol->GetName(name);
595 if ((mounted == B_OK) && /* Disk is currently Mounted */
596 (vol->IsReadOnly()) ) /* Disk is read-only */
599 fs_stat_dev(dev, &info);
603 i_dev = open( info.device_name, O_RDONLY );
607 if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
609 if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
612 msg = new BMessage( OPEN_DVD );
613 msg->AddString( "device", info.device_name );
614 BMenuItem *menu_item;
615 menu_item = new BMenuItem( name, msg );
616 AddItem( menu_item );
623 status = volRoster->GetNextVolume(vol);
627 /*****************************************************************************
628 * LanguageMenu::LanguageMenu
629 *****************************************************************************/
630 LanguageMenu::LanguageMenu(const char *name, int menu_kind,
631 intf_thread_t *p_interface)
635 p_intf = p_interface;
638 /*****************************************************************************
639 * LanguageMenu::~LanguageMenu
640 *****************************************************************************/
641 LanguageMenu::~LanguageMenu()
645 /*****************************************************************************
646 * LanguageMenu::AttachedToWindow
647 *****************************************************************************/
648 void LanguageMenu::AttachedToWindow(void)
650 while( RemoveItem((long int)0) != NULL )
652 ; // remove all items
657 BMenu::AttachedToWindow();
660 /*****************************************************************************
661 * LanguageMenu::GetChannels
662 *****************************************************************************/
663 int LanguageMenu::GetChannels()
669 es_descriptor_t *p_es = NULL;
671 /* Insert the null */
672 if( kind == AUDIO_ES ) //audio
674 msg = new BMessage(SELECT_CHANNEL);
675 msg->AddInt32("channel", -1);
679 msg = new BMessage(SELECT_SUBTITLE);
680 msg->AddInt32("subtitle", -1);
682 BMenuItem *menu_item;
683 menu_item = new BMenuItem("None", msg);
685 menu_item->SetMarked(TRUE);
687 if( p_intf->p_input == NULL )
693 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
694 for( i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++ )
696 if( kind == p_intf->p_input->stream.pp_selected_es[i]->i_cat )
698 p_es = p_intf->p_input->stream.pp_selected_es[i];
702 for( i = 0; i < p_intf->p_input->stream.i_es_number; i++ )
704 if( kind == p_intf->p_input->stream.pp_es[i]->i_cat )
706 psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
707 if( kind == AUDIO_ES ) //audio
709 msg = new BMessage(SELECT_CHANNEL);
710 msg->AddInt32("channel", i);
714 msg = new BMessage(SELECT_SUBTITLE);
715 msg->AddInt32("subtitle", i);
717 BMenuItem *menu_item;
718 menu_item = new BMenuItem(psz_name, msg);
720 b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
721 menu_item->SetMarked(b_active);
724 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );