]> git.sesse.net Git - vlc/blob - plugins/beos/InterfaceWindow.cpp
Fixed the slider overflow problem.
[vlc] / plugins / beos / InterfaceWindow.cpp
1 /*****************************************************************************
2  * InterfaceWindow.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: InterfaceWindow.cpp,v 1.3 2001/09/12 01:30:07 tcastley Exp $
6  *
7  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *          Tony Castley <tony@castley.net>
10  *          Richard Shepherd <richard@rshepherd.demon.co.uk>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26 #include "defs.h"
27
28 /* System headers */
29 #include <kernel/OS.h>
30 #include <InterfaceKit.h>
31 #include <AppKit.h>
32 #include <StorageKit.h>
33 #include <malloc.h>
34 #include <scsi.h>
35 #include <scsiprobe_driver.h>
36
37 /* VLC headers */
38 extern "C"
39 {
40 #include "config.h"
41 #include "common.h"
42 #include "threads.h"
43 #include "mtime.h"
44 #include "main.h"
45 #include "tests.h"
46 #include "stream_control.h"
47 #include "input_ext-intf.h"
48 #include "interface.h"
49 #include "intf_msg.h"
50 #include "intf_playlist.h"
51 #include "audio_output.h"
52 }
53
54 /* BeOS interface headers */
55 #include "MsgVals.h"
56 #include "MediaControlView.h"
57 #include "InterfaceWindow.h"
58 #include "PlayListWindow.h"
59
60 /*****************************************************************************
61  * InterfaceWindow
62  *****************************************************************************/
63
64 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
65                                   intf_thread_t  *p_interface )
66     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
67                B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
68                 | B_ASYNCHRONOUS_CONTROLS )
69 {
70     file_panel = NULL;
71     p_intf = p_interface;
72     BRect controlRect(0,0,0,0);
73     b_empty_playlist = (p_main->p_playlist->i_size < 0);
74
75     /* set the title bar */
76     SetName( "interface" );
77     SetTitle(VOUT_TITLE);
78
79     /* set up the main menu */
80     BMenuBar *menu_bar;
81     menu_bar = new BMenuBar(controlRect, "main menu");
82     AddChild( menu_bar );
83
84     BMenu *mFile;
85     BMenu *mAudio;
86     CDMenu *cd_menu;
87     
88     /* Add the file Menu */
89     BMenuItem *mItem;
90     menu_bar->AddItem( mFile = new BMenu( "File" ) );
91     menu_bar->ResizeToPreferred();
92     mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
93                                            new BMessage(OPEN_FILE), 'O') );
94     
95     cd_menu = new CDMenu( "Open Disc" );
96     mFile->AddItem( cd_menu );
97     
98     mFile->AddSeparatorItem();
99     mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
100                                            new BMessage(OPEN_PLAYLIST), 'P') );
101     
102     mFile->AddSeparatorItem();
103     mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
104                                        new BMessage(B_ABOUT_REQUESTED), 'A') );
105     mItem->SetTarget( be_app );
106     mFile->AddItem(mItem = new BMenuItem( "Quit",
107                                         new BMessage(B_QUIT_REQUESTED), 'Q') );
108
109     /* Add the Audio menu */
110     menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
111     menu_bar->ResizeToPreferred();
112     mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
113     mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
114
115     ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
116     controlRect = Bounds();
117     controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
118
119     p_mediaControl = new MediaControlView( controlRect );
120     p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
121
122     /* Show */
123     AddChild( p_mediaControl );
124     Show();
125     
126 }
127
128 InterfaceWindow::~InterfaceWindow()
129 {
130 }
131
132 /*****************************************************************************
133  * InterfaceWindow::MessageReceived
134  *****************************************************************************/
135 void InterfaceWindow::MessageReceived( BMessage * p_message )
136 {
137     int vol_val = p_mediaControl->GetVolume();    // remember the current volume
138     int playback_status;      // remember playback state
139     int     i_index;
140     BAlert *alert;
141
142     Activate();
143     if (p_intf->p_input)
144     {
145             playback_status = p_intf->p_input->stream.control.i_status;
146         }
147         else
148         {
149             playback_status = UNDEF_S;
150         }
151
152     switch( p_message->what )
153     {
154     case B_ABOUT_REQUESTED:
155         alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
156         alert->Go();
157         break;
158
159     case OPEN_FILE:
160         if( file_panel )
161         {
162             file_panel->Show();
163             break;
164         }
165         file_panel = new BFilePanel();
166         file_panel->SetTarget( this );
167         file_panel->Show();
168         break;
169
170         case OPEN_PLAYLIST:
171                 {
172                     BRect rect(20,20,320,420);
173             PlayListWindow* playlist_window = new PlayListWindow(rect,
174                          "Playlist", (playlist_t *)p_main->p_playlist);
175             playlist_window->Show();
176         }
177                 break;
178     case OPEN_DVD:
179         const char *psz_device;
180         char psz_source[ B_FILE_NAME_LENGTH + 4 ];
181         if( p_message->FindString("device", &psz_device) != B_ERROR )
182         {
183             snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
184                       "dvd:%s", psz_device );
185             psz_source[ strlen(psz_source) ] = '\0';
186             intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, (char*)psz_source );
187             if( p_intf->p_input != NULL )
188             {
189                 p_intf->p_input->b_eof = 1;
190             }
191             intf_PlaylistJumpto( p_main->p_playlist, 
192                                  p_main->p_playlist->i_size - 1 );
193         }
194         break;
195
196     case STOP_PLAYBACK:
197         // this currently stops playback not nicely
198         if( p_intf->p_input != NULL )
199         {
200             // silence the sound, otherwise very horrible
201             vlc_mutex_lock( &p_aout_bank->lock );
202             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
203             {
204                 p_aout_bank->pp_aout[i_index]->i_savedvolume = p_aout_bank->pp_aout[i_index]->i_volume;
205                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
206             }
207             vlc_mutex_unlock( &p_aout_bank->lock );
208             snooze( 400000 );
209
210             /* end playing item */
211             p_intf->p_input->b_eof = 1;
212             
213             /* update playlist */
214             vlc_mutex_lock( &p_main->p_playlist->change_lock );
215             p_main->p_playlist->i_index--;
216             p_main->p_playlist->b_stopped = 1;
217             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
218         }
219         p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
220         break;
221
222     case START_PLAYBACK:
223         /*  starts playing in normal mode */
224
225     case PAUSE_PLAYBACK:
226         /* toggle between pause and play */
227         if( p_intf->p_input != NULL )
228         {
229             /* pause if currently playing */
230             if( playback_status == PLAYING_S )
231             {
232                 /* mute the sound */
233                 vlc_mutex_lock( &p_aout_bank->lock );
234                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
235                 {
236                     p_aout_bank->pp_aout[i_index]->i_savedvolume =
237                                        p_aout_bank->pp_aout[i_index]->i_volume;
238                     p_aout_bank->pp_aout[i_index]->i_volume = 0;
239                 }
240                 vlc_mutex_unlock( &p_aout_bank->lock );
241                 snooze( 400000 );
242                 
243                 /* pause the movie */
244                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PAUSE );
245                 vlc_mutex_lock( &p_main->p_playlist->change_lock );
246                 p_main->p_playlist->b_stopped = 0;
247                 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
248             }
249             else
250             {
251                 /* Play after pausing */
252                 /* Restore the volume */
253                 vlc_mutex_lock( &p_aout_bank->lock );
254                 for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
255                 {
256                     p_aout_bank->pp_aout[i_index]->i_volume =
257                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
258                     p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
259                 }
260                 vlc_mutex_unlock( &p_aout_bank->lock );
261                 snooze( 400000 );
262                 
263                 /* Start playing */
264                 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
265                 p_main->p_playlist->b_stopped = 0;
266             }
267         }
268         else
269         {
270             /* Play a new file */
271             vlc_mutex_lock( &p_main->p_playlist->change_lock );
272             if( p_main->p_playlist->b_stopped )
273             {
274                 if( p_main->p_playlist->i_size )
275                 {
276                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
277                     intf_PlaylistJumpto( p_main->p_playlist, 
278                                          p_main->p_playlist->i_index );
279                     p_main->p_playlist->b_stopped = 0;
280                 }
281                 else
282                 {
283                     vlc_mutex_unlock( &p_main->p_playlist->change_lock );
284                 }
285             }
286         }    
287         break;
288
289     case FASTER_PLAY:
290         /* cycle the fast playback modes */
291         if( p_intf->p_input != NULL )
292         {
293             /* mute the sound */
294             vlc_mutex_lock( &p_aout_bank->lock );
295             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
296             {
297                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
298                                        p_aout_bank->pp_aout[i_index]->i_volume;
299                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
300             }
301             vlc_mutex_unlock( &p_aout_bank->lock );
302             snooze( 400000 );
303
304             /* change the fast play mode */
305             input_SetStatus( p_intf->p_input, INPUT_STATUS_FASTER );
306             vlc_mutex_lock( &p_main->p_playlist->change_lock );
307             p_main->p_playlist->b_stopped = 0;
308             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
309         }
310         break;
311
312     case SLOWER_PLAY:
313         /*  cycle the slow playback modes */
314         if (p_intf->p_input != NULL )
315         {
316             /* mute the sound */
317             vlc_mutex_lock( &p_aout_bank->lock );
318             for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
319             {
320                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
321                                        p_aout_bank->pp_aout[i_index]->i_volume;
322                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
323             }
324             vlc_mutex_unlock( &p_aout_bank->lock );
325             snooze( 400000 );
326
327             /* change the slower play */
328             input_SetStatus( p_intf->p_input, INPUT_STATUS_SLOWER );
329             vlc_mutex_lock( &p_main->p_playlist->change_lock );
330             p_main->p_playlist->b_stopped = 0;
331             vlc_mutex_unlock( &p_main->p_playlist->change_lock );
332         }
333         break;
334
335     case SEEK_PLAYBACK:
336         /* handled by semaphores */
337         break;
338
339     case VOLUME_CHG:
340         /* adjust the volume */
341         vlc_mutex_lock( &p_aout_bank->lock );
342         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
343         {
344             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
345             {
346                 p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
347             }
348             else
349             {
350                 p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
351             }
352         }
353         vlc_mutex_unlock( &p_aout_bank->lock );
354         break;
355
356     case VOLUME_MUTE:
357         /* toggle muting */
358         vlc_mutex_lock( &p_aout_bank->lock );
359         for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
360         {
361             if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
362             {
363                 p_aout_bank->pp_aout[i_index]->i_volume =
364                                   p_aout_bank->pp_aout[i_index]->i_savedvolume;
365                 p_aout_bank->pp_aout[i_index]->i_savedvolume = 0;
366             }
367             else
368             {
369                 p_aout_bank->pp_aout[i_index]->i_savedvolume =
370                                        p_aout_bank->pp_aout[i_index]->i_volume;
371                 p_aout_bank->pp_aout[i_index]->i_volume = 0;
372             }
373         }
374         vlc_mutex_unlock( &p_aout_bank->lock );
375         break;
376
377     case SELECT_CHANNEL:
378         {
379             int32 i = p_message->FindInt32( "channel" );
380             if ( i == -1 )
381             {
382                 input_ChangeES( p_intf->p_input, NULL, AUDIO_ES );
383             }
384             else
385             {
386                 input_ChangeES( p_intf->p_input,
387                         p_intf->p_input->stream.pp_es[i], AUDIO_ES );
388             }
389         }
390         break;
391
392     case SELECT_SUBTITLE:
393         {
394             int32 i = p_message->FindInt32( "subtitle" );
395             if ( i == -1 )
396             {
397                 input_ChangeES( p_intf->p_input, NULL, SPU_ES);
398             }
399             else
400             {
401                 input_ChangeES( p_intf->p_input,
402                         p_intf->p_input->stream.pp_es[i], SPU_ES );
403             }
404         }
405         break;
406
407     case B_REFS_RECEIVED:
408     case B_SIMPLE_DATA:
409         {
410             entry_ref ref;
411             if( p_message->FindRef( "refs", &ref ) == B_OK )
412             {
413                 BPath path( &ref );
414                 intf_PlaylistAdd( p_main->p_playlist,
415                                   PLAYLIST_END, (char*)path.Path() );
416                 if( p_intf->p_input != NULL )
417                 {
418                     p_intf->p_input->b_eof = 1;
419                 }
420                 intf_PlaylistJumpto( p_main->p_playlist, 
421                                      p_main->p_playlist->i_size - 1 );
422                                   
423              }
424         }
425         break;
426
427     default:
428         BWindow::MessageReceived( p_message );
429         break;
430     }
431
432 }
433
434 /*****************************************************************************
435  * InterfaceWindow::updateInterface
436  *****************************************************************************/
437 void InterfaceWindow::updateInterface()
438 {
439         if ( p_intf->p_input )
440         {
441         if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
442         {
443             uint64 seekTo = (p_mediaControl->GetSeekTo() *
444                         p_intf->p_input->stream.p_selected_area->i_size) / 100;
445             intf_Msg("Move to: %u", seekTo);
446             input_Seek( p_intf->p_input, seekTo);
447         }
448         else if( Lock() )
449         {
450             p_mediaControl->SetStatus(p_intf->p_input->stream.control.i_status, 
451                                       p_intf->p_input->stream.control.i_rate);
452             p_mediaControl->SetProgress(p_intf->p_input->stream.p_selected_area->i_tell,
453                                         p_intf->p_input->stream.p_selected_area->i_size);
454             Unlock();
455         }
456     }
457     if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) )
458     {
459         if (Lock())
460         {
461             b_empty_playlist = !b_empty_playlist;
462             p_mediaControl->SetEnabled( !b_empty_playlist );
463             Unlock();
464         }
465     }
466 }
467
468 /*****************************************************************************
469  * InterfaceWindow::QuitRequested
470  *****************************************************************************/
471 bool InterfaceWindow::QuitRequested()
472 {
473     p_intf->b_die = 1;
474
475     return( false );
476 }
477
478 /*****************************************************************************
479  * CDMenu::CDMenu
480  *****************************************************************************/
481 CDMenu::CDMenu(const char *name)
482       : BMenu(name)
483 {
484 }
485
486 /*****************************************************************************
487  * CDMenu::~CDMenu
488  *****************************************************************************/
489 CDMenu::~CDMenu()
490 {
491 }
492
493 /*****************************************************************************
494  * CDMenu::AttachedToWindow
495  *****************************************************************************/
496 void CDMenu::AttachedToWindow(void)
497 {
498     while (RemoveItem((long int)0) != NULL);  // remove all items
499     GetCD("/dev/disk");
500     BMenu::AttachedToWindow();
501 }
502
503 /*****************************************************************************
504  * CDMenu::GetCD
505  *****************************************************************************/
506 int CDMenu::GetCD( const char *directory )
507 {
508     int i_dev;
509     BDirectory dir;
510     dir.SetTo( directory );
511
512     if( dir.InitCheck() != B_NO_ERROR )
513     {
514         return B_ERROR;
515     }
516
517     dir.Rewind();
518     BEntry entry;
519
520     while( dir.GetNextEntry(&entry) >= 0 )
521     {
522         const char *name;
523         entry_ref e;
524         BPath path;
525
526         if( entry.GetPath(&path) != B_NO_ERROR )
527         {
528             continue;
529         }
530
531         name = path.Path();
532
533         if( entry.GetRef(&e) != B_NO_ERROR )
534         {
535             continue;
536         }
537
538         if( entry.IsDirectory() )
539         {
540             if( strcmp(e.name, "floppy") == 0 )
541             {
542                 continue; // ignore floppy (it is not silent)
543             }
544
545             i_dev = GetCD( name );
546
547             if( i_dev >= 0 )
548             {
549                 return i_dev;
550             }
551         }
552         else
553         {
554             device_geometry g;
555             status_t m;
556
557             if( strcmp(e.name, "raw") != 0 )
558             {
559                 continue; // ignore partitions
560             }
561
562             i_dev = open( name, O_RDONLY );
563
564             if( i_dev < 0 )
565             {
566                 continue;
567             }
568
569             if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
570             {
571                 if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
572                 {
573                     if( ioctl(i_dev, B_GET_MEDIA_STATUS, &m, sizeof(m)) >= 0 )
574                     {
575                         if( m == B_NO_ERROR ) //ensure media is present
576                         {
577                             BMessage *msg;
578                             msg = new BMessage( OPEN_DVD );
579                             msg->AddString( "device", name );
580                             BMenuItem *menu_item;
581                             menu_item = new BMenuItem( name, msg );
582                             AddItem( menu_item );
583                             continue;
584                         }
585                     }
586                 }
587             }
588             close( i_dev );
589         }
590     }
591     return B_ERROR;
592 }
593
594 /*****************************************************************************
595  * LanguageMenu::LanguageMenu
596  *****************************************************************************/
597 LanguageMenu::LanguageMenu(const char *name, int menu_kind, 
598                             intf_thread_t  *p_interface)
599     :BMenu(name)
600 {
601     kind = menu_kind;
602     p_intf = p_interface;
603 }
604
605 /*****************************************************************************
606  * LanguageMenu::~LanguageMenu
607  *****************************************************************************/
608 LanguageMenu::~LanguageMenu()
609 {
610 }
611
612 /*****************************************************************************
613  * LanguageMenu::AttachedToWindow
614  *****************************************************************************/
615 void LanguageMenu::AttachedToWindow(void)
616 {
617     while( RemoveItem((long int)0) != NULL )
618     {
619         ; // remove all items
620     }
621
622     SetRadioMode(true);
623     GetChannels();
624     BMenu::AttachedToWindow();
625 }
626
627 /*****************************************************************************
628  * LanguageMenu::GetChannels
629  *****************************************************************************/
630 int LanguageMenu::GetChannels()
631 {
632     char  *psz_name;
633     bool   b_active;
634     BMessage *msg;
635     int    i;
636     es_descriptor_t *p_es  = NULL;
637
638     /* Insert the null */
639     if( kind == AUDIO_ES ) //audio
640     {
641         msg = new BMessage(SELECT_CHANNEL);
642         msg->AddInt32("channel", -1);
643     }
644     else
645     {
646         msg = new BMessage(SELECT_SUBTITLE);
647         msg->AddInt32("subtitle", -1);
648     }
649     BMenuItem *menu_item;
650     menu_item = new BMenuItem("None", msg);
651     AddItem(menu_item);
652     menu_item->SetMarked(TRUE);
653
654     if( p_intf->p_input == NULL )
655     {
656         return 1;
657     }
658
659
660     vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
661     for( i = 0; i < p_intf->p_input->stream.i_selected_es_number; i++ )
662     {
663         if( kind == p_intf->p_input->stream.pp_selected_es[i]->i_cat )
664         {
665             p_es = p_intf->p_input->stream.pp_selected_es[i];
666         }
667     }
668
669     for( i = 0; i < p_intf->p_input->stream.i_es_number; i++ )
670     {
671         if( kind == p_intf->p_input->stream.pp_es[i]->i_cat )
672         {
673             psz_name = p_intf->p_input->stream.pp_es[i]->psz_desc;
674             if( kind == AUDIO_ES ) //audio
675             {
676                 msg = new BMessage(SELECT_CHANNEL);
677                 msg->AddInt32("channel", i);
678             }
679             else
680             {
681                 msg = new BMessage(SELECT_SUBTITLE);
682                 msg->AddInt32("subtitle", i);
683             }
684             BMenuItem *menu_item;
685             menu_item = new BMenuItem(psz_name, msg);
686             AddItem(menu_item);
687             b_active = (p_es == p_intf->p_input->stream.pp_es[i]);
688             menu_item->SetMarked(b_active);
689         }
690     }
691     vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
692
693 }
694
695
696