fcd439d6b84b9c99b05397a7bfdd32be65b61852
[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.1 2001/06/02 09:42:26 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 #include "defs.h"
27
28  
29 /* System headers */
30 #include <kernel/OS.h>
31 #include <InterfaceKit.h>
32 #include <AppKit.h>
33 #include <StorageKit.h>
34 #include <malloc.h>
35 #include <scsi.h>
36 #include <scsiprobe_driver.h>
37
38 /* VLC headers */
39 extern "C"
40 {
41 #include "config.h"
42 #include "common.h"
43 #include "threads.h"
44 #include "mtime.h"
45 #include "main.h"
46 #include "tests.h"
47 #include "stream_control.h"
48 #include "input_ext-intf.h"
49 #include "interface.h"
50 #include "intf_msg.h"
51 #include "intf_playlist.h"
52 #include "audio_output.h"
53 }
54
55 /* BeOS interface headers */
56 #include "MsgVals.h"
57 #include "InterfaceWindow.h"
58 #include "Bitmaps.h"
59 #include "TransportButton.h"
60
61 /*****************************************************************************
62  * InterfaceWindow
63  *****************************************************************************/
64
65 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
66                                   intf_thread_t  *p_interface )
67     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
68                B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
69                 | B_ASYNCHRONOUS_CONTROLS )
70 {
71     file_panel = NULL;
72     p_intf = p_interface;
73     BRect ButtonRect;
74     float xStart = 5.0;
75     float yStart = 20.0;
76
77     SetName( "interface" );
78     SetTitle(VOUT_TITLE " (BeOS interface)");
79     BRect rect(0, 0, 0, 0);
80
81     BMenuBar *menu_bar;
82     menu_bar = new BMenuBar(rect, "main menu");
83     AddChild( menu_bar );
84
85     BMenu *mFile;
86     BMenu *mAudio;
87     CDMenu *cd_menu;
88
89     BMenuItem *mItem;
90
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     cd_menu = new CDMenu( "Open Disc" );
96     mFile->AddItem( cd_menu );
97     mFile->AddSeparatorItem();
98     mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
99                                        new BMessage(B_ABOUT_REQUESTED), 'A') );
100     mItem->SetTarget( be_app );
101     mFile->AddItem(mItem = new BMenuItem( "Quit",
102                                         new BMessage(B_QUIT_REQUESTED), 'Q') );
103
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
110     rect = Bounds();
111     rect.top += menu_bar->Bounds().IntegerHeight() + 1;
112
113     BBox* p_view;
114     p_view = new BBox( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER );
115     p_view->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
116
117     /* Buttons */
118     /* Slow play */
119     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
120     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
121     xStart += kRewindBitmapWidth;
122     TransportButton* p_slow = new TransportButton(ButtonRect, B_EMPTY_STRING,
123                                             kSkipBackBitmapBits,
124                                             kPressedSkipBackBitmapBits,
125                                             kDisabledSkipBackBitmapBits,
126                                             new BMessage(SLOWER_PLAY));
127     p_view->AddChild( p_slow );
128
129     /* Play Pause */
130     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
131     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kPlayButtonSize);
132     xStart += kPlayPauseBitmapWidth + 1.0;
133     PlayPauseButton* p_play = new PlayPauseButton(ButtonRect, B_EMPTY_STRING,
134                                             kPlayButtonBitmapBits,
135                                             kPressedPlayButtonBitmapBits,
136                                             kDisabledPlayButtonBitmapBits,
137                                             kPlayingPlayButtonBitmapBits,
138                                             kPressedPlayingPlayButtonBitmapBits,
139                                             kPausedPlayButtonBitmapBits,
140                                             kPressedPausedPlayButtonBitmapBits,
141                                             new BMessage(START_PLAYBACK));
142
143     p_view->AddChild( p_play );
144     /* p_play->SetPlaying(); */
145
146     /* Fast Foward */
147     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
148     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
149     xStart += kRewindBitmapWidth;
150     TransportButton* p_fast = new TransportButton(ButtonRect, B_EMPTY_STRING,
151                                             kSkipForwardBitmapBits,
152                                             kPressedSkipForwardBitmapBits,
153                                             kDisabledSkipForwardBitmapBits,
154                                             new BMessage(FASTER_PLAY));
155     p_view->AddChild( p_fast );
156
157     /* Stop */
158     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
159     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kStopButtonSize);
160     xStart += kStopBitmapWidth;
161     TransportButton* p_stop = new TransportButton(ButtonRect, B_EMPTY_STRING,
162                                             kStopButtonBitmapBits,
163                                             kPressedStopButtonBitmapBits,
164                                             kDisabledStopButtonBitmapBits,
165                                             new BMessage(STOP_PLAYBACK));
166     p_view->AddChild( p_stop );
167
168     ButtonRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
169     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSpeakerButtonSize);
170     xStart += kSpeakerIconBitmapWidth;
171
172     TransportButton* p_mute = new TransportButton(ButtonRect, B_EMPTY_STRING,
173                                             kSpeakerIconBits,
174                                             kPressedSpeakerIconBits,
175                                             kSpeakerIconBits,
176                                             new BMessage(VOLUME_MUTE));
177
178     p_view->AddChild( p_mute );
179
180     /* Seek Status */
181     rgb_color fill_color = {0,255,0};
182     p_seek = new SeekSlider(BRect(5,2,255,15), this, 0, 100,
183                         B_TRIANGLE_THUMB);
184     p_seek->SetValue(0);
185     p_seek->UseFillColor(true, &fill_color);
186     p_view->AddChild( p_seek );
187
188     /* Volume Slider */
189     p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
190                             0, VOLUME_MAX);
191     p_vol->SetValue(VOLUME_DEFAULT);
192     p_vol->UseFillColor(true, &fill_color);
193     p_view->AddChild( p_vol );
194
195     /* Set size and Show */
196     AddChild( p_view );
197     ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
198     Show();
199 }
200
201 InterfaceWindow::~InterfaceWindow()
202 {
203 }
204
205 /*****************************************************************************
206  * InterfaceWindow::MessageReceived
207  *****************************************************************************/
208 void InterfaceWindow::MessageReceived( BMessage * p_message )
209 {
210     int vol_val = p_vol->Value();    // remember the current volume
211     static int playback_status;      // remember playback state
212     int     i_index;
213     BAlert *alert;
214
215     Activate();
216
217     switch( p_message->what )
218     {
219     case B_ABOUT_REQUESTED:
220         alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
221         alert->Go();
222         break;
223
224     case OPEN_FILE:
225         if( file_panel )
226         {
227             file_panel->Show();
228             break;
229         }
230         file_panel = new BFilePanel();
231         file_panel->SetTarget( this );
232         file_panel->Show();
233         break;
234
235     case OPEN_DVD:
236         const char *psz_device;
237         char psz_source[ B_FILE_NAME_LENGTH + 4 ];
238         if( p_message->FindString("device", &psz_device) != B_ERROR )
239         {
240             snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
241                       "dvd:%s", psz_device );
242             psz_source[ strlen(psz_source) ] = '\0';
243             intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, (char*)psz_source );
244         }
245         break;
246
247     case STOP_PLAYBACK:
248         // this currently stops playback not nicely
249         if( p_intf->p_input != NULL )
250         {
251             // silence the sound, otherwise very horrible
252             vlc_mutex_lock( &p_aout_bank->lock );
253             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
254             {
255                 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
256                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
257             }
258             vlc_mutex_unlock( &p_aout_bank->lock );
259             snooze( 400000 );
260
261             /* end playing item */
262             p_intf->p_input->b_eof = 1;
263             
264             /* update playlist */
265             vlc_mutex_lock( &p_main->p_playlist->change_lock );
266             p_main->p_playlist->i_index--;
267             p_main->p_playlist->b_stopped = 1;
268             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
269         }
270         break;
271
272     case START_PLAYBACK:
273         /*  starts playing in normal mode */
274 /*        if (p_intf->p_input != NULL )
275
276             if (p_main->p_aout != NULL)
277             {
278                 p_main->p_aout->i_vol = vol_val;
279             }
280             snooze(400000);
281             input_SetStatus(p_intf->p_input, INPUT_STATUS_PLAY);
282             playback_status = PLAYING;
283         }
284         break;
285 */
286
287     case PAUSE_PLAYBACK:
288         /* toggle between pause and play */
289         if( p_intf->p_input != NULL )
290         {
291             /* pause if currently playing */
292             if( playback_status == PLAYING )
293             {
294                 /* mute the sound */
295                 vlc_mutex_lock( &p_aout_bank->lock );
296                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
297                 {
298                     p_aout_bank->pp_aout[i_index]->i_savedvolume =
299                                        p_aout_bank->pp_aout[i_index]->i_volume;
300                     p_aout_bank->pp_aout[i_index]->i_volume = 0;
301                 }
302                 vlc_mutex_unlock( &p_aout_bank->lock );
303                 
304                 /* pause the movie */
305                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PAUSE );
306                 vlc_mutex_lock( &p_main->p_playlist->change_lock );
307                 p_main->p_playlist->b_stopped = 0;
308                 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
309                 playback_status = PAUSED;
310             }
311             else
312             {
313                 /* Play after pausing */
314                 /* Restore the volume */
315                 vlc_mutex_lock( &p_aout_bank->lock );
316                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
317                 {
318                     p_aout_bank->pp_aout[i_index]->i_volume =
319                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
320                     p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
321                 }
322                 vlc_mutex_unlock( &p_aout_bank->lock );
323                 snooze( 400000 );
324                 
325                 /* Start playing */
326                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
327                 p_main->p_playlist->b_stopped = 0;
328                 playback_status = PLAYING;
329             }
330         }
331         else
332         {
333             /* Play a new file */
334             vlc_mutex_lock( &p_main->p_playlist->change_lock );
335             if( p_main->p_playlist->b_stopped )
336             {
337                 if( p_main->p_playlist->i_size )
338                 {
339                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
340                     intf_PlaylistJumpto( p_main->p_playlist, 
341                                          p_main->p_playlist->i_index );
342                     playback_status = PLAYING;
343                 }
344                 else
345                 {
346                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
347                 }
348             }
349         }    
350         break;
351
352     case FASTER_PLAY:
353         /* cycle the fast playback modes */
354         if( p_intf->p_input != 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 fast play mode */
368             input_SetStatus( p_intf->p_input, INPUT_STATUS_FASTER );
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 SLOWER_PLAY:
376         /*  cycle the slow playback modes */
377         if (p_intf->p_input != NULL )
378         {
379             /* mute the sound */
380             vlc_mutex_lock( &p_aout_bank->lock );
381             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
382             {
383                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
384                                        p_aout_bank->pp_aout[i_index]->i_volume;
385                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
386             }
387             vlc_mutex_unlock( &p_aout_bank->lock );
388             snooze( 400000 );
389
390             /* change the slower play */
391             input_SetStatus( p_intf->p_input, INPUT_STATUS_SLOWER );
392             vlc_mutex_lock( &p_main->p_playlist->change_lock );
393             p_main->p_playlist->b_stopped = 0;
394             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
395         }
396         break;
397
398     case SEEK_PLAYBACK:
399         /* handled by semaphores */
400         break;
401
402     case VOLUME_CHG:
403         /* adjust the volume */
404         vlc_mutex_lock( &p_aout_bank->lock );
405         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
406         {
407             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
408             {
409                 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
410             }
411             else
412             {
413                 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
414             }
415         }
416         vlc_mutex_unlock( &p_aout_bank->lock );
417         break;
418
419     case VOLUME_MUTE:
420         /* toggle muting */
421         vlc_mutex_lock( &p_aout_bank->lock );
422         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
423         {
424             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
425             {
426                 p_aout_bank->pp_aout[i_index]->i_volume =
427                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
428                 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
429             }
430             else
431             {
432                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
433                                        p_aout_bank->pp_aout[i_index]->i_volume;
434                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
435             }
436         }
437         vlc_mutex_unlock( &p_aout_bank->lock );
438         break;
439
440     case SELECT_CHANNEL:
441         {
442             int32 i = p_message->FindInt32( "channel" );
443             if ( i == -1 )
444             {
445                 input_ChangeES( p_intf->p_input, NULL, AUDIO_ES );
446             }
447             else
448             {
449                 input_ChangeES( p_intf->p_input,
450                         p_intf->p_input->stream.pp_es[i], AUDIO_ES );
451             }
452         }
453         break;
454
455     case SELECT_SUBTITLE:
456         {
457             int32 i = p_message->FindInt32( "subtitle" );
458             if ( i == -1 )
459             {
460                 input_ChangeES( p_intf->p_input, NULL, SPU_ES);
461             }
462             else
463             {
464                 input_ChangeES( p_intf->p_input,
465                         p_intf->p_input->stream.pp_es[i], SPU_ES );
466             }
467         }
468         break;
469
470     case B_REFS_RECEIVED:
471     case B_SIMPLE_DATA:
472         {
473             entry_ref ref;
474             if( p_message->FindRef( "refs", &ref ) == B_OK )
475             {
476                 BPath path( &ref );
477                 intf_PlaylistAdd( p_main->p_playlist,
478                                   PLAYLIST_END, (char*)path.Path() );
479              }
480         }
481         break;
482
483     default:
484         BWindow::MessageReceived( p_message );
485         break;
486     }
487 }
488
489 /*****************************************************************************
490  * InterfaceWindow::updateInterface
491  *****************************************************************************/
492 void InterfaceWindow::updateInterface()
493 {
494     float progress;
495     bool seekNeeded = false;
496
497     if( acquire_sem(fScrubSem) == B_OK )
498     {
499         seekNeeded = true;
500     }
501     if( seekNeeded )
502     {
503         uint32 seekTo = (p_seek->Value() *
504                     p_intf->p_input->stream.p_selected_area->i_size) / 100;
505         input_Seek( p_intf->p_input, seekTo );
506         seekNeeded = false;
507     }
508     else if( Lock() )
509     {
510         progress = (100. * p_intf->p_input->stream.p_selected_area->i_tell) /
511                     p_intf->p_input->stream.p_selected_area->i_size;
512         p_seek->SetValue(progress);
513         Unlock();
514     }
515 }
516
517 /*****************************************************************************
518  * InterfaceWindow::QuitRequested
519  *****************************************************************************/
520 bool InterfaceWindow::QuitRequested()
521 {
522     p_intf->b_die = 1;
523
524     return( false );
525 }
526
527 /*****************************************************************************
528  * CDMenu::CDMenu
529  *****************************************************************************/
530 CDMenu::CDMenu(const char *name)
531       : BMenu(name)
532 {
533 }
534
535 /*****************************************************************************
536  * CDMenu::~CDMenu
537  *****************************************************************************/
538 CDMenu::~CDMenu()
539 {
540 }
541
542 /*****************************************************************************
543  * CDMenu::AttachedToWindow
544  *****************************************************************************/
545 void CDMenu::AttachedToWindow(void)
546 {
547     while (RemoveItem((long int)0) != NULL);  // remove all items
548     GetCD("/dev/disk");
549     BMenu::AttachedToWindow();
550 }
551
552 /*****************************************************************************
553  * CDMenu::GetCD
554  *****************************************************************************/
555 int CDMenu::GetCD( const char *directory )
556 {
557     int i_dev;
558     BDirectory dir;
559     dir.SetTo( directory );
560
561     if( dir.InitCheck() != B_NO_ERROR )
562     {
563         return B_ERROR;
564     }
565
566     dir.Rewind();
567     BEntry entry;
568
569     while( dir.GetNextEntry(&entry) >= 0 )
570     {
571         const char *name;
572         entry_ref e;
573         BPath path;
574
575         if( entry.GetPath(&path) != B_NO_ERROR )
576         {
577             continue;
578         }
579
580         name = path.Path();
581
582         if( entry.GetRef(&e) != B_NO_ERROR )
583         {
584             continue;
585         }
586
587         if( entry.IsDirectory() )
588         {
589             if( strcmp(e.name, "floppy") == 0 )
590             {
591                 continue; // ignore floppy (it is not silent)
592             }
593
594             i_dev = GetCD( name );
595
596             if( i_dev >= 0 )
597             {
598                 return i_dev;
599             }
600         }
601         else
602         {
603             device_geometry g;
604             status_t m;
605
606             if( strcmp(e.name, "raw") != 0 )
607             {
608                 continue; // ignore partitions
609             }
610
611             i_dev = open( name, O_RDONLY );
612
613             if( i_dev < 0 )
614             {
615                 continue;
616             }
617
618             if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
619             {
620                 if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
621                 {
622                     if( ioctl(i_dev, B_GET_MEDIA_STATUS, &m, sizeof(m)) >= 0 )
623                     {
624                         if( m == B_NO_ERROR ) //ensure media is present
625                         {
626                             BMessage *msg;
627                             msg = new BMessage( OPEN_DVD );
628                             msg->AddString( "device", name );
629                             BMenuItem *menu_item;
630                             menu_item = new BMenuItem( name, msg );
631                             AddItem( menu_item );
632                             continue;
633                         }
634                     }
635                 }
636             }
637             close( i_dev );
638         }
639     }
640     return B_ERROR;
641 }
642
643 /*****************************************************************************
644  * LanguageMenu::LanguageMenu
645  *****************************************************************************/
646 LanguageMenu::LanguageMenu(const char *name, int menu_kind, intf_thread_t  *p_interface)
647     :BMenu(name)
648 {
649     kind = menu_kind;
650     p_intf = p_interface;
651 }
652
653 /*****************************************************************************
654  * LanguageMenu::~LanguageMenu
655  *****************************************************************************/
656 LanguageMenu::~LanguageMenu()
657 {
658 }
659
660 /*****************************************************************************
661  * LanguageMenu::AttachedToWindow
662  *****************************************************************************/
663 void LanguageMenu::AttachedToWindow(void)
664 {
665     while( RemoveItem((long int)0) != NULL )
666     {
667         ; // remove all items
668     }
669
670     SetRadioMode(true);
671     GetChannels();
672     BMenu::AttachedToWindow();
673 }
674
675 /*****************************************************************************
676  * LanguageMenu::GetChannels
677  *****************************************************************************/
678 int LanguageMenu::GetChannels()
679 {
680     char  *psz_name;
681     bool   b_active;
682     BMessage *msg;
683     int    i;
684     es_descriptor_t *p_es  = NULL;
685
686     /* Insert the null */
687     if( kind == AUDIO_ES ) //audio
688     {
689         msg = new BMessage(SELECT_CHANNEL);
690         msg->AddInt32("channel", -1);
691     }
692     else
693     {
694         msg = new BMessage(SELECT_SUBTITLE);
695         msg->AddInt32("subtitle", -1);
696     }
697     BMenuItem *menu_item;
698     menu_item = new BMenuItem("None", msg);
699     AddItem(menu_item);
700     menu_item->SetMarked(TRUE);
701
702     if( p_intf->p_input == NULL )
703     {
704         return 1;
705     }
706
707
708     vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
709     for( i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++ )
710     {
711         if( kind == p_intf->p_input->stream.pp_selected_es[i]->i_cat )
712         {
713             p_es = p_intf->p_input->stream.pp_selected_es[i];
714         }
715     }
716
717     for( i = 0; i < p_intf->p_input->stream.i_es_number; i++ )
718     {
719         if( kind == p_intf->p_input->stream.pp_es[i]->i_cat )
720         {
721             psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
722             if( kind == AUDIO_ES ) //audio
723             {
724                 msg = new BMessage(SELECT_CHANNEL);
725                 msg->AddInt32("channel", i);
726             }
727             else
728             {
729                 msg = new BMessage(SELECT_SUBTITLE);
730                 msg->AddInt32("subtitle", i);
731             }
732             BMenuItem *menu_item;
733             menu_item = new BMenuItem(psz_name, msg);
734             AddItem(menu_item);
735             b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
736             menu_item->SetMarked(b_active);
737         }
738     }
739     vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
740
741 }
742
743 /*****************************************************************************
744  * MediaSlider
745  *****************************************************************************/
746 MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
747                           int32 i_min, int32 i_max )
748             :BSlider(frame, NULL, NULL, p_message, i_min, i_max )
749 {
750
751 }
752
753 MediaSlider::~MediaSlider()
754 {
755
756 }
757
758 void MediaSlider::DrawThumb(void)
759 {
760     BRect r;
761     BView *v;
762
763     rgb_color black = {0,0,0};
764     r = ThumbFrame();
765     v = OffscreenView();
766
767     if(IsEnabled())
768     {
769         v->SetHighColor(black);
770     }
771     else
772     {
773         v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
774     }
775
776     r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
777     v->StrokeEllipse(r);
778
779     if(IsEnabled())
780     {
781         v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
782     }
783     else
784     {
785         v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
786     }
787
788     r.InsetBy(1,1);
789     v->FillEllipse(r);
790 }
791
792 /*****************************************************************************
793  * SeekSlider
794  *****************************************************************************/
795 SeekSlider::SeekSlider( BRect frame, InterfaceWindow *p_owner, int32 i_min,
796                         int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
797            :MediaSlider( frame, NULL, i_min, i_max )
798 {
799     fOwner = p_owner;
800     fMouseDown = false;
801 }
802
803 SeekSlider::~SeekSlider()
804 {
805 }
806
807 /*****************************************************************************
808  * SeekSlider::MouseDown
809  *****************************************************************************/
810 void SeekSlider::MouseDown(BPoint where)
811 {
812     BSlider::MouseDown(where);
813     fOwner->fScrubSem = create_sem(1, "Vlc::fScrubSem");
814     fMouseDown = true;
815 }
816
817 /*****************************************************************************
818  * SeekSlider::MouseUp
819  *****************************************************************************/
820 void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
821 {
822     BSlider::MouseMoved(where, code, message);
823     if (!fMouseDown)
824         return;
825     release_sem(fOwner->fScrubSem);
826 }
827
828 /*****************************************************************************
829  * SeekSlider::MouseUp
830  *****************************************************************************/
831 void SeekSlider::MouseUp(BPoint where)
832 {
833     BSlider::MouseUp(where);
834     delete_sem(fOwner->fScrubSem);
835     fOwner->fScrubSem = B_ERROR;
836     fMouseDown = false;
837 }
838
839