* Fixed title / chapter menus
[vlc.git] / modules / gui / beos / InterfaceWindow.cpp
1 /*****************************************************************************
2  * InterfaceWindow.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: InterfaceWindow.cpp,v 1.20 2003/01/22 01:13:22 titer Exp $
6  *
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>
11  *          Stephan Aßmus <stippi@yellowbites.com>
12  *
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.
17  *
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.
22  *
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  *****************************************************************************/
27
28 /* System headers */
29 #include <kernel/OS.h>
30 #include <InterfaceKit.h>
31 #include <AppKit.h>
32 #include <StorageKit.h>
33 #include <SupportKit.h>
34 #include <malloc.h>
35 #include <scsi.h>
36 #include <scsiprobe_driver.h>
37 #include <fs_info.h>
38 #include <string.h>
39
40 /* VLC headers */
41 #include <vlc/vlc.h>
42 #include <vlc/aout.h>
43 #include <vlc/intf.h>
44
45 /* BeOS interface headers */
46 #include "VlcWrapper.h"
47 #include "MsgVals.h"
48 #include "MediaControlView.h"
49 #include "PlayListWindow.h"
50 #include "PreferencesWindow.h"
51 #include "InterfaceWindow.h"
52
53 #define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps
54
55
56 /*****************************************************************************
57  * InterfaceWindow
58  *****************************************************************************/
59
60 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
61                                                                   intf_thread_t  *p_interface )
62         : BWindow( frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
63                            B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
64           p_intf( p_interface ),
65           fFilePanel( NULL ),
66           fSubtitlesPanel( NULL ),
67           fLastUpdateTime( system_time() )
68 {
69     p_intf = p_interface;
70     p_wrapper = p_intf->p_sys->p_wrapper;
71     p_intf->p_sys->b_dvdold = false;
72     
73     fPlaylistIsEmpty = ( p_wrapper->PlaylistSize() < 0 );
74     
75     fPlaylistWindow = new PlayListWindow( BRect( 100.0, 100.0, 400.0, 350.0 ),
76                                                                                   "Playlist",
77                                                                                   this,
78                                                                                   p_intf );
79     BScreen *p_screen = new BScreen();
80     BRect screen_rect = p_screen->Frame();
81     delete p_screen;
82     BRect window_rect;
83     window_rect.Set( ( screen_rect.right - PREFS_WINDOW_WIDTH ) / 2,
84                      ( screen_rect.bottom - PREFS_WINDOW_HEIGHT ) / 2,
85                      ( screen_rect.right + PREFS_WINDOW_WIDTH ) / 2,
86                      ( screen_rect.bottom + PREFS_WINDOW_HEIGHT ) / 2 );
87         fPreferencesWindow = new PreferencesWindow( window_rect,
88                                                     "Preferences",
89                                                     p_intf );
90     
91         // set the title bar
92         SetName( "interface" );
93         SetTitle( VOUT_TITLE );
94
95         // the media control view
96         p_mediaControl = new MediaControlView( BRect( 0.0, 0.0, 250.0, 50.0 ),
97                                                p_intf );
98         p_mediaControl->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
99         p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
100
101         float width, height;
102         p_mediaControl->GetPreferredSize( &width, &height );
103
104         // set up the main menu
105         fMenuBar = new BMenuBar( BRect(0.0, 0.0, width, 15.0), "main menu",
106                                                          B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
107
108         // make menu bar resize to correct height
109         float menuWidth, menuHeight;
110         fMenuBar->GetPreferredSize( &menuWidth, &menuHeight );
111         fMenuBar->ResizeTo( width, menuHeight );        // don't change! it's a workarround!
112         // take care of proper size for ourself
113         height += fMenuBar->Bounds().Height();
114         ResizeTo( width, height );
115
116         p_mediaControl->MoveTo( fMenuBar->Bounds().LeftBottom() + BPoint(0.0, 1.0) );
117         AddChild( fMenuBar );
118         AddChild( p_mediaControl );
119
120         // Add the file Menu
121         BMenu* fileMenu = new BMenu( "File" );
122         fMenuBar->AddItem( fileMenu );
123         fileMenu->AddItem( new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
124                                                                           new BMessage( OPEN_FILE ), 'O') );
125         
126         fileMenu->AddItem( new CDMenu( "Open Disc" ) );
127
128         fileMenu->AddItem( new BMenuItem( "Load a subtitle file" B_UTF8_ELLIPSIS,
129                                                                           new BMessage( LOAD_SUBFILE ) ) );
130         
131         fileMenu->AddSeparatorItem();
132         fileMenu->AddItem( new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
133                                                                           new BMessage( OPEN_PLAYLIST ), 'P') );
134         
135         fileMenu->AddSeparatorItem();
136         BMenuItem* item = new BMenuItem( "About" B_UTF8_ELLIPSIS,
137                                                                          new BMessage( B_ABOUT_REQUESTED ), 'A');
138         item->SetTarget( be_app );
139         fileMenu->AddItem( item );
140         fileMenu->AddItem( new BMenuItem( "Quit", new BMessage( B_QUIT_REQUESTED ), 'Q') );
141
142         fLanguageMenu = new LanguageMenu("Language", AUDIO_ES, p_wrapper);
143         fSubtitlesMenu = new LanguageMenu("Subtitles", SPU_ES, p_wrapper);
144
145         /* Add the Audio menu */
146         fAudioMenu = new BMenu( "Audio" );
147         fMenuBar->AddItem ( fAudioMenu );
148         fAudioMenu->AddItem( fLanguageMenu );
149         fAudioMenu->AddItem( fSubtitlesMenu );
150
151         fPrevTitleMI = new BMenuItem( "Prev Title", new BMessage( PREV_TITLE ) );
152         fNextTitleMI = new BMenuItem( "Next Title", new BMessage( NEXT_TITLE ) );
153         fPrevChapterMI = new BMenuItem( "Prev Chapter", new BMessage( PREV_CHAPTER ) );
154         fNextChapterMI = new BMenuItem( "Next Chapter", new BMessage( NEXT_CHAPTER ) );
155
156         /* Add the Navigation menu */
157         fNavigationMenu = new BMenu( "Navigation" );
158         fMenuBar->AddItem( fNavigationMenu );
159         fNavigationMenu->AddItem( fPrevTitleMI );
160         fNavigationMenu->AddItem( fNextTitleMI );
161         fNavigationMenu->AddItem( fTitleMenu = new TitleMenu( "Go to Title", p_intf ) );
162         fNavigationMenu->AddSeparatorItem();
163         fNavigationMenu->AddItem( fPrevChapterMI );
164         fNavigationMenu->AddItem( fNextChapterMI );
165         fNavigationMenu->AddItem( fChapterMenu = new ChapterMenu( "Go to Chapter", p_intf ) );
166
167         /* Add the Speed menu */
168         fSpeedMenu = new BMenu( "Speed" );
169         fSpeedMenu->SetRadioMode( true );
170         fSpeedMenu->AddItem( fSlowerMI = new BMenuItem( "Slower", new BMessage( SLOWER_PLAY ) ) );
171         fNormalMI = new BMenuItem( "Normal", new BMessage( NORMAL_PLAY ) );
172         fNormalMI->SetMarked(true); // default to normal speed
173         fSpeedMenu->AddItem( fNormalMI );
174         fSpeedMenu->AddItem( fFasterMI = new BMenuItem( "Faster", new BMessage( FASTER_PLAY) ) );
175         fSpeedMenu->SetTargetForItems( this );
176         fMenuBar->AddItem( fSpeedMenu );
177
178     /* Add the Settings menu */
179     fSettingsMenu = new BMenu( "Settings" );
180     fSettingsMenu->AddItem( fPreferencesMI =
181         new BMenuItem( "Preferences", new BMessage( OPEN_PREFERENCES ) ) );
182         fMenuBar->AddItem( fSettingsMenu );                                                     
183
184         // prepare fow showing
185         _SetMenusEnabled( false );
186         p_mediaControl->SetEnabled( false );
187
188         Show();
189 }
190
191 InterfaceWindow::~InterfaceWindow()
192 {
193         if (fPlaylistWindow)
194                 fPlaylistWindow->ReallyQuit();
195 }
196
197 /*****************************************************************************
198  * InterfaceWindow::FrameResized
199  *****************************************************************************/
200 void
201 InterfaceWindow::FrameResized(float width, float height)
202 {
203         BRect r(Bounds());
204         fMenuBar->MoveTo(r.LeftTop());
205         fMenuBar->ResizeTo(r.Width(), fMenuBar->Bounds().Height());
206         r.top += fMenuBar->Bounds().Height() + 1.0;
207         p_mediaControl->MoveTo(r.LeftTop());
208         p_mediaControl->ResizeTo(r.Width(), r.Height());
209 }
210
211 /*****************************************************************************
212  * InterfaceWindow::MessageReceived
213  *****************************************************************************/
214 void InterfaceWindow::MessageReceived( BMessage * p_message )
215 {
216         int playback_status;      // remember playback state
217         playback_status = p_wrapper->InputStatus();
218
219         switch( p_message->what )
220         {
221                 case B_ABOUT_REQUESTED:
222                 {
223                         BAlert* alert = new BAlert( VOUT_TITLE,
224                                                                                 "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
225                         alert->Go();
226                         break;
227                 }
228                 case TOGGLE_ON_TOP:
229                         break;
230                         
231                 case OPEN_FILE:
232                         if( fFilePanel )
233                         {
234                                 fFilePanel->Show();
235                                 break;
236                         }
237                         fFilePanel = new BFilePanel();
238                         fFilePanel->SetTarget( this );
239                         fFilePanel->Show();
240                         break;
241         
242                 case OPEN_PLAYLIST:
243                         if (fPlaylistWindow->Lock())
244                         {
245                                 if (fPlaylistWindow->IsHidden())
246                                         fPlaylistWindow->Show();
247                                 else
248                                         fPlaylistWindow->Activate();
249                                 fPlaylistWindow->Unlock();
250                         }
251                         break;
252                 case OPEN_DVD:
253                         {
254                                 const char *psz_device;
255                                 BString type( "dvd" );
256                                 if( p_message->FindString( "device", &psz_device ) == B_OK )
257                                 {
258                                         BString device( psz_device );
259                                         p_wrapper->OpenDisc( type, device, 0, 0 );
260                                 }
261                                 _UpdatePlaylist();
262                         }
263                         break;
264                 
265                 case LOAD_SUBFILE:
266                         if( fSubtitlesPanel )
267                         {
268                                 fSubtitlesPanel->Show();
269                                 break;
270                         }
271                         fSubtitlesPanel = new BFilePanel();
272                         fSubtitlesPanel->SetTarget( this );
273                         fSubtitlesPanel->SetMessage( new BMessage( SUBFILE_RECEIVED ) );
274                         fSubtitlesPanel->Show();
275                         break;
276
277                 case SUBFILE_RECEIVED:
278                 {
279                         entry_ref ref;
280                         if( p_message->FindRef( "refs", 0, &ref ) == B_OK )
281                         {
282                                 BPath path( &ref );
283                                 if ( path.InitCheck() == B_OK )
284                                         p_wrapper->LoadSubFile( (char*)path.Path() );
285                         }
286                         break;
287                 }
288         
289                 case STOP_PLAYBACK:
290                         // this currently stops playback not nicely
291                         if (playback_status > UNDEF_S)
292                         {
293                                 snooze( 400000 );
294                                 p_wrapper->PlaylistStop();
295                                 p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
296                         }
297                         break;
298         
299                 case START_PLAYBACK:
300                         /*  starts playing in normal mode */
301         
302                 case PAUSE_PLAYBACK:
303                         /* toggle between pause and play */
304                         if (playback_status > UNDEF_S)
305                         {
306                                 /* pause if currently playing */
307                                 if ( playback_status == PLAYING_S )
308                                 {
309                                         p_wrapper->PlaylistPause();
310                                 }
311                                 else
312                                 {
313                                         p_wrapper->PlaylistPlay();
314                                 }
315                         }
316                         else
317                         {
318                                 /* Play a new file */
319                                 p_wrapper->PlaylistPlay();
320                         }       
321                         break;
322         
323                 case FASTER_PLAY:
324                         /* cycle the fast playback modes */
325                         if (playback_status > UNDEF_S)
326                         {
327                                 p_wrapper->InputFaster();
328                         }
329                         break;
330         
331                 case SLOWER_PLAY:
332                         /*  cycle the slow playback modes */
333                         if (playback_status > UNDEF_S)
334                         {
335                                 p_wrapper->InputSlower();
336                         }
337                         break;
338         
339                 case NORMAL_PLAY:
340                         /*  restore speed to normal if already playing */
341                         if (playback_status > UNDEF_S)
342                         {
343                                 p_wrapper->PlaylistPlay();
344                         }
345                         break;
346         
347                 case SEEK_PLAYBACK:
348                         /* handled by semaphores */
349                         break;
350                 // volume related messages
351                 case VOLUME_CHG:
352                         /* adjust the volume */
353                         if (playback_status > UNDEF_S)
354                         {
355                                 p_wrapper->SetVolume( p_mediaControl->GetVolume() );
356                                 p_mediaControl->SetMuted( p_wrapper->IsMuted() );
357                         }
358                         break;
359         
360                 case VOLUME_MUTE:
361                         // toggle muting
362                         if( p_wrapper->IsMuted() )
363                             p_wrapper->VolumeRestore();
364                         else
365                             p_wrapper->VolumeMute();
366                         p_mediaControl->SetMuted( p_wrapper->IsMuted() );
367                         break;
368         
369                 case SELECT_CHANNEL:
370                         if ( playback_status > UNDEF_S )
371                         {
372                                 int32 channel;
373                                 if ( p_message->FindInt32( "channel", &channel ) == B_OK )
374                                 {
375                                         p_wrapper->ToggleLanguage( channel );
376                                 }
377                         }
378                         break;
379         
380                 case SELECT_SUBTITLE:
381                         if ( playback_status > UNDEF_S )
382                         {
383                                 int32 subtitle;
384                                 if ( p_message->FindInt32( "subtitle", &subtitle ) == B_OK )
385                                          p_wrapper->ToggleSubtitle( subtitle );
386                         }
387                         break;
388         
389                 // specific navigation messages
390                 case PREV_TITLE:
391                 {
392                         p_wrapper->PrevTitle();
393                         break;
394                 }
395                 case NEXT_TITLE:
396                 {
397             p_wrapper->NextTitle();
398                         break;
399                 }
400                 case TOGGLE_TITLE:
401                         if ( playback_status > UNDEF_S )
402                         {
403                                 int32 index;
404                                 if( p_message->FindInt32( "index", &index ) == B_OK )
405                                         p_wrapper->ToggleTitle( index );
406                         }
407                         break;
408                 case PREV_CHAPTER:
409                 {
410             p_wrapper->PrevChapter();
411                         break;
412                 }
413                 case NEXT_CHAPTER:
414                 {
415             p_wrapper->NextChapter();
416                         break;
417                 }
418                 case TOGGLE_CHAPTER:
419                         if ( playback_status > UNDEF_S )
420                         {
421                                 int32 index;
422                                 if( p_message->FindInt32( "index", &index ) == B_OK )
423                     p_wrapper->ToggleChapter( index );
424                         }
425                         break;
426                 case PREV_FILE:
427                         p_wrapper->PlaylistPrev();
428                         break;
429                 case NEXT_FILE:
430                         p_wrapper->PlaylistNext();
431                         break;
432                 // general next/prev functionality (skips to whatever makes most sense)
433                 case NAVIGATE_PREV:
434                         p_wrapper->NavigatePrev();
435                         break;
436                 case NAVIGATE_NEXT:
437                         p_wrapper->NavigateNext();
438                         break;
439                 // drag'n'drop and system messages
440                 case B_REFS_RECEIVED:
441                 case B_SIMPLE_DATA:
442                         {
443                                 /* file(s) opened by the File menu -> append to the playlist;
444                                  * file(s) opened by drag & drop -> replace playlist;
445                                  * file(s) opened by 'shift' + drag & drop -> append */
446                                 bool replace = false;
447                                 if ( p_message->WasDropped() )
448                                         replace = !( modifiers() & B_SHIFT_KEY );
449                                         
450                                 // build list of files to be played from message contents
451                                 entry_ref ref;
452                                 BList files;
453                                 for ( int i = 0; p_message->FindRef( "refs", i, &ref ) == B_OK; i++ )
454                                 {
455                                         BPath path( &ref );
456                                         if ( path.InitCheck() == B_OK )
457                                         {
458                                                 bool add = true;
459                                                 // has the user dropped a dvd disk icon?
460                                                 BDirectory dir( &ref );
461                                                 if ( dir.InitCheck() == B_OK && dir.IsRootDirectory() )
462                                                 {
463                                                         BVolumeRoster volRoster;
464                                                         BVolume vol;
465                                                         BDirectory volumeRoot;
466                                                         status_t status = volRoster.GetNextVolume( &vol );
467                                                         while( status == B_NO_ERROR )
468                                                         {
469                                                                 if( vol.GetRootDirectory( &volumeRoot ) == B_OK
470                                                                         && dir == volumeRoot )
471                                                                 {
472                                                                         BString volumeName;
473                                                                         BString deviceName;
474                                                                         bool isCDROM = false;
475                                                                         bool success = false;
476                                                                         deviceName = "";
477                                                                         volumeName = "";
478                                                                         char name[B_FILE_NAME_LENGTH];
479                                                                         if ( vol.GetName( name ) >= B_OK )      // disk is currently mounted
480                                                                         {
481                                                                                 volumeName = name;
482                                                                                 dev_t dev = vol.Device();
483                                                                                 fs_info info;
484                                                                                 if ( fs_stat_dev( dev, &info ) == B_OK )
485                                                                                 {
486                                                                                         success = true;
487                                                                                         deviceName = info.device_name;
488                                                                                         if ( vol.IsReadOnly() )
489                                                                                         {
490                                                                                                 int i_dev = open( info.device_name, O_RDONLY );
491                                                                                                 if ( i_dev >= 0 )
492                                                                                                 {
493                                                                                                         device_geometry g;
494                                                                                                         if ( ioctl( i_dev, B_GET_GEOMETRY, &g, sizeof( g ) ) >= 0 )
495                                                                                                         isCDROM = ( g.device_type == B_CD );
496                                                                                                         close( i_dev );
497                                                                                                 }
498                                                                                         }
499                                                                                 }
500                                                                         }
501                                                                         
502                                                                         if( success && isCDROM )
503                                                                         {
504                                                                                 BMessage msg( OPEN_DVD );
505                                                                                 msg.AddString( "device", deviceName.String() );
506                                                                                 PostMessage( &msg );
507                                                                                 add = false;
508                                                                         }
509                                                                         break;
510                                                                 }
511                                                                 else
512                                                                 {
513                                                                         vol.Unset();
514                                                                         status = volRoster.GetNextVolume( &vol );
515                                                                 }
516                                                         }
517                                                 }
518                                                 if( add )
519                                                 {
520                                                         files.AddItem( new BString( (char*)path.Path() ) );
521                                                 }
522                                         }
523                                 }
524                                 // give the list to VLC
525                                 p_wrapper->OpenFiles(&files, replace);
526                                 _UpdatePlaylist();
527                         }
528                         break;
529
530                 case OPEN_PREFERENCES:
531                     if( fPreferencesWindow->Lock() )
532                     {
533                             if (fPreferencesWindow->IsHidden())
534                                     fPreferencesWindow->Show();
535                             else
536                                     fPreferencesWindow->Activate();
537                                 fPreferencesWindow->Unlock();
538                         }
539                         break;
540                                 
541                 default:
542                         BWindow::MessageReceived( p_message );
543                         break;
544         }
545
546 }
547
548 /*****************************************************************************
549  * InterfaceWindow::QuitRequested
550  *****************************************************************************/
551 bool InterfaceWindow::QuitRequested()
552 {
553         p_wrapper->PlaylistStop();
554         p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
555         
556         p_intf->b_die = 1;
557
558         return( true );
559 }
560
561 /*****************************************************************************
562  * InterfaceWindow::updateInterface
563  *****************************************************************************/
564 void InterfaceWindow::updateInterface()
565 {
566     if( p_wrapper->HasInput() )
567     {
568                 if ( acquire_sem( p_mediaControl->fScrubSem ) == B_OK )
569                 {
570                     p_wrapper->SetTimeAsFloat(p_mediaControl->GetSeekTo());
571                 }
572                 else if ( Lock() )
573                 {
574 //                      p_mediaControl->SetEnabled( true );
575                         bool hasTitles = p_wrapper->HasTitles();
576                         bool hasChapters = p_wrapper->HasChapters();
577                         p_mediaControl->SetStatus( p_wrapper->InputStatus(), 
578                                                                            p_wrapper->InputRate() );
579                         p_mediaControl->SetProgress( p_wrapper->GetTimeAsFloat() );
580                         _SetMenusEnabled( true, hasChapters, hasTitles );
581
582                         _UpdateSpeedMenu( p_wrapper->InputRate() );
583
584                         // enable/disable skip buttons
585                         bool canSkipPrev;
586                         bool canSkipNext;
587                         p_wrapper->GetNavCapabilities( &canSkipPrev, &canSkipNext );
588                         p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
589
590                         if ( p_wrapper->HasAudio() )
591                         {
592                                 p_mediaControl->SetAudioEnabled( true );
593                                 p_mediaControl->SetMuted( p_wrapper->IsMuted() );
594                         } else
595                                 p_mediaControl->SetAudioEnabled( false );
596
597                         Unlock();
598                 }
599                 // update playlist as well
600                 if ( fPlaylistWindow->Lock() )
601                 {
602                         fPlaylistWindow->UpdatePlaylist();
603                         fPlaylistWindow->Unlock();
604                 }
605         }
606     else
607     {
608         _SetMenusEnabled( false );
609 //              p_mediaControl->SetEnabled( false );
610     }
611
612     /* always force the user-specified volume */
613     /* FIXME : I'm quite sure there is a cleaner way to do this */
614     if( p_wrapper->GetVolume() != p_mediaControl->GetVolume() )
615     {
616         p_wrapper->SetVolume( p_mediaControl->GetVolume() );
617     }
618
619         fLastUpdateTime = system_time();
620 }
621
622 /*****************************************************************************
623  * InterfaceWindow::IsStopped
624  *****************************************************************************/
625 bool
626 InterfaceWindow::IsStopped() const
627 {
628         return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
629 }
630
631 /*****************************************************************************
632  * InterfaceWindow::_UpdatePlaylist
633  *****************************************************************************/
634 void
635 InterfaceWindow::_UpdatePlaylist()
636 {
637         if ( fPlaylistWindow->Lock() )
638         {
639                 fPlaylistWindow->UpdatePlaylist( true );
640                 fPlaylistWindow->Unlock();
641                 p_mediaControl->SetEnabled( p_wrapper->PlaylistSize() );
642         }
643 }
644
645 /*****************************************************************************
646  * InterfaceWindow::_SetMenusEnabled
647  *****************************************************************************/
648 void
649 InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles)
650 {
651         if (!hasFile)
652         {
653                 hasChapters = false;
654                 hasTitles = false;
655         }
656         if (Lock())
657         {
658                 if (fNextChapterMI->IsEnabled() != hasChapters)
659                         fNextChapterMI->SetEnabled(hasChapters);
660                 if (fPrevChapterMI->IsEnabled() != hasChapters)
661                         fPrevChapterMI->SetEnabled(hasChapters);
662                 if (fChapterMenu->IsEnabled() != hasChapters)
663                         fChapterMenu->SetEnabled(hasChapters);
664                 if (fNextTitleMI->IsEnabled() != hasTitles)
665                         fNextTitleMI->SetEnabled(hasTitles);
666                 if (fPrevTitleMI->IsEnabled() != hasTitles)
667                         fPrevTitleMI->SetEnabled(hasTitles);
668                 if (fTitleMenu->IsEnabled() != hasTitles)
669                         fTitleMenu->SetEnabled(hasTitles);
670                 if (fAudioMenu->IsEnabled() != hasFile)
671                         fAudioMenu->SetEnabled(hasFile);
672                 if (fNavigationMenu->IsEnabled() != hasFile)
673                         fNavigationMenu->SetEnabled(hasFile);
674                 if (fLanguageMenu->IsEnabled() != hasFile)
675                         fLanguageMenu->SetEnabled(hasFile);
676                 if (fSubtitlesMenu->IsEnabled() != hasFile)
677                         fSubtitlesMenu->SetEnabled(hasFile);
678                 if (fSpeedMenu->IsEnabled() != hasFile)
679                         fSpeedMenu->SetEnabled(hasFile);
680                 Unlock();
681         }
682 }
683
684 /*****************************************************************************
685  * InterfaceWindow::_UpdateSpeedMenu
686  *****************************************************************************/
687 void
688 InterfaceWindow::_UpdateSpeedMenu( int rate )
689 {
690         if ( rate == DEFAULT_RATE )
691         {
692                 if ( !fNormalMI->IsMarked() )
693                         fNormalMI->SetMarked( true );
694         }
695         else if ( rate < DEFAULT_RATE )
696         {
697                 if ( !fFasterMI->IsMarked() )
698                         fFasterMI->SetMarked( true );
699         }
700         else
701         {
702                 if ( !fSlowerMI->IsMarked() )
703                         fSlowerMI->SetMarked( true );
704         }
705 }
706
707 /*****************************************************************************
708  * InterfaceWindow::_InputStreamChanged
709  *****************************************************************************/
710 void
711 InterfaceWindow::_InputStreamChanged()
712 {
713         // TODO: move more stuff from updateInterface() here!
714         snooze( 400000 );
715         p_wrapper->SetVolume( p_mediaControl->GetVolume() );
716 }
717
718 void
719 make_sure_frame_is_within_limits( BRect& frame, float minWidth, float minHeight,
720                                                                   float maxWidth, float maxHeight )
721 {
722         if ( frame.Width() < minWidth )
723                 frame.right = frame.left + minWidth;
724         if ( frame.Height() < minHeight )
725                 frame.bottom = frame.top + minHeight;
726         if ( frame.Width() > maxWidth )
727                 frame.right = frame.left + maxWidth;
728         if ( frame.Height() > maxHeight )
729                 frame.bottom = frame.top + maxHeight;
730 }
731
732 /*****************************************************************************
733  * CDMenu::CDMenu
734  *****************************************************************************/
735 CDMenu::CDMenu(const char *name)
736           : BMenu(name)
737 {
738 }
739
740 /*****************************************************************************
741  * CDMenu::~CDMenu
742  *****************************************************************************/
743 CDMenu::~CDMenu()
744 {
745 }
746
747 /*****************************************************************************
748  * CDMenu::AttachedToWindow
749  *****************************************************************************/
750 void CDMenu::AttachedToWindow(void)
751 {
752         // remove all items
753         while (BMenuItem* item = RemoveItem(0L))
754                 delete item;
755         GetCD("/dev/disk");
756         BMenu::AttachedToWindow();
757 }
758
759 /*****************************************************************************
760  * CDMenu::GetCD
761  *****************************************************************************/
762 int CDMenu::GetCD( const char *directory )
763 {
764         BVolumeRoster *volRoster;
765         BVolume    *vol;
766         BDirectory      *dir;
767         int                status;
768         int                mounted;   
769         char              name[B_FILE_NAME_LENGTH]; 
770         fs_info    info;
771         dev_t            dev;
772         
773         volRoster = new BVolumeRoster();
774         vol = new BVolume();
775         dir = new BDirectory();
776         status = volRoster->GetNextVolume(vol);
777         status = vol->GetRootDirectory(dir);
778         while (status ==  B_NO_ERROR)
779         {
780                 mounted = vol->GetName(name);   
781                 if ((mounted == B_OK) && /* Disk is currently Mounted */
782                         (vol->IsReadOnly()) ) /* Disk is read-only */
783                 {
784                         dev = vol->Device();
785                         fs_stat_dev(dev, &info);
786                         
787                         device_geometry g;
788                         int i_dev;
789                         i_dev = open( info.device_name, O_RDONLY );
790                    
791                         if( i_dev >= 0 )
792                         {
793                                 if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
794                                 {
795                                         if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
796                                         {
797                                                 BMessage *msg;
798                                                 msg = new BMessage( OPEN_DVD );
799                                                 msg->AddString( "device", info.device_name );
800                                                 BMenuItem *menu_item;
801                                                 menu_item = new BMenuItem( name, msg );
802                                                 AddItem( menu_item );
803                                         }
804                                         close(i_dev);
805                                 }
806                         }
807                 }
808                 vol->Unset();
809                 status = volRoster->GetNextVolume(vol);
810         }
811         return 0;
812 }
813
814 /*****************************************************************************
815  * LanguageMenu::LanguageMenu
816  *****************************************************************************/
817 LanguageMenu::LanguageMenu( const char *name, int menu_kind, 
818                                                         VlcWrapper *p_wrapper )
819         :BMenu(name)
820 {
821         kind = menu_kind;
822         this->p_wrapper = p_wrapper;
823 }
824
825 /*****************************************************************************
826  * LanguageMenu::~LanguageMenu
827  *****************************************************************************/
828 LanguageMenu::~LanguageMenu()
829 {
830 }
831
832 /*****************************************************************************
833  * LanguageMenu::AttachedToWindow
834  *****************************************************************************/
835 void LanguageMenu::AttachedToWindow()
836 {
837         // remove all items
838         while ( BMenuItem* item = RemoveItem( 0L ) )
839                 delete item;
840
841         SetRadioMode( true );
842         _GetChannels();
843         BMenu::AttachedToWindow();
844 }
845
846 /*****************************************************************************
847  * LanguageMenu::_GetChannels
848  *****************************************************************************/
849 void LanguageMenu::_GetChannels()
850 {
851     BMenuItem *item;
852     BList *list;
853     
854     if( ( list = p_wrapper->GetChannels( kind ) ) == NULL )
855         return;
856     
857     for( int i = 0; i < list->CountItems(); i++ )
858     {
859         item = (BMenuItem*)list->ItemAt( i );
860         AddItem( item );
861     }
862     
863     if( list->CountItems() > 1 )
864         AddItem( new BSeparatorItem(), 1 );
865 }
866
867
868 /*****************************************************************************
869  * TitleMenu::TitleMenu
870  *****************************************************************************/
871 TitleMenu::TitleMenu( const char *name, intf_thread_t  *p_interface )
872         : BMenu(name),
873         p_intf( p_interface )
874 {
875 }
876
877 /*****************************************************************************
878  * TitleMenu::~TitleMenu
879  *****************************************************************************/
880 TitleMenu::~TitleMenu()
881 {
882 }
883
884 /*****************************************************************************
885  * TitleMenu::AttachedToWindow
886  *****************************************************************************/
887 void TitleMenu::AttachedToWindow()
888 {
889     BMenuItem *item;
890     BList *list;
891
892         while( ( item = RemoveItem( 0L ) ) )
893                 delete item;
894     
895     if( ( list = p_intf->p_sys->p_wrapper->GetTitles() ) == NULL )
896         return;
897     
898     for( int i = 0; i < list->CountItems(); i++ )
899     {
900         item = (BMenuItem*)list->ItemAt( i );
901         AddItem( item );
902     }
903     
904         BMenu::AttachedToWindow();
905 }
906
907
908 /*****************************************************************************
909  * ChapterMenu::ChapterMenu
910  *****************************************************************************/
911 ChapterMenu::ChapterMenu( const char *name, intf_thread_t  *p_interface )
912         : BMenu(name),
913         p_intf( p_interface )
914 {
915 }
916
917 /*****************************************************************************
918  * ChapterMenu::~ChapterMenu
919  *****************************************************************************/
920 ChapterMenu::~ChapterMenu()
921 {
922 }
923
924 /*****************************************************************************
925  * ChapterMenu::AttachedToWindow
926  *****************************************************************************/
927 void ChapterMenu::AttachedToWindow()
928 {
929     BMenuItem *item;
930     BList *list;
931
932         while( ( item = RemoveItem( 0L ) ) )
933                 delete item;
934     
935     if( ( list = p_intf->p_sys->p_wrapper->GetChapters() ) == NULL )
936         return;
937     
938     for( int i = 0; i < list->CountItems(); i++ )
939     {
940         item = (BMenuItem*)list->ItemAt( i );
941         AddItem( item );
942     }
943     
944         BMenu::AttachedToWindow();
945 }
946