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