]> git.sesse.net Git - vlc/blob - modules/gui/beos/InterfaceWindow.cpp
beos/*: fixed fullscreen shortcuts
[vlc] / 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.33 2003/04/18 16:10:28 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 "MessagesWindow.h"
52 #include "InterfaceWindow.h"
53
54 #define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps
55 #define INTERFACE_LOCKING_TIMEOUT 5000
56 #define USE_VLC_CONFIG_FILE 0
57
58 // make_sure_frame_is_on_screen
59 bool
60 make_sure_frame_is_on_screen( BRect& frame )
61 {
62         BScreen screen( B_MAIN_SCREEN_ID );
63         if (frame.IsValid() && screen.IsValid()) {
64                 if (!screen.Frame().Contains(frame)) {
65                         // make sure frame fits in the screen
66                         if (frame.Width() > screen.Frame().Width())
67                                 frame.right -= frame.Width() - screen.Frame().Width() + 10.0;
68                         if (frame.Height() > screen.Frame().Height())
69                                 frame.bottom -= frame.Height() - screen.Frame().Height() + 30.0;
70                         // frame is now at the most the size of the screen
71                         if (frame.right > screen.Frame().right)
72                                 frame.OffsetBy(-(frame.right - screen.Frame().right), 0.0);
73                         if (frame.bottom > screen.Frame().bottom)
74                                 frame.OffsetBy(0.0, -(frame.bottom - screen.Frame().bottom));
75                         if (frame.left < screen.Frame().left)
76                                 frame.OffsetBy((screen.Frame().left - frame.left), 0.0);
77                         if (frame.top < screen.Frame().top)
78                                 frame.OffsetBy(0.0, (screen.Frame().top - frame.top));
79                 }
80                 return true;
81         }
82         return false;
83 }
84
85 // make_sure_frame_is_within_limits
86 void
87 make_sure_frame_is_within_limits( BRect& frame, float minWidth, float minHeight,
88                                   float maxWidth, float maxHeight )
89 {
90     if ( frame.Width() < minWidth )
91         frame.right = frame.left + minWidth;
92     if ( frame.Height() < minHeight )
93         frame.bottom = frame.top + minHeight;
94     if ( frame.Width() > maxWidth )
95         frame.right = frame.left + maxWidth;
96     if ( frame.Height() > maxHeight )
97         frame.bottom = frame.top + maxHeight;
98 }
99
100 // get_volume_info
101 bool
102 get_volume_info( BVolume& volume, BString& volumeName, bool& isCDROM, BString& deviceName )
103 {
104         bool success = false;
105         isCDROM = false;
106         deviceName = "";
107         volumeName = "";
108         char name[B_FILE_NAME_LENGTH];
109         if ( volume.GetName( name ) >= B_OK )   // disk is currently mounted
110         {
111                 volumeName = name;
112                 dev_t dev = volume.Device();
113                 fs_info info;
114                 if ( fs_stat_dev( dev, &info ) == B_OK )
115                 {
116                         success = true;
117                         deviceName = info.device_name;
118                         if ( volume.IsReadOnly() )
119                         {
120                                 int i_dev = open( info.device_name, O_RDONLY );
121                                 if ( i_dev >= 0 )
122                                 {
123                                         device_geometry g;
124                                         if ( ioctl( i_dev, B_GET_GEOMETRY, &g, sizeof( g ) ) >= 0 )
125                                                 isCDROM = ( g.device_type == B_CD );
126                                         close( i_dev );
127                                 }
128                         }
129                 }
130         }
131         return success;
132 }
133
134 // collect_folder_contents
135 void
136 collect_folder_contents( BDirectory& dir, BList& list, bool& deep, bool& asked, BEntry& entry )
137 {
138         while ( dir.GetNextEntry( &entry, true ) == B_OK )
139         {
140                 if ( !entry.IsDirectory() )
141                 {
142                         BPath path;
143                         // since the directory will give us the entries in reverse order,
144                         // we put them each at the same index, effectively reversing the
145                         // items while adding them
146                         if ( entry.GetPath( &path ) == B_OK )
147                         {
148                                 BString* string = new BString( path.Path() );
149                                 if ( !list.AddItem( string, 0 ) )
150                                         delete string;  // at least don't leak
151                         }
152                 }
153                 else
154                 {
155                         if ( !asked )
156                         {
157                                 // ask user if we should parse sub-folders as well
158                                 BAlert* alert = new BAlert( "sub-folders?",
159                                                                                         "Open files from all sub-folders as well?",
160                                                                                         "No", "Yes", NULL, B_WIDTH_AS_USUAL,
161                                                                                         B_IDEA_ALERT );
162                                 int32 buttonIndex = alert->Go();
163                                 deep = buttonIndex == 1;
164                                 asked = true;
165                                 // never delete BAlerts!!
166                         }
167                         if ( deep )
168                         {
169                                 BDirectory subDir( &entry );
170                                 if ( subDir.InitCheck() == B_OK )
171                                         collect_folder_contents( subDir, list,
172                                                                                          deep, asked, entry );
173                         }
174                 }
175         }
176 }
177
178
179 /*****************************************************************************
180  * InterfaceWindow
181  *****************************************************************************/
182
183 InterfaceWindow::InterfaceWindow( BRect frame, const char* name,
184                                   intf_thread_t* p_interface )
185     : BWindow( frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
186                B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
187       p_intf( p_interface ),
188       fFilePanel( NULL ),
189       fLastUpdateTime( system_time() ),
190           fSettings( new BMessage( 'sett' ) ),
191           p_wrapper( p_intf->p_sys->p_wrapper )
192 {
193         // TODO: ?!? what about user settings?
194     p_intf->p_sys->b_dvdmenus = false;
195     
196     fPlaylistIsEmpty = !( p_wrapper->PlaylistSize() > 0 );
197     
198     BScreen screen;
199     BRect screen_rect = screen.Frame();
200     BRect window_rect;
201     window_rect.Set( ( screen_rect.right - PREFS_WINDOW_WIDTH ) / 2,
202                      ( screen_rect.bottom - PREFS_WINDOW_HEIGHT ) / 2,
203                      ( screen_rect.right + PREFS_WINDOW_WIDTH ) / 2,
204                      ( screen_rect.bottom + PREFS_WINDOW_HEIGHT ) / 2 );
205     fPreferencesWindow = new PreferencesWindow( p_intf, window_rect, "Settings" );
206     window_rect.Set( screen_rect.right - 500,
207                      screen_rect.top + 50,
208                      screen_rect.right - 150,
209                      screen_rect.top + 250 );
210     fPlaylistWindow = new PlayListWindow( window_rect, "Playlist", this, p_intf );
211     window_rect.Set( screen_rect.right - 500,
212                      screen_rect.top + 300,
213                      screen_rect.right - 150,
214                      screen_rect.top + 600 );
215     fMessagesWindow = new MessagesWindow( p_intf, window_rect, "Messages" );
216
217     // the media control view
218     p_mediaControl = new MediaControlView( BRect( 0.0, 0.0, 250.0, 50.0 ),
219                                            p_intf );
220     p_mediaControl->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
221
222     float width, height;
223     p_mediaControl->GetPreferredSize( &width, &height );
224
225     // set up the main menu
226     fMenuBar = new BMenuBar( BRect(0.0, 0.0, width, 15.0), "main menu",
227                              B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
228
229     // make menu bar resize to correct height
230     float menuWidth, menuHeight;
231     fMenuBar->GetPreferredSize( &menuWidth, &menuHeight );
232     fMenuBar->ResizeTo( width, menuHeight );    // don't change! it's a workarround!
233     // take care of proper size for ourself
234     height += fMenuBar->Bounds().Height();
235     ResizeTo( width, height );
236
237     p_mediaControl->MoveTo( fMenuBar->Bounds().LeftBottom() + BPoint(0.0, 1.0) );
238     AddChild( fMenuBar );
239     AddChild( p_mediaControl );
240
241     // Add the file Menu
242     BMenu* fileMenu = new BMenu( _("File") );
243     fMenuBar->AddItem( fileMenu );
244     fileMenu->AddItem( new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
245                                       new BMessage( OPEN_FILE ), 'O') );
246     
247     fileMenu->AddItem( new CDMenu( "Open Disc" ) );
248
249     fileMenu->AddItem( new BMenuItem( "Open Subtitles" B_UTF8_ELLIPSIS,
250                                       new BMessage( LOAD_SUBFILE ) ) );
251     
252     fileMenu->AddSeparatorItem();
253     BMenuItem* item = new BMenuItem( "About" B_UTF8_ELLIPSIS,
254                                      new BMessage( B_ABOUT_REQUESTED ), 'A');
255     item->SetTarget( be_app );
256     fileMenu->AddItem( item );
257     fileMenu->AddItem( new BMenuItem( "Quit", new BMessage( B_QUIT_REQUESTED ), 'Q') );
258
259     fLanguageMenu = new LanguageMenu("Language", AUDIO_ES, p_wrapper);
260     fSubtitlesMenu = new LanguageMenu("Subtitles", SPU_ES, p_wrapper);
261
262     /* Add the Audio menu */
263     fAudioMenu = new BMenu( _("Audio") );
264     fMenuBar->AddItem ( fAudioMenu );
265     fAudioMenu->AddItem( fLanguageMenu );
266     fAudioMenu->AddItem( fSubtitlesMenu );
267
268     fPrevTitleMI = new BMenuItem( "Prev Title", new BMessage( PREV_TITLE ) );
269     fNextTitleMI = new BMenuItem( "Next Title", new BMessage( NEXT_TITLE ) );
270     fPrevChapterMI = new BMenuItem( "Prev Chapter", new BMessage( PREV_CHAPTER ) );
271     fNextChapterMI = new BMenuItem( "Next Chapter", new BMessage( NEXT_CHAPTER ) );
272     fGotoMenuMI = new BMenuItem( "Goto Menu", new BMessage( NAVIGATE_MENU ) );
273
274     /* Add the Navigation menu */
275     fNavigationMenu = new BMenu( _("Navigation") );
276     fMenuBar->AddItem( fNavigationMenu );
277     fNavigationMenu->AddItem( fGotoMenuMI );
278     fNavigationMenu->AddSeparatorItem();
279     fNavigationMenu->AddItem( fPrevTitleMI );
280     fNavigationMenu->AddItem( fNextTitleMI );
281     fNavigationMenu->AddItem( fTitleMenu = new TitleMenu( "Go to Title", p_intf ) );
282     fNavigationMenu->AddSeparatorItem();
283     fNavigationMenu->AddItem( fPrevChapterMI );
284     fNavigationMenu->AddItem( fNextChapterMI );
285     fNavigationMenu->AddItem( fChapterMenu = new ChapterMenu( "Go to Chapter", p_intf ) );
286
287     /* Add the Speed menu */
288     fSpeedMenu = new BMenu( _("Speed") );
289     fSpeedMenu->SetRadioMode( true );
290     fSpeedMenu->AddItem( fSlowerMI = new BMenuItem( "Slower", new BMessage( SLOWER_PLAY ) ) );
291     fNormalMI = new BMenuItem( "Normal", new BMessage( NORMAL_PLAY ) );
292     fNormalMI->SetMarked(true); // default to normal speed
293     fSpeedMenu->AddItem( fNormalMI );
294     fSpeedMenu->AddItem( fFasterMI = new BMenuItem( "Faster", new BMessage( FASTER_PLAY) ) );
295     fSpeedMenu->SetTargetForItems( this );
296     fMenuBar->AddItem( fSpeedMenu );
297
298     /* Add the Show menu */
299     fShowMenu = new BMenu( _("Window") );
300     fShowMenu->AddItem( new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
301                                        new BMessage( OPEN_PLAYLIST ), 'P') );
302     fShowMenu->AddItem( new BMenuItem( "Messages" B_UTF8_ELLIPSIS,
303                                        new BMessage( OPEN_MESSAGES ), 'M' ) );
304     fShowMenu->AddItem( new BMenuItem( "Settings" B_UTF8_ELLIPSIS,
305                                        new BMessage( OPEN_PREFERENCES ), 'S' ) );
306     fMenuBar->AddItem( fShowMenu );                            
307
308     /* Prepare fow showing */
309     _SetMenusEnabled( false );
310     p_mediaControl->SetEnabled( false );
311
312         _RestoreSettings();    
313
314     Show();
315 }
316
317 InterfaceWindow::~InterfaceWindow()
318 {
319     if( fPlaylistWindow )
320         fPlaylistWindow->ReallyQuit();
321     fPlaylistWindow = NULL;
322     if( fMessagesWindow )
323         fMessagesWindow->ReallyQuit();
324     fMessagesWindow = NULL;
325     if( fPreferencesWindow )
326         fPreferencesWindow->ReallyQuit();
327     fPreferencesWindow = NULL;
328         delete fFilePanel;
329         delete fSettings;
330 }
331
332 /*****************************************************************************
333  * InterfaceWindow::FrameResized
334  *****************************************************************************/
335 void
336 InterfaceWindow::FrameResized(float width, float height)
337 {
338     BRect r(Bounds());
339     fMenuBar->MoveTo(r.LeftTop());
340     fMenuBar->ResizeTo(r.Width(), fMenuBar->Bounds().Height());
341     r.top += fMenuBar->Bounds().Height() + 1.0;
342     p_mediaControl->MoveTo(r.LeftTop());
343     p_mediaControl->ResizeTo(r.Width(), r.Height());
344 }
345
346 /*****************************************************************************
347  * InterfaceWindow::MessageReceived
348  *****************************************************************************/
349 void InterfaceWindow::MessageReceived( BMessage * p_message )
350 {
351     int playback_status;      // remember playback state
352     playback_status = p_wrapper->InputStatus();
353
354     switch( p_message->what )
355     {
356         case B_ABOUT_REQUESTED:
357         {
358             BAlert* alert = new BAlert( "VLC " PACKAGE_VERSION,
359                                         "VLC " PACKAGE_VERSION " for BeOS\n\n"
360                                         "<www.videolan.org>", "OK");
361             alert->Go();
362             break;
363         }
364         case TOGGLE_ON_TOP:
365             break;
366             
367         case OPEN_FILE:
368                 _ShowFilePanel( B_REFS_RECEIVED, "VideoLAN Client: Open Media Files" );
369             break;
370
371         case LOAD_SUBFILE:
372                 _ShowFilePanel( SUBFILE_RECEIVED, "VideoLAN Client: Open Subtitle File" );
373             break;
374
375         case OPEN_PLAYLIST:
376             if (fPlaylistWindow->Lock())
377             {
378                 if (fPlaylistWindow->IsHidden())
379                     fPlaylistWindow->Show();
380                 else
381                     fPlaylistWindow->Activate();
382                 fPlaylistWindow->Unlock();
383             }
384             break;
385         case OPEN_DVD:
386             {
387                 const char *psz_device;
388                 BString type( "dvd" );
389                 if( p_message->FindString( "device", &psz_device ) == B_OK )
390                 {
391                     BString device( psz_device );
392                     p_wrapper->OpenDisc( type, device, 0, 0 );
393                 }
394                 _UpdatePlaylist();
395             }
396             break;
397         
398         case SUBFILE_RECEIVED:
399         {
400             entry_ref ref;
401             if( p_message->FindRef( "refs", 0, &ref ) == B_OK )
402             {
403                 BPath path( &ref );
404                 if ( path.InitCheck() == B_OK )
405                     p_wrapper->LoadSubFile( path.Path() );
406             }
407             break;
408         }
409     
410         case STOP_PLAYBACK:
411             // this currently stops playback not nicely
412             if (playback_status > UNDEF_S)
413             {
414                 p_wrapper->PlaylistStop();
415                 p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
416             }
417             break;
418     
419         case START_PLAYBACK:
420             /*  starts playing in normal mode */
421     
422         case PAUSE_PLAYBACK:
423             /* toggle between pause and play */
424             if (playback_status > UNDEF_S)
425             {
426                 /* pause if currently playing */
427                 if ( playback_status == PLAYING_S )
428                 {
429                     p_wrapper->PlaylistPause();
430                 }
431                 else
432                 {
433                     p_wrapper->PlaylistPlay();
434                 }
435             }
436             else
437             {
438                 /* Play a new file */
439                 p_wrapper->PlaylistPlay();
440             }    
441             break;
442     
443         case FASTER_PLAY:
444             /* cycle the fast playback modes */
445             if (playback_status > UNDEF_S)
446             {
447                 p_wrapper->InputFaster();
448             }
449             break;
450     
451         case SLOWER_PLAY:
452             /*  cycle the slow playback modes */
453             if (playback_status > UNDEF_S)
454             {
455                 p_wrapper->InputSlower();
456             }
457             break;
458     
459         case NORMAL_PLAY:
460             /*  restore speed to normal if already playing */
461             if (playback_status > UNDEF_S)
462             {
463                 p_wrapper->PlaylistPlay();
464             }
465             break;
466     
467         case SEEK_PLAYBACK:
468             /* handled by semaphores */
469             break;
470         // volume related messages
471         case VOLUME_CHG:
472             /* adjust the volume */
473             if (playback_status > UNDEF_S)
474             {
475                 p_wrapper->SetVolume( p_mediaControl->GetVolume() );
476                 p_mediaControl->SetMuted( p_wrapper->IsMuted() );
477             }
478             break;
479     
480         case VOLUME_MUTE:
481             // toggle muting
482             if( p_wrapper->IsMuted() )
483                 p_wrapper->VolumeRestore();
484             else
485                 p_wrapper->VolumeMute();
486             p_mediaControl->SetMuted( p_wrapper->IsMuted() );
487             break;
488     
489         case SELECT_CHANNEL:
490             if ( playback_status > UNDEF_S )
491             {
492                 int32 channel;
493                 if ( p_message->FindInt32( "channel", &channel ) == B_OK )
494                 {
495                     p_wrapper->ToggleLanguage( channel );
496                 }
497             }
498             break;
499     
500         case SELECT_SUBTITLE:
501             if ( playback_status > UNDEF_S )
502             {
503                 int32 subtitle;
504                 if ( p_message->FindInt32( "subtitle", &subtitle ) == B_OK )
505                      p_wrapper->ToggleSubtitle( subtitle );
506             }
507             break;
508     
509         // specific navigation messages
510         case PREV_TITLE:
511         {
512             p_wrapper->PrevTitle();
513             break;
514         }
515         case NEXT_TITLE:
516         {
517             p_wrapper->NextTitle();
518             break;
519         }
520         case NAVIGATE_MENU:
521                 p_wrapper->ToggleTitle( 0 );
522                 break;
523         case TOGGLE_TITLE:
524             if ( playback_status > UNDEF_S )
525             {
526                 int32 index;
527                 if( p_message->FindInt32( "index", &index ) == B_OK )
528                     p_wrapper->ToggleTitle( index );
529             }
530             break;
531         case PREV_CHAPTER:
532         {
533             p_wrapper->PrevChapter();
534             break;
535         }
536         case NEXT_CHAPTER:
537         {
538             p_wrapper->NextChapter();
539             break;
540         }
541         case TOGGLE_CHAPTER:
542             if ( playback_status > UNDEF_S )
543             {
544                 int32 index;
545                 if( p_message->FindInt32( "index", &index ) == B_OK )
546                     p_wrapper->ToggleChapter( index );
547             }
548             break;
549         case PREV_FILE:
550             p_wrapper->PlaylistPrev();
551             break;
552         case NEXT_FILE:
553             p_wrapper->PlaylistNext();
554             break;
555         // general next/prev functionality (skips to whatever makes most sense)
556         case NAVIGATE_PREV:
557             p_wrapper->NavigatePrev();
558             break;
559         case NAVIGATE_NEXT:
560             p_wrapper->NavigateNext();
561             break;
562         // drag'n'drop and system messages
563         case MSG_SOUNDPLAY:
564                 // convert soundplay drag'n'drop message (containing paths)
565                 // to normal message (containing refs)
566                 {
567                         const char* path;
568                         for ( int32 i = 0; p_message->FindString( "path", i, &path ) == B_OK; i++ )
569                         {
570                                 entry_ref ref;
571                                 if ( get_ref_for_path( path, &ref ) == B_OK )
572                                         p_message->AddRef( "refs", &ref );
573                         }
574                 }
575                 // fall through
576         case B_REFS_RECEIVED:
577         case B_SIMPLE_DATA:
578             {
579                 /* file(s) opened by the File menu -> append to the playlist;
580                  * file(s) opened by drag & drop -> replace playlist;
581                  * file(s) opened by 'shift' + drag & drop -> append */
582                 bool replace = false;
583                 bool reverse = false;
584                 if ( p_message->WasDropped() )
585                 {
586                     replace = !( modifiers() & B_SHIFT_KEY );
587                     reverse = true;
588                 }
589                     
590                 // build list of files to be played from message contents
591                 entry_ref ref;
592                 BList files;
593                 
594                 // if we should parse sub-folders as well
595                         bool askedAlready = false;
596                         bool parseSubFolders = askedAlready;
597                         // traverse refs in reverse order
598                         int32 count;
599                         type_code dummy;
600                         if ( p_message->GetInfo( "refs", &dummy, &count ) == B_OK && count > 0 )
601                         {
602                                 int32 i = reverse ? count - 1 : 0;
603                                 int32 increment = reverse ? -1 : 1;
604                         for ( ; p_message->FindRef( "refs", i, &ref ) == B_OK; i += increment )
605                         {
606                             BPath path( &ref );
607                             if ( path.InitCheck() == B_OK )
608                             {
609                                 bool add = true;
610                                 // has the user dropped a folder?
611                                 BDirectory dir( &ref );
612                                 if ( dir.InitCheck() == B_OK)
613                                 {
614                                         // has the user dropped a dvd disk icon?
615                                                                 if ( dir.IsRootDirectory() )
616                                                                 {
617                                                                         BVolumeRoster volRoster;
618                                                                         BVolume vol;
619                                                                         BDirectory volumeRoot;
620                                                                         status_t status = volRoster.GetNextVolume( &vol );
621                                                                         while ( status == B_NO_ERROR )
622                                                                         {
623                                                                                 if ( vol.GetRootDirectory( &volumeRoot ) == B_OK
624                                                                                          && dir == volumeRoot )
625                                                                                 {
626                                                                                         BString volumeName;
627                                                                                         BString deviceName;
628                                                                                         bool isCDROM;
629                                                                                         if ( get_volume_info( vol, volumeName, isCDROM, deviceName )
630                                                                                                  && isCDROM )
631                                                                                         {
632                                                                                                 BMessage msg( OPEN_DVD );
633                                                                                                 msg.AddString( "device", deviceName.String() );
634                                                                                                 PostMessage( &msg );
635                                                                                                 add = false;
636                                                                                         }
637                                                                                         break;
638                                                                                 }
639                                                                                 else
640                                                                                 {
641                                                                                         vol.Unset();
642                                                                                         status = volRoster.GetNextVolume( &vol );
643                                                                                 }
644                                                                         }
645                                                                 }
646                                         if ( add )
647                                         {
648                                                 add = false;
649                                                 dir.Rewind();   // defensive programming
650                                                 BEntry entry;
651                                                                         collect_folder_contents( dir, files,
652                                                                                                                          parseSubFolders,
653                                                                                                                          askedAlready,
654                                                                                                                          entry );
655                                         }
656                                 }
657                                 if ( add )
658                                 {
659                                         BString* string = new BString( path.Path() );
660                                         if ( !files.AddItem( string, 0 ) )
661                                                 delete string;  // at least don't leak
662                                 }
663                             }
664                         }
665                         // give the list to VLC
666                         // BString objects allocated here will be deleted there
667                         int32 index;
668                         if ( p_message->FindInt32("drop index", &index) != B_OK )
669                                 index = -1;
670                         p_wrapper->OpenFiles( &files, replace, index );
671                         _UpdatePlaylist();
672                         }
673             }
674             break;
675
676         case OPEN_PREFERENCES:
677         {
678             if( fPreferencesWindow->Lock() )
679             {
680                 if (fPreferencesWindow->IsHidden())
681                     fPreferencesWindow->Show();
682                 else
683                     fPreferencesWindow->Activate();
684                 fPreferencesWindow->Unlock();
685             }
686             break;
687         }
688
689         case OPEN_MESSAGES:
690         {
691             if( fMessagesWindow->Lock() )
692             {
693                 if (fMessagesWindow->IsHidden())
694                     fMessagesWindow->Show();
695                 else
696                     fMessagesWindow->Activate();
697                 fMessagesWindow->Unlock();
698             }
699             break;
700         }
701         case MSG_UPDATE:
702                 UpdateInterface();
703                 break;
704         default:
705             BWindow::MessageReceived( p_message );
706             break;
707     }
708
709 }
710
711 /*****************************************************************************
712  * InterfaceWindow::QuitRequested
713  *****************************************************************************/
714 bool InterfaceWindow::QuitRequested()
715 {
716     p_wrapper->PlaylistStop();
717     p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
718
719         _StoreSettings();
720    
721     p_intf->b_die = 1;
722
723     return( true );
724 }
725
726 /*****************************************************************************
727  * InterfaceWindow::UpdateInterface
728  *****************************************************************************/
729 void InterfaceWindow::UpdateInterface()
730 {
731     if( p_wrapper->HasInput() )
732     {
733         if ( acquire_sem( p_mediaControl->fScrubSem ) == B_OK )
734         {
735             p_wrapper->SetTimeAsFloat( p_mediaControl->GetSeekTo() );
736         }
737         else if ( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK )
738         {
739             p_mediaControl->SetEnabled( true );
740             bool hasTitles = p_wrapper->HasTitles();
741             bool hasChapters = p_wrapper->HasChapters();
742             p_mediaControl->SetStatus( p_wrapper->InputStatus(), 
743                                        p_wrapper->InputRate() );
744             p_mediaControl->SetProgress( p_wrapper->GetTimeAsFloat() );
745             _SetMenusEnabled( true, hasChapters, hasTitles );
746
747             _UpdateSpeedMenu( p_wrapper->InputRate() );
748
749             // enable/disable skip buttons
750             bool canSkipPrev;
751             bool canSkipNext;
752             p_wrapper->GetNavCapabilities( &canSkipPrev, &canSkipNext );
753             p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
754
755             if ( p_wrapper->HasInput() )
756             {
757                 p_mediaControl->SetAudioEnabled( true );
758                 p_mediaControl->SetMuted( p_wrapper->IsMuted() );
759             } else
760                 p_mediaControl->SetAudioEnabled( false );
761
762             Unlock();
763         }
764         // update playlist as well
765         if ( fPlaylistWindow->LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK )
766         {
767             fPlaylistWindow->UpdatePlaylist();
768             fPlaylistWindow->Unlock();
769         }
770     }
771     else
772     {
773                 if ( LockWithTimeout(INTERFACE_LOCKING_TIMEOUT) == B_OK )
774                 {
775                 _SetMenusEnabled( false );
776                 if( !( p_wrapper->PlaylistSize() > 0 ) )
777                     p_mediaControl->SetEnabled( false );
778                 else
779                 {
780                     p_mediaControl->SetProgress( 0 );
781                     // enable/disable skip buttons
782                     bool canSkipPrev;
783                     bool canSkipNext;
784                     p_wrapper->GetNavCapabilities( &canSkipPrev, &canSkipNext );
785                     p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
786                         }
787             Unlock();
788         }
789     }
790
791     fLastUpdateTime = system_time();
792 }
793
794 /*****************************************************************************
795  * InterfaceWindow::IsStopped
796  *****************************************************************************/
797 bool
798 InterfaceWindow::IsStopped() const
799 {
800     return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
801 }
802
803 /*****************************************************************************
804  * InterfaceWindow::_UpdatePlaylist
805  *****************************************************************************/
806 void
807 InterfaceWindow::_UpdatePlaylist()
808 {
809     if ( fPlaylistWindow->Lock() )
810     {
811         fPlaylistWindow->UpdatePlaylist( true );
812         fPlaylistWindow->Unlock();
813         p_mediaControl->SetEnabled( p_wrapper->PlaylistSize() );
814     }
815 }
816
817 /*****************************************************************************
818  * InterfaceWindow::_SetMenusEnabled
819  *****************************************************************************/
820 void
821 InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles)
822 {
823     if (!hasFile)
824     {
825         hasChapters = false;
826         hasTitles = false;
827     }
828     if ( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK)
829     {
830         if ( fNextChapterMI->IsEnabled() != hasChapters )
831              fNextChapterMI->SetEnabled( hasChapters );
832         if ( fPrevChapterMI->IsEnabled() != hasChapters )
833              fPrevChapterMI->SetEnabled( hasChapters );
834         if ( fChapterMenu->IsEnabled() != hasChapters )
835              fChapterMenu->SetEnabled( hasChapters );
836         if ( fNextTitleMI->IsEnabled() != hasTitles )
837              fNextTitleMI->SetEnabled( hasTitles );
838         if ( fPrevTitleMI->IsEnabled() != hasTitles )
839              fPrevTitleMI->SetEnabled( hasTitles );
840         if ( fTitleMenu->IsEnabled() != hasTitles )
841              fTitleMenu->SetEnabled( hasTitles );
842         if ( fAudioMenu->IsEnabled() != hasFile )
843              fAudioMenu->SetEnabled( hasFile );
844         if ( fNavigationMenu->IsEnabled() != hasFile )
845              fNavigationMenu->SetEnabled( hasFile );
846         if ( fLanguageMenu->IsEnabled() != hasFile )
847              fLanguageMenu->SetEnabled( hasFile );
848         if ( fSubtitlesMenu->IsEnabled() != hasFile )
849              fSubtitlesMenu->SetEnabled( hasFile );
850         if ( fSpeedMenu->IsEnabled() != hasFile )
851              fSpeedMenu->SetEnabled( hasFile );
852         // "goto menu" menu item
853         bool hasMenu = p_intf->p_sys->b_dvdmenus ? hasTitles : false;
854         if ( fGotoMenuMI->IsEnabled() != hasMenu )
855              fGotoMenuMI->SetEnabled( hasMenu );
856         Unlock();
857     }
858 }
859
860 /*****************************************************************************
861  * InterfaceWindow::_UpdateSpeedMenu
862  *****************************************************************************/
863 void
864 InterfaceWindow::_UpdateSpeedMenu( int rate )
865 {
866     if ( rate == DEFAULT_RATE )
867     {
868         if ( !fNormalMI->IsMarked() )
869             fNormalMI->SetMarked( true );
870     }
871     else if ( rate < DEFAULT_RATE )
872     {
873         if ( !fFasterMI->IsMarked() )
874             fFasterMI->SetMarked( true );
875     }
876     else
877     {
878         if ( !fSlowerMI->IsMarked() )
879             fSlowerMI->SetMarked( true );
880     }
881 }
882
883 /*****************************************************************************
884  * InterfaceWindow::_InputStreamChanged
885  *****************************************************************************/
886 void
887 InterfaceWindow::_InputStreamChanged()
888 {
889     // TODO: move more stuff from updateInterface() here!
890     snooze( 400000 );
891     p_wrapper->SetVolume( p_mediaControl->GetVolume() );
892 }
893
894 /*****************************************************************************
895  * InterfaceWindow::_ShowFilePanel
896  *****************************************************************************/
897 void
898 InterfaceWindow::_ShowFilePanel( uint32 command, const char* windowTitle )
899 {
900         if( !fFilePanel )
901         {
902                 fFilePanel = new BFilePanel( B_OPEN_PANEL, NULL, NULL,
903                                                                          B_FILE_NODE | B_DIRECTORY_NODE );
904                 fFilePanel->SetTarget( this );
905         }
906         fFilePanel->Window()->SetTitle( windowTitle );
907         BMessage message( command );
908         fFilePanel->SetMessage( &message );
909         if ( !fFilePanel->IsShowing() )
910         {
911                 fFilePanel->Refresh();
912                 fFilePanel->Show();
913         }
914 }
915
916 // set_window_pos
917 void
918 set_window_pos( BWindow* window, BRect frame )
919 {
920         // sanity checks: make sure window is not too big/small
921         // and that it's not off-screen
922         float minWidth, maxWidth, minHeight, maxHeight;
923         window->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight );
924
925         make_sure_frame_is_within_limits( frame,
926                                                                           minWidth, minHeight, maxWidth, maxHeight );
927         if ( make_sure_frame_is_on_screen( frame ) )
928         {
929                 window->MoveTo( frame.LeftTop() );
930                 window->ResizeTo( frame.Width(), frame.Height() );
931         }
932 }
933
934 // set_window_pos
935 void
936 launch_window( BWindow* window, bool showing )
937 {
938         if ( window->Lock() )
939         {
940                 if ( showing )
941                 {
942                         if ( window->IsHidden() )
943                                 window->Show();
944                 }
945                 else
946                 {
947                         if ( !window->IsHidden() )
948                                 window->Hide();
949                 }
950                 window->Unlock();
951         }
952 }
953
954 /*****************************************************************************
955  * InterfaceWindow::_RestoreSettings
956  *****************************************************************************/
957 void
958 InterfaceWindow::_RestoreSettings()
959 {
960         if ( USE_VLC_CONFIG_FILE )
961         {
962                 // main window size and position
963             int i_width = config_GetInt( p_intf, "beos-intf-width" ),
964                 i_height = config_GetInt( p_intf, "beos-intf-height" ),
965                 i_xpos = config_GetInt( p_intf, "beos-intf-xpos" ),
966                 i_ypos = config_GetInt( p_intf, "beos-intf-ypos" );
967             if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 )
968             {
969                 BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height );
970                 set_window_pos( this, r );
971             }
972                 // playlist window size and position
973             i_width = config_GetInt( p_intf, "beos-playlist-width" ),
974             i_height = config_GetInt( p_intf, "beos-playlist-height" ),
975             i_xpos = config_GetInt( p_intf, "beos-playlist-xpos" ),
976             i_ypos = config_GetInt( p_intf, "beos-playlist-ypos" );
977             if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 )
978             {
979                 BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height );
980                 set_window_pos( fPlaylistWindow, r );
981             }
982             // playlist showing
983             launch_window( fPlaylistWindow, config_GetInt( p_intf, "beos-playlist-show" ) );
984             // messages window size and position
985             i_width = config_GetInt( p_intf, "beos-messages-width" ),
986             i_height = config_GetInt( p_intf, "beos-messages-height" ),
987             i_xpos = config_GetInt( p_intf, "beos-messages-xpos" ),
988             i_ypos = config_GetInt( p_intf, "beos-messages-ypos" );
989             if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 )
990             {
991                 BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height );
992                 set_window_pos( fMessagesWindow, r );
993             }
994             // messages showing
995             launch_window( fMessagesWindow, config_GetInt( p_intf, "beos-messages-show" ) );
996
997                 // messages window size and position
998             i_width = config_GetInt( p_intf, "beos-settings-width" ),
999             i_height = config_GetInt( p_intf, "beos-settings-height" ),
1000             i_xpos = config_GetInt( p_intf, "beos-settings-xpos" ),
1001             i_ypos = config_GetInt( p_intf, "beos-settings-ypos" );
1002             if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 )
1003             {
1004                 BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height );
1005                 set_window_pos( fPreferencesWindow, r );
1006             }
1007             // settings showing
1008             launch_window( fPreferencesWindow, config_GetInt( p_intf, "beos-settings-show" ) );
1009         }
1010         else
1011         {
1012                 if ( load_settings( fSettings, "interface_settings", "VideoLAN Client" ) == B_OK )
1013                 {
1014                         BRect frame;
1015                         if ( fSettings->FindRect( "main frame", &frame ) == B_OK )
1016                                 set_window_pos( this, frame );
1017                         if (fSettings->FindRect( "playlist frame", &frame ) == B_OK )
1018                                 set_window_pos( fPlaylistWindow, frame );
1019                         if (fSettings->FindRect( "messages frame", &frame ) == B_OK )
1020                                 set_window_pos( fMessagesWindow, frame );
1021                         if (fSettings->FindRect( "settings frame", &frame ) == B_OK )
1022                                 set_window_pos( fPreferencesWindow, frame );
1023                         
1024                         bool showing;
1025                         if ( fSettings->FindBool( "playlist showing", &showing ) == B_OK )
1026                                 launch_window( fPlaylistWindow, showing );
1027                         if ( fSettings->FindBool( "messages showing", &showing ) == B_OK )
1028                                 launch_window( fMessagesWindow, showing );
1029                         if ( fSettings->FindBool( "settings showing", &showing ) == B_OK )
1030                                 launch_window( fPreferencesWindow, showing );
1031         
1032                         uint32 displayMode;
1033                         if ( fSettings->FindInt32( "playlist display mode", (int32*)&displayMode ) == B_OK )
1034                                 fPlaylistWindow->SetDisplayMode( displayMode );
1035                 }
1036         }
1037 }
1038
1039 /*****************************************************************************
1040  * InterfaceWindow::_StoreSettings
1041  *****************************************************************************/
1042 void
1043 InterfaceWindow::_StoreSettings()
1044 {
1045         if ( USE_VLC_CONFIG_FILE )
1046         {
1047             // save interface settings in vlc config file
1048             BRect frame = Frame();
1049             config_PutInt( p_intf, "beos-intf-width", (int)frame.Width() );
1050             config_PutInt( p_intf, "beos-intf-height", (int)frame.Height() );
1051             config_PutInt( p_intf, "beos-intf-xpos", (int)frame.left );
1052             config_PutInt( p_intf, "beos-intf-ypos", (int)frame.top );
1053             if( fPlaylistWindow->Lock() )
1054             {
1055                 frame = fPlaylistWindow->Frame();
1056                 config_PutInt( p_intf, "beos-playlist-width", (int)frame.Width() );
1057                 config_PutInt( p_intf, "beos-playlist-height", (int)frame.Height() );
1058                 config_PutInt( p_intf, "beos-playlist-xpos", (int)frame.left );
1059                 config_PutInt( p_intf, "beos-playlist-ypos", (int)frame.top );
1060                 config_PutInt( p_intf, "beos-playlist-show", !fPlaylistWindow->IsHidden() );
1061                 fPlaylistWindow->Unlock();
1062             }
1063             if( fMessagesWindow->Lock() )
1064             {
1065                 frame = fMessagesWindow->Frame();
1066                 config_PutInt( p_intf, "beos-messages-width", (int)frame.Width() );
1067                 config_PutInt( p_intf, "beos-messages-height", (int)frame.Height() );
1068                 config_PutInt( p_intf, "beos-messages-xpos", (int)frame.left );
1069                 config_PutInt( p_intf, "beos-messages-ypos", (int)frame.top );
1070                 config_PutInt( p_intf, "beos-messages-show", !fMessagesWindow->IsHidden() );
1071                 fMessagesWindow->Unlock();
1072             }
1073             if( fPreferencesWindow->Lock() )
1074             {
1075                 frame = fPreferencesWindow->Frame();
1076                 config_PutInt( p_intf, "beos-messages-width", (int)frame.Width() );
1077                 config_PutInt( p_intf, "beos-messages-height", (int)frame.Height() );
1078                 config_PutInt( p_intf, "beos-messages-xpos", (int)frame.left );
1079                 config_PutInt( p_intf, "beos-messages-ypos", (int)frame.top );
1080                 config_PutInt( p_intf, "beos-messages-show", !fPreferencesWindow->IsHidden() );
1081                 fPreferencesWindow->Unlock();
1082             }
1083         }
1084     else
1085     {
1086                 if ( fSettings->ReplaceRect( "main frame", Frame() ) != B_OK )
1087                         fSettings->AddRect( "main frame", Frame() );
1088                 if ( fPlaylistWindow->Lock() )
1089                 {
1090                         if (fSettings->ReplaceRect( "playlist frame", fPlaylistWindow->Frame() ) != B_OK)
1091                                 fSettings->AddRect( "playlist frame", fPlaylistWindow->Frame() );
1092                         if (fSettings->ReplaceBool( "playlist showing", !fPlaylistWindow->IsHidden() ) != B_OK)
1093                                 fSettings->AddBool( "playlist showing", !fPlaylistWindow->IsHidden() );
1094                         fPlaylistWindow->Unlock();
1095                 }
1096                 if ( fMessagesWindow->Lock() )
1097                 {
1098                         if (fSettings->ReplaceRect( "messages frame", fMessagesWindow->Frame() ) != B_OK)
1099                                 fSettings->AddRect( "messages frame", fMessagesWindow->Frame() );
1100                         if (fSettings->ReplaceBool( "messages showing", !fMessagesWindow->IsHidden() ) != B_OK)
1101                                 fSettings->AddBool( "messages showing", !fMessagesWindow->IsHidden() );
1102                         fMessagesWindow->Unlock();
1103                 }
1104                 if ( fPreferencesWindow->Lock() )
1105                 {
1106                         if (fSettings->ReplaceRect( "settings frame", fPreferencesWindow->Frame() ) != B_OK)
1107                                 fSettings->AddRect( "settings frame", fPreferencesWindow->Frame() );
1108                         if (fSettings->ReplaceBool( "settings showing", !fPreferencesWindow->IsHidden() ) != B_OK)
1109                                 fSettings->AddBool( "settings showing", !fPreferencesWindow->IsHidden() );
1110                         fPreferencesWindow->Unlock();
1111                 }
1112                 uint32 displayMode = fPlaylistWindow->DisplayMode();
1113                 if (fSettings->ReplaceInt32( "playlist display mode", displayMode ) != B_OK )
1114                         fSettings->AddInt32( "playlist display mode", displayMode );
1115         
1116                 save_settings( fSettings, "interface_settings", "VideoLAN Client" );
1117     }
1118
1119         // save VLC internal settings
1120         config_SaveConfigFile( p_intf, "beos" );
1121         config_SaveConfigFile( p_intf, "main" );
1122         config_SaveConfigFile( p_intf, "adjust" );
1123         config_SaveConfigFile( p_intf, "ffmpeg" );
1124 }
1125
1126
1127
1128
1129
1130
1131 /*****************************************************************************
1132  * CDMenu::CDMenu
1133  *****************************************************************************/
1134 CDMenu::CDMenu(const char *name)
1135       : BMenu(name)
1136 {
1137 }
1138
1139 /*****************************************************************************
1140  * CDMenu::~CDMenu
1141  *****************************************************************************/
1142 CDMenu::~CDMenu()
1143 {
1144 }
1145
1146 /*****************************************************************************
1147  * CDMenu::AttachedToWindow
1148  *****************************************************************************/
1149 void CDMenu::AttachedToWindow(void)
1150 {
1151     // remove all items
1152     while ( BMenuItem* item = RemoveItem( 0L ) )
1153         delete item;
1154     GetCD( "/dev/disk" );
1155     BMenu::AttachedToWindow();
1156 }
1157
1158 /*****************************************************************************
1159  * CDMenu::GetCD
1160  *****************************************************************************/
1161 int CDMenu::GetCD( const char *directory )
1162 {
1163         BVolumeRoster volRoster;
1164         BVolume vol;
1165         BDirectory dir;
1166         status_t status = volRoster.GetNextVolume( &vol );
1167         while ( status ==  B_NO_ERROR )
1168         {
1169                 BString deviceName;
1170                 BString volumeName;
1171                 bool isCDROM;
1172                 if ( get_volume_info( vol, volumeName, isCDROM, deviceName )
1173                          && isCDROM )
1174                 {
1175                         BMessage* msg = new BMessage( OPEN_DVD );
1176                         msg->AddString( "device", deviceName.String() );
1177                         BMenuItem* item = new BMenuItem( volumeName.String(), msg );
1178                         AddItem( item );
1179                 }
1180                 vol.Unset();
1181                 status = volRoster.GetNextVolume( &vol );
1182         }
1183 }
1184
1185 /*****************************************************************************
1186  * LanguageMenu::LanguageMenu
1187  *****************************************************************************/
1188 LanguageMenu::LanguageMenu( const char *name, int menu_kind, 
1189                             VlcWrapper *p_wrapper )
1190     :BMenu(name)
1191 {
1192     kind = menu_kind;
1193     this->p_wrapper = p_wrapper;
1194 }
1195
1196 /*****************************************************************************
1197  * LanguageMenu::~LanguageMenu
1198  *****************************************************************************/
1199 LanguageMenu::~LanguageMenu()
1200 {
1201 }
1202
1203 /*****************************************************************************
1204  * LanguageMenu::AttachedToWindow
1205  *****************************************************************************/
1206 void LanguageMenu::AttachedToWindow()
1207 {
1208     // remove all items
1209     while ( BMenuItem* item = RemoveItem( 0L ) )
1210         delete item;
1211
1212     SetRadioMode( true );
1213         if ( BList *list = p_wrapper->GetChannels( kind ) )
1214         {
1215             for ( int32 i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ )
1216                 AddItem( item );
1217             
1218             if ( list->CountItems() > 1 )
1219                 AddItem( new BSeparatorItem(), 1 );
1220         }
1221     BMenu::AttachedToWindow();
1222 }
1223
1224 /*****************************************************************************
1225  * TitleMenu::TitleMenu
1226  *****************************************************************************/
1227 TitleMenu::TitleMenu( const char *name, intf_thread_t  *p_interface )
1228     : BMenu(name),
1229     p_intf( p_interface )
1230 {
1231 }
1232
1233 /*****************************************************************************
1234  * TitleMenu::~TitleMenu
1235  *****************************************************************************/
1236 TitleMenu::~TitleMenu()
1237 {
1238 }
1239
1240 /*****************************************************************************
1241  * TitleMenu::AttachedToWindow
1242  *****************************************************************************/
1243 void TitleMenu::AttachedToWindow()
1244 {
1245     while( BMenuItem* item = RemoveItem( 0L ) )
1246         delete item;
1247
1248     if ( BList *list = p_intf->p_sys->p_wrapper->GetTitles() )
1249         {    
1250                 for( int i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ )
1251                 AddItem( item );
1252         }
1253     BMenu::AttachedToWindow();
1254 }
1255
1256
1257 /*****************************************************************************
1258  * ChapterMenu::ChapterMenu
1259  *****************************************************************************/
1260 ChapterMenu::ChapterMenu( const char *name, intf_thread_t  *p_interface )
1261     : BMenu(name),
1262     p_intf( p_interface )
1263 {
1264 }
1265
1266 /*****************************************************************************
1267  * ChapterMenu::~ChapterMenu
1268  *****************************************************************************/
1269 ChapterMenu::~ChapterMenu()
1270 {
1271 }
1272
1273 /*****************************************************************************
1274  * ChapterMenu::AttachedToWindow
1275  *****************************************************************************/
1276 void ChapterMenu::AttachedToWindow()
1277 {
1278     while( BMenuItem* item = RemoveItem( 0L ) )
1279         delete item;
1280
1281     if ( BList* list = p_intf->p_sys->p_wrapper->GetChapters() )
1282         {    
1283             for( int i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ )
1284                 AddItem( item );
1285         }
1286     
1287     BMenu::AttachedToWindow();
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 /*****************************************************************************
1299  * load_settings
1300  *****************************************************************************/
1301 status_t
1302 load_settings( BMessage* message, const char* fileName, const char* folder )
1303 {
1304         status_t ret = B_BAD_VALUE;
1305         if ( message )
1306         {
1307                 BPath path;
1308                 if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
1309                 {
1310                         // passing folder is optional
1311                         if ( folder )
1312                                 ret = path.Append( folder );
1313                         if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
1314                         {
1315                                 BFile file( path.Path(), B_READ_ONLY );
1316                                 if ( ( ret = file.InitCheck() ) == B_OK )
1317                                 {
1318                                         ret = message->Unflatten( &file );
1319                                         file.Unset();
1320                                 }
1321                         }
1322                 }
1323         }
1324         return ret;
1325 }
1326
1327 /*****************************************************************************
1328  * save_settings
1329  *****************************************************************************/
1330 status_t
1331 save_settings( BMessage* message, const char* fileName, const char* folder )
1332 {
1333         status_t ret = B_BAD_VALUE;
1334         if ( message )
1335         {
1336                 BPath path;
1337                 if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
1338                 {
1339                         // passing folder is optional
1340                         if ( folder && ( ret = path.Append( folder ) ) == B_OK )
1341                                 ret = create_directory( path.Path(), 0777 );
1342                         if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
1343                         {
1344                                 BFile file( path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE );
1345                                 if ( ( ret = file.InitCheck() ) == B_OK )
1346                                 {
1347                                         ret = message->Flatten( &file );
1348                                         file.Unset();
1349                                 }
1350                         }
1351                 }
1352         }
1353         return ret;
1354 }