]> git.sesse.net Git - vlc/blob - plugins/beos/intf_beos.cpp
2229f021e8c1b70955ef93487aaad6f9c6b6a209
[vlc] / plugins / beos / intf_beos.cpp
1 /*****************************************************************************
2  * intf_beos.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: intf_beos.cpp,v 1.31 2001/05/31 03:57:54 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 #define MODULE_NAME beos
28 #include "modules_inner.h"
29
30 /*****************************************************************************
31  * Preamble
32  *****************************************************************************/
33 #include "defs.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>                                      /* malloc(), free() */
37
38 #include <kernel/OS.h>
39 #include <storage/Path.h>
40 #include <Alert.h>
41 #include <View.h>
42 #include <CheckBox.h>
43 #include <Button.h>
44 #include <Slider.h>
45 #include <StatusBar.h>
46 #include <Application.h>
47 #include <Message.h>
48 #include <NodeInfo.h>
49 #include <Locker.h>
50 #include <DirectWindow.h>
51 #include <Box.h>
52 #include <Alert.h>
53 #include <MenuBar.h>
54 #include <MenuItem.h>
55 #include <FilePanel.h>
56 #include <Screen.h>
57 #include <malloc.h>
58 #include <string.h>
59 #include <Directory.h>
60 #include <Entry.h>
61 #include <Path.h>
62 #include <StorageDefs.h>
63 #include <scsi.h>
64 #include <scsiprobe_driver.h>
65
66 extern "C"
67 {
68 #include "config.h"
69 #include "common.h"
70 #include "threads.h"
71 #include "mtime.h"
72 #include "tests.h"
73
74 #include "stream_control.h"
75 #include "input_ext-intf.h"
76
77 #include "interface.h"
78 #include "intf_playlist.h"
79 #include "intf_msg.h"
80 #include "audio_output.h"
81 #include "MsgVals.h"
82
83 #include "main.h"
84
85 #include "modules.h"
86 #include "modules_export.h"
87 }
88
89 #include "InterfaceWindow.h"
90 #include "Bitmaps.h"
91 #include "TransportButton.h"
92
93 /*****************************************************************************
94  * intf_sys_t: description and status of FB interface
95  *****************************************************************************/
96 typedef struct intf_sys_s
97 {
98     InterfaceWindow * p_window;
99     char              i_key;
100 } intf_sys_t;
101
102 /*****************************************************************************
103  * InterfaceWindow
104  *****************************************************************************/
105
106 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
107                                   intf_thread_t  *p_interface )
108     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
109                B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
110                 | B_ASYNCHRONOUS_CONTROLS )
111 {
112     file_panel = NULL;
113     p_intf = p_interface;
114     BRect ButtonRect;
115     float xStart = 5.0;
116     float yStart = 20.0;
117
118     SetName( "interface" );
119     SetTitle(VOUT_TITLE " (BeOS interface)");
120     BRect rect(0, 0, 0, 0);
121
122     BMenuBar *menu_bar;
123     menu_bar = new BMenuBar(rect, "main menu");
124     AddChild( menu_bar );
125
126     BMenu *mFile;
127     BMenu *mAudio;
128     CDMenu *cd_menu;
129
130     BMenuItem *mItem;
131
132     menu_bar->AddItem( mFile = new BMenu( "File" ) );
133     menu_bar->ResizeToPreferred();
134     mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
135                                            new BMessage(OPEN_FILE), 'O') );
136     cd_menu = new CDMenu( "Open Disc" );
137     mFile->AddItem( cd_menu );
138     mFile->AddSeparatorItem();
139     mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
140                                        new BMessage(B_ABOUT_REQUESTED), 'A') );
141     mItem->SetTarget( be_app );
142     mFile->AddItem(mItem = new BMenuItem( "Quit",
143                                         new BMessage(B_QUIT_REQUESTED), 'Q') );
144
145     menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
146     menu_bar->ResizeToPreferred();
147     mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
148     mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
149
150
151     rect = Bounds();
152     rect.top += menu_bar->Bounds().IntegerHeight() + 1;
153
154     BBox* p_view;
155     p_view = new BBox( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER );
156     p_view->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
157
158     /* Buttons */
159     /* Slow play */
160     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
161     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
162     xStart += kRewindBitmapWidth;
163     TransportButton* p_slow = new TransportButton(ButtonRect, B_EMPTY_STRING,
164                                             kSkipBackBitmapBits,
165                                             kPressedSkipBackBitmapBits,
166                                             kDisabledSkipBackBitmapBits,
167                                             new BMessage(SLOWER_PLAY));
168     p_view->AddChild( p_slow );
169
170     /* Play Pause */
171     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
172     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kPlayButtonSize);
173     xStart += kPlayPauseBitmapWidth + 1.0;
174     PlayPauseButton* p_play = new PlayPauseButton(ButtonRect, B_EMPTY_STRING,
175                                             kPlayButtonBitmapBits,
176                                             kPressedPlayButtonBitmapBits,
177                                             kDisabledPlayButtonBitmapBits,
178                                             kPlayingPlayButtonBitmapBits,
179                                             kPressedPlayingPlayButtonBitmapBits,
180                                             kPausedPlayButtonBitmapBits,
181                                             kPressedPausedPlayButtonBitmapBits,
182                                             new BMessage(START_PLAYBACK));
183
184     p_view->AddChild( p_play );
185     /* p_play->SetPlaying(); */
186
187     /* Fast Foward */
188     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
189     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
190     xStart += kRewindBitmapWidth;
191     TransportButton* p_fast = new TransportButton(ButtonRect, B_EMPTY_STRING,
192                                             kSkipForwardBitmapBits,
193                                             kPressedSkipForwardBitmapBits,
194                                             kDisabledSkipForwardBitmapBits,
195                                             new BMessage(FASTER_PLAY));
196     p_view->AddChild( p_fast );
197
198     /* Stop */
199     ButtonRect.SetLeftTop(BPoint(xStart, yStart));
200     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kStopButtonSize);
201     xStart += kStopBitmapWidth;
202     TransportButton* p_stop = new TransportButton(ButtonRect, B_EMPTY_STRING,
203                                             kStopButtonBitmapBits,
204                                             kPressedStopButtonBitmapBits,
205                                             kDisabledStopButtonBitmapBits,
206                                             new BMessage(STOP_PLAYBACK));
207     p_view->AddChild( p_stop );
208
209     ButtonRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
210     ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSpeakerButtonSize);
211     xStart += kSpeakerIconBitmapWidth;
212
213     TransportButton* p_mute = new TransportButton(ButtonRect, B_EMPTY_STRING,
214                                             kSpeakerIconBits,
215                                             kPressedSpeakerIconBits,
216                                             kSpeakerIconBits,
217                                             new BMessage(VOLUME_MUTE));
218
219     p_view->AddChild( p_mute );
220
221     /* Seek Status */
222     rgb_color fill_color = {0,255,0};
223     p_seek = new SeekSlider(BRect(5,2,255,15), this, 0, 100,
224                         B_TRIANGLE_THUMB);
225     p_seek->SetValue(0);
226     p_seek->UseFillColor(true, &fill_color);
227     p_view->AddChild( p_seek );
228
229     /* Volume Slider */
230     p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
231                             0, VOLUME_MAX);
232     p_vol->SetValue(VOLUME_DEFAULT);
233     p_vol->UseFillColor(true, &fill_color);
234     p_view->AddChild( p_vol );
235
236     /* Set size and Show */
237     AddChild( p_view );
238     ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
239     Show();
240 }
241
242 InterfaceWindow::~InterfaceWindow()
243 {
244 }
245
246 /*****************************************************************************
247  * InterfaceWindow::MessageReceived
248  *****************************************************************************/
249 void InterfaceWindow::MessageReceived( BMessage * p_message )
250 {
251     int vol_val = p_vol->Value();    // remember the current volume
252     static int playback_status;      // remember playback state
253     int     i_index;
254     BAlert *alert;
255
256     Activate();
257
258     switch( p_message->what )
259     {
260     case B_ABOUT_REQUESTED:
261         alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
262         alert->Go();
263         break;
264
265     case OPEN_FILE:
266         if( file_panel )
267         {
268             file_panel->Show();
269             break;
270         }
271         file_panel = new BFilePanel();
272         file_panel->SetTarget( this );
273         file_panel->Show();
274         break;
275
276     case OPEN_DVD:
277         const char *psz_device;
278         char psz_source[ B_FILE_NAME_LENGTH + 4 ];
279         if( p_message->FindString("device", &psz_device) != B_ERROR )
280         {
281             snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
282                       "dvd:%s", psz_device );
283             psz_source[ strlen(psz_source) ] = '\0';
284             intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, (char*)psz_source );
285         }
286         break;
287
288     case STOP_PLAYBACK:
289         // this currently stops playback not nicely
290         if( p_intf->p_input != NULL )
291         {
292             // silence the sound, otherwise very horrible
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_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
297                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
298             }
299             vlc_mutex_unlock( &p_aout_bank->lock );
300             snooze( 400000 );
301
302             /* end playing item */
303             p_intf->p_input->b_eof = 1;
304             
305             /* update playlist */
306             vlc_mutex_lock( &p_main->p_playlist->change_lock );
307             p_main->p_playlist->i_index--;
308             p_main->p_playlist->b_stopped = 1;
309             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
310         }
311         break;
312
313     case START_PLAYBACK:
314         /*  starts playing in normal mode */
315 /*        if (p_intf->p_input != NULL )
316
317             if (p_main->p_aout != NULL)
318             {
319                 p_main->p_aout->i_vol = vol_val;
320             }
321             snooze(400000);
322             input_SetStatus(p_intf->p_input, INPUT_STATUS_PLAY);
323             playback_status = PLAYING;
324         }
325         break;
326 */
327
328     case PAUSE_PLAYBACK:
329         /* toggle between pause and play */
330         if( p_intf->p_input != NULL )
331         {
332             /* pause if currently playing */
333             if( playback_status == PLAYING )
334             {
335                 /* mute the sound */
336                 vlc_mutex_lock( &p_aout_bank->lock );
337                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
338                 {
339                     p_aout_bank->pp_aout[i_index]->i_savedvolume =
340                                        p_aout_bank->pp_aout[i_index]->i_volume;
341                     p_aout_bank->pp_aout[i_index]->i_volume = 0;
342                 }
343                 vlc_mutex_unlock( &p_aout_bank->lock );
344                 
345                 /* pause the movie */
346                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PAUSE );
347                 vlc_mutex_lock( &p_main->p_playlist->change_lock );
348                 p_main->p_playlist->b_stopped = 0;
349                 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
350                 playback_status = PAUSED;
351             }
352             else
353             {
354                 /* Play after pausing */
355                 /* Restore the volume */
356                 vlc_mutex_lock( &p_aout_bank->lock );
357                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
358                 {
359                     p_aout_bank->pp_aout[i_index]->i_volume =
360                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
361                     p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
362                 }
363                 vlc_mutex_unlock( &p_aout_bank->lock );
364                 snooze( 400000 );
365                 
366                 /* Start playing */
367                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
368                 p_main->p_playlist->b_stopped = 0;
369                 playback_status = PLAYING;
370             }
371         }
372         else
373         {
374             /* Play a new file */
375             vlc_mutex_lock( &p_main->p_playlist->change_lock );
376             if( p_main->p_playlist->b_stopped )
377             {
378                 if( p_main->p_playlist->i_size )
379                 {
380                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
381                     intf_PlaylistJumpto( p_main->p_playlist, 
382                                          p_main->p_playlist->i_index );
383                     playback_status = PLAYING;
384                 }
385                 else
386                 {
387                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
388                 }
389             }
390         }    
391         break;
392
393     case FASTER_PLAY:
394         /* cycle the fast playback modes */
395         if( p_intf->p_input != NULL )
396         {
397             /* mute the sound */
398             vlc_mutex_lock( &p_aout_bank->lock );
399             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
400             {
401                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
402                                        p_aout_bank->pp_aout[i_index]->i_volume;
403                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
404             }
405             vlc_mutex_unlock( &p_aout_bank->lock );
406             snooze( 400000 );
407
408             /* change the fast play mode */
409             input_SetStatus( p_intf->p_input, INPUT_STATUS_FASTER );
410             vlc_mutex_lock( &p_main->p_playlist->change_lock );
411             p_main->p_playlist->b_stopped = 0;
412             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
413         }
414         break;
415
416     case SLOWER_PLAY:
417         /*  cycle the slow playback modes */
418         if (p_intf->p_input != NULL )
419         {
420             /* mute the sound */
421             vlc_mutex_lock( &p_aout_bank->lock );
422             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
423             {
424                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
425                                        p_aout_bank->pp_aout[i_index]->i_volume;
426                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
427             }
428             vlc_mutex_unlock( &p_aout_bank->lock );
429             snooze( 400000 );
430
431             /* change the slower play */
432             input_SetStatus( p_intf->p_input, INPUT_STATUS_SLOWER );
433             vlc_mutex_lock( &p_main->p_playlist->change_lock );
434             p_main->p_playlist->b_stopped = 0;
435             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
436         }
437         break;
438
439     case SEEK_PLAYBACK:
440         /* handled by semaphores */
441         break;
442
443     case VOLUME_CHG:
444         /* adjust the volume */
445         vlc_mutex_lock( &p_aout_bank->lock );
446         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
447         {
448             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
449             {
450                 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
451             }
452             else
453             {
454                 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
455             }
456         }
457         vlc_mutex_unlock( &p_aout_bank->lock );
458         break;
459
460     case VOLUME_MUTE:
461         /* toggle muting */
462         vlc_mutex_lock( &p_aout_bank->lock );
463         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
464         {
465             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
466             {
467                 p_aout_bank->pp_aout[i_index]->i_volume =
468                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
469                 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
470             }
471             else
472             {
473                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
474                                        p_aout_bank->pp_aout[i_index]->i_volume;
475                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
476             }
477         }
478         vlc_mutex_unlock( &p_aout_bank->lock );
479         break;
480
481     case SELECT_CHANNEL:
482         {
483             int32 i = p_message->FindInt32( "channel" );
484             if ( i == -1 )
485             {
486                 input_ChangeES( p_intf->p_input, NULL, AUDIO_ES );
487             }
488             else
489             {
490                 input_ChangeES( p_intf->p_input,
491                         p_intf->p_input->stream.pp_es[i], AUDIO_ES );
492             }
493         }
494         break;
495
496     case SELECT_SUBTITLE:
497         {
498             int32 i = p_message->FindInt32( "subtitle" );
499             if ( i == -1 )
500             {
501                 input_ChangeES( p_intf->p_input, NULL, SPU_ES);
502             }
503             else
504             {
505                 input_ChangeES( p_intf->p_input,
506                         p_intf->p_input->stream.pp_es[i], SPU_ES );
507             }
508         }
509         break;
510
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_main->p_playlist,
519                                   PLAYLIST_END, (char*)path.Path() );
520              }
521         }
522         break;
523
524     default:
525         BWindow::MessageReceived( p_message );
526         break;
527     }
528 }
529
530 /*****************************************************************************
531  * InterfaceWindow::QuitRequested
532  *****************************************************************************/
533 bool InterfaceWindow::QuitRequested()
534 {
535     p_intf->b_die = 1;
536
537     return( false );
538 }
539
540 /*****************************************************************************
541  * CDMenu::CDMenu
542  *****************************************************************************/
543 CDMenu::CDMenu(const char *name)
544       : BMenu(name)
545 {
546 }
547
548 /*****************************************************************************
549  * CDMenu::~CDMenu
550  *****************************************************************************/
551 CDMenu::~CDMenu()
552 {
553 }
554
555 /*****************************************************************************
556  * CDMenu::AttachedToWindow
557  *****************************************************************************/
558 void CDMenu::AttachedToWindow(void)
559 {
560     while (RemoveItem((long int)0) != NULL);  // remove all items
561     GetCD("/dev/disk");
562     BMenu::AttachedToWindow();
563 }
564
565 /*****************************************************************************
566  * CDMenu::GetCD
567  *****************************************************************************/
568 int CDMenu::GetCD( const char *directory )
569 {
570     int i_dev;
571     BDirectory dir;
572     dir.SetTo( directory );
573
574     if( dir.InitCheck() != B_NO_ERROR )
575     {
576         return B_ERROR;
577     }
578
579     dir.Rewind();
580     BEntry entry;
581
582     while( dir.GetNextEntry(&entry) >= 0 )
583     {
584         const char *name;
585         entry_ref e;
586         BPath path;
587
588         if( entry.GetPath(&path) != B_NO_ERROR )
589         {
590             continue;
591         }
592
593         name = path.Path();
594
595         if( entry.GetRef(&e) != B_NO_ERROR )
596         {
597             continue;
598         }
599
600         if( entry.IsDirectory() )
601         {
602             if( strcmp(e.name, "floppy") == 0 )
603             {
604                 continue; // ignore floppy (it is not silent)
605             }
606
607             i_dev = GetCD( name );
608
609             if( i_dev >= 0 )
610             {
611                 return i_dev;
612             }
613         }
614         else
615         {
616             device_geometry g;
617             status_t m;
618
619             if( strcmp(e.name, "raw") != 0 )
620             {
621                 continue; // ignore partitions
622             }
623
624             i_dev = open( name, O_RDONLY );
625
626             if( i_dev < 0 )
627             {
628                 continue;
629             }
630
631             if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
632             {
633                 if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
634                 {
635                     if( ioctl(i_dev, B_GET_MEDIA_STATUS, &m, sizeof(m)) >= 0 )
636                     {
637                         if( m == B_NO_ERROR ) //ensure media is present
638                         {
639                             BMessage *msg;
640                             msg = new BMessage( OPEN_DVD );
641                             msg->AddString( "device", name );
642                             BMenuItem *menu_item;
643                             menu_item = new BMenuItem( name, msg );
644                             AddItem( menu_item );
645                             continue;
646                         }
647                     }
648                 }
649             }
650             close( i_dev );
651         }
652     }
653     return B_ERROR;
654 }
655
656 /*****************************************************************************
657  * LanguageMenu::LanguageMenu
658  *****************************************************************************/
659 LanguageMenu::LanguageMenu(const char *name, int menu_kind, intf_thread_t  *p_interface)
660     :BMenu(name)
661 {
662     kind = menu_kind;
663     p_intf = p_interface;
664 }
665
666 /*****************************************************************************
667  * LanguageMenu::~LanguageMenu
668  *****************************************************************************/
669 LanguageMenu::~LanguageMenu()
670 {
671 }
672
673 /*****************************************************************************
674  * LanguageMenu::AttachedToWindow
675  *****************************************************************************/
676 void LanguageMenu::AttachedToWindow(void)
677 {
678     while( RemoveItem((long int)0) != NULL )
679     {
680         ; // remove all items
681     }
682
683     SetRadioMode(true);
684     GetChannels();
685     BMenu::AttachedToWindow();
686 }
687
688 /*****************************************************************************
689  * LanguageMenu::GetChannels
690  *****************************************************************************/
691 int LanguageMenu::GetChannels()
692 {
693     char  *psz_name;
694     bool   b_active;
695     BMessage *msg;
696     int    i;
697     es_descriptor_t *p_es  = NULL;
698
699     /* Insert the null */
700     if( kind == AUDIO_ES ) //audio
701     {
702         msg = new BMessage(SELECT_CHANNEL);
703         msg->AddInt32("channel", -1);
704     }
705     else
706     {
707         msg = new BMessage(SELECT_SUBTITLE);
708         msg->AddInt32("subtitle", -1);
709     }
710     BMenuItem *menu_item;
711     menu_item = new BMenuItem("None", msg);
712     AddItem(menu_item);
713     menu_item->SetMarked(TRUE);
714
715     if( p_intf->p_input == NULL )
716     {
717         return 1;
718     }
719
720
721     vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
722     for( i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++ )
723     {
724         if( kind == p_intf->p_input->stream.pp_selected_es[i]->i_cat )
725         {
726             p_es = p_intf->p_input->stream.pp_selected_es[i];
727         }
728     }
729
730     for( i = 0; i < p_intf->p_input->stream.i_es_number; i++ )
731     {
732         if( kind == p_intf->p_input->stream.pp_es[i]->i_cat )
733         {
734             psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
735             if( kind == AUDIO_ES ) //audio
736             {
737                 msg = new BMessage(SELECT_CHANNEL);
738                 msg->AddInt32("channel", i);
739             }
740             else
741             {
742                 msg = new BMessage(SELECT_SUBTITLE);
743                 msg->AddInt32("subtitle", i);
744             }
745             BMenuItem *menu_item;
746             menu_item = new BMenuItem(psz_name, msg);
747             AddItem(menu_item);
748             b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
749             menu_item->SetMarked(b_active);
750         }
751     }
752     vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
753
754 }
755
756 /*****************************************************************************
757  * MediaSlider
758  *****************************************************************************/
759 MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
760                           int32 i_min, int32 i_max )
761             :BSlider(frame, NULL, NULL, p_message, i_min, i_max )
762 {
763
764 }
765
766 MediaSlider::~MediaSlider()
767 {
768
769 }
770
771 void MediaSlider::DrawThumb(void)
772 {
773     BRect r;
774     BView *v;
775
776     rgb_color black = {0,0,0};
777     r = ThumbFrame();
778     v = OffscreenView();
779
780     if(IsEnabled())
781     {
782         v->SetHighColor(black);
783     }
784     else
785     {
786         v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
787     }
788
789     r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
790     v->StrokeEllipse(r);
791
792     if(IsEnabled())
793     {
794         v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
795     }
796     else
797     {
798         v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
799     }
800
801     r.InsetBy(1,1);
802     v->FillEllipse(r);
803 }
804
805 /*****************************************************************************
806  * SeekSlider
807  *****************************************************************************/
808 SeekSlider::SeekSlider( BRect frame, InterfaceWindow *p_owner, int32 i_min,
809                         int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
810            :MediaSlider( frame, NULL, i_min, i_max )
811 {
812     fOwner = p_owner;
813     fMouseDown = false;
814 }
815
816 SeekSlider::~SeekSlider()
817 {
818 }
819
820 /*****************************************************************************
821  * SeekSlider::MouseDown
822  *****************************************************************************/
823 void SeekSlider::MouseDown(BPoint where)
824 {
825     BSlider::MouseDown(where);
826     fOwner->fScrubSem = create_sem(1, "Vlc::fScrubSem");
827     fMouseDown = true;
828 }
829
830 /*****************************************************************************
831  * SeekSlider::MouseUp
832  *****************************************************************************/
833 void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
834 {
835     BSlider::MouseMoved(where, code, message);
836     if (!fMouseDown)
837         return;
838     release_sem(fOwner->fScrubSem);
839 }
840
841 /*****************************************************************************
842  * SeekSlider::MouseUp
843  *****************************************************************************/
844 void SeekSlider::MouseUp(BPoint where)
845 {
846     BSlider::MouseUp(where);
847     delete_sem(fOwner->fScrubSem);
848     fOwner->fScrubSem = B_ERROR;
849     fMouseDown = false;
850 }
851
852
853 extern "C"
854 {
855
856 /*****************************************************************************
857  * Local prototypes.
858  *****************************************************************************/
859 static int  intf_Probe     ( probedata_t *p_data );
860 static int  intf_Open      ( intf_thread_t *p_intf );
861 static void intf_Close     ( intf_thread_t *p_intf );
862 static void intf_Run       ( intf_thread_t *p_intf );
863
864 /*****************************************************************************
865  * Functions exported as capabilities. They are declared as static so that
866  * we don't pollute the namespace too much.
867  *****************************************************************************/
868 void _M( intf_getfunctions )( function_list_t * p_function_list )
869 {
870     p_function_list->pf_probe = intf_Probe;
871     p_function_list->functions.intf.pf_open  = intf_Open;
872     p_function_list->functions.intf.pf_close = intf_Close;
873     p_function_list->functions.intf.pf_run   = intf_Run;
874 }
875
876 /*****************************************************************************
877  * intf_Probe: probe the interface and return a score
878  *****************************************************************************
879  * This function tries to initialize Gnome and returns a score to the
880  * plugin manager so that it can select the best plugin.
881  *****************************************************************************/
882 static int intf_Probe( probedata_t *p_data )
883 {
884     if( TestMethod( INTF_METHOD_VAR, "beos" ) )
885     {
886         return( 999 );
887     }
888
889     return( 100 );
890 }
891
892 /*****************************************************************************
893  * intf_Open: initialize interface
894  *****************************************************************************/
895 static int intf_Open( intf_thread_t *p_intf )
896 {
897     BScreen *screen;
898     screen = new BScreen();
899     BRect rect = screen->Frame();
900     rect.top = rect.bottom-100;
901     rect.bottom -= 50;
902     rect.left += 50;
903     rect.right = rect.left + 350;
904     delete screen;
905
906     /* Allocate instance and initialize some members */
907     p_intf->p_sys = (intf_sys_t*) malloc( sizeof( intf_sys_t ) );
908     if( p_intf->p_sys == NULL )
909     {
910         intf_ErrMsg("error: %s", strerror(ENOMEM));
911         return( 1 );
912     }
913     p_intf->p_sys->i_key = -1;
914
915     /* Create the interface window */
916     p_intf->p_sys->p_window =
917         new InterfaceWindow( rect,
918                              VOUT_TITLE " (BeOS interface)", p_intf );
919     if( p_intf->p_sys->p_window == 0 )
920     {
921         free( p_intf->p_sys );
922         intf_ErrMsg( "error: cannot allocate memory for InterfaceWindow" );
923         return( 1 );
924     }
925
926     return( 0 );
927 }
928
929 /*****************************************************************************
930  * intf_Close: destroy dummy interface
931  *****************************************************************************/
932 static void intf_Close( intf_thread_t *p_intf )
933 {
934     /* Destroy the interface window */
935     p_intf->p_sys->p_window->Lock();
936     p_intf->p_sys->p_window->Quit();
937
938     /* Destroy structure */
939     free( p_intf->p_sys );
940 }
941
942
943 /*****************************************************************************
944  * intf_Run: event loop
945  *****************************************************************************/
946 static void intf_Run( intf_thread_t *p_intf )
947 {
948     float progress;
949     bool seekNeeded = false;
950
951     while( !p_intf->b_die )
952     {
953         /* Manage core vlc functions through the callback */
954         p_intf->pf_manage( p_intf );
955
956         /* Manage the slider */
957         if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL)
958         {
959             if( acquire_sem(p_intf->p_sys->p_window->fScrubSem) == B_OK )
960             {
961                 seekNeeded = true;
962             }
963
964             if( seekNeeded )
965             {
966                 uint32 seekTo = (p_intf->p_sys->p_window->p_seek->Value() *
967                         p_intf->p_input->stream.p_selected_area->i_size) / 100;
968                 input_Seek( p_intf->p_input, seekTo );
969                 seekNeeded = false;
970             }
971             else if( p_intf->p_sys->p_window->Lock() )
972             {
973                 progress = (100. * p_intf->p_input->stream.p_selected_area->i_tell) /
974                             p_intf->p_input->stream.p_selected_area->i_size;
975                 p_intf->p_sys->p_window->p_seek->SetValue(progress);
976                 p_intf->p_sys->p_window->Unlock();
977             }
978         }
979
980         /* Wait a bit */
981         msleep( INTF_IDLE_SLEEP );
982     }
983 }
984
985 } /* extern "C" */
986