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