* ./modules/*: moved plugins to the new tree. Yet untested builds include
[vlc.git] / modules / gui / beos / InterfaceWindow.cpp
1 /*****************************************************************************
2  * InterfaceWindow.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: InterfaceWindow.cpp,v 1.1 2002/08/04 17:23:43 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 /* System headers */
28 #include <kernel/OS.h>
29 #include <InterfaceKit.h>
30 #include <AppKit.h>
31 #include <StorageKit.h>
32 #include <SupportKit.h>
33 #include <malloc.h>
34 #include <scsi.h>
35 #include <scsiprobe_driver.h>
36 #include <fs_info.h>
37 #include <string.h>
38
39
40 /* VLC headers */
41 #include <vlc/vlc.h>
42 #include <vlc/aout.h>
43 #include <vlc/intf.h>
44
45 /* BeOS interface headers */
46 #include "MsgVals.h"
47 #include "MediaControlView.h"
48 #include "PlayListWindow.h"
49 #include "VlcWrapper.h"
50 #include "InterfaceWindow.h"
51
52
53 /*****************************************************************************
54  * InterfaceWindow
55  *****************************************************************************/
56
57 InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
58                                   intf_thread_t  *p_interface )
59     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
60                B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
61                 | B_ASYNCHRONOUS_CONTROLS )
62 {
63     file_panel = NULL;
64     playlist_window = NULL;
65     p_intf = p_interface;
66     p_vlc_wrapper = Intf_VLCWrapper::getVLCWrapper(p_intf);
67     BRect controlRect(0,0,0,0);
68     
69     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
70                                                        FIND_ANYWHERE );
71     b_empty_playlist = (p_playlist->i_size < 0);
72     b_mute = false;
73
74     /* set the title bar */
75     SetName( "interface" );
76     SetTitle(VOUT_TITLE);
77
78     /* set up the main menu */
79     BMenuBar *menu_bar;
80     menu_bar = new BMenuBar(controlRect, "main menu");
81     AddChild( menu_bar );
82
83     BMenu *mFile;
84     BMenu *mAudio;
85     CDMenu *cd_menu;
86     BMenu *mNavigation;
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     /* Add the Navigation menu */
116     menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
117     menu_bar->ResizeToPreferred();
118     mNavigation->AddItem( new BMenuItem( "Prev Title",
119                                         new BMessage(PREV_TITLE)) );
120     mNavigation->AddItem( new BMenuItem( "Next Title",
121                                         new BMessage(NEXT_TITLE)) );
122     mNavigation->AddItem( new BMenuItem( "Prev Chapter",
123                                         new BMessage(PREV_CHAPTER)) );
124     mNavigation->AddItem( new BMenuItem( "Next Chapter",
125                                         new BMessage(NEXT_CHAPTER)) );
126                                         
127     ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
128     controlRect = Bounds();
129     controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
130
131     p_mediaControl = new MediaControlView( controlRect );
132     p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
133     b_empty_playlist = true;
134     p_mediaControl->SetEnabled( !b_empty_playlist );
135
136     /* Show */
137     AddChild( p_mediaControl );
138     Show();
139     
140 }
141
142 InterfaceWindow::~InterfaceWindow()
143 {
144     if (playlist_window) playlist_window->ReallyQuit();
145 }
146
147 /*****************************************************************************
148  * InterfaceWindow::MessageReceived
149  *****************************************************************************/
150 void InterfaceWindow::MessageReceived( BMessage * p_message )
151 {
152     int vol_val = p_mediaControl->GetVolume();    // remember the current volume
153     int playback_status;      // remember playback state
154     int     i_index;
155     BAlert *alert;
156
157     Activate();
158     playback_status = p_vlc_wrapper->inputGetStatus();
159
160     switch( p_message->what )
161     {
162     case B_ABOUT_REQUESTED:
163         alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
164         alert->Go();
165         break;
166
167     case TOGGLE_ON_TOP:
168         break;
169         
170     case OPEN_FILE:
171         if( file_panel )
172         {
173             file_panel->Show();
174             break;
175         }
176         file_panel = new BFilePanel();
177         file_panel->SetTarget( this );
178         file_panel->Show();
179         b_empty_playlist = false;
180         p_mediaControl->SetEnabled( !b_empty_playlist );
181         break;
182
183         case OPEN_PLAYLIST:
184                 {
185                     BRect rect(20,20,320,420);
186             playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
187                                                        FIND_ANYWHERE );
188
189             playlist_window = PlayListWindow::getPlayList(rect,
190                                 "Playlist", p_playlist);
191             playlist_window->Show();                    
192         }
193                 break;
194     case OPEN_DVD:
195         {
196             const char *psz_device;
197             BString type("dvd");
198             if( p_message->FindString("device", &psz_device) != B_ERROR )
199             {
200                 BString device(psz_device);
201                 p_vlc_wrapper->openDisc(type, device, 0,0);
202             }
203         }
204         break;
205
206     case STOP_PLAYBACK:
207         // this currently stops playback not nicely
208         //p_vlc_wrapper->volume_mute();
209         //snooze( 400000 );
210         p_vlc_wrapper->playlistStop();
211         p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
212         break;
213
214     case START_PLAYBACK:
215         /*  starts playing in normal mode */
216
217     case PAUSE_PLAYBACK:
218         /* toggle between pause and play */
219         if( p_intf->p_sys->p_input != NULL )
220         {
221             /* pause if currently playing */
222             if ( playback_status == PLAYING_S )
223             {
224                 //p_vlc_wrapper->volume_mute();
225                 //snooze( 400000 );
226                 p_vlc_wrapper->playlistPause();
227             }
228             else
229             {
230                 //p_vlc_wrapper->volume_restore();
231                 p_vlc_wrapper->playlistPlay();
232             }
233         }
234         else
235         {
236             /* Play a new file */
237             p_vlc_wrapper->playlistPlay();
238         }    
239         break;
240
241     case FASTER_PLAY:
242         /* cycle the fast playback modes */
243         //p_vlc_wrapper->volume_mute();
244         //snooze( 400000 );
245         p_vlc_wrapper->playFaster();
246         break;
247
248     case SLOWER_PLAY:
249         /*  cycle the slow playback modes */
250         //p_vlc_wrapper->volume_mute();
251         //snooze( 400000 );
252         p_vlc_wrapper->playSlower();
253         break;
254
255     case SEEK_PLAYBACK:
256         /* handled by semaphores */
257         break;
258
259     case VOLUME_CHG:
260         /* adjust the volume */
261 //        vlc_mutex_lock( &p_intf->p_sys->p_input->lock );
262 //        for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
263 //        {
264 //            if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
265 //            {
266 //                p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
267 //            }
268 //            else
269 //            {
270 //                p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
271 //            }
272 //        }
273 //        vlc_mutex_unlock( &p_aout_bank->lock );
274         break;
275
276     case VOLUME_MUTE:
277         /* toggle muting */
278         p_vlc_wrapper->toggleMute( );
279         break;
280
281     case SELECT_AUDIO:
282         {
283             int32 i = p_message->FindInt32( "audio" );
284             p_vlc_wrapper->toggleLanguage( i );
285         }
286         break;
287
288     case SELECT_SUBTITLE:
289         {
290             int32 i = p_message->FindInt32( "subtitle" );
291             p_vlc_wrapper->toggleSubtitle( i );
292         }
293         break;
294     case PREV_TITLE:
295         {
296             int             i_id;
297             i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
298
299             /* Disallow area 0 since it is used for video_ts.vob */
300             if( i_id > 0 )
301             {
302                 p_vlc_wrapper->toggleTitle(i_id);
303             }
304             break;
305         }
306     case NEXT_TITLE:
307         {
308             int             i_id;
309
310             i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
311
312             if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
313             {
314                 p_vlc_wrapper->toggleTitle(i_id);
315             }
316         }
317         break;
318     case PREV_CHAPTER:
319         {
320             int             i_id;
321
322             i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part - 1;
323
324             if( i_id >= 0 )
325             {
326                 p_vlc_wrapper->toggleChapter(i_id);
327             }
328         }
329         break;
330     case NEXT_CHAPTER:
331         {
332             int             i_id;
333
334             i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_part + 1;
335
336             if( i_id >= 0 )
337             {
338                 p_vlc_wrapper->toggleChapter(i_id);
339             }
340         }
341         break;
342     case B_REFS_RECEIVED:
343     case B_SIMPLE_DATA:
344         {
345             entry_ref ref;
346             BList* files = new BList();
347
348             int i = 0;
349             while( p_message->FindRef( "refs", i, &ref ) == B_OK )
350             {
351                 BPath path( &ref );
352
353                 files->AddItem(new BString((char*)path.Path()) );
354                 i++;
355             }
356             p_vlc_wrapper->openFiles(files);
357             delete files;
358         }
359         break;
360
361     default:
362         BWindow::MessageReceived( p_message );
363         break;
364     }
365
366 }
367
368 /*****************************************************************************
369  * InterfaceWindow::updateInterface
370  *****************************************************************************/
371 void InterfaceWindow::updateInterface()
372 {
373
374         if ( p_intf->p_sys->p_input != NULL )
375         {
376         if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
377         {
378             p_vlc_wrapper->setTimeAsFloat(p_mediaControl->GetSeekTo());
379         }
380         else if( Lock() )
381         {
382             p_mediaControl->SetStatus(p_intf->p_sys->p_input->stream.control.i_status, 
383                                       p_intf->p_sys->p_input->stream.control.i_rate);
384             p_mediaControl->SetProgress(p_intf->p_sys->p_input->stream.p_selected_area->i_tell,
385                                         p_intf->p_sys->p_input->stream.p_selected_area->i_size);
386             Unlock();
387         }
388     }
389     
390     playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
391                                                        FIND_ANYWHERE );
392
393     if ( b_empty_playlist != (p_playlist->i_size < 1) )
394     {
395         if (Lock())
396         {
397             b_empty_playlist = !b_empty_playlist;
398             p_mediaControl->SetEnabled( !b_empty_playlist );
399             Unlock();
400         }
401     }
402 }
403
404 /*****************************************************************************
405  * InterfaceWindow::QuitRequested
406  *****************************************************************************/
407 bool InterfaceWindow::QuitRequested()
408 {
409     p_intf->p_vlc->b_die = VLC_TRUE;
410
411     return( true );
412 }
413
414 /*****************************************************************************
415  * CDMenu::CDMenu
416  *****************************************************************************/
417 CDMenu::CDMenu(const char *name)
418       : BMenu(name)
419 {
420 }
421
422 /*****************************************************************************
423  * CDMenu::~CDMenu
424  *****************************************************************************/
425 CDMenu::~CDMenu()
426 {
427 }
428
429 /*****************************************************************************
430  * CDMenu::AttachedToWindow
431  *****************************************************************************/
432 void CDMenu::AttachedToWindow(void)
433 {
434     while (RemoveItem((long int)0) != NULL);  // remove all items
435     GetCD("/dev/disk");
436     BMenu::AttachedToWindow();
437 }
438
439 /*****************************************************************************
440  * CDMenu::GetCD
441  *****************************************************************************/
442 int CDMenu::GetCD( const char *directory )
443 {
444         BVolumeRoster *volRoster;
445         BVolume       *vol;
446         BDirectory    *dir;
447         int           status;
448         int           mounted;   
449         char          name[B_FILE_NAME_LENGTH]; 
450     fs_info       info;
451         dev_t         dev;
452         
453         volRoster = new BVolumeRoster();
454         vol = new BVolume();
455         dir = new BDirectory();
456         status = volRoster->GetNextVolume(vol);
457         status = vol->GetRootDirectory(dir);
458         while (status ==  B_NO_ERROR)
459         {
460             mounted = vol->GetName(name);       
461             if ((mounted == B_OK) && /* Disk is currently Mounted */
462                 (vol->IsReadOnly()) ) /* Disk is read-only */
463             {
464                 dev = vol->Device();
465             fs_stat_dev(dev, &info);
466             
467             device_geometry g;
468             int i_dev;
469             i_dev = open( info.device_name, O_RDONLY );
470            
471             if( i_dev >= 0 )
472             {
473                 if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
474                 {
475                     if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
476                     {
477                         BMessage *msg;
478                         msg = new BMessage( OPEN_DVD );
479                         msg->AddString( "device", info.device_name );
480                         BMenuItem *menu_item;
481                         menu_item = new BMenuItem( name, msg );
482                         AddItem( menu_item );
483                     }
484                     close(i_dev);
485                 }
486             }
487             }
488             vol->Unset();
489             status = volRoster->GetNextVolume(vol);
490         }
491 }
492
493 /*****************************************************************************
494  * LanguageMenu::LanguageMenu
495  *****************************************************************************/
496 LanguageMenu::LanguageMenu(const char *name, int menu_kind, 
497                             intf_thread_t  *p_interface)
498     :BMenu(name)
499 {
500     kind = menu_kind;
501     p_intf = p_interface;
502 }
503
504 /*****************************************************************************
505  * LanguageMenu::~LanguageMenu
506  *****************************************************************************/
507 LanguageMenu::~LanguageMenu()
508 {
509 }
510
511 /*****************************************************************************
512  * LanguageMenu::AttachedToWindow
513  *****************************************************************************/
514 void LanguageMenu::AttachedToWindow(void)
515 {
516     while( RemoveItem((long int)0) != NULL )
517     {
518         ; // remove all items
519     }
520
521     SetRadioMode(true);
522     GetChannels();
523     BMenu::AttachedToWindow();
524 }
525
526 /*****************************************************************************
527  * LanguageMenu::GetChannels
528  *****************************************************************************/
529 int LanguageMenu::GetChannels()
530 {
531     char  *psz_name;
532     bool   b_active;
533     BMessage *msg;
534     int    i;
535     es_descriptor_t *p_es  = NULL;
536
537     /* Insert the null */
538     if( kind == SPU_ES ) //audio
539     {
540         msg = new BMessage(SELECT_SUBTITLE);
541         msg->AddInt32("subtitle", -1);
542         BMenuItem *menu_item;
543         menu_item = new BMenuItem("None", msg);
544         AddItem(menu_item);
545         menu_item->SetMarked(TRUE);
546
547     }
548
549     if( p_intf->p_sys->p_input == NULL )
550     {
551         return 1;
552     }
553
554
555     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
556     for( i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number; i++ )
557     {
558         if( kind == p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat )
559         {
560             p_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
561         }
562     }
563
564     for( i = 0; i < p_intf->p_sys->p_input->stream.i_es_number; i++ )
565     {
566         if( kind == p_intf->p_sys->p_input->stream.pp_es[i]->i_cat )
567         {
568             psz_name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
569             if( kind == AUDIO_ES ) //audio
570             {
571                 msg = new BMessage(SELECT_AUDIO);
572                 msg->AddInt32("audio", i);
573             }
574             else
575             {
576                 msg = new BMessage(SELECT_SUBTITLE);
577                 msg->AddInt32("subtitle", i);
578             }
579             BMenuItem *menu_item;
580             menu_item = new BMenuItem(psz_name, msg);
581             AddItem(menu_item);
582             b_active = (p_es == p_intf->p_sys->p_input->stream.pp_es[i]);
583             menu_item->SetMarked(b_active);
584         }
585     }
586     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
587
588 }
589
590
591