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