VideoOutput.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:47k
源码类别:

midi

开发平台:

Unix_Linux

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