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