00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <kernel/OS.h>
00030 #include <InterfaceKit.h>
00031 #include <AppKit.h>
00032 #include <StorageKit.h>
00033 #include <SupportKit.h>
00034 #include <malloc.h>
00035 #include <scsi.h>
00036 #include <scsiprobe_driver.h>
00037 #include <fs_info.h>
00038 #include <string.h>
00039
00040
00041 #include <vlc/vlc.h>
00042 #include <vlc/aout.h>
00043 #include <vlc/intf.h>
00044 #include <vlc/input.h>
00045
00046
00047 #include "MsgVals.h"
00048 #include "MediaControlView.h"
00049 #include "PlayListWindow.h"
00050 #include "PreferencesWindow.h"
00051 #include "MessagesWindow.h"
00052 #include "InterfaceWindow.h"
00053
00054 #define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps
00055 #define INTERFACE_LOCKING_TIMEOUT 5000
00056
00057
00058 bool
00059 make_sure_frame_is_on_screen( BRect& frame )
00060 {
00061 BScreen screen( B_MAIN_SCREEN_ID );
00062 if (frame.IsValid() && screen.IsValid()) {
00063 if (!screen.Frame().Contains(frame)) {
00064
00065 if (frame.Width() > screen.Frame().Width())
00066 frame.right -= frame.Width() - screen.Frame().Width() + 10.0;
00067 if (frame.Height() > screen.Frame().Height())
00068 frame.bottom -= frame.Height() - screen.Frame().Height() + 30.0;
00069
00070 if (frame.right > screen.Frame().right)
00071 frame.OffsetBy(-(frame.right - screen.Frame().right), 0.0);
00072 if (frame.bottom > screen.Frame().bottom)
00073 frame.OffsetBy(0.0, -(frame.bottom - screen.Frame().bottom));
00074 if (frame.left < screen.Frame().left)
00075 frame.OffsetBy((screen.Frame().left - frame.left), 0.0);
00076 if (frame.top < screen.Frame().top)
00077 frame.OffsetBy(0.0, (screen.Frame().top - frame.top));
00078 }
00079 return true;
00080 }
00081 return false;
00082 }
00083
00084
00085 void
00086 make_sure_frame_is_within_limits( BRect& frame, float minWidth, float minHeight,
00087 float maxWidth, float maxHeight )
00088 {
00089 if ( frame.Width() < minWidth )
00090 frame.right = frame.left + minWidth;
00091 if ( frame.Height() < minHeight )
00092 frame.bottom = frame.top + minHeight;
00093 if ( frame.Width() > maxWidth )
00094 frame.right = frame.left + maxWidth;
00095 if ( frame.Height() > maxHeight )
00096 frame.bottom = frame.top + maxHeight;
00097 }
00098
00099
00100 bool
00101 get_volume_info( BVolume& volume, BString& volumeName, bool& isCDROM, BString& deviceName )
00102 {
00103 bool success = false;
00104 isCDROM = false;
00105 deviceName = "";
00106 volumeName = "";
00107 char name[B_FILE_NAME_LENGTH];
00108 if ( volume.GetName( name ) >= B_OK )
00109 {
00110 volumeName = name;
00111 dev_t dev = volume.Device();
00112 fs_info info;
00113 if ( fs_stat_dev( dev, &info ) == B_OK )
00114 {
00115 success = true;
00116 deviceName = info.device_name;
00117 if ( volume.IsReadOnly() )
00118 {
00119 int i_dev = open( info.device_name, O_RDONLY );
00120 if ( i_dev >= 0 )
00121 {
00122 device_geometry g;
00123 if ( ioctl( i_dev, B_GET_GEOMETRY, &g, sizeof( g ) ) >= 0 )
00124 isCDROM = ( g.device_type == B_CD );
00125 close( i_dev );
00126 }
00127 }
00128 }
00129 }
00130 return success;
00131 }
00132
00133
00134 void
00135 collect_folder_contents( BDirectory& dir, BList& list, bool& deep, bool& asked, BEntry& entry )
00136 {
00137 while ( dir.GetNextEntry( &entry, true ) == B_OK )
00138 {
00139 if ( !entry.IsDirectory() )
00140 {
00141 BPath path;
00142
00143
00144
00145 if ( entry.GetPath( &path ) == B_OK )
00146 {
00147 BString* string = new BString( path.Path() );
00148 if ( !list.AddItem( string, 0 ) )
00149 delete string;
00150 }
00151 }
00152 else
00153 {
00154 if ( !asked )
00155 {
00156
00157 BAlert* alert = new BAlert( "sub-folders?",
00158 _("Open files from all sub-folders as well?"),
00159 _("Cancel"), _("Open"), NULL, B_WIDTH_AS_USUAL,
00160 B_IDEA_ALERT );
00161 int32 buttonIndex = alert->Go();
00162 deep = buttonIndex == 1;
00163 asked = true;
00164
00165 }
00166 if ( deep )
00167 {
00168 BDirectory subDir( &entry );
00169 if ( subDir.InitCheck() == B_OK )
00170 collect_folder_contents( subDir, list,
00171 deep, asked, entry );
00172 }
00173 }
00174 }
00175 }
00176
00177 static int PlaylistChanged( vlc_object_t *p_this, const char * psz_variable,
00178 vlc_value_t old_val, vlc_value_t new_val,
00179 void * param )
00180 {
00181 InterfaceWindow * w = (InterfaceWindow *) param;
00182 w->UpdatePlaylist();
00183 return VLC_SUCCESS;
00184 }
00185
00186
00187
00188
00189
00190 InterfaceWindow::InterfaceWindow( intf_thread_t * _p_intf, BRect frame,
00191 const char * name )
00192 : BWindow( frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
00193 B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
00194
00195
00196 p_intf( _p_intf ),
00197 p_input( NULL ),
00198 p_playlist( NULL ),
00199
00200 fFilePanel( NULL ),
00201 fLastUpdateTime( system_time() ),
00202 fSettings( new BMessage( 'sett' ) )
00203 {
00204 p_playlist = (playlist_t *)
00205 vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00206
00207 var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
00208 var_AddCallback( p_playlist, "item-change", PlaylistChanged, this );
00209 var_AddCallback( p_playlist, "item-append", PlaylistChanged, this );
00210 var_AddCallback( p_playlist, "item-deleted", PlaylistChanged, this );
00211 var_AddCallback( p_playlist, "playlist-current", PlaylistChanged, this );
00212
00213 char psz_tmp[1024];
00214 #define ADD_ELLIPSIS( a ) \
00215 memset( psz_tmp, 0, 1024 ); \
00216 snprintf( psz_tmp, 1024, "%s%s", a, B_UTF8_ELLIPSIS );
00217
00218 BScreen screen;
00219 BRect screen_rect = screen.Frame();
00220 BRect window_rect;
00221 window_rect.Set( ( screen_rect.right - PREFS_WINDOW_WIDTH ) / 2,
00222 ( screen_rect.bottom - PREFS_WINDOW_HEIGHT ) / 2,
00223 ( screen_rect.right + PREFS_WINDOW_WIDTH ) / 2,
00224 ( screen_rect.bottom + PREFS_WINDOW_HEIGHT ) / 2 );
00225 fPreferencesWindow = new PreferencesWindow( p_intf, window_rect, _("Preferences") );
00226 window_rect.Set( screen_rect.right - 500,
00227 screen_rect.top + 50,
00228 screen_rect.right - 150,
00229 screen_rect.top + 250 );
00230 fPlaylistWindow = new PlayListWindow( window_rect, _("Playlist"), this, p_intf );
00231 window_rect.Set( screen_rect.right - 550,
00232 screen_rect.top + 300,
00233 screen_rect.right - 150,
00234 screen_rect.top + 500 );
00235 fMessagesWindow = new MessagesWindow( p_intf, window_rect, _("Messages") );
00236
00237
00238 p_mediaControl = new MediaControlView( p_intf, BRect( 0.0, 0.0, 250.0, 50.0 ) );
00239 p_mediaControl->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
00240
00241 float width, height;
00242 p_mediaControl->GetPreferredSize( &width, &height );
00243
00244
00245 fMenuBar = new BMenuBar( BRect(0.0, 0.0, width, 15.0), "main menu",
00246 B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
00247
00248
00249 float menuWidth, menuHeight;
00250 fMenuBar->GetPreferredSize( &menuWidth, &menuHeight );
00251 fMenuBar->ResizeTo( width, menuHeight );
00252
00253 height += fMenuBar->Bounds().Height();
00254 ResizeTo( width, height );
00255
00256 p_mediaControl->MoveTo( fMenuBar->Bounds().LeftBottom() + BPoint(0.0, 1.0) );
00257 AddChild( fMenuBar );
00258
00259
00260
00261 BMenu* fileMenu = new BMenu( _("File") );
00262 fMenuBar->AddItem( fileMenu );
00263 ADD_ELLIPSIS( _("Open File") );
00264 fileMenu->AddItem( new BMenuItem( psz_tmp, new BMessage( OPEN_FILE ), 'O') );
00265 fileMenu->AddItem( new CDMenu( _("Open Disc") ) );
00266 ADD_ELLIPSIS( _("Open Subtitles") );
00267 fileMenu->AddItem( new BMenuItem( psz_tmp, new BMessage( LOAD_SUBFILE ) ) );
00268
00269 fileMenu->AddSeparatorItem();
00270 ADD_ELLIPSIS( _("About") );
00271 BMenuItem* item = new BMenuItem( psz_tmp, new BMessage( B_ABOUT_REQUESTED ), 'A');
00272 item->SetTarget( be_app );
00273 fileMenu->AddItem( item );
00274 fileMenu->AddItem( new BMenuItem( _("Quit"), new BMessage( B_QUIT_REQUESTED ), 'Q') );
00275
00276 fLanguageMenu = new LanguageMenu( p_intf, _("Language"), "audio-es" );
00277 fSubtitlesMenu = new LanguageMenu( p_intf, _("Subtitles"), "spu-es" );
00278
00279
00280 fAudioMenu = new BMenu( _("Audio") );
00281 fMenuBar->AddItem ( fAudioMenu );
00282 fAudioMenu->AddItem( fLanguageMenu );
00283 fAudioMenu->AddItem( fSubtitlesMenu );
00284
00285 fPrevTitleMI = new BMenuItem( _("Prev Title"), new BMessage( PREV_TITLE ) );
00286 fNextTitleMI = new BMenuItem( _("Next Title"), new BMessage( NEXT_TITLE ) );
00287 fPrevChapterMI = new BMenuItem( _("Previous chapter"), new BMessage( PREV_CHAPTER ) );
00288 fNextChapterMI = new BMenuItem( _("Next chapter"), new BMessage( NEXT_CHAPTER ) );
00289
00290
00291 fNavigationMenu = new BMenu( _("Navigation") );
00292 fMenuBar->AddItem( fNavigationMenu );
00293 fNavigationMenu->AddItem( fPrevTitleMI );
00294 fNavigationMenu->AddItem( fNextTitleMI );
00295 fNavigationMenu->AddItem( fTitleMenu = new TitleMenu( _("Go to Title"), p_intf ) );
00296 fNavigationMenu->AddSeparatorItem();
00297 fNavigationMenu->AddItem( fPrevChapterMI );
00298 fNavigationMenu->AddItem( fNextChapterMI );
00299 fNavigationMenu->AddItem( fChapterMenu = new ChapterMenu( _("Go to Chapter"), p_intf ) );
00300
00301
00302 fSpeedMenu = new BMenu( _("Speed") );
00303 fSpeedMenu->SetRadioMode( true );
00304 fSpeedMenu->AddItem(
00305 fHeighthMI = new BMenuItem( "1/8x", new BMessage( HEIGHTH_PLAY ) ) );
00306 fSpeedMenu->AddItem(
00307 fQuarterMI = new BMenuItem( "1/4x", new BMessage( QUARTER_PLAY ) ) );
00308 fSpeedMenu->AddItem(
00309 fHalfMI = new BMenuItem( "1/2x", new BMessage( HALF_PLAY ) ) );
00310 fSpeedMenu->AddItem(
00311 fNormalMI = new BMenuItem( "1x", new BMessage( NORMAL_PLAY ) ) );
00312 fSpeedMenu->AddItem(
00313 fTwiceMI = new BMenuItem( "2x", new BMessage( TWICE_PLAY ) ) );
00314 fSpeedMenu->AddItem(
00315 fFourMI = new BMenuItem( "4x", new BMessage( FOUR_PLAY ) ) );
00316 fSpeedMenu->AddItem(
00317 fHeightMI = new BMenuItem( "8x", new BMessage( HEIGHT_PLAY ) ) );
00318 fMenuBar->AddItem( fSpeedMenu );
00319
00320
00321 fShowMenu = new BMenu( _("Window") );
00322 ADD_ELLIPSIS( _("Playlist") );
00323 fShowMenu->AddItem( new BMenuItem( psz_tmp, new BMessage( OPEN_PLAYLIST ), 'P') );
00324 ADD_ELLIPSIS( _("Messages") );
00325 fShowMenu->AddItem( new BMenuItem( psz_tmp, new BMessage( OPEN_MESSAGES ), 'M' ) );
00326 ADD_ELLIPSIS( _("Preferences") );
00327 fShowMenu->AddItem( new BMenuItem( psz_tmp, new BMessage( OPEN_PREFERENCES ), 'S' ) );
00328 fMenuBar->AddItem( fShowMenu );
00329
00330
00331
00332
00333 AddChild( p_mediaControl );
00334
00335
00336 _SetMenusEnabled( false );
00337 p_mediaControl->SetEnabled( false );
00338
00339 _RestoreSettings();
00340
00341 Show();
00342 }
00343
00344 InterfaceWindow::~InterfaceWindow()
00345 {
00346 if( p_input )
00347 {
00348 vlc_object_release( p_input );
00349 }
00350 if( p_playlist )
00351 {
00352 vlc_object_release( p_playlist );
00353 }
00354 if( fPlaylistWindow )
00355 {
00356 fPlaylistWindow->ReallyQuit();
00357 }
00358 if( fMessagesWindow )
00359 {
00360 fMessagesWindow->ReallyQuit();
00361 }
00362 if( fPreferencesWindow )
00363 {
00364 fPreferencesWindow->ReallyQuit();
00365 }
00366 delete fFilePanel;
00367 delete fSettings;
00368 }
00369
00370
00371
00372
00373 void
00374 InterfaceWindow::FrameResized(float width, float height)
00375 {
00376 BRect r(Bounds());
00377 fMenuBar->MoveTo(r.LeftTop());
00378 fMenuBar->ResizeTo(r.Width(), fMenuBar->Bounds().Height());
00379 r.top += fMenuBar->Bounds().Height() + 1.0;
00380 p_mediaControl->MoveTo(r.LeftTop());
00381 p_mediaControl->ResizeTo(r.Width(), r.Height());
00382 }
00383
00384
00385
00386
00387 void InterfaceWindow::MessageReceived( BMessage * p_message )
00388 {
00389 switch( p_message->what )
00390 {
00391 case B_ABOUT_REQUESTED:
00392 {
00393 BAlert * alert;
00394
00395 alert = new BAlert( "VLC media player" VERSION,
00396 "VLC media player" VERSION " (BeOS interface)\n\n"
00397 "The VideoLAN team <[email protected]>\n"
00398 "http://www.videolan.org/", _("OK") );
00399 alert->Go();
00400 break;
00401 }
00402 case TOGGLE_ON_TOP:
00403 break;
00404
00405 case OPEN_FILE:
00406 _ShowFilePanel( B_REFS_RECEIVED, _("VLC media player: Open Media Files") );
00407 break;
00408
00409 case LOAD_SUBFILE:
00410 _ShowFilePanel( SUBFILE_RECEIVED, _("VLC media player: Open Subtitle File") );
00411 break;
00412
00413 case OPEN_PLAYLIST:
00414 if (fPlaylistWindow->Lock())
00415 {
00416 if (fPlaylistWindow->IsHidden())
00417 fPlaylistWindow->Show();
00418 else
00419 fPlaylistWindow->Activate();
00420 fPlaylistWindow->Unlock();
00421 }
00422 break;
00423
00424 case OPEN_DVD:
00425 {
00426 const char * psz_device;
00427 if( p_playlist &&
00428 p_message->FindString( "device", &psz_device ) == B_OK )
00429 {
00430 char psz_uri[1024];
00431 memset( psz_uri, 0, 1024 );
00432 snprintf( psz_uri, 1024, "dvdnav:%s", psz_device );
00433 playlist_Add( p_playlist, psz_uri, psz_device,
00434 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
00435 }
00436 UpdatePlaylist();
00437 }
00438 break;
00439
00440 case SUBFILE_RECEIVED:
00441 {
00442 entry_ref ref;
00443 if( p_message->FindRef( "refs", 0, &ref ) == B_OK )
00444 {
00445 BPath path( &ref );
00446 if ( path.InitCheck() == B_OK )
00447 config_PutPsz( p_intf, "sub-file", path.Path() );
00448 }
00449 break;
00450 }
00451
00452 case STOP_PLAYBACK:
00453 if( p_playlist )
00454 {
00455 playlist_Stop( p_playlist );
00456 }
00457 p_mediaControl->SetStatus(-1, INPUT_RATE_DEFAULT);
00458 break;
00459
00460 case START_PLAYBACK:
00461 case PAUSE_PLAYBACK:
00462 {
00463 vlc_value_t val;
00464 val.i_int = PLAYING_S;
00465 if( p_input )
00466 {
00467 var_Get( p_input, "state", &val );
00468 }
00469 if( p_input && val.i_int != PAUSE_S )
00470 {
00471 val.i_int = PAUSE_S;
00472 var_Set( p_input, "state", val );
00473 }
00474 else
00475 {
00476 playlist_Play( p_playlist );
00477 }
00478 break;
00479 }
00480 case HEIGHTH_PLAY:
00481 if( p_input )
00482 {
00483 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT * 8 );
00484 }
00485 break;
00486
00487 case QUARTER_PLAY:
00488 if( p_input )
00489 {
00490 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT * 4 );
00491 }
00492 break;
00493
00494 case HALF_PLAY:
00495 if( p_input )
00496 {
00497 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT * 2 );
00498 }
00499 break;
00500
00501 case NORMAL_PLAY:
00502 if( p_input )
00503 {
00504 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
00505 }
00506 break;
00507
00508 case TWICE_PLAY:
00509 if( p_input )
00510 {
00511 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT / 2 );
00512 }
00513 break;
00514
00515 case FOUR_PLAY:
00516 if( p_input )
00517 {
00518 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT / 4 );
00519 }
00520 break;
00521
00522 case HEIGHT_PLAY:
00523 if( p_input )
00524 {
00525 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT / 8 );
00526 }
00527 break;
00528
00529 case SEEK_PLAYBACK:
00530
00531 break;
00532
00533 case VOLUME_CHG:
00534 aout_VolumeSet( p_intf, p_mediaControl->GetVolume() );
00535 break;
00536
00537 case VOLUME_MUTE:
00538 aout_VolumeMute( p_intf, NULL );
00539 break;
00540
00541 case SELECT_CHANNEL:
00542 {
00543 int32 channel;
00544 if( p_input )
00545 {
00546 if( p_message->FindInt32( "audio-es", &channel ) == B_OK )
00547 {
00548 var_SetInteger( p_input, "audio-es", channel );
00549 }
00550 else if( p_message->FindInt32( "spu-es", &channel ) == B_OK )
00551 {
00552 var_SetInteger( p_input, "spu-es", channel );
00553 }
00554 }
00555 break;
00556 }
00557
00558 case PREV_TITLE:
00559 if( p_input )
00560 {
00561 var_SetVoid( p_input, "prev-title" );
00562 }
00563 break;
00564
00565 case NEXT_TITLE:
00566 if( p_input )
00567 {
00568 var_SetVoid( p_input, "next-title" );
00569 }
00570 break;
00571
00572 case TOGGLE_TITLE:
00573 {
00574 int32 index;
00575 if( p_input &&
00576 p_message->FindInt32( "index", &index ) == B_OK )
00577 {
00578 var_SetInteger( p_input, "title", index );
00579 }
00580 break;
00581 }
00582
00583 case PREV_CHAPTER:
00584 if( p_input )
00585 {
00586 var_SetVoid( p_input, "prev-chapter" );
00587 }
00588 break;
00589
00590 case NEXT_CHAPTER:
00591 if( p_input )
00592 {
00593 var_SetVoid( p_input, "next-chapter" );
00594 }
00595 break;
00596
00597 case TOGGLE_CHAPTER:
00598 {
00599 int32 index;
00600 if( p_input &&
00601 p_message->FindInt32( "index", &index ) == B_OK )
00602 {
00603 var_SetInteger( p_input, "chapter", index );
00604 }
00605 break;
00606 }
00607
00608 case PREV_FILE:
00609 if( p_playlist )
00610 {
00611 playlist_Prev( p_playlist );
00612 }
00613 break;
00614
00615 case NEXT_FILE:
00616 if( p_playlist )
00617 {
00618 playlist_Next( p_playlist );
00619 }
00620 break;
00621
00622 case NAVIGATE_PREV:
00623 if( p_input )
00624 {
00625 vlc_value_t val;
00626
00627
00628 if( !var_Get( p_input, "chapter", &val ) )
00629 {
00630 if( val.i_int > 1 )
00631 {
00632 var_SetVoid( p_input, "prev-chapter" );
00633 break;
00634 }
00635 }
00636
00637
00638 if( !var_Get( p_input, "title", &val ) )
00639 {
00640 if( val.i_int > 1 )
00641 {
00642 var_SetVoid( p_input, "prev-title" );
00643 break;
00644 }
00645 }
00646
00647
00648 if( p_playlist )
00649 {
00650 playlist_Prev( p_playlist );
00651 }
00652 }
00653 break;
00654
00655 case NAVIGATE_NEXT:
00656 if( p_input )
00657 {
00658 vlc_value_t val, val_list;
00659
00660
00661 if( !var_Get( p_input, "chapter", &val ) )
00662 {
00663 var_Change( p_input, "chapter", VLC_VAR_GETCHOICES,
00664 &val_list, NULL );
00665 if( val_list.p_list->i_count > val.i_int )
00666 {
00667 var_Change( p_input, "chapter", VLC_VAR_FREELIST,
00668 &val_list, NULL );
00669 var_SetVoid( p_input, "next-chapter" );
00670 break;
00671 }
00672 var_Change( p_input, "chapter", VLC_VAR_FREELIST,
00673 &val_list, NULL );
00674 }
00675
00676
00677 if( !var_Get( p_input, "title", &val ) )
00678 {
00679 var_Change( p_input, "title", VLC_VAR_GETCHOICES,
00680 &val_list, NULL );
00681 if( val_list.p_list->i_count > val.i_int )
00682 {
00683 var_Change( p_input, "title", VLC_VAR_FREELIST,
00684 &val_list, NULL );
00685 var_SetVoid( p_input, "next-title" );
00686 break;
00687 }
00688 var_Change( p_input, "title", VLC_VAR_FREELIST,
00689 &val_list, NULL );
00690 }
00691
00692
00693 if( p_playlist )
00694 {
00695 playlist_Next( p_playlist );
00696 }
00697 }
00698 break;
00699
00700
00701 case MSG_SOUNDPLAY:
00702
00703
00704 {
00705 const char* path;
00706 for ( int32 i = 0; p_message->FindString( "path", i, &path ) == B_OK; i++ )
00707 {
00708 entry_ref ref;
00709 if ( get_ref_for_path( path, &ref ) == B_OK )
00710 p_message->AddRef( "refs", &ref );
00711 }
00712 }
00713
00714 case B_REFS_RECEIVED:
00715 case B_SIMPLE_DATA:
00716 {
00717
00718
00719
00720
00721 int32 count;
00722 type_code dummy;
00723 if( p_message->GetInfo( "refs", &dummy, &count ) != B_OK ||
00724 count < 1 )
00725 {
00726 break;
00727 }
00728
00729 vlc_bool_t b_remove = ( p_message->WasDropped() &&
00730 !( modifiers() & B_SHIFT_KEY ) );
00731
00732 if( b_remove && p_playlist )
00733 {
00734 playlist_Clear( p_playlist );
00735 }
00736
00737 entry_ref ref;
00738 for( int i = 0; p_message->FindRef( "refs", i, &ref ) == B_OK; i++ )
00739 {
00740 BPath path( &ref );
00741
00742
00743
00744 if( p_playlist )
00745 {
00746 playlist_Add( p_playlist, path.Path(), path.Path(),
00747 PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
00748 }
00749 }
00750
00751 UpdatePlaylist();
00752 break;
00753 }
00754
00755 case OPEN_PREFERENCES:
00756 {
00757 if( fPreferencesWindow->Lock() )
00758 {
00759 if (fPreferencesWindow->IsHidden())
00760 fPreferencesWindow->Show();
00761 else
00762 fPreferencesWindow->Activate();
00763 fPreferencesWindow->Unlock();
00764 }
00765 break;
00766 }
00767
00768 case OPEN_MESSAGES:
00769 {
00770 if( fMessagesWindow->Lock() )
00771 {
00772 if (fMessagesWindow->IsHidden())
00773 fMessagesWindow->Show();
00774 else
00775 fMessagesWindow->Activate();
00776 fMessagesWindow->Unlock();
00777 }
00778 break;
00779 }
00780 case MSG_UPDATE:
00781 UpdateInterface();
00782 break;
00783 default:
00784 BWindow::MessageReceived( p_message );
00785 break;
00786 }
00787 }
00788
00789
00790
00791
00792 bool InterfaceWindow::QuitRequested()
00793 {
00794 if( p_playlist )
00795 {
00796 playlist_Stop( p_playlist );
00797 }
00798 p_mediaControl->SetStatus(-1, INPUT_RATE_DEFAULT);
00799
00800 _StoreSettings();
00801
00802 p_intf->b_die = 1;
00803
00804 return( true );
00805 }
00806
00807
00808
00809
00810 void InterfaceWindow::UpdateInterface()
00811 {
00812 if( !p_input )
00813 {
00814 p_input = (input_thread_t *)
00815 vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
00816 }
00817 else if( p_input->b_dead )
00818 {
00819 vlc_object_release( p_input );
00820 p_input = NULL;
00821 }
00822
00823
00824 if( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) != B_OK )
00825 {
00826 return;
00827 }
00828
00829 if( b_playlist_update )
00830 {
00831 if( fPlaylistWindow->Lock() )
00832 {
00833 fPlaylistWindow->UpdatePlaylist( true );
00834 fPlaylistWindow->Unlock();
00835 b_playlist_update = false;
00836 }
00837 p_mediaControl->SetEnabled( p_playlist->i_size );
00838 }
00839
00840 if( p_input )
00841 {
00842 vlc_value_t val;
00843 p_mediaControl->SetEnabled( true );
00844 bool hasTitles = !var_Get( p_input, "title", &val );
00845 bool hasChapters = !var_Get( p_input, "chapter", &val );
00846 p_mediaControl->SetStatus( var_GetInteger( p_input, "state" ),
00847 var_GetInteger( p_input, "rate" ) );
00848 var_Get( p_input, "position", &val );
00849 p_mediaControl->SetProgress( val.f_float );
00850 _SetMenusEnabled( true, hasChapters, hasTitles );
00851 _UpdateSpeedMenu( var_GetInteger( p_input, "rate" ) );
00852
00853
00854 #if 0
00855 bool canSkipPrev;
00856 bool canSkipNext;
00857 p_wrapper->GetNavCapabilities( &canSkipPrev, &canSkipNext );
00858 p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
00859 #endif
00860
00861 audio_volume_t i_volume;
00862 aout_VolumeGet( p_intf, &i_volume );
00863 p_mediaControl->SetAudioEnabled( true );
00864 p_mediaControl->SetMuted( i_volume );
00865 }
00866 else
00867 {
00868 p_mediaControl->SetAudioEnabled( false );
00869
00870 _SetMenusEnabled( false );
00871
00872 if( !playlist_IsEmpty( p_playlist ) )
00873 {
00874 p_mediaControl->SetProgress( 0 );
00875
00876 #if 0
00877
00878 bool canSkipPrev;
00879 bool canSkipNext;
00880 p_wrapper->GetNavCapabilities( &canSkipPrev, &canSkipNext );
00881 p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
00882 #endif
00883 }
00884 else
00885 {
00886 p_mediaControl->SetEnabled( false );
00887 }
00888 }
00889
00890 Unlock();
00891 fLastUpdateTime = system_time();
00892 }
00893
00894
00895
00896
00897 void
00898 InterfaceWindow::UpdatePlaylist()
00899 {
00900 b_playlist_update = true;
00901 }
00902
00903
00904
00905
00906 bool
00907 InterfaceWindow::IsStopped() const
00908 {
00909 return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
00910 }
00911
00912
00913
00914
00915 void
00916 InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles)
00917 {
00918 if (!hasFile)
00919 {
00920 hasChapters = false;
00921 hasTitles = false;
00922 }
00923 if ( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK)
00924 {
00925 if ( fNextChapterMI->IsEnabled() != hasChapters )
00926 fNextChapterMI->SetEnabled( hasChapters );
00927 if ( fPrevChapterMI->IsEnabled() != hasChapters )
00928 fPrevChapterMI->SetEnabled( hasChapters );
00929 if ( fChapterMenu->IsEnabled() != hasChapters )
00930 fChapterMenu->SetEnabled( hasChapters );
00931 if ( fNextTitleMI->IsEnabled() != hasTitles )
00932 fNextTitleMI->SetEnabled( hasTitles );
00933 if ( fPrevTitleMI->IsEnabled() != hasTitles )
00934 fPrevTitleMI->SetEnabled( hasTitles );
00935 if ( fTitleMenu->IsEnabled() != hasTitles )
00936 fTitleMenu->SetEnabled( hasTitles );
00937 if ( fAudioMenu->IsEnabled() != hasFile )
00938 fAudioMenu->SetEnabled( hasFile );
00939 if ( fNavigationMenu->IsEnabled() != hasFile )
00940 fNavigationMenu->SetEnabled( hasFile );
00941 if ( fLanguageMenu->IsEnabled() != hasFile )
00942 fLanguageMenu->SetEnabled( hasFile );
00943 if ( fSubtitlesMenu->IsEnabled() != hasFile )
00944 fSubtitlesMenu->SetEnabled( hasFile );
00945 if ( fSpeedMenu->IsEnabled() != hasFile )
00946 fSpeedMenu->SetEnabled( hasFile );
00947 Unlock();
00948 }
00949 }
00950
00951
00952
00953
00954 void
00955 InterfaceWindow::_UpdateSpeedMenu( int rate )
00956 {
00957 BMenuItem * toMark = NULL;
00958
00959 switch( rate )
00960 {
00961 case ( INPUT_RATE_DEFAULT * 8 ):
00962 toMark = fHeighthMI;
00963 break;
00964
00965 case ( INPUT_RATE_DEFAULT * 4 ):
00966 toMark = fQuarterMI;
00967 break;
00968
00969 case ( INPUT_RATE_DEFAULT * 2 ):
00970 toMark = fHalfMI;
00971 break;
00972
00973 case ( INPUT_RATE_DEFAULT ):
00974 toMark = fNormalMI;
00975 break;
00976
00977 case ( INPUT_RATE_DEFAULT / 2 ):
00978 toMark = fTwiceMI;
00979 break;
00980
00981 case ( INPUT_RATE_DEFAULT / 4 ):
00982 toMark = fFourMI;
00983 break;
00984
00985 case ( INPUT_RATE_DEFAULT / 8 ):
00986 toMark = fHeightMI;
00987 break;
00988 }
00989
00990 if ( toMark && !toMark->IsMarked() )
00991 {
00992 toMark->SetMarked( true );
00993 }
00994 }
00995
00996
00997
00998
00999 void
01000 InterfaceWindow::_ShowFilePanel( uint32 command, const char* windowTitle )
01001 {
01002 if( !fFilePanel )
01003 {
01004 fFilePanel = new BFilePanel( B_OPEN_PANEL, NULL, NULL,
01005 B_FILE_NODE | B_DIRECTORY_NODE );
01006 fFilePanel->SetTarget( this );
01007 }
01008 fFilePanel->Window()->SetTitle( windowTitle );
01009 BMessage message( command );
01010 fFilePanel->SetMessage( &message );
01011 if ( !fFilePanel->IsShowing() )
01012 {
01013 fFilePanel->Refresh();
01014 fFilePanel->Show();
01015 }
01016 }
01017
01018
01019 void
01020 set_window_pos( BWindow* window, BRect frame )
01021 {
01022
01023
01024 float minWidth, maxWidth, minHeight, maxHeight;
01025 window->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight );
01026
01027 make_sure_frame_is_within_limits( frame,
01028 minWidth, minHeight, maxWidth, maxHeight );
01029 if ( make_sure_frame_is_on_screen( frame ) )
01030 {
01031 window->MoveTo( frame.LeftTop() );
01032 window->ResizeTo( frame.Width(), frame.Height() );
01033 }
01034 }
01035
01036
01037 void
01038 launch_window( BWindow* window, bool showing )
01039 {
01040 if ( window->Lock() )
01041 {
01042 if ( showing )
01043 {
01044 if ( window->IsHidden() )
01045 window->Show();
01046 }
01047 else
01048 {
01049 if ( !window->IsHidden() )
01050 window->Hide();
01051 }
01052 window->Unlock();
01053 }
01054 }
01055
01056
01057
01058
01059 void
01060 InterfaceWindow::_RestoreSettings()
01061 {
01062 if ( load_settings( fSettings, "interface_settings", "VideoLAN Client" ) == B_OK )
01063 {
01064 BRect frame;
01065 if ( fSettings->FindRect( "main frame", &frame ) == B_OK )
01066 set_window_pos( this, frame );
01067 if (fSettings->FindRect( "playlist frame", &frame ) == B_OK )
01068 set_window_pos( fPlaylistWindow, frame );
01069 if (fSettings->FindRect( "messages frame", &frame ) == B_OK )
01070 set_window_pos( fMessagesWindow, frame );
01071 if (fSettings->FindRect( "settings frame", &frame ) == B_OK )
01072 {
01073
01074 frame.right = frame.left + fPreferencesWindow->Frame().Width();
01075 frame.bottom = frame.top + fPreferencesWindow->Frame().Height();
01076 set_window_pos( fPreferencesWindow, frame );
01077 }
01078
01079 bool showing;
01080 if ( fSettings->FindBool( "playlist showing", &showing ) == B_OK )
01081 launch_window( fPlaylistWindow, showing );
01082 if ( fSettings->FindBool( "messages showing", &showing ) == B_OK )
01083 launch_window( fMessagesWindow, showing );
01084 if ( fSettings->FindBool( "settings showing", &showing ) == B_OK )
01085 launch_window( fPreferencesWindow, showing );
01086
01087 uint32 displayMode;
01088 if ( fSettings->FindInt32( "playlist display mode", (int32*)&displayMode ) == B_OK )
01089 fPlaylistWindow->SetDisplayMode( displayMode );
01090 }
01091 }
01092
01093
01094
01095
01096 void
01097 InterfaceWindow::_StoreSettings()
01098 {
01099
01100 config_PutInt( p_intf, "volume", p_mediaControl->GetVolume() );
01101 config_SaveConfigFile( p_intf, "main" );
01102
01103
01104 if ( fSettings->ReplaceRect( "main frame", Frame() ) != B_OK )
01105 fSettings->AddRect( "main frame", Frame() );
01106 if ( fPlaylistWindow->Lock() )
01107 {
01108 if (fSettings->ReplaceRect( "playlist frame", fPlaylistWindow->Frame() ) != B_OK)
01109 fSettings->AddRect( "playlist frame", fPlaylistWindow->Frame() );
01110 if (fSettings->ReplaceBool( "playlist showing", !fPlaylistWindow->IsHidden() ) != B_OK)
01111 fSettings->AddBool( "playlist showing", !fPlaylistWindow->IsHidden() );
01112 fPlaylistWindow->Unlock();
01113 }
01114 if ( fMessagesWindow->Lock() )
01115 {
01116 if (fSettings->ReplaceRect( "messages frame", fMessagesWindow->Frame() ) != B_OK)
01117 fSettings->AddRect( "messages frame", fMessagesWindow->Frame() );
01118 if (fSettings->ReplaceBool( "messages showing", !fMessagesWindow->IsHidden() ) != B_OK)
01119 fSettings->AddBool( "messages showing", !fMessagesWindow->IsHidden() );
01120 fMessagesWindow->Unlock();
01121 }
01122 if ( fPreferencesWindow->Lock() )
01123 {
01124 if (fSettings->ReplaceRect( "settings frame", fPreferencesWindow->Frame() ) != B_OK)
01125 fSettings->AddRect( "settings frame", fPreferencesWindow->Frame() );
01126 if (fSettings->ReplaceBool( "settings showing", !fPreferencesWindow->IsHidden() ) != B_OK)
01127 fSettings->AddBool( "settings showing", !fPreferencesWindow->IsHidden() );
01128 fPreferencesWindow->Unlock();
01129 }
01130 uint32 displayMode = fPlaylistWindow->DisplayMode();
01131 if (fSettings->ReplaceInt32( "playlist display mode", displayMode ) != B_OK )
01132 fSettings->AddInt32( "playlist display mode", displayMode );
01133
01134 save_settings( fSettings, "interface_settings", "VideoLAN Client" );
01135 }
01136
01137
01138
01139
01140
01141 CDMenu::CDMenu(const char *name)
01142 : BMenu(name)
01143 {
01144 }
01145
01146
01147
01148
01149 CDMenu::~CDMenu()
01150 {
01151 }
01152
01153
01154
01155
01156 void CDMenu::AttachedToWindow(void)
01157 {
01158
01159 while ( BMenuItem* item = RemoveItem( 0L ) )
01160 delete item;
01161 GetCD( "/dev/disk" );
01162 BMenu::AttachedToWindow();
01163 }
01164
01165
01166
01167
01168 int CDMenu::GetCD( const char *directory )
01169 {
01170 BVolumeRoster volRoster;
01171 BVolume vol;
01172 BDirectory dir;
01173 status_t status = volRoster.GetNextVolume( &vol );
01174 while ( status == B_NO_ERROR )
01175 {
01176 BString deviceName;
01177 BString volumeName;
01178 bool isCDROM;
01179 if ( get_volume_info( vol, volumeName, isCDROM, deviceName )
01180 && isCDROM )
01181 {
01182 BMessage* msg = new BMessage( OPEN_DVD );
01183 msg->AddString( "device", deviceName.String() );
01184 BMenuItem* item = new BMenuItem( volumeName.String(), msg );
01185 AddItem( item );
01186 }
01187 vol.Unset();
01188 status = volRoster.GetNextVolume( &vol );
01189 }
01190 return 0;
01191 }
01192
01193
01194
01195
01196 LanguageMenu::LanguageMenu( intf_thread_t * _p_intf, const char * psz_name,
01197 char * _psz_variable )
01198 : BMenu( psz_name )
01199 {
01200 p_intf = _p_intf;
01201 psz_variable = strdup( _psz_variable );
01202 }
01203
01204
01205
01206
01207 LanguageMenu::~LanguageMenu()
01208 {
01209 free( psz_variable );
01210 }
01211
01212
01213
01214
01215 void LanguageMenu::AttachedToWindow()
01216 {
01217 BMenuItem * item;
01218
01219
01220 while( ( item = RemoveItem( 0L ) ) )
01221 {
01222 delete item;
01223 }
01224
01225 SetRadioMode( true );
01226
01227 input_thread_t * p_input = (input_thread_t *)
01228 vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
01229 if( !p_input )
01230 {
01231 return;
01232 }
01233
01234 vlc_value_t val_list, text_list;
01235 BMessage * message;
01236 int i_current;
01237
01238 i_current = var_GetInteger( p_input, psz_variable );
01239 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list );
01240 for( int i = 0; i < val_list.p_list->i_count; i++ )
01241 {
01242 message = new BMessage( SELECT_CHANNEL );
01243 message->AddInt32( psz_variable, val_list.p_list->p_values[i].i_int );
01244 item = new BMenuItem( text_list.p_list->p_values[i].psz_string, message );
01245 if( val_list.p_list->p_values[i].i_int == i_current )
01246 {
01247 item->SetMarked( true );
01248 }
01249 AddItem( item );
01250 }
01251 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
01252
01253 vlc_object_release( p_input );
01254
01255 BMenu::AttachedToWindow();
01256 }
01257
01258
01259
01260
01261 TitleMenu::TitleMenu( const char *name, intf_thread_t *p_interface )
01262 : BMenu(name),
01263 p_intf( p_interface )
01264 {
01265 }
01266
01267
01268
01269
01270 TitleMenu::~TitleMenu()
01271 {
01272 }
01273
01274
01275
01276
01277 void TitleMenu::AttachedToWindow()
01278 {
01279 BMenuItem * item;
01280 while( ( item = RemoveItem( 0L ) ) )
01281 {
01282 delete item;
01283 }
01284
01285 input_thread_t * p_input;
01286 p_input = (input_thread_t *)
01287 vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
01288 if( !p_input )
01289 {
01290 return;
01291 }
01292
01293 vlc_value_t val;
01294 BMessage * message;
01295 if( !var_Get( p_input, "title", &val ) )
01296 {
01297 vlc_value_t val_list, text_list;
01298 var_Change( p_input, "title", VLC_VAR_GETCHOICES,
01299 &val_list, &text_list );
01300
01301 for( int i = 0; i < val_list.p_list->i_count; i++ )
01302 {
01303 message = new BMessage( TOGGLE_TITLE );
01304 message->AddInt32( "index", val_list.p_list->p_values[i].i_int );
01305 item = new BMenuItem( text_list.p_list->p_values[i].psz_string,
01306 message );
01307 if( val_list.p_list->p_values[i].i_int == val.i_int )
01308 {
01309 item->SetMarked( true );
01310 }
01311 AddItem( item );
01312 }
01313
01314 var_Change( p_input, "title", VLC_VAR_FREELIST,
01315 &val_list, &text_list );
01316 }
01317 vlc_object_release( p_input );
01318 BMenu::AttachedToWindow();
01319 }
01320
01321
01322
01323
01324
01325 ChapterMenu::ChapterMenu( const char *name, intf_thread_t *p_interface )
01326 : BMenu(name),
01327 p_intf( p_interface )
01328 {
01329 }
01330
01331
01332
01333
01334 ChapterMenu::~ChapterMenu()
01335 {
01336 }
01337
01338
01339
01340
01341 void ChapterMenu::AttachedToWindow()
01342 {
01343 BMenuItem * item;
01344 while( ( item = RemoveItem( 0L ) ) )
01345 {
01346 delete item;
01347 }
01348
01349 input_thread_t * p_input;
01350 p_input = (input_thread_t *)
01351 vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
01352 if( !p_input )
01353 {
01354 return;
01355 }
01356
01357 vlc_value_t val;
01358 BMessage * message;
01359 if( !var_Get( p_input, "chapter", &val ) )
01360 {
01361 vlc_value_t val_list, text_list;
01362 var_Change( p_input, "chapter", VLC_VAR_GETCHOICES,
01363 &val_list, &text_list );
01364
01365 for( int i = 0; i < val_list.p_list->i_count; i++ )
01366 {
01367 message = new BMessage( TOGGLE_CHAPTER );
01368 message->AddInt32( "index", val_list.p_list->p_values[i].i_int );
01369 item = new BMenuItem( text_list.p_list->p_values[i].psz_string,
01370 message );
01371 if( val_list.p_list->p_values[i].i_int == val.i_int )
01372 {
01373 item->SetMarked( true );
01374 }
01375 AddItem( item );
01376 }
01377
01378 var_Change( p_input, "chapter", VLC_VAR_FREELIST,
01379 &val_list, &text_list );
01380 }
01381 vlc_object_release( p_input );
01382 BMenu::AttachedToWindow();
01383 }
01384
01385
01386
01387
01388
01389 status_t
01390 load_settings( BMessage* message, const char* fileName, const char* folder )
01391 {
01392 status_t ret = B_BAD_VALUE;
01393 if ( message )
01394 {
01395 BPath path;
01396 if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
01397 {
01398
01399 if ( folder )
01400 ret = path.Append( folder );
01401 if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
01402 {
01403 BFile file( path.Path(), B_READ_ONLY );
01404 if ( ( ret = file.InitCheck() ) == B_OK )
01405 {
01406 ret = message->Unflatten( &file );
01407 file.Unset();
01408 }
01409 }
01410 }
01411 }
01412 return ret;
01413 }
01414
01415
01416
01417
01418 status_t
01419 save_settings( BMessage* message, const char* fileName, const char* folder )
01420 {
01421 status_t ret = B_BAD_VALUE;
01422 if ( message )
01423 {
01424 BPath path;
01425 if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
01426 {
01427
01428 if ( folder && ( ret = path.Append( folder ) ) == B_OK )
01429 ret = create_directory( path.Path(), 0777 );
01430 if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
01431 {
01432 BFile file( path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE );
01433 if ( ( ret = file.InitCheck() ) == B_OK )
01434 {
01435 ret = message->Flatten( &file );
01436 file.Unset();
01437 }
01438 }
01439 }
01440 }
01441 return ret;
01442 }