]> git.sesse.net Git - vlc/blob - modules/gui/beos/VideoOutput.cpp
Remove _GNU_SOURCE and string.h too
[vlc] / modules / gui / beos / VideoOutput.cpp
1 /*****************************************************************************
2  * vout_beos.cpp: beos video output display method
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 the VideoLAN team
5  * $Id$
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  *          Stephan Aßmus <stippi@yellowbites.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <errno.h>                                                 /* ENOMEM */
32 #include <stdio.h>
33
34 #include <Application.h>
35 #include <BitmapStream.h>
36 #include <Bitmap.h>
37 #include <Directory.h>
38 #include <DirectWindow.h>
39 #include <File.h>
40 #include <InterfaceKit.h>
41 #include <NodeInfo.h>
42 #include <String.h>
43 #include <TranslatorRoster.h>
44 #include <WindowScreen.h>
45
46 /* VLC headers */
47 #include <vlc/vlc.h>
48 #include <vlc_interface.h>
49 #include <vlc_vout.h>
50 #include <vlc_keys.h>
51
52 #include "InterfaceWindow.h"    // for load/save_settings()
53 #include "DrawingTidbits.h"
54 #include "MsgVals.h"
55
56 #include "VideoWindow.h"
57
58 /*****************************************************************************
59  * vout_sys_t: BeOS video output method descriptor
60  *****************************************************************************
61  * This structure is part of the video output thread descriptor.
62  * It describes the BeOS specific properties of an output thread.
63  *****************************************************************************/
64 struct vout_sys_t
65 {
66     VideoWindow *  p_window;
67
68     int32_t i_width;
69     int32_t i_height;
70
71 //    uint8_t *pp_buffer[3];
72     uint32_t source_chroma;
73     int i_index;
74
75 };
76
77 #define MOUSE_IDLE_TIMEOUT 2000000    // two seconds
78 #define MIN_AUTO_VSYNC_REFRESH 61    // Hz
79
80 /*****************************************************************************
81  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
82  *****************************************************************************/
83 BWindow*
84 beos_GetAppWindow(char *name)
85 {
86     int32_t     index;
87     BWindow     *window;
88
89     for (index = 0 ; ; index++)
90     {
91         window = be_app->WindowAt(index);
92         if (window == NULL)
93             break;
94         if (window->LockWithTimeout(20000) == B_OK)
95         {
96             if (strcmp(window->Name(), name) == 0)
97             {
98                 window->Unlock();
99                 break;
100             }
101             window->Unlock();
102         }
103     }
104     return window;
105 }
106
107 static const int beos_keys[][2] =
108 {
109     { B_LEFT_ARROW,  KEY_LEFT },
110     { B_RIGHT_ARROW, KEY_RIGHT },
111     { B_UP_ARROW,    KEY_UP },
112     { B_DOWN_ARROW,  KEY_DOWN },
113     { B_SPACE,       KEY_SPACE },
114     { B_ENTER,       KEY_ENTER },
115     { B_F1_KEY,      KEY_F1 },
116     { B_F2_KEY,      KEY_F2 },
117     { B_F3_KEY,      KEY_F3 },
118     { B_F4_KEY,      KEY_F4 },
119     { B_F5_KEY,      KEY_F5 },
120     { B_F6_KEY,      KEY_F6 },
121     { B_F7_KEY,      KEY_F7 },
122     { B_F8_KEY,      KEY_F8 },
123     { B_F9_KEY,      KEY_F9 },
124     { B_F10_KEY,     KEY_F10 },
125     { B_F11_KEY,     KEY_F11 },
126     { B_F12_KEY,     KEY_F12 },
127     { B_HOME,        KEY_HOME },
128     { B_END,         KEY_END },
129     { B_ESCAPE,      KEY_ESC },
130     { B_PAGE_UP,     KEY_PAGEUP },
131     { B_PAGE_DOWN,   KEY_PAGEDOWN },
132     { B_TAB,         KEY_TAB },
133     { B_BACKSPACE,   KEY_BACKSPACE }
134 };
135
136 static int ConvertKeyFromVLC( int key )
137 {
138     for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
139     {
140         if( beos_keys[i][1] == key )
141         {
142             return beos_keys[i][0];
143         }
144     }
145     return key;
146 }
147
148 static int ConvertKeyToVLC( int key )
149 {
150     for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
151     {
152         if( beos_keys[i][0] == key )
153         {
154             return beos_keys[i][1];
155         }
156     }
157     return key;
158 }
159
160 /*****************************************************************************
161  * get_interface_window
162  *****************************************************************************/
163 BWindow*
164 get_interface_window()
165 {
166     return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
167 }
168
169 class BackgroundView : public BView
170 {
171  public:
172                             BackgroundView(BRect frame, VLCView* view)
173                             : BView(frame, "background",
174                                     B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
175                               fVideoView(view)
176                             {
177                                 SetViewColor(kBlack);
178                             }
179     virtual                    ~BackgroundView() {}
180
181     virtual    void            MouseDown(BPoint where)
182                             {
183                                 // convert coordinates
184                                 where = fVideoView->ConvertFromParent(where);
185                                 // let him handle it
186                                 fVideoView->MouseDown(where);
187                             }
188     virtual    void            MouseMoved(BPoint where, uint32_t transit,
189                                        const BMessage* dragMessage)
190                             {
191                                 // convert coordinates
192                                 where = fVideoView->ConvertFromParent(where);
193                                 // let him handle it
194                                 fVideoView->MouseMoved(where, transit, dragMessage);
195                                 // notice: It might look like transit should be
196                                 // B_OUTSIDE_VIEW regardless, but leave it like this,
197                                 // otherwise, unwanted things will happen!
198                             }
199
200  private:
201     VLCView*                fVideoView;
202 };
203
204
205 /*****************************************************************************
206  * VideoSettings constructor and destructor
207  *****************************************************************************/
208 VideoSettings::VideoSettings()
209     : fVideoSize( SIZE_100 ),
210       fFlags( FLAG_CORRECT_RATIO ),
211       fSettings( new BMessage( 'sett' ) )
212 {
213     // read settings from disk
214     status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
215     if ( ret == B_OK )
216     {
217         uint32_t flags;
218         if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
219             SetFlags( flags );
220         uint32_t size;
221         if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
222             SetVideoSize( size );
223     }
224     else
225     {
226         // figure out if we should use vertical sync by default
227         BScreen screen(B_MAIN_SCREEN_ID);
228         if (screen.IsValid())
229         {
230             display_mode mode;
231             screen.GetMode(&mode);
232             float refresh = (mode.timing.pixel_clock * 1000)
233                             / ((mode.timing.h_total)* (mode.timing.v_total));
234             if (refresh < MIN_AUTO_VSYNC_REFRESH)
235                 AddFlags(FLAG_SYNC_RETRACE);
236         }
237     }
238 }
239
240 VideoSettings::VideoSettings( const VideoSettings& clone )
241     : fVideoSize( clone.VideoSize() ),
242       fFlags( clone.Flags() ),
243       fSettings( NULL )
244 {
245 }
246
247
248 VideoSettings::~VideoSettings()
249 {
250     if ( fSettings )
251     {
252         // we are the default settings
253         // and write our settings to disk
254         if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
255             fSettings->AddInt32( "video size", VideoSize() );
256         if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
257             fSettings->AddInt32( "flags", Flags() );
258
259         save_settings( fSettings, "video_settings", "VideoLAN Client" );
260         delete fSettings;
261     }
262     else
263     {
264         // we are just a clone of the default settings
265         fDefaultSettings.SetVideoSize( VideoSize() );
266         fDefaultSettings.SetFlags( Flags() );
267     }
268 }
269
270 /*****************************************************************************
271  * VideoSettings::DefaultSettings
272  *****************************************************************************/
273 VideoSettings*
274 VideoSettings::DefaultSettings()
275 {
276     return &fDefaultSettings;
277 }
278
279 /*****************************************************************************
280  * VideoSettings::SetVideoSize
281  *****************************************************************************/
282 void
283 VideoSettings::SetVideoSize( uint32_t mode )
284 {
285     fVideoSize = mode;
286 }
287
288 // static variable initialization
289 VideoSettings
290 VideoSettings::fDefaultSettings;
291
292
293 /*****************************************************************************
294  * VideoWindow constructor and destructor
295  *****************************************************************************/
296 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
297                          vout_thread_t *p_videoout)
298     : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
299       i_width(frame.IntegerWidth()),
300       i_height(frame.IntegerHeight()),
301       winSize(frame),
302       i_buffer(0),
303       teardownwindow(false),
304       fTrueWidth(v_width),
305       fTrueHeight(v_height),
306       fCachedFeel(B_NORMAL_WINDOW_FEEL),
307       fInterfaceShowing(false),
308       fInitStatus(B_ERROR),
309       fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
310 {
311     p_vout = p_videoout;
312
313     // create the view to do the display
314     view = new VLCView( Bounds(), p_vout );
315
316     // create background view
317     BView *mainView =  new BackgroundView( Bounds(), view );
318     AddChild(mainView);
319     mainView->AddChild(view);
320
321     // allocate bitmap buffers
322     for (int32_t i = 0; i < 3; i++)
323         bitmap[i] = NULL;
324     fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
325
326     // make sure we layout the view correctly
327     FrameResized(i_width, i_height);
328
329     if (fInitStatus >= B_OK && mode == OVERLAY)
330     {
331        overlay_restrictions r;
332
333        bitmap[0]->GetOverlayRestrictions(&r);
334        SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
335                      (i_height * r.min_height_scale), i_height * r.max_height_scale);
336     }
337
338     // vlc settings override settings from disk
339     if (config_GetInt(p_vout, "fullscreen"))
340         fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
341
342     _SetToSettings();
343 }
344
345 VideoWindow::~VideoWindow()
346 {
347     int32 result;
348
349     teardownwindow = true;
350     wait_for_thread(fDrawThreadID, &result);
351     _FreeBuffers();
352     delete fSettings;
353 }
354
355 /*****************************************************************************
356  * VideoWindow::MessageReceived
357  *****************************************************************************/
358 void
359 VideoWindow::MessageReceived( BMessage *p_message )
360 {
361     switch( p_message->what )
362     {
363         case SHOW_INTERFACE:
364             SetInterfaceShowing( true );
365             break;
366         case TOGGLE_FULL_SCREEN:
367             BWindow::Zoom();
368             break;
369         case RESIZE_50:
370         case RESIZE_100:
371         case RESIZE_200:
372             if (IsFullScreen())
373                 BWindow::Zoom();
374             _SetVideoSize(p_message->what);
375             break;
376         case VERT_SYNC:
377             SetSyncToRetrace(!IsSyncedToRetrace());
378             break;
379         case WINDOW_FEEL:
380             {
381                 window_feel winFeel;
382                 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
383                 {
384                     SetFeel(winFeel);
385                     fCachedFeel = winFeel;
386                     if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
387                         fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
388                     else
389                         fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
390                 }
391             }
392             break;
393         case ASPECT_CORRECT:
394             SetCorrectAspectRatio(!CorrectAspectRatio());
395             break;
396
397         case B_KEY_DOWN:
398         case B_UNMAPPED_KEY_DOWN:
399         case B_KEY_UP:
400         case B_UNMAPPED_KEY_UP:
401         {
402             key_map * keys;
403             char    * chars;
404             int32     key, modifiers;
405
406             if( p_message->FindInt32( "key", &key ) != B_OK ||
407                 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
408             {
409                 /* Shouldn't happen */
410                 break;
411             }
412
413             if( ( p_message->what == B_KEY_UP ||
414                   p_message->what == B_UNMAPPED_KEY_UP ) &&
415                 !( modifiers & B_COMMAND_KEY ) )
416             {
417                 /* We only use the KEY_UP messages to detect Alt+X
418                    shortcuts (because the KEY_DOWN messages aren't
419                    sent when Alt is pressed) */
420                 break;
421             }
422
423             /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
424                the character depends on the keymap, we use the key codes
425                directly (18, 19, 20) */
426             if( ( modifiers & B_COMMAND_KEY ) &&
427                 key >= 18 && key <= 20 )
428             {
429                 if( key == 18 )
430                     PostMessage( RESIZE_50 );
431                 else if( key == 19 )
432                     PostMessage( RESIZE_100 );
433                 else
434                     PostMessage( RESIZE_200 );
435
436                 break;
437             }
438
439             /* Get the current keymap */
440             get_key_map( &keys, &chars );
441
442             if( key >= 128 || chars[keys->normal_map[key]] != 1 )
443             {
444                 /* Weird key or Unicode character */
445                 free( keys );
446                 free( chars );
447                 break;
448             }
449
450             vlc_value_t val;
451             val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
452
453             if( modifiers & B_COMMAND_KEY )
454             {
455                 val.i_int |= KEY_MODIFIER_ALT;
456             }
457             if( modifiers & B_SHIFT_KEY )
458             {
459                 val.i_int |= KEY_MODIFIER_SHIFT;
460             }
461             if( modifiers & B_CONTROL_KEY )
462             {
463                 val.i_int |= KEY_MODIFIER_CTRL;
464             }
465             var_Set( p_vout->p_libvlc, "key-pressed", val );
466
467             free( keys );
468             free( chars );
469             break;
470         }
471
472         default:
473             BWindow::MessageReceived( p_message );
474             break;
475     }
476 }
477
478 /*****************************************************************************
479  * VideoWindow::Zoom
480  *****************************************************************************/
481 void
482 VideoWindow::Zoom(BPoint origin, float width, float height )
483 {
484     ToggleFullScreen();
485 }
486
487 /*****************************************************************************
488  * VideoWindow::FrameMoved
489  *****************************************************************************/
490 void
491 VideoWindow::FrameMoved(BPoint origin)
492 {
493     if (IsFullScreen())
494         return ;
495     winSize = Frame();
496 }
497
498 /*****************************************************************************
499  * VideoWindow::FrameResized
500  *****************************************************************************/
501 void
502 VideoWindow::FrameResized( float width, float height )
503 {
504     int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
505     int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
506     float out_width, out_height;
507     float out_left, out_top;
508     float width_scale = width / useWidth;
509     float height_scale = height / useHeight;
510
511     if (width_scale <= height_scale)
512     {
513         out_width = (useWidth * width_scale);
514         out_height = (useHeight * width_scale);
515         out_left = 0;
516         out_top = (height - out_height) / 2;
517     }
518     else   /* if the height is proportionally smaller */
519     {
520         out_width = (useWidth * height_scale);
521         out_height = (useHeight * height_scale);
522         out_top = 0;
523         out_left = (width - out_width) / 2;
524     }
525     view->MoveTo(out_left,out_top);
526     view->ResizeTo(out_width, out_height);
527
528     if (!IsFullScreen())
529         winSize = Frame();
530 }
531
532 /*****************************************************************************
533  * VideoWindow::ScreenChanged
534  *****************************************************************************/
535 void
536 VideoWindow::ScreenChanged(BRect frame, color_space format)
537 {
538     BScreen screen(this);
539     display_mode mode;
540     screen.GetMode(&mode);
541     float refresh = (mode.timing.pixel_clock * 1000)
542                     / ((mode.timing.h_total) * (mode.timing.v_total));
543     SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
544 }
545
546 /*****************************************************************************
547  * VideoWindow::Activate
548  *****************************************************************************/
549 void
550 VideoWindow::WindowActivated(bool active)
551 {
552 }
553
554 /*****************************************************************************
555  * VideoWindow::drawBuffer
556  *****************************************************************************/
557 void
558 VideoWindow::drawBuffer(int bufferIndex)
559 {
560     i_buffer = bufferIndex;
561
562     // sync to the screen if required
563     if (IsSyncedToRetrace())
564     {
565         BScreen screen(this);
566         screen.WaitForRetrace(22000);
567     }
568     if (fInitStatus >= B_OK && LockLooper())
569     {
570        // switch the overlay bitmap
571        if (mode == OVERLAY)
572        {
573           rgb_color key;
574           view->SetViewOverlay(bitmap[i_buffer],
575                             bitmap[i_buffer]->Bounds() ,
576                             view->Bounds(),
577                             &key, B_FOLLOW_ALL,
578                             B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
579                             B_OVERLAY_TRANSFER_CHANNEL);
580            view->SetViewColor(key);
581        }
582        else
583        {
584          // switch the bitmap
585          view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
586        }
587        UnlockLooper();
588     }
589 }
590
591 /*****************************************************************************
592  * VideoWindow::SetInterfaceShowing
593  *****************************************************************************/
594 void
595 VideoWindow::ToggleInterfaceShowing()
596 {
597     SetInterfaceShowing(!fInterfaceShowing);
598 }
599
600 /*****************************************************************************
601  * VideoWindow::SetInterfaceShowing
602  *****************************************************************************/
603 void
604 VideoWindow::SetInterfaceShowing(bool showIt)
605 {
606     BWindow* window = get_interface_window();
607     if (window)
608     {
609         if (showIt)
610         {
611             if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
612                 SetFeel(B_NORMAL_WINDOW_FEEL);
613             window->Activate(true);
614             SendBehind(window);
615         }
616         else
617         {
618             SetFeel(fCachedFeel);
619             Activate(true);
620             window->SendBehind(this);
621         }
622         fInterfaceShowing = showIt;
623     }
624 }
625
626 /*****************************************************************************
627  * VideoWindow::SetCorrectAspectRatio
628  *****************************************************************************/
629 void
630 VideoWindow::SetCorrectAspectRatio(bool doIt)
631 {
632     if (CorrectAspectRatio() != doIt)
633     {
634         if (doIt)
635             fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
636         else
637             fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
638         FrameResized(Bounds().Width(), Bounds().Height());
639     }
640 }
641
642 /*****************************************************************************
643  * VideoWindow::CorrectAspectRatio
644  *****************************************************************************/
645 bool
646 VideoWindow::CorrectAspectRatio() const
647 {
648     return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
649 }
650
651 /*****************************************************************************
652  * VideoWindow::ToggleFullScreen
653  *****************************************************************************/
654 void
655 VideoWindow::ToggleFullScreen()
656 {
657     SetFullScreen(!IsFullScreen());
658 }
659
660 /*****************************************************************************
661  * VideoWindow::SetFullScreen
662  *****************************************************************************/
663 void
664 VideoWindow::SetFullScreen(bool doIt)
665 {
666     if (doIt)
667     {
668         SetLook( B_NO_BORDER_WINDOW_LOOK );
669         BScreen screen( this );
670         BRect rect = screen.Frame();
671         Activate();
672         MoveTo(0.0, 0.0);
673         ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
674         be_app->ObscureCursor();
675         fInterfaceShowing = false;
676         fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
677     }
678     else
679     {
680         SetLook( B_TITLED_WINDOW_LOOK );
681         MoveTo(winSize.left, winSize.top);
682         ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
683         be_app->ShowCursor();
684         fInterfaceShowing = true;
685         fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
686     }
687 }
688
689 /*****************************************************************************
690  * VideoWindow::IsFullScreen
691  *****************************************************************************/
692 bool
693 VideoWindow::IsFullScreen() const
694 {
695     return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
696 }
697
698 /*****************************************************************************
699  * VideoWindow::SetSyncToRetrace
700  *****************************************************************************/
701 void
702 VideoWindow::SetSyncToRetrace(bool doIt)
703 {
704     if (doIt)
705         fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
706     else
707         fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
708 }
709
710 /*****************************************************************************
711  * VideoWindow::IsSyncedToRetrace
712  *****************************************************************************/
713 bool
714 VideoWindow::IsSyncedToRetrace() const
715 {
716     return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
717 }
718
719
720 /*****************************************************************************
721  * VideoWindow::_AllocateBuffers
722  *****************************************************************************/
723 status_t
724 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
725 {
726     // clear any old buffers
727     _FreeBuffers();
728     // set default mode
729     *mode = BITMAP;
730     bitmap_count = 3;
731
732     BRect bitmapFrame( 0, 0, width, height );
733     // read from config, if we are supposed to use overlay at all
734     int noOverlay = !config_GetInt( p_vout, "overlay" );
735
736     /* Test for overlay capability: for every chroma in colspace,
737        we try to do double-buffered overlay, single-buffered overlay
738        or basic overlay. If nothing worked, we then have to work with
739        a non-overlay BBitmap. */
740     for( int i = 0; i < COLOR_COUNT; i++ )
741     {
742         if( noOverlay )
743             break;
744
745         bitmap[0] = new BBitmap( bitmapFrame,
746                                  B_BITMAP_WILL_OVERLAY |
747                                  B_BITMAP_RESERVE_OVERLAY_CHANNEL,
748                                  colspace[i].colspace );
749         if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
750         {
751             colspace_index = i;
752
753             *mode = OVERLAY;
754             rgb_color key;
755             view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
756                                   view->Bounds(), &key, B_FOLLOW_ALL,
757                                   B_OVERLAY_FILTER_HORIZONTAL |
758                                   B_OVERLAY_FILTER_VERTICAL );
759             view->SetViewColor( key );
760             SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
761
762             bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
763                                      colspace[colspace_index].colspace);
764             if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
765             {
766
767                 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
768                                          colspace[colspace_index].colspace);
769                 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
770                 {
771                     msg_Dbg( p_vout, "using double-buffered overlay" );
772                 }
773                 else
774                 {
775                     msg_Dbg( p_vout, "using single-buffered overlay" );
776                     bitmap_count = 2;
777                     if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
778                 }
779             }
780             else
781             {
782                 msg_Dbg( p_vout, "using simple overlay" );
783                 bitmap_count = 1;
784                 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
785             }
786             break;
787         }
788         else
789         {
790             if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
791         }
792     }
793
794     if (*mode == BITMAP)
795     {
796         msg_Warn( p_vout, "no possible overlay" );
797
798         // fallback to RGB
799         colspace_index = DEFAULT_COL;    // B_RGB32
800         bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
801         bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
802         bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
803         SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
804     }
805     // see if everything went well
806     status_t status = B_ERROR;
807     for (int32_t i = 0; i < bitmap_count; i++)
808     {
809         if (bitmap[i])
810             status = bitmap[i]->InitCheck();
811         if (status < B_OK)
812             break;
813     }
814     if (status >= B_OK)
815     {
816         // clear bitmaps to black
817         for (int32_t i = 0; i < bitmap_count; i++)
818             _BlankBitmap(bitmap[i]);
819     }
820     return status;
821 }
822
823 /*****************************************************************************
824  * VideoWindow::_FreeBuffers
825  *****************************************************************************/
826 void
827 VideoWindow::_FreeBuffers()
828 {
829     if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
830     if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
831     if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
832     fInitStatus = B_ERROR;
833 }
834
835 /*****************************************************************************
836  * VideoWindow::_BlankBitmap
837  *****************************************************************************/
838 void
839 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
840 {
841     // no error checking (we do that earlier on and since it's a private function...
842
843     // YCbCr:
844     // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
845
846     // YUV:
847     // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
848
849     // we only handle weird colorspaces with special care
850     switch (bitmap->ColorSpace()) {
851         case B_YCbCr422: {
852             // Y0[7:0]  Cb0[7:0]  Y1[7:0]  Cr0[7:0]  Y2[7:0]  Cb2[7:0]  Y3[7:0]  Cr2[7:0]
853             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
854             uint8_t* bits = (uint8_t*)bitmap->Bits();
855             int32_t bpr = bitmap->BytesPerRow();
856             for (int32_t y = 0; y < height; y++) {
857                 // handle 2 bytes at a time
858                 for (int32_t i = 0; i < bpr; i += 2) {
859                     // offset into line
860                     bits[i] = 16;
861                     bits[i + 1] = 128;
862                 }
863                 // next line
864                 bits += bpr;
865             }
866             break;
867         }
868         case B_YCbCr420: {
869 // TODO: untested!!
870             // Non-interlaced only, Cb0  Y0  Y1  Cb2 Y2  Y3  on even scan lines ...
871             // Cr0  Y0  Y1  Cr2 Y2  Y3  on odd scan lines
872             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
873             uint8_t* bits = (uint8_t*)bitmap->Bits();
874             int32_t bpr = bitmap->BytesPerRow();
875             for (int32_t y = 0; y < height; y += 1) {
876                 // handle 3 bytes at a time
877                 for (int32_t i = 0; i < bpr; i += 3) {
878                     // offset into line
879                     bits[i] = 128;
880                     bits[i + 1] = 16;
881                     bits[i + 2] = 16;
882                 }
883                 // next line
884                 bits += bpr;
885             }
886             break;
887         }
888         case B_YUV422: {
889 // TODO: untested!!
890             // U0[7:0]  Y0[7:0]   V0[7:0]  Y1[7:0]  U2[7:0]  Y2[7:0]   V2[7:0]  Y3[7:0]
891             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
892             uint8_t* bits = (uint8_t*)bitmap->Bits();
893             int32_t bpr = bitmap->BytesPerRow();
894             for (int32_t y = 0; y < height; y += 1) {
895                 // handle 2 bytes at a time
896                 for (int32_t i = 0; i < bpr; i += 2) {
897                     // offset into line
898                     bits[i] = 128;
899                     bits[i + 1] = 0;
900                 }
901                 // next line
902                 bits += bpr;
903             }
904             break;
905         }
906         default:
907             memset(bitmap->Bits(), 0, bitmap->BitsLength());
908             break;
909     }
910 }
911
912 /*****************************************************************************
913  * VideoWindow::_SetVideoSize
914  *****************************************************************************/
915 void
916 VideoWindow::_SetVideoSize(uint32_t mode)
917 {
918     // let size depend on aspect correction
919     int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
920     int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
921     switch (mode)
922     {
923         case RESIZE_50:
924             width /= 2;
925             height /= 2;
926             break;
927         case RESIZE_200:
928             width *= 2;
929             height *= 2;
930             break;
931         case RESIZE_100:
932         default:
933             break;
934     }
935     fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
936     ResizeTo(width, height);
937 }
938
939 /*****************************************************************************
940  * VideoWindow::_SetToSettings
941  *****************************************************************************/
942 void
943 VideoWindow::_SetToSettings()
944 {
945     // adjust dimensions
946     uint32_t mode = RESIZE_100;
947     switch (fSettings->VideoSize())
948     {
949         case VideoSettings::SIZE_50:
950             mode = RESIZE_50;
951             break;
952         case VideoSettings::SIZE_200:
953             mode = RESIZE_200;
954             break;
955         case VideoSettings::SIZE_100:
956         case VideoSettings::SIZE_OTHER:
957         default:
958             break;
959     }
960     bool fullscreen = IsFullScreen();    // remember settings
961     _SetVideoSize(mode);                // because this will reset settings
962     // the fullscreen status is reflected in the settings,
963     // but not yet in the windows state
964     if (fullscreen)
965         SetFullScreen(true);
966     if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
967         fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
968     else
969         fCachedFeel = B_NORMAL_WINDOW_FEEL;
970     SetFeel(fCachedFeel);
971 }
972
973 /*****************************************************************************
974  * VLCView::VLCView
975  *****************************************************************************/
976 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
977     : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
978       fLastMouseMovedTime(mdate()),
979       fCursorHidden(false),
980       fCursorInside(false),
981       fIgnoreDoubleClick(false)
982 {
983     p_vout = p_vout_instance;
984     SetViewColor(B_TRANSPARENT_32_BIT);
985 }
986
987 /*****************************************************************************
988  * VLCView::~VLCView
989  *****************************************************************************/
990 VLCView::~VLCView()
991 {
992 }
993
994 /*****************************************************************************
995  * VLCVIew::AttachedToWindow
996  *****************************************************************************/
997 void
998 VLCView::AttachedToWindow()
999 {
1000     // periodically check if we want to hide the pointer
1001     Window()->SetPulseRate(1000000);
1002 }
1003
1004 /*****************************************************************************
1005  * VLCVIew::MouseDown
1006  *****************************************************************************/
1007 void
1008 VLCView::MouseDown(BPoint where)
1009 {
1010     VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
1011     BMessage* msg = Window()->CurrentMessage();
1012     int32 clicks;
1013     uint32_t buttons;
1014     msg->FindInt32("clicks", &clicks);
1015     msg->FindInt32("buttons", (int32*)&buttons);
1016
1017     if (videoWindow)
1018     {
1019         if (buttons & B_PRIMARY_MOUSE_BUTTON)
1020         {
1021             if (clicks == 2 && !fIgnoreDoubleClick)
1022                 Window()->Zoom();
1023             /* else
1024                 videoWindow->ToggleInterfaceShowing(); */
1025             fIgnoreDoubleClick = false;
1026         }
1027         else
1028         {
1029             if (buttons & B_SECONDARY_MOUSE_BUTTON)
1030             {
1031                 // clicks will be 2 next time (if interval short enough)
1032                 // even if the first click and the second
1033                 // have not been made with the same mouse button
1034                 fIgnoreDoubleClick = true;
1035                 // launch popup menu
1036                 BPopUpMenu *menu = new BPopUpMenu("context menu");
1037                 menu->SetRadioMode(false);
1038                 // In full screen, add an item to show/hide the interface
1039                 if( videoWindow->IsFullScreen() )
1040                 {
1041                     BMenuItem *intfItem =
1042                         new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
1043                     menu->AddItem( intfItem );
1044                 }
1045                 // Resize to 50%
1046                 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
1047                 menu->AddItem(halfItem);
1048                 // Resize to 100%
1049                 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
1050                 menu->AddItem(origItem);
1051                 // Resize to 200%
1052                 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
1053                 menu->AddItem(doubleItem);
1054                 // Toggle FullScreen
1055                 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
1056                 zoomItem->SetMarked(videoWindow->IsFullScreen());
1057                 menu->AddItem(zoomItem);
1058     
1059                 menu->AddSeparatorItem();
1060     
1061                 // Toggle vSync
1062                 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
1063                 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
1064                 menu->AddItem(vsyncItem);
1065                 // Correct Aspect Ratio
1066                 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
1067                 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
1068                 menu->AddItem(aspectItem);
1069     
1070                 menu->AddSeparatorItem();
1071     
1072                 // Window Feel Items
1073 /*                BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
1074                 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
1075                 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
1076                 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
1077                 menu->AddItem(normWindItem);
1078                 
1079                 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
1080                 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
1081                 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
1082                 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
1083                 menu->AddItem(onTopWindItem);
1084                 
1085                 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
1086                 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
1087                 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
1088                 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
1089                 menu->AddItem(allSpacesWindItem);*/
1090
1091                 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
1092                 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
1093                 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
1094                 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
1095                 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
1096                 windowFeelItem->SetMarked( onTop );
1097                 menu->AddItem( windowFeelItem );
1098
1099                 menu->AddSeparatorItem();
1100
1101                 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
1102                                                            new BMessage( SCREEN_SHOT ) );
1103                 menu->AddItem( screenShotItem );
1104
1105                 menu->SetTargetForItems( this );
1106                 ConvertToScreen( &where );
1107                 BRect mouseRect( where.x - 5, where.y - 5,
1108                                  where.x + 5, where.y + 5 );
1109                 menu->Go( where, true, false, mouseRect, true );
1110             }
1111         }
1112     }
1113     fLastMouseMovedTime = mdate();
1114     fCursorHidden = false;
1115 }
1116
1117 /*****************************************************************************
1118  * VLCVIew::MouseUp
1119  *****************************************************************************/
1120 void
1121 VLCView::MouseUp( BPoint where )
1122 {
1123     vlc_value_t val;
1124     val.b_bool = VLC_TRUE;
1125     var_Set( p_vout, "mouse-clicked", val );
1126 }
1127
1128 /*****************************************************************************
1129  * VLCVIew::MouseMoved
1130  *****************************************************************************/
1131 void
1132 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
1133 {
1134     fLastMouseMovedTime = mdate();
1135     fCursorHidden = false;
1136     fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
1137
1138     if( !fCursorInside )
1139     {
1140         return;
1141     }
1142
1143     vlc_value_t val;
1144     unsigned int i_width, i_height, i_x, i_y;
1145     vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
1146                        (unsigned int)Bounds().Height(),
1147                        &i_x, &i_y, &i_width, &i_height );
1148     val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
1149     var_Set( p_vout, "mouse-x", val );
1150     val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
1151     var_Set( p_vout, "mouse-y", val );
1152     val.b_bool = VLC_TRUE;
1153     var_Set( p_vout, "mouse-moved", val );
1154 }
1155
1156 /*****************************************************************************
1157  * VLCVIew::Pulse
1158  *****************************************************************************/
1159 void
1160 VLCView::Pulse()
1161 {
1162     // We are getting the pulse messages no matter if the mouse is over
1163     // this view. If we are in full screen mode, we want to hide the cursor
1164     // even if it is not.
1165     VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
1166     if (!fCursorHidden)
1167     {
1168         if (fCursorInside
1169             && mdate() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
1170         {
1171             be_app->ObscureCursor();
1172             fCursorHidden = true;
1173             
1174             // hide the interface window as well if full screen
1175             if (videoWindow && videoWindow->IsFullScreen())
1176                 videoWindow->SetInterfaceShowing(false);
1177         }
1178     }
1179
1180     // Workaround to disable the screensaver in full screen:
1181     // we simulate an activity every 29 seconds    
1182     if( videoWindow && videoWindow->IsFullScreen() &&
1183         mdate() - fLastMouseMovedTime > 29000000 )
1184     {
1185         BPoint where;
1186         uint32 buttons;
1187         GetMouse(&where, &buttons, false);
1188         ConvertToScreen(&where);
1189         set_mouse_position((int32_t) where.x, (int32_t) where.y);
1190     }
1191 }
1192
1193 /*****************************************************************************
1194  * VLCVIew::Draw
1195  *****************************************************************************/
1196 void
1197 VLCView::Draw(BRect updateRect)
1198 {
1199     VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
1200     if ( window && window->mode == BITMAP )
1201         FillRect( updateRect );
1202 }
1203
1204 /*****************************************************************************
1205  * Local prototypes
1206  *****************************************************************************/
1207 static int  Init       ( vout_thread_t * );
1208 static void End        ( vout_thread_t * );
1209 static int  Manage     ( vout_thread_t * );
1210 static void Display    ( vout_thread_t *, picture_t * );
1211 static int  Control    ( vout_thread_t *, int, va_list );
1212
1213 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
1214 static void BeosCloseDisplay( vout_thread_t *p_vout );
1215
1216 /*****************************************************************************
1217  * OpenVideo: allocates BeOS video thread output method
1218  *****************************************************************************
1219  * This function allocates and initializes a BeOS vout method.
1220  *****************************************************************************/
1221 int E_(OpenVideo) ( vlc_object_t *p_this )
1222 {
1223     vout_thread_t * p_vout = (vout_thread_t *)p_this;
1224
1225     /* Allocate structure */
1226     p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
1227     if( p_vout->p_sys == NULL )
1228     {
1229         msg_Err( p_vout, "out of memory" );
1230         return( 1 );
1231     }
1232     p_vout->p_sys->i_width = p_vout->render.i_width;
1233     p_vout->p_sys->i_height = p_vout->render.i_height;
1234     p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
1235
1236     p_vout->pf_init = Init;
1237     p_vout->pf_end = End;
1238     p_vout->pf_manage = Manage;
1239     p_vout->pf_render = NULL;
1240     p_vout->pf_display = Display;
1241     p_vout->pf_control = Control;
1242
1243     return( 0 );
1244 }
1245
1246 /*****************************************************************************
1247  * Init: initialize BeOS video thread output method
1248  *****************************************************************************/
1249 int Init( vout_thread_t *p_vout )
1250 {
1251     int i_index;
1252     picture_t *p_pic;
1253
1254     I_OUTPUTPICTURES = 0;
1255
1256     /* Open and initialize device */
1257     if( BeosOpenDisplay( p_vout ) )
1258     {
1259         msg_Err(p_vout, "vout error: can't open display");
1260         return 0;
1261     }
1262     p_vout->output.i_width  = p_vout->render.i_width;
1263     p_vout->output.i_height = p_vout->render.i_height;
1264
1265     /* Assume we have square pixels */
1266     p_vout->output.i_aspect = p_vout->p_sys->i_width
1267                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
1268     p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
1269     p_vout->p_sys->i_index = 0;
1270
1271     p_vout->b_direct = 1;
1272
1273     p_vout->output.i_rmask  = 0x00ff0000;
1274     p_vout->output.i_gmask  = 0x0000ff00;
1275     p_vout->output.i_bmask  = 0x000000ff;
1276
1277     for( int buffer_index = 0 ;
1278          buffer_index < p_vout->p_sys->p_window->bitmap_count;
1279          buffer_index++ )
1280     {
1281        p_pic = NULL;
1282        /* Find an empty picture slot */
1283        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
1284        {
1285            p_pic = NULL;
1286            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
1287            {
1288                p_pic = p_vout->p_picture + i_index;
1289                break;
1290            }
1291        }
1292
1293        if( p_pic == NULL )
1294        {
1295            return 0;
1296        }
1297        p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
1298        p_pic->p->i_lines = p_vout->p_sys->i_height;
1299        p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
1300
1301        p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
1302        p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
1303        p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
1304        p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
1305
1306        p_pic->i_status = DESTROYED_PICTURE;
1307        p_pic->i_type   = DIRECT_PICTURE;
1308
1309        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
1310
1311        I_OUTPUTPICTURES++;
1312     }
1313
1314     return( 0 );
1315 }
1316
1317 /*****************************************************************************
1318  * End: terminate BeOS video thread output method
1319  *****************************************************************************/
1320 void End( vout_thread_t *p_vout )
1321 {
1322     BeosCloseDisplay( p_vout );
1323 }
1324
1325 /*****************************************************************************
1326  * Manage
1327  *****************************************************************************/
1328 static int Manage( vout_thread_t * p_vout )
1329 {
1330     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
1331     {
1332         p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
1333         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
1334     }
1335
1336     return 0;
1337 }
1338
1339 /*****************************************************************************
1340  * CloseVideo: destroy BeOS video thread output method
1341  *****************************************************************************
1342  * Terminate an output method created by DummyCreateOutputMethod
1343  *****************************************************************************/
1344 void E_(CloseVideo) ( vlc_object_t *p_this )
1345 {
1346     vout_thread_t * p_vout = (vout_thread_t *)p_this;
1347
1348     free( p_vout->p_sys );
1349 }
1350
1351 /*****************************************************************************
1352  * Display: displays previously rendered output
1353  *****************************************************************************
1354  * This function send the currently rendered image to BeOS image, waits until
1355  * it is displayed and switch the two rendering buffers, preparing next frame.
1356  *****************************************************************************/
1357 void Display( vout_thread_t *p_vout, picture_t *p_pic )
1358 {
1359     VideoWindow * p_win = p_vout->p_sys->p_window;
1360
1361     /* draw buffer if required */
1362     if (!p_win->teardownwindow)
1363     {
1364        p_win->drawBuffer(p_vout->p_sys->i_index);
1365     }
1366     /* change buffer */
1367     p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
1368         p_vout->p_sys->p_window->bitmap_count;
1369     p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
1370 }
1371
1372 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
1373 {
1374     return vout_vaControlDefault( p_vout, i_query, args );
1375 }
1376
1377 /* following functions are local */
1378
1379 /*****************************************************************************
1380  * BeosOpenDisplay: open and initialize BeOS device
1381  *****************************************************************************/
1382 static int BeosOpenDisplay( vout_thread_t *p_vout )
1383 {
1384
1385     p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
1386                                                p_vout->p_sys->i_height - 1,
1387                                                BRect( 20, 50,
1388                                                       20 + p_vout->i_window_width - 1,
1389                                                       50 + p_vout->i_window_height - 1 ),
1390                                                p_vout );
1391     if( p_vout->p_sys->p_window == NULL )
1392     {
1393         msg_Err( p_vout, "cannot allocate VideoWindow" );
1394         return( 1 );
1395     }
1396     else
1397     {
1398         p_vout->p_sys->p_window->Show();
1399     }
1400
1401     return( 0 );
1402 }
1403
1404 /*****************************************************************************
1405  * BeosDisplay: close and reset BeOS device
1406  *****************************************************************************
1407  * Returns all resources allocated by BeosOpenDisplay and restore the original
1408  * state of the device.
1409  *****************************************************************************/
1410 static void BeosCloseDisplay( vout_thread_t *p_vout )
1411 {
1412     VideoWindow * p_win = p_vout->p_sys->p_window;
1413     /* Destroy the video window */
1414     if( p_win != NULL && !p_win->teardownwindow)
1415     {
1416         p_win->Lock();
1417         p_win->teardownwindow = true;
1418         p_win->Hide();
1419         p_win->Quit();
1420     }
1421     p_win = NULL;
1422 }