* ALL: decoders now use a fourcc as a probe value.
[vlc.git] / plugins / beos / InterfaceWindow.cpp
1 /*****************************************************************************
2  * InterfaceWindow.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: InterfaceWindow.cpp,v 1.20 2002/07/23 00:39:16 sam 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  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /* System headers */
28 #include <kernel/OS.h>
29 #include <InterfaceKit.h>
30 #include <AppKit.h>
31 #include <StorageKit.h>
32 #include <malloc.h>
33 #include <scsi.h>
34 #include <scsiprobe_driver.h>
35 #include <fs_info.h>
36 #include <string.h>
37
38
39 /* VLC headers */
40 #include <vlc/vlc.h>
41 #include <vlc/aout.h>
42 #include <vlc/intf.h>
43
44 /* BeOS interface headers */
45 #include "MsgVals.h"
46 #include "MediaControlView.h"
47 #include "PlayListWindow.h"
48 #include "InterfaceWindow.h"
49
50
51 /*****************************************************************************
52  * InterfaceWindow
53  *****************************************************************************/
54
55 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
56                                   intf_thread_t  *p_interface )
57     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
58                B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
59                 | B_ASYNCHRONOUS_CONTROLS )
60 {
61     file_panel = NULL;
62     playlist_window = NULL;
63     p_intf = p_interface;
64     BRect controlRect(0,0,0,0);
65     b_empty_playlist = (p_intf->p_vlc->p_playlist->i_size < 0);
66
67     /* set the title bar */
68     SetName( "interface" );
69     SetTitle(VOUT_TITLE);
70
71     /* set up the main menu */
72     BMenuBar *menu_bar;
73     menu_bar = new BMenuBar(controlRect, "main menu");
74     AddChild( menu_bar );
75
76     BMenu *mFile;
77     BMenu *mAudio;
78     CDMenu *cd_menu;
79     BMenu *mNavigation;
80     BMenu *mConfig;
81     
82     /* Add the file Menu */
83     BMenuItem *mItem;
84     menu_bar->AddItem( mFile = new BMenu( "File" ) );
85     menu_bar->ResizeToPreferred();
86     mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
87                                            new BMessage(OPEN_FILE), 'O') );
88     
89     cd_menu = new CDMenu( "Open Disc" );
90     mFile->AddItem( cd_menu );
91     
92     mFile->AddSeparatorItem();
93     mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
94                                            new BMessage(OPEN_PLAYLIST), 'P') );
95     
96     mFile->AddSeparatorItem();
97     mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
98                                        new BMessage(B_ABOUT_REQUESTED), 'A') );
99     mItem->SetTarget( be_app );
100     mFile->AddItem(mItem = new BMenuItem( "Quit",
101                                         new BMessage(B_QUIT_REQUESTED), 'Q') );
102
103     /* Add the Audio menu */
104     menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
105     menu_bar->ResizeToPreferred();
106     mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
107     mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
108
109     /* Add the Navigation menu */
110     menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
111     menu_bar->ResizeToPreferred();
112     mNavigation->AddItem( new BMenuItem( "Prev Title",
113                                         new BMessage(PREV_TITLE)) );
114     mNavigation->AddItem( new BMenuItem( "Next Title",
115                                         new BMessage(NEXT_TITLE)) );
116     mNavigation->AddItem( new BMenuItem( "Prev Chapter",
117                                         new BMessage(PREV_CHAPTER)) );
118     mNavigation->AddItem( new BMenuItem( "Next Chapter",
119                                         new BMessage(NEXT_CHAPTER)) );
120                                         
121     /* Add the Config menu */
122     menu_bar->AddItem( mConfig = new BMenu( "Config" ) );
123     menu_bar->ResizeToPreferred();
124     mConfig->AddItem( miOnTop = new BMenuItem( "Always on Top",
125                                         new BMessage(TOGGLE_ON_TOP)) );
126     miOnTop->SetMarked(false);                                    
127
128     ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
129     controlRect = Bounds();
130     controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
131
132     p_mediaControl = new MediaControlView( controlRect );
133     p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
134     b_empty_playlist = true;
135     p_mediaControl->SetEnabled( !b_empty_playlist );
136
137     /* Show */
138     AddChild( p_mediaControl );
139     Show();
140     
141 }
142
143 InterfaceWindow::~InterfaceWindow()
144 {
145     if (playlist_window) playlist_window->ReallyQuit();
146 }
147
148 /*****************************************************************************
149  * InterfaceWindow::MessageReceived
150  *****************************************************************************/
151 void InterfaceWindow::MessageReceived( BMessage * p_message )
152 {
153     int vol_val = p_mediaControl->GetVolume();    // remember the current volume
154     int playback_status;      // remember playback state
155     int     i_index;
156     BAlert *alert;
157     aout_bank_t *p_aout_bank = p_intf->p_vlc->p_aout_bank;
158     input_bank_t *p_input_bank = p_intf->p_vlc->p_input_bank;
159
160     Activate();
161     if (p_input_bank->pp_input[0])
162     {
163             playback_status = p_input_bank->pp_input[0]->stream.control.i_status;
164         }
165         else
166         {
167             playback_status = UNDEF_S;
168         }
169
170     switch( p_message->what )
171     {
172     case B_ABOUT_REQUESTED:
173         alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
174         alert->Go();
175         break;
176
177     case TOGGLE_ON_TOP:
178         miOnTop->SetMarked(! miOnTop->IsMarked() );
179         if ( miOnTop->IsMarked() )
180         {
181             SetFeel(B_FLOATING_ALL_WINDOW_FEEL);
182             SetWorkspaces(B_CURRENT_WORKSPACE); 
183         }
184         else
185         {
186             SetFeel(B_NORMAL_WINDOW_FEEL);
187             SetWorkspaces(B_CURRENT_WORKSPACE); 
188         }
189         break;
190         
191     case OPEN_FILE:
192         if( file_panel )
193         {
194             file_panel->Show();
195             break;
196         }
197         file_panel = new BFilePanel();
198         file_panel->SetTarget( this );
199         file_panel->Show();
200         b_empty_playlist = false;
201         p_mediaControl->SetEnabled( !b_empty_playlist );
202         break;
203
204         case OPEN_PLAYLIST:
205                 {
206                     BRect rect(20,20,320,420);
207             playlist_window = PlayListWindow::getPlayList(rect,
208                                 "Playlist", (playlist_t *)p_main->p_playlist);
209             playlist_window->Show();                    
210         }
211                 break;
212     case OPEN_DVD:
213         const char *psz_device;
214         char psz_source[ B_FILE_NAME_LENGTH + 4 ];
215         if( p_message->FindString("device", &psz_device) != B_ERROR )
216         {
217             snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
218                       "dvd:%s", psz_device );
219             psz_source[ strlen(psz_source) ] = '\0';
220             intf_PlaylistAdd( p_intf->p_vlc->p_playlist, PLAYLIST_END, (char*)psz_source );
221             if( p_input_bank->pp_input[0] != NULL )
222             {
223                 p_input_bank->pp_input[0]->b_eof = 1;
224             }
225             intf_PlaylistJumpto( p_intf->p_vlc->p_playlist, 
226                                  p_intf->p_vlc->p_playlist->i_size - 1 );
227             b_empty_playlist = false;
228             p_mediaControl->SetEnabled( !b_empty_playlist );
229         }
230         break;
231
232     case STOP_PLAYBACK:
233         // this currently stops playback not nicely
234         if( p_input_bank->pp_input[0] != NULL )
235         {
236             // silence the sound, otherwise very horrible
237             vlc_mutex_lock( &p_aout_bank->lock );
238             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
239             {
240                 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
241                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
242             }
243             vlc_mutex_unlock( &p_aout_bank->lock );
244             snooze( 400000 );
245
246             /* end playing item */
247             p_input_bank->pp_input[0]->b_eof = 1;
248             
249             /* update playlist */
250             vlc_mutex_lock( &p_intf->p_vlc->p_playlist->change_lock );
251             p_intf->p_vlc->p_playlist->i_index--;
252             p_intf->p_vlc->p_playlist->b_stopped = 1;
253             vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
254         }
255         p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
256         break;
257
258     case START_PLAYBACK:
259         /*  starts playing in normal mode */
260
261     case PAUSE_PLAYBACK:
262         /* toggle between pause and play */
263         if( p_input_bank->pp_input[0] != NULL )
264         {
265             /* pause if currently playing */
266             if( playback_status == PLAYING_S )
267             {
268                 /* mute the sound */
269                 vlc_mutex_lock( &p_aout_bank->lock );
270                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
271                 {
272                     p_aout_bank->pp_aout[i_index]->i_savedvolume =
273                                        p_aout_bank->pp_aout[i_index]->i_volume;
274                     p_aout_bank->pp_aout[i_index]->i_volume = 0;
275                 }
276                 vlc_mutex_unlock( &p_aout_bank->lock );
277                 snooze( 400000 );
278                 
279                 /* pause the movie */
280                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PAUSE );
281                 vlc_mutex_lock( &p_intf->p_vlc->p_playlist->change_lock );
282                 p_intf->p_vlc->p_playlist->b_stopped = 0;
283                 vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
284             }
285             else
286             {
287                 /* Play after pausing */
288                 /* Restore the volume */
289                 vlc_mutex_lock( &p_aout_bank->lock );
290                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
291                 {
292                     p_aout_bank->pp_aout[i_index]->i_volume =
293                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
294                     p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
295                 }
296                 vlc_mutex_unlock( &p_aout_bank->lock );
297                 snooze( 400000 );
298                 
299                 /* Start playing */
300                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
301                 p_intf->p_vlc->p_playlist->b_stopped = 0;
302             }
303         }
304         else
305         {
306             /* Play a new file */
307             vlc_mutex_lock( &p_intf->p_vlc->p_playlist->change_lock );
308             if( p_intf->p_vlc->p_playlist->b_stopped )
309             {
310                 if( p_intf->p_vlc->p_playlist->i_size )
311                 {
312                     vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
313                     intf_PlaylistJumpto( p_intf->p_vlc->p_playlist, 
314                                          p_intf->p_vlc->p_playlist->i_index );
315                     p_intf->p_vlc->p_playlist->b_stopped = 0;
316                 }
317                 else
318                 {
319                     vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
320                 }
321             }
322         }    
323         break;
324
325     case FASTER_PLAY:
326         /* cycle the fast playback modes */
327         if( p_input_bank->pp_input[0] != NULL )
328         {
329             /* mute the sound */
330             vlc_mutex_lock( &p_aout_bank->lock );
331             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
332             {
333                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
334                                        p_aout_bank->pp_aout[i_index]->i_volume;
335                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
336             }
337             vlc_mutex_unlock( &p_aout_bank->lock );
338             snooze( 400000 );
339
340             /* change the fast play mode */
341             input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_FASTER );
342             vlc_mutex_lock( &p_intf->p_vlc->p_playlist->change_lock );
343             p_intf->p_vlc->p_playlist->b_stopped = 0;
344             vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
345         }
346         break;
347
348     case SLOWER_PLAY:
349         /*  cycle the slow playback modes */
350         if (p_input_bank->pp_input[0] != NULL )
351         {
352             /* mute the sound */
353             vlc_mutex_lock( &p_aout_bank->lock );
354             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
355             {
356                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
357                                        p_aout_bank->pp_aout[i_index]->i_volume;
358                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
359             }
360             vlc_mutex_unlock( &p_aout_bank->lock );
361             snooze( 400000 );
362
363             /* change the slower play */
364             input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_SLOWER );
365             vlc_mutex_lock( &p_intf->p_vlc->p_playlist->change_lock );
366             p_intf->p_vlc->p_playlist->b_stopped = 0;
367             vlc_mutex_unlock( &p_intf->p_vlc->p_playlist->change_lock );
368         }
369         break;
370
371     case SEEK_PLAYBACK:
372         /* handled by semaphores */
373         break;
374
375     case VOLUME_CHG:
376         /* adjust the volume */
377         vlc_mutex_lock( &p_aout_bank->lock );
378         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
379         {
380             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
381             {
382                 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
383             }
384             else
385             {
386                 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
387             }
388         }
389         vlc_mutex_unlock( &p_aout_bank->lock );
390         break;
391
392     case VOLUME_MUTE:
393         /* toggle muting */
394         vlc_mutex_lock( &p_aout_bank->lock );
395         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
396         {
397             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
398             {
399                 p_aout_bank->pp_aout[i_index]->i_volume =
400                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
401                 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
402             }
403             else
404             {
405                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
406                                        p_aout_bank->pp_aout[i_index]->i_volume;
407                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
408             }
409         }
410         vlc_mutex_unlock( &p_aout_bank->lock );
411         break;
412
413     case SELECT_CHANNEL:
414     case SELECT_SUBTITLE:
415         {
416             int32 i_new, i_old = -1;
417             if( p_message->what == SELECT_CHANNEL )
418             {
419                 i_new = p_message->FindInt32( "channel" );
420                 i_cat = AUDIO_ES;
421             }
422             else
423             {
424                 i_new = p_message->FindInt32( "subtitle" );
425                 i_cat = AUDIO_ES;
426             }
427
428             vlc_mutex_lock( &p_input->stream.stream_lock );
429             for( int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
430             {
431                 if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
432                 {
433                     i_old = i;
434                     break;
435                 }
436             }
437             vlc_mutex_unlock( &p_input->stream.stream_lock );
438
439             if( i_new != -1 )
440             {
441                 input_ToggleES( p_input, p_input->stream.pp_selected_es[i_new],
442                                 VLC_TRUE );
443             }
444
445             if( i_old != -1 )
446             {
447                 input_ToggleES( p_input, p_input->stream.pp_selected_es[i_old],
448                                 VLC_FALSE );
449             }
450         }
451         break;
452     case PREV_TITLE:
453         {
454             input_area_t *  p_area;
455             int             i_id;
456
457             i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1;
458
459             /* Disallow area 0 since it is used for video_ts.vob */
460             if( i_id > 0 )
461             {
462                 p_area = p_input_bank->pp_input[0]->stream.pp_areas[i_id];
463                 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
464                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
465             }
466             break;
467         }
468     case NEXT_TITLE:
469         {
470             input_area_t *  p_area;
471             int             i_id;
472
473             i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id + 1;
474
475             if( i_id < p_input_bank->pp_input[0]->stream.i_area_nb )
476             {
477                 p_area = p_input_bank->pp_input[0]->stream.pp_areas[i_id];
478                 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
479                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
480             }
481         }
482         break;
483     case PREV_CHAPTER:
484         {
485             input_area_t *  p_area;
486
487             p_area = p_input_bank->pp_input[0]->stream.p_selected_area;
488
489             if( p_area->i_part > 0 )
490             {
491                 p_area->i_part--;
492                 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
493                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
494             }
495         }
496         break;
497     case NEXT_CHAPTER:
498         {
499             input_area_t *  p_area;
500
501             p_area = p_input_bank->pp_input[0]->stream.p_selected_area;
502
503             if( p_area->i_part > 0 )
504             {
505                 p_area->i_part++;
506                 input_ChangeArea( p_input_bank->pp_input[0], (input_area_t*)p_area );
507                 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
508             }
509         }
510         break;
511     case B_REFS_RECEIVED:
512     case B_SIMPLE_DATA:
513         {
514             entry_ref ref;
515             if( p_message->FindRef( "refs", &ref ) == B_OK )
516             {
517                 BPath path( &ref );
518                 intf_PlaylistAdd( p_intf->p_vlc->p_playlist,
519                                   PLAYLIST_END, (char*)path.Path() );
520                 if( p_input_bank->pp_input[0] != NULL )
521                 {
522                     p_input_bank->pp_input[0]->b_eof = 1;
523                 }
524                 intf_PlaylistJumpto( p_intf->p_vlc->p_playlist, 
525                                      p_intf->p_vlc->p_playlist->i_size - 1 );
526                                   
527              }
528         }
529         break;
530
531     default:
532         BWindow::MessageReceived( p_message );
533         break;
534     }
535
536 }
537
538 /*****************************************************************************
539  * InterfaceWindow::updateInterface
540  *****************************************************************************/
541 void InterfaceWindow::updateInterface()
542 {
543         input_bank_t *p_input_bank = p_intf->p_vlc->p_input_bank;
544
545         if ( p_input_bank->pp_input[0] )
546         {
547         if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
548         {
549             uint64 seekTo = (p_mediaControl->GetSeekTo() *
550                         p_input_bank->pp_input[0]->stream.p_selected_area->i_size) / 100;
551             input_Seek( p_input_bank->pp_input[0]->p_this, seekTo, INPUT_SEEK_SET );
552         }
553         else if( Lock() )
554         {
555             p_mediaControl->SetStatus(p_input_bank->pp_input[0]->stream.control.i_status, 
556                                       p_input_bank->pp_input[0]->stream.control.i_rate);
557             p_mediaControl->SetProgress(p_input_bank->pp_input[0]->stream.p_selected_area->i_tell,
558                                         p_input_bank->pp_input[0]->stream.p_selected_area->i_size);
559             Unlock();
560         }
561     }
562     if ( b_empty_playlist != (p_intf->p_vlc->p_playlist->i_size < 1) )
563     {
564         if (Lock())
565         {
566             b_empty_playlist = !b_empty_playlist;
567             p_mediaControl->SetEnabled( !b_empty_playlist );
568             Unlock();
569         }
570     }
571 }
572
573 /*****************************************************************************
574  * InterfaceWindow::QuitRequested
575  *****************************************************************************/
576 bool InterfaceWindow::QuitRequested()
577 {
578     p_intf->p_vlc->b_die = VLC_TRUE;
579
580     return( true );
581 }
582
583 /*****************************************************************************
584  * CDMenu::CDMenu
585  *****************************************************************************/
586 CDMenu::CDMenu(const char *name)
587       : BMenu(name)
588 {
589 }
590
591 /*****************************************************************************
592  * CDMenu::~CDMenu
593  *****************************************************************************/
594 CDMenu::~CDMenu()
595 {
596 }
597
598 /*****************************************************************************
599  * CDMenu::AttachedToWindow
600  *****************************************************************************/
601 void CDMenu::AttachedToWindow(void)
602 {
603     while (RemoveItem((long int)0) != NULL);  // remove all items
604     GetCD("/dev/disk");
605     BMenu::AttachedToWindow();
606 }
607
608 /*****************************************************************************
609  * CDMenu::GetCD
610  *****************************************************************************/
611 int CDMenu::GetCD( const char *directory )
612 {
613         BVolumeRoster *volRoster;
614         BVolume       *vol;
615         BDirectory    *dir;
616         int           status;
617         int           mounted;   
618         char          name[B_FILE_NAME_LENGTH]; 
619     fs_info       info;
620         dev_t         dev;
621         
622         volRoster = new BVolumeRoster();
623         vol = new BVolume();
624         dir = new BDirectory();
625         status = volRoster->GetNextVolume(vol);
626         status = vol->GetRootDirectory(dir);
627         while (status ==  B_NO_ERROR)
628         {
629             mounted = vol->GetName(name);       
630             if ((mounted == B_OK) && /* Disk is currently Mounted */
631                 (vol->IsReadOnly()) ) /* Disk is read-only */
632             {
633                 dev = vol->Device();
634             fs_stat_dev(dev, &info);
635             
636             device_geometry g;
637             int i_dev;
638             i_dev = open( info.device_name, O_RDONLY );
639            
640             if( i_dev >= 0 )
641             {
642                 if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
643                 {
644                     if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
645                     {
646                         BMessage *msg;
647                         msg = new BMessage( OPEN_DVD );
648                         msg->AddString( "device", info.device_name );
649                         BMenuItem *menu_item;
650                         menu_item = new BMenuItem( name, msg );
651                         AddItem( menu_item );
652                     }
653                     close(i_dev);
654                 }
655             }
656             }
657             vol->Unset();
658             status = volRoster->GetNextVolume(vol);
659         }
660 }
661
662 /*****************************************************************************
663  * LanguageMenu::LanguageMenu
664  *****************************************************************************/
665 LanguageMenu::LanguageMenu(const char *name, int menu_kind, 
666                             intf_thread_t  *p_interface)
667     :BMenu(name)
668 {
669     kind = menu_kind;
670     p_intf = p_interface;
671 }
672
673 /*****************************************************************************
674  * LanguageMenu::~LanguageMenu
675  *****************************************************************************/
676 LanguageMenu::~LanguageMenu()
677 {
678 }
679
680 /*****************************************************************************
681  * LanguageMenu::AttachedToWindow
682  *****************************************************************************/
683 void LanguageMenu::AttachedToWindow(void)
684 {
685     while( RemoveItem((long int)0) != NULL )
686     {
687         ; // remove all items
688     }
689
690     SetRadioMode(true);
691     GetChannels();
692     BMenu::AttachedToWindow();
693 }
694
695 /*****************************************************************************
696  * LanguageMenu::GetChannels
697  *****************************************************************************/
698 int LanguageMenu::GetChannels()
699 {
700     char  *psz_name;
701     bool   b_active;
702     BMessage *msg;
703     int    i;
704     es_descriptor_t *p_es  = NULL;
705     input_bank_t *p_input_bank = p_intf->p_vlc->p_input_bank;
706
707     /* Insert the null */
708     if( kind == AUDIO_ES ) //audio
709     {
710         msg = new BMessage(SELECT_CHANNEL);
711         msg->AddInt32("channel", -1);
712     }
713     else
714     {
715         msg = new BMessage(SELECT_SUBTITLE);
716         msg->AddInt32("subtitle", -1);
717     }
718     BMenuItem *menu_item;
719     menu_item = new BMenuItem("None", msg);
720     AddItem(menu_item);
721     menu_item->SetMarked(TRUE);
722
723     if( p_input_bank->pp_input[0] == NULL )
724     {
725         return 1;
726     }
727
728
729     vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
730     for( i = 0; i < p_input_bank->pp_input[0]->stream.i_selected_es_number; i++ )
731     {
732         if( kind == p_input_bank->pp_input[0]->stream.pp_selected_es[i]->i_cat )
733         {
734             p_es = p_input_bank->pp_input[0]->stream.pp_selected_es[i];
735         }
736     }
737
738     for( i = 0; i < p_input_bank->pp_input[0]->stream.i_es_number; i++ )
739     {
740         if( kind == p_input_bank->pp_input[0]->stream.pp_es[i]->i_cat )
741         {
742             psz_name = p_input_bank->pp_input[0]->stream.pp_es[i]->psz_desc;
743             if( kind == AUDIO_ES ) //audio
744             {
745                 msg = new BMessage(SELECT_CHANNEL);
746                 msg->AddInt32("channel", i);
747             }
748             else
749             {
750                 msg = new BMessage(SELECT_SUBTITLE);
751                 msg->AddInt32("subtitle", i);
752             }
753             BMenuItem *menu_item;
754             menu_item = new BMenuItem(psz_name, msg);
755             AddItem(menu_item);
756             b_active = (p_es == p_input_bank->pp_input[0]->stream.pp_es[i]);
757             menu_item->SetMarked(b_active);
758         }
759     }
760     vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
761
762 }
763
764
765