1 /*****************************************************************************
2 * InterfaceWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: InterfaceWindow.cpp,v 1.5 2001/10/29 11:07:09 tcastley 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 *****************************************************************************/
29 #include <kernel/OS.h>
30 #include <InterfaceKit.h>
32 #include <StorageKit.h>
35 #include <scsiprobe_driver.h>
47 #include "stream_control.h"
48 #include "input_ext-intf.h"
49 #include "interface.h"
51 #include "intf_playlist.h"
52 #include "audio_output.h"
55 /* BeOS interface headers */
57 #include "MediaControlView.h"
58 #include "InterfaceWindow.h"
59 #include "PlayListWindow.h"
61 /*****************************************************************************
63 *****************************************************************************/
65 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
66 intf_thread_t *p_interface )
67 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
68 B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
69 | B_ASYNCHRONOUS_CONTROLS )
73 BRect controlRect(0,0,0,0);
74 b_empty_playlist = (p_main->p_playlist->i_size < 0);
76 /* set the title bar */
77 SetName( "interface" );
80 /* set up the main menu */
82 menu_bar = new BMenuBar(controlRect, "main menu");
90 /* Add the file Menu */
92 menu_bar->AddItem( mFile = new BMenu( "File" ) );
93 menu_bar->ResizeToPreferred();
94 mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
95 new BMessage(OPEN_FILE), 'O') );
97 cd_menu = new CDMenu( "Open Disc" );
98 mFile->AddItem( cd_menu );
100 mFile->AddSeparatorItem();
101 mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
102 new BMessage(OPEN_PLAYLIST), 'P') );
104 mFile->AddSeparatorItem();
105 mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
106 new BMessage(B_ABOUT_REQUESTED), 'A') );
107 mItem->SetTarget( be_app );
108 mFile->AddItem(mItem = new BMenuItem( "Quit",
109 new BMessage(B_QUIT_REQUESTED), 'Q') );
111 /* Add the Audio menu */
112 menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
113 menu_bar->ResizeToPreferred();
114 mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
115 mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
117 /* Add the Navigation menu */
118 menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
119 menu_bar->ResizeToPreferred();
120 mNavigation->AddItem( new BMenuItem( "Prev Title",
121 new BMessage(PREV_TITLE)) );
122 mNavigation->AddItem( new BMenuItem( "Next Title",
123 new BMessage(NEXT_TITLE)) );
124 mNavigation->AddItem( new BMenuItem( "Prev Chapter",
125 new BMessage(PREV_CHAPTER)) );
126 mNavigation->AddItem( new BMenuItem( "Next Chapter",
127 new BMessage(NEXT_CHAPTER)) );
130 ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
131 controlRect = Bounds();
132 controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
134 p_mediaControl = new MediaControlView( controlRect );
135 p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
138 AddChild( p_mediaControl );
143 InterfaceWindow::~InterfaceWindow()
147 /*****************************************************************************
148 * InterfaceWindow::MessageReceived
149 *****************************************************************************/
150 void InterfaceWindow::MessageReceived( BMessage * p_message )
152 int vol_val = p_mediaControl->GetVolume(); // remember the current volume
153 int playback_status; // remember playback state
160 playback_status = p_intf->p_input->stream.control.i_status;
164 playback_status = UNDEF_S;
167 switch( p_message->what )
169 case B_ABOUT_REQUESTED:
170 alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
180 file_panel = new BFilePanel();
181 file_panel->SetTarget( this );
187 BRect rect(20,20,320,420);
188 PlayListWindow* playlist_window = new PlayListWindow(rect,
189 "Playlist", (playlist_t *)p_main->p_playlist);
190 playlist_window->Show();
194 const char *psz_device;
195 char psz_source[ B_FILE_NAME_LENGTH + 4 ];
196 if( p_message->FindString("device", &psz_device) != B_ERROR )
198 snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
199 "dvd:%s", psz_device );
200 psz_source[ strlen(psz_source) ] = '\0';
201 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, (char*)psz_source );
202 if( p_intf->p_input != NULL )
204 p_intf->p_input->b_eof = 1;
206 intf_PlaylistJumpto( p_main->p_playlist,
207 p_main->p_playlist->i_size - 1 );
212 // this currently stops playback not nicely
213 if( p_intf->p_input != NULL )
215 // silence the sound, otherwise very horrible
216 vlc_mutex_lock( &p_aout_bank->lock );
217 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
219 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
220 p_aout_bank->pp_aout[i_index]->i_volume = 0;
222 vlc_mutex_unlock( &p_aout_bank->lock );
225 /* end playing item */
226 p_intf->p_input->b_eof = 1;
228 /* update playlist */
229 vlc_mutex_lock( &p_main->p_playlist->change_lock );
230 p_main->p_playlist->i_index--;
231 p_main->p_playlist->b_stopped = 1;
232 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
234 p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
238 /* starts playing in normal mode */
241 /* toggle between pause and play */
242 if( p_intf->p_input != NULL )
244 /* pause if currently playing */
245 if( playback_status == PLAYING_S )
248 vlc_mutex_lock( &p_aout_bank->lock );
249 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
251 p_aout_bank->pp_aout[i_index]->i_savedvolume =
252 p_aout_bank->pp_aout[i_index]->i_volume;
253 p_aout_bank->pp_aout[i_index]->i_volume = 0;
255 vlc_mutex_unlock( &p_aout_bank->lock );
258 /* pause the movie */
259 input_SetStatus( p_intf->p_input, INPUT_STATUS_PAUSE );
260 vlc_mutex_lock( &p_main->p_playlist->change_lock );
261 p_main->p_playlist->b_stopped = 0;
262 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
266 /* Play after pausing */
267 /* Restore the volume */
268 vlc_mutex_lock( &p_aout_bank->lock );
269 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
271 p_aout_bank->pp_aout[i_index]->i_volume =
272 p_aout_bank->pp_aout[i_index]->i_savedvolume;
273 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
275 vlc_mutex_unlock( &p_aout_bank->lock );
279 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
280 p_main->p_playlist->b_stopped = 0;
285 /* Play a new file */
286 vlc_mutex_lock( &p_main->p_playlist->change_lock );
287 if( p_main->p_playlist->b_stopped )
289 if( p_main->p_playlist->i_size )
291 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
292 intf_PlaylistJumpto( p_main->p_playlist,
293 p_main->p_playlist->i_index );
294 p_main->p_playlist->b_stopped = 0;
298 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
305 /* cycle the fast playback modes */
306 if( p_intf->p_input != NULL )
309 vlc_mutex_lock( &p_aout_bank->lock );
310 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
312 p_aout_bank->pp_aout[i_index]->i_savedvolume =
313 p_aout_bank->pp_aout[i_index]->i_volume;
314 p_aout_bank->pp_aout[i_index]->i_volume = 0;
316 vlc_mutex_unlock( &p_aout_bank->lock );
319 /* change the fast play mode */
320 input_SetStatus( p_intf->p_input, INPUT_STATUS_FASTER );
321 vlc_mutex_lock( &p_main->p_playlist->change_lock );
322 p_main->p_playlist->b_stopped = 0;
323 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
328 /* cycle the slow playback modes */
329 if (p_intf->p_input != NULL )
332 vlc_mutex_lock( &p_aout_bank->lock );
333 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
335 p_aout_bank->pp_aout[i_index]->i_savedvolume =
336 p_aout_bank->pp_aout[i_index]->i_volume;
337 p_aout_bank->pp_aout[i_index]->i_volume = 0;
339 vlc_mutex_unlock( &p_aout_bank->lock );
342 /* change the slower play */
343 input_SetStatus( p_intf->p_input, INPUT_STATUS_SLOWER );
344 vlc_mutex_lock( &p_main->p_playlist->change_lock );
345 p_main->p_playlist->b_stopped = 0;
346 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
351 /* handled by semaphores */
355 /* adjust the volume */
356 vlc_mutex_lock( &p_aout_bank->lock );
357 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
359 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
361 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
365 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
368 vlc_mutex_unlock( &p_aout_bank->lock );
373 vlc_mutex_lock( &p_aout_bank->lock );
374 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
376 if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
378 p_aout_bank->pp_aout[i_index]->i_volume =
379 p_aout_bank->pp_aout[i_index]->i_savedvolume;
380 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
384 p_aout_bank->pp_aout[i_index]->i_savedvolume =
385 p_aout_bank->pp_aout[i_index]->i_volume;
386 p_aout_bank->pp_aout[i_index]->i_volume = 0;
389 vlc_mutex_unlock( &p_aout_bank->lock );
394 int32 i = p_message->FindInt32( "channel" );
397 input_ChangeES( p_intf->p_input, NULL, AUDIO_ES );
401 input_ChangeES( p_intf->p_input,
402 p_intf->p_input->stream.pp_es[i], AUDIO_ES );
407 case SELECT_SUBTITLE:
409 int32 i = p_message->FindInt32( "subtitle" );
412 input_ChangeES( p_intf->p_input, NULL, SPU_ES);
416 input_ChangeES( p_intf->p_input,
417 p_intf->p_input->stream.pp_es[i], SPU_ES );
423 input_area_t * p_area;
426 i_id = p_intf->p_input->stream.p_selected_area->i_id - 1;
428 /* Disallow area 0 since it is used for video_ts.vob */
431 p_area = p_intf->p_input->stream.pp_areas[i_id];
432 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
433 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
439 input_area_t * p_area;
442 i_id = p_intf->p_input->stream.p_selected_area->i_id + 1;
444 if( i_id < p_intf->p_input->stream.i_area_nb )
446 p_area = p_intf->p_input->stream.pp_areas[i_id];
447 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
448 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
454 input_area_t * p_area;
456 p_area = p_intf->p_input->stream.p_selected_area;
458 if( p_area->i_part > 0 )
461 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
462 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
468 input_area_t * p_area;
470 p_area = p_intf->p_input->stream.p_selected_area;
472 if( p_area->i_part > 0 )
475 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
476 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
480 case B_REFS_RECEIVED:
484 if( p_message->FindRef( "refs", &ref ) == B_OK )
487 intf_PlaylistAdd( p_main->p_playlist,
488 PLAYLIST_END, (char*)path.Path() );
489 if( p_intf->p_input != NULL )
491 p_intf->p_input->b_eof = 1;
493 intf_PlaylistJumpto( p_main->p_playlist,
494 p_main->p_playlist->i_size - 1 );
501 BWindow::MessageReceived( p_message );
507 /*****************************************************************************
508 * InterfaceWindow::updateInterface
509 *****************************************************************************/
510 void InterfaceWindow::updateInterface()
512 if ( p_intf->p_input )
514 if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
516 uint64 seekTo = (p_mediaControl->GetSeekTo() *
517 p_intf->p_input->stream.p_selected_area->i_size) / 100;
518 input_Seek( p_intf->p_input, seekTo);
522 p_mediaControl->SetStatus(p_intf->p_input->stream.control.i_status,
523 p_intf->p_input->stream.control.i_rate);
524 p_mediaControl->SetProgress(p_intf->p_input->stream.p_selected_area->i_tell,
525 p_intf->p_input->stream.p_selected_area->i_size);
529 if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) )
533 b_empty_playlist = !b_empty_playlist;
534 p_mediaControl->SetEnabled( !b_empty_playlist );
540 /*****************************************************************************
541 * InterfaceWindow::QuitRequested
542 *****************************************************************************/
543 bool InterfaceWindow::QuitRequested()
550 /*****************************************************************************
552 *****************************************************************************/
553 CDMenu::CDMenu(const char *name)
558 /*****************************************************************************
560 *****************************************************************************/
565 /*****************************************************************************
566 * CDMenu::AttachedToWindow
567 *****************************************************************************/
568 void CDMenu::AttachedToWindow(void)
570 while (RemoveItem((long int)0) != NULL); // remove all items
572 BMenu::AttachedToWindow();
575 /*****************************************************************************
577 *****************************************************************************/
578 int CDMenu::GetCD( const char *directory )
580 BVolumeRoster *volRoster;
585 char name[B_FILE_NAME_LENGTH];
589 volRoster = new BVolumeRoster();
591 dir = new BDirectory();
592 status = volRoster->GetNextVolume(vol);
593 status = vol->GetRootDirectory(dir);
594 while (status == B_NO_ERROR)
596 mounted = vol->GetName(name);
597 if ((mounted == B_OK) && /* Disk is currently Mounted */
598 (vol->IsReadOnly()) && /* Disk is a readonly medium */
599 (vol->IsPersistent()) ) /* not a volitile device */
602 fs_stat_dev(dev, &info);
604 msg = new BMessage( OPEN_DVD );
606 intf_Msg(info.device_name);
607 msg->AddString( "device", info.device_name );
608 BMenuItem *menu_item;
609 menu_item = new BMenuItem( name, msg );
610 AddItem( menu_item );
613 status = volRoster->GetNextVolume(vol);
621 if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
622 if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
626 /*****************************************************************************
627 * LanguageMenu::LanguageMenu
628 *****************************************************************************/
629 LanguageMenu::LanguageMenu(const char *name, int menu_kind,
630 intf_thread_t *p_interface)
634 p_intf = p_interface;
637 /*****************************************************************************
638 * LanguageMenu::~LanguageMenu
639 *****************************************************************************/
640 LanguageMenu::~LanguageMenu()
644 /*****************************************************************************
645 * LanguageMenu::AttachedToWindow
646 *****************************************************************************/
647 void LanguageMenu::AttachedToWindow(void)
649 while( RemoveItem((long int)0) != NULL )
651 ; // remove all items
656 BMenu::AttachedToWindow();
659 /*****************************************************************************
660 * LanguageMenu::GetChannels
661 *****************************************************************************/
662 int LanguageMenu::GetChannels()
668 es_descriptor_t *p_es = NULL;
670 /* Insert the null */
671 if( kind == AUDIO_ES ) //audio
673 msg = new BMessage(SELECT_CHANNEL);
674 msg->AddInt32("channel", -1);
678 msg = new BMessage(SELECT_SUBTITLE);
679 msg->AddInt32("subtitle", -1);
681 BMenuItem *menu_item;
682 menu_item = new BMenuItem("None", msg);
684 menu_item->SetMarked(TRUE);
686 if( p_intf->p_input == NULL )
692 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
693 for( i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++ )
695 if( kind == p_intf->p_input->stream.pp_selected_es[i]->i_cat )
697 p_es = p_intf->p_input->stream.pp_selected_es[i];
701 for( i = 0; i < p_intf->p_input->stream.i_es_number; i++ )
703 if( kind == p_intf->p_input->stream.pp_es[i]->i_cat )
705 psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
706 if( kind == AUDIO_ES ) //audio
708 msg = new BMessage(SELECT_CHANNEL);
709 msg->AddInt32("channel", i);
713 msg = new BMessage(SELECT_SUBTITLE);
714 msg->AddInt32("subtitle", i);
716 BMenuItem *menu_item;
717 menu_item = new BMenuItem(psz_name, msg);
719 b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
720 menu_item->SetMarked(b_active);
723 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );