]> git.sesse.net Git - vlc/blob - plugins/beos/intf_beos.cpp
* Mandatory step for video output IV and the audio output quality
[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.27 2001/05/01 04:18:17 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 #include "modules.h"
74
75 #include "stream_control.h"
76 #include "input_ext-intf.h"
77
78 #include "interface.h"
79 #include "intf_playlist.h"
80 #include "intf_msg.h"
81 #include "audio_output.h"
82 #include "MsgVals.h"
83
84 #include "main.h"
85 }
86
87 #include "InterfaceWindow.h"
88 #include "Bitmaps.h"
89 #include "TransportButton.h"
90
91 /*****************************************************************************
92  * intf_sys_t: description and status of FB interface
93  *****************************************************************************/
94 typedef struct intf_sys_s
95 {
96     InterfaceWindow * p_window;
97     char              i_key;
98 } intf_sys_t;
99
100 /*****************************************************************************
101  * InterfaceWindow
102  *****************************************************************************/
103  
104 InterfaceWindow::InterfaceWindow( BRect frame, const char *name , intf_thread_t  *p_interface )
105     : BWindow(frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
106         B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK |B_ASYNCHRONOUS_CONTROLS)
107 {
108     file_panel = NULL;
109     p_intf = p_interface;
110         BRect ButtonRect;
111         float xStart = 5.0;
112         float yStart = 20.0;
113
114     SetName( "interface" );
115     SetTitle(VOUT_TITLE " (BeOS interface)");
116     BRect rect(0, 0, 0, 0);
117     
118     BMenuBar *menu_bar; 
119     menu_bar = new BMenuBar(rect, "main menu");
120     AddChild( menu_bar );
121
122         BMenu *mFile; 
123         BMenu *mAudio;
124         CDMenu *cd_menu;
125         
126         BMenuItem *mItem;
127
128         menu_bar->AddItem( mFile = new BMenu("File") );
129         menu_bar->ResizeToPreferred();
130         mFile->AddItem(mItem = new BMenuItem("Open File" B_UTF8_ELLIPSIS, new BMessage(OPEN_FILE), 'O'));
131         cd_menu = new CDMenu("Open Disc");
132         mFile->AddItem(cd_menu);
133         mFile->AddSeparatorItem();
134         mFile->AddItem(mItem = new BMenuItem("About" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED), 'A'));
135         mItem->SetTarget( be_app );
136         mFile->AddItem(mItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'));
137
138         menu_bar->AddItem ( mAudio = new BMenu("Audio") );
139         menu_bar->ResizeToPreferred();
140         mAudio->AddItem( new LanguageMenu("Language", AUDIO_ES, p_intf) );
141         mAudio->AddItem( new LanguageMenu("Subtitles", SPU_ES, p_intf) );
142         
143
144     rect = Bounds();
145     rect.top += menu_bar->Bounds().IntegerHeight()+1;
146
147     BBox* p_view;
148         p_view = new BBox( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER );
149         p_view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
150     
151         /* Buttons */
152         /* Slow play */
153         ButtonRect.SetLeftTop(BPoint(xStart, yStart));
154         ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
155         xStart += kRewindBitmapWidth;
156         TransportButton* p_slow = new TransportButton(ButtonRect, B_EMPTY_STRING,
157                                                                                         kSkipBackBitmapBits,
158                                                                                         kPressedSkipBackBitmapBits,
159                                                                                         kDisabledSkipBackBitmapBits,
160                                                                                         new BMessage(SLOWER_PLAY));
161         p_view->AddChild( p_slow );
162
163         /* Play Pause */
164         ButtonRect.SetLeftTop(BPoint(xStart, yStart));
165         ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kPlayButtonSize);
166         xStart += kPlayPauseBitmapWidth + 1.0;
167         PlayPauseButton* p_play = new PlayPauseButton(ButtonRect, B_EMPTY_STRING,
168                                                                                         kPlayButtonBitmapBits,
169                                                                                         kPressedPlayButtonBitmapBits,
170                                                                                         kDisabledPlayButtonBitmapBits,
171                                                                                         kPlayingPlayButtonBitmapBits,
172                                                                                         kPressedPlayingPlayButtonBitmapBits,
173                                                                                         kPausedPlayButtonBitmapBits,
174                                                                                         kPressedPausedPlayButtonBitmapBits,
175                                                                                         new BMessage(START_PLAYBACK));
176    
177         p_view->AddChild( p_play );
178         p_play->SetPlaying();
179
180         /* Fast Foward */
181         ButtonRect.SetLeftTop(BPoint(xStart, yStart));
182         ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSkipButtonSize);
183         xStart += kRewindBitmapWidth;
184         TransportButton* p_fast = new TransportButton(ButtonRect, B_EMPTY_STRING,
185                                                                                         kSkipForwardBitmapBits,
186                                                                                         kPressedSkipForwardBitmapBits,
187                                                                                         kDisabledSkipForwardBitmapBits,
188                                                                                         new BMessage(FASTER_PLAY));
189         p_view->AddChild( p_fast );
190
191         /* Stop */
192         ButtonRect.SetLeftTop(BPoint(xStart, yStart));
193         ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kStopButtonSize);
194         xStart += kStopBitmapWidth;
195         TransportButton* p_stop = new TransportButton(ButtonRect, B_EMPTY_STRING,
196                                                                                         kStopButtonBitmapBits,
197                                                                                         kPressedStopButtonBitmapBits,
198                                                                                         kDisabledStopButtonBitmapBits,
199                                                                                         new BMessage(STOP_PLAYBACK));
200         p_view->AddChild( p_stop );
201
202         ButtonRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
203         ButtonRect.SetRightBottom(ButtonRect.LeftTop() + kSpeakerButtonSize);
204         xStart += kSpeakerIconBitmapWidth;
205  
206         TransportButton* p_mute = new TransportButton(ButtonRect, B_EMPTY_STRING,
207                                                                                         kSpeakerIconBits,
208                                                                                         kPressedSpeakerIconBits,
209                                                                                         kSpeakerIconBits,
210                                                                                         new BMessage(VOLUME_MUTE));
211
212         p_view->AddChild( p_mute );
213  
214         /* Seek Status */       
215     rgb_color fill_color = {0,255,0};
216         p_seek = new SeekSlider(BRect(5,2,255,15), this, 0, 100,
217                                                 B_TRIANGLE_THUMB);
218         p_seek->SetValue(0);
219         p_seek->UseFillColor(true, &fill_color);
220     p_view->AddChild( p_seek );
221
222         /* Volume Slider */     
223         p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
224                                                         0, VOLUME_MAX);
225         p_vol->SetValue(VOLUME_DEFAULT);
226         p_vol->UseFillColor(true, &fill_color);
227     p_view->AddChild( p_vol );
228     
229         /* Set size and Show */
230     AddChild( p_view );
231         ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
232     Show();
233 }
234
235 InterfaceWindow::~InterfaceWindow()
236 {
237 }
238
239 /*****************************************************************************
240  * InterfaceWindow::MessageReceived
241  *****************************************************************************/
242 void InterfaceWindow::MessageReceived( BMessage * p_message )
243 {
244         int vol_val = p_vol->Value();   // remember the current volume
245         static int playback_status;             // remember playback state
246         
247         BAlert *alert;
248         Activate();
249     switch( p_message->what )
250     {
251 //    case B_ABOUT_REQUESTED:
252 //              alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
253 //          alert->Go();
254 //          break;      
255     
256     case OPEN_FILE:
257         if(file_panel)
258                 {
259                 file_panel->Show();
260                 break;
261                 }
262         file_panel = new BFilePanel();
263         file_panel->SetTarget(this);
264         file_panel->Show();
265         break;
266
267     case OPEN_DVD:
268             const char **device;
269             char device_method_and_name[B_FILE_NAME_LENGTH + 4];
270             if(p_message->FindString("device", device) != B_ERROR)
271                 {
272                 sprintf(device_method_and_name, "dvd:%s", *device); 
273                 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, device_method_and_name );
274                 }
275         break;
276
277     case STOP_PLAYBACK:
278         // this currently stops playback not nicely
279                 if (p_intf->p_input != NULL )
280                 {
281                         // silence the sound, otherwise very horrible
282                         if (p_main->p_aout != NULL)
283                         {
284                                 p_main->p_aout->i_vol = 0;
285                         }
286                         snooze(400000);
287                         input_SetStatus(p_intf->p_input, INPUT_STATUS_END);
288                 }
289         break;
290         case START_PLAYBACK:
291                 // starts playing in normal mode
292 //              if (p_intf->p_input != NULL )
293 //              {                       
294 //                      if (p_main->p_aout != NULL)
295 //                      {
296 //                              p_main->p_aout->i_vol = vol_val;
297 //                      }
298 //                      snooze(400000);
299 //                      input_SetStatus(p_intf->p_input, INPUT_STATUS_PLAY);
300 //                      playback_status = PLAYING;
301 //              } 
302 //              break;
303         case PAUSE_PLAYBACK:
304                 // pause the playback
305                 if (p_intf->p_input != NULL )
306                 {
307                         // mute the volume if currently playing
308                         if (playback_status == PLAYING)
309                         {
310                                 if (p_main->p_aout != NULL)
311                                 {
312                                         p_main->p_aout->i_vol = 0;
313                                 }
314                                 playback_status = PAUSED;
315                         }
316                         else
317                         // restore the volume
318                         {
319                                 if (p_main->p_aout != NULL)
320                                 {
321                                         p_main->p_aout->i_vol = vol_val;
322                                 }
323                                 playback_status = PLAYING;
324                         }
325                         snooze(400000);
326                         input_SetStatus(p_intf->p_input, INPUT_STATUS_PAUSE);
327                 }
328                 break;
329         case FASTER_PLAY:
330                 // cycle the fast playback modes
331                 if (p_intf->p_input != NULL )
332                 {
333                         if (p_main->p_aout != NULL)
334                         {
335                                 p_main->p_aout->i_vol = 0;
336                         }
337                         snooze(400000);
338                         input_SetStatus(p_intf->p_input, INPUT_STATUS_FASTER);
339                 }
340                 break;
341         case SLOWER_PLAY:
342                 // cycle the slow playback modes
343                 if (p_intf->p_input != NULL )
344                 {
345                         if (p_main->p_aout != NULL)
346                         {
347                                 p_main->p_aout->i_vol = 0;
348                         }
349                         snooze(400000);
350                         input_SetStatus(p_intf->p_input, INPUT_STATUS_SLOWER);
351                 }
352                 break;
353         case SEEK_PLAYBACK:
354                 // handled by semaphores;
355                 break;
356         case VOLUME_CHG:
357                 // adjust the volume
358         if (p_main->p_aout != NULL) 
359         {
360                         p_main->p_aout->i_vol = vol_val;
361                 }
362                 break;
363         case VOLUME_MUTE:
364                 // mute
365         if (p_main->p_aout != NULL) 
366             {
367                         if (p_main->p_aout->i_vol == 0)
368                         {
369                                 p_vol->SetEnabled(true);
370                                 p_main->p_aout->i_vol = vol_val;
371                         }       
372                         else
373                         {
374                                 p_vol->SetEnabled(false);
375                                 p_main->p_aout->i_vol = 0;
376                         }
377                 }
378                 break;
379         case SELECT_CHANNEL:
380                 {
381                         int32 i = p_message->FindInt32("channel");
382                         input_ChangeES(p_intf->p_input, 
383                                         p_intf->p_input->stream.pp_es[i], 1);
384                 }
385                 break;
386         case SELECT_SUBTITLE:
387                 {
388                         int32 i = p_message->FindInt32("subtitle");
389                         input_ChangeES(p_intf->p_input, 
390                                         p_intf->p_input->stream.pp_es[i], 2);
391                 }
392                 break;
393         case B_REFS_RECEIVED:
394     case B_SIMPLE_DATA:
395         {
396             entry_ref ref;
397             if( p_message->FindRef( "refs", &ref ) == B_OK )
398             {
399                 BPath path( &ref );
400                 intf_PlaylistAdd( p_main->p_playlist,
401                                   PLAYLIST_END, path.Path() );
402             }
403
404         }
405         break;
406     default:
407         BWindow::MessageReceived( p_message );
408         break;
409     }
410 }
411
412 /*****************************************************************************
413  * InterfaceWindow::QuitRequested
414  *****************************************************************************/
415 bool InterfaceWindow::QuitRequested()
416 {
417     p_intf->b_die = 1;
418
419     return( false );
420 }
421
422 /*****************************************************************************
423  * CDMenu::CDMenu
424  *****************************************************************************/
425 CDMenu::CDMenu(const char *name)
426         : BMenu(name)
427 {
428 }
429
430 /*****************************************************************************
431  * CDMenu::~CDMenu
432  *****************************************************************************/
433 CDMenu::~CDMenu()
434 {
435 }
436
437 /*****************************************************************************
438  * CDMenu::AttachedToWindow
439  *****************************************************************************/
440 void CDMenu::AttachedToWindow(void)
441 {
442         while (RemoveItem((long int)0) != NULL);  // remove all items
443         GetCD("/dev/disk");
444         BMenu::AttachedToWindow();
445 }
446
447 /*****************************************************************************
448  * CDMenu::GetCD
449  *****************************************************************************/
450 int CDMenu::GetCD(const char *directory)
451
452         BDirectory dir; 
453         dir.SetTo(directory); 
454         if(dir.InitCheck() != B_NO_ERROR) { 
455                 return B_ERROR; 
456         } 
457         dir.Rewind(); 
458         BEntry entry; 
459         while(dir.GetNextEntry(&entry) >= 0) { 
460                 BPath path; 
461                 const char *name; 
462                 entry_ref e; 
463                 
464                 if(entry.GetPath(&path) != B_NO_ERROR) 
465                         continue; 
466                 name = path.Path(); 
467                 
468                 
469                 if(entry.GetRef(&e) != B_NO_ERROR) 
470                         continue; 
471
472                 if(entry.IsDirectory()) { 
473                         if(strcmp(e.name, "floppy") == 0) 
474                                 continue; // ignore floppy (it is not silent) 
475                         int devfd = GetCD(name);
476                         if(devfd >= 0)
477                                 {
478                                 return devfd;
479                                 }
480                 } 
481                 else { 
482                         int devfd; 
483                         device_geometry g;
484                         status_t m;
485
486                         if(strcmp(e.name, "raw") != 0) 
487                                 continue; // ignore partitions 
488
489                         devfd = open(name, O_RDONLY); 
490                         if(devfd < 0) 
491                                 continue; 
492
493                         if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) {
494                                 if(g.device_type == B_CD) //ensure the drive is a CD-ROM
495                                 { 
496                                         if(ioctl(devfd, B_GET_MEDIA_STATUS, &m, sizeof(m)) >= 0 )
497                                                 if(m == B_NO_ERROR) //ensure media is present
498                                                         {
499                                                         BMessage *msg;
500                                                         msg = new BMessage(OPEN_DVD);
501                                                         msg->AddString("device", name);
502                                                         BMenuItem *menu_item;
503                                                         menu_item = new BMenuItem(name, msg);
504                                                         AddItem(menu_item);
505                                                         continue;
506                                                         }
507                                 }
508                         }
509                         close(devfd);
510                 } 
511         }
512         return B_ERROR;
513 }
514
515 /*****************************************************************************
516  * LanguageMenu::LanguageMenu
517  *****************************************************************************/
518 LanguageMenu::LanguageMenu(const char *name, int menu_kind, intf_thread_t  *p_interface)
519         :BMenu(name)
520 {
521         kind = menu_kind;
522         p_intf = p_interface;
523 }
524
525 /*****************************************************************************
526  * LanguageMenu::~LanguageMenu
527  *****************************************************************************/
528 LanguageMenu::~LanguageMenu()
529 {
530 }
531
532 /*****************************************************************************
533  * LanguageMenu::AttachedToWindow
534  *****************************************************************************/
535 void LanguageMenu::AttachedToWindow(void)
536 {
537         while (RemoveItem((long int)0) != NULL); // remove all items
538         SetRadioMode(true);
539         GetChannels();
540         BMenu::AttachedToWindow();
541 }
542
543 /*****************************************************************************
544  * LanguageMenu::GetChannels
545  *****************************************************************************/
546 int LanguageMenu::GetChannels()
547
548         char*   psz_name;
549         bool    b_active;
550         bool    b_found;
551         int32   i;
552         es_descriptor_t *p_es;
553         
554         if (p_intf->p_input == NULL)
555                 return 1;
556                 
557         for (i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++)
558         {
559                 if (kind ==
560                         p_intf->p_input->stream.pp_selected_es[i]->i_cat)
561                 {
562                         p_es = p_intf->p_input->stream.pp_selected_es[i];
563                 }
564         }               
565         for (i = 0; i < p_intf->p_input->stream.i_es_number; i++)
566         {
567                 if (kind == p_intf->p_input->stream.pp_es[i]->i_cat)
568                 {
569                         psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
570                         BMessage *msg;
571                         if (kind == AUDIO_ES) //audio
572                         {
573                                 msg = new BMessage(SELECT_CHANNEL);
574                                 msg->AddInt32("channel", i);
575                         }
576                         else
577                         {
578                                 msg = new BMessage(SELECT_SUBTITLE);
579                                 msg->AddInt32("subtitle", i);
580                         }
581                         BMenuItem *menu_item;
582                         menu_item = new BMenuItem(psz_name, msg);
583                         AddItem(menu_item);
584                         b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
585                         menu_item->SetMarked(b_active);
586                 }
587         }
588 }
589
590
591 /*****************************************************************************
592  * MediaSlider
593  *****************************************************************************/
594 MediaSlider::MediaSlider(BRect frame,
595                                                 BMessage *message,
596                                                 int32 minValue,
597                                                 int32 maxValue)
598                                         :BSlider(frame, NULL, NULL, message, minValue, maxValue)
599 {
600
601 }
602
603 MediaSlider::~MediaSlider()
604 {
605
606 }
607
608 void MediaSlider::DrawThumb(void)
609 {
610         BRect r;
611         BView *v;
612
613         rgb_color black = {0,0,0};
614         r = ThumbFrame();
615         v = OffscreenView();
616         if(IsEnabled())
617                 v->SetHighColor(black);
618         else
619                 v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
620         r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
621         v->StrokeEllipse(r);
622         if(IsEnabled())
623                 v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
624         else
625                 v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
626         r.InsetBy(1,1);
627         v->FillEllipse(r);
628 }
629
630 /*****************************************************************************
631  * SeekSlider
632  *****************************************************************************/
633 SeekSlider::SeekSlider(BRect frame,
634                                 InterfaceWindow *owner,
635                                 int32 minValue,
636                                 int32 maxValue,
637                                 thumb_style thumbType = B_TRIANGLE_THUMB)
638                         :MediaSlider(frame, NULL, minValue, maxValue)
639 {
640         fOwner = owner;
641         fMouseDown = false;
642 }
643
644 SeekSlider::~SeekSlider()
645 {
646 }
647
648 /*****************************************************************************
649  * SeekSlider::MouseDown
650  *****************************************************************************/
651 void SeekSlider::MouseDown(BPoint where)
652 {
653         BSlider::MouseDown(where);
654         fOwner->fScrubSem = create_sem(1, "Vlc::fScrubSem");
655         fMouseDown = true;                                      
656 }
657
658 /*****************************************************************************
659  * SeekSlider::MouseUp
660  *****************************************************************************/
661 void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
662 {
663         BSlider::MouseMoved(where, code, message);
664         if (!fMouseDown)
665                 return;
666         release_sem(fOwner->fScrubSem);
667 }
668
669 /*****************************************************************************
670  * SeekSlider::MouseUp
671  *****************************************************************************/
672 void SeekSlider::MouseUp(BPoint where)
673 {
674         BSlider::MouseUp(where);
675         delete_sem(fOwner->fScrubSem);
676         fOwner->fScrubSem = B_ERROR;
677         fMouseDown = false;                                     
678 }
679         
680
681 extern "C"
682 {
683
684 /*****************************************************************************
685  * Local prototypes.
686  *****************************************************************************/
687 static int  intf_Probe     ( probedata_t *p_data );
688 static int  intf_Open      ( intf_thread_t *p_intf );
689 static void intf_Close     ( intf_thread_t *p_intf );
690 static void intf_Run       ( intf_thread_t *p_intf );
691
692 /*****************************************************************************
693  * Functions exported as capabilities. They are declared as static so that
694  * we don't pollute the namespace too much.
695  *****************************************************************************/
696 void _M( intf_getfunctions )( function_list_t * p_function_list )
697 {
698     p_function_list->pf_probe = intf_Probe;
699     p_function_list->functions.intf.pf_open  = intf_Open;
700     p_function_list->functions.intf.pf_close = intf_Close;
701     p_function_list->functions.intf.pf_run   = intf_Run;
702 }
703
704 /*****************************************************************************
705  * intf_Probe: probe the interface and return a score
706  *****************************************************************************
707  * This function tries to initialize Gnome and returns a score to the
708  * plugin manager so that it can select the best plugin.
709  *****************************************************************************/
710 static int intf_Probe( probedata_t *p_data )
711 {
712     if( TestMethod( INTF_METHOD_VAR, "beos" ) )
713     {
714         return( 999 );
715     }
716
717     return( 100 );
718 }
719
720 /*****************************************************************************
721  * intf_Open: initialize interface
722  *****************************************************************************/
723 static int intf_Open( intf_thread_t *p_intf )
724 {
725     BScreen *screen;
726     screen = new BScreen();
727     BRect rect = screen->Frame();
728     rect.top = rect.bottom-100;
729     rect.bottom -= 50;
730     rect.left += 50;
731     rect.right = rect.left + 350;
732     delete screen;
733     
734     /* Allocate instance and initialize some members */
735     p_intf->p_sys = (intf_sys_t*) malloc( sizeof( intf_sys_t ) );
736     if( p_intf->p_sys == NULL )
737     {
738         intf_ErrMsg("error: %s", strerror(ENOMEM));
739         return( 1 );
740     }
741     p_intf->p_sys->i_key = -1;
742     
743     /* Create the interface window */
744     p_intf->p_sys->p_window =
745         new InterfaceWindow( rect,
746                              VOUT_TITLE " (BeOS interface)", p_intf );
747     if( p_intf->p_sys->p_window == 0 )
748     {
749         free( p_intf->p_sys );
750         intf_ErrMsg( "error: cannot allocate memory for InterfaceWindow" );
751         return( 1 );
752     }
753     
754     return( 0 );
755 }
756
757 /*****************************************************************************
758  * intf_Close: destroy dummy interface
759  *****************************************************************************/
760 static void intf_Close( intf_thread_t *p_intf )
761 {
762     /* Destroy the interface window */
763     p_intf->p_sys->p_window->Lock();
764     p_intf->p_sys->p_window->Quit();    
765
766     /* Destroy structure */
767     free( p_intf->p_sys );
768 }
769
770
771 /*****************************************************************************
772  * intf_Run: event loop
773  *****************************************************************************/
774 static void intf_Run( intf_thread_t *p_intf )
775 {
776         
777         float progress;
778         bool seekNeeded = false;
779         
780     while( !p_intf->b_die )
781     {
782
783         /* Manage core vlc functions through the callback */
784         p_intf->pf_manage( p_intf );
785
786             /* Manage the slider */
787             if( p_intf->p_input != NULL && p_intf->p_sys->p_window != NULL)
788         {
789             if (acquire_sem(p_intf->p_sys->p_window->fScrubSem) == B_OK)
790                         {
791                                 seekNeeded = true;
792                         }               
793
794                         if (seekNeeded)
795             {
796                 uint32 seekTo = (p_intf->p_sys->p_window->p_seek->Value() * 
797                                 p_intf->p_input->stream.p_selected_area->i_size) / 100;
798                                 input_Seek( p_intf->p_input, seekTo );
799                                 seekNeeded = false;             
800             }
801                         else if (p_intf->p_sys->p_window->Lock())
802             {
803                     progress = (100. * p_intf->p_input->stream.p_selected_area->i_tell) /
804                                         p_intf->p_input->stream.p_selected_area->i_size;
805                     p_intf->p_sys->p_window->p_seek->SetValue(progress);
806                     p_intf->p_sys->p_window->Unlock();
807                 }
808          }
809
810         /* Wait a bit */
811         msleep( INTF_IDLE_SLEEP );
812     }
813 }
814
815 } /* extern "C" */