Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

VideoOutput.cpp

00001 /*****************************************************************************
00002  * vout_beos.cpp: beos video output display method
00003  *****************************************************************************
00004  * Copyright (C) 2000, 2001 the VideoLAN team
00005  * $Id: VideoOutput.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Jean-Marc Dressler <[email protected]>
00008  *          Samuel Hocevar <[email protected]>
00009  *          Tony Castley <[email protected]>
00010  *          Richard Shepherd <[email protected]>
00011  *          Stephan Aßmus <[email protected]>
00012  *
00013  * This program is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00026  *****************************************************************************/
00027 
00028 /*****************************************************************************
00029  * Preamble
00030  *****************************************************************************/
00031 #include <errno.h>                                                 /* ENOMEM */
00032 #include <stdlib.h>                                                /* free() */
00033 #include <stdio.h>
00034 #include <string.h>                                            /* strerror() */
00035 
00036 #include <Application.h>
00037 #include <BitmapStream.h>
00038 #include <Bitmap.h>
00039 #include <Directory.h>
00040 #include <DirectWindow.h>
00041 #include <File.h>
00042 #include <InterfaceKit.h>
00043 #include <NodeInfo.h>
00044 #include <String.h>
00045 #include <TranslatorRoster.h>
00046 #include <WindowScreen.h>
00047 
00048 /* VLC headers */
00049 #include <vlc/vlc.h>
00050 #include <vlc/intf.h>
00051 #include <vlc/vout.h>
00052 #include <vlc_keys.h>
00053 
00054 #include "InterfaceWindow.h"    // for load/save_settings()
00055 #include "DrawingTidbits.h"
00056 #include "MsgVals.h"
00057 
00058 #include "VideoWindow.h"
00059 
00060 /*****************************************************************************
00061  * vout_sys_t: BeOS video output method descriptor
00062  *****************************************************************************
00063  * This structure is part of the video output thread descriptor.
00064  * It describes the BeOS specific properties of an output thread.
00065  *****************************************************************************/
00066 struct vout_sys_t
00067 {
00068     VideoWindow *  p_window;
00069 
00070     int32_t i_width;
00071     int32_t i_height;
00072 
00073 //    uint8_t *pp_buffer[3];
00074     uint32_t source_chroma;
00075     int i_index;
00076 
00077 };
00078 
00079 #define MOUSE_IDLE_TIMEOUT 2000000    // two seconds
00080 #define MIN_AUTO_VSYNC_REFRESH 61    // Hz
00081 
00082 /*****************************************************************************
00083  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
00084  *****************************************************************************/
00085 BWindow*
00086 beos_GetAppWindow(char *name)
00087 {
00088     int32_t     index;
00089     BWindow     *window;
00090 
00091     for (index = 0 ; ; index++)
00092     {
00093         window = be_app->WindowAt(index);
00094         if (window == NULL)
00095             break;
00096         if (window->LockWithTimeout(20000) == B_OK)
00097         {
00098             if (strcmp(window->Name(), name) == 0)
00099             {
00100                 window->Unlock();
00101                 break;
00102             }
00103             window->Unlock();
00104         }
00105     }
00106     return window;
00107 }
00108 
00109 static const int beos_keys[][2] =
00110 {
00111     { B_LEFT_ARROW,  KEY_LEFT },
00112     { B_RIGHT_ARROW, KEY_RIGHT },
00113     { B_UP_ARROW,    KEY_UP },
00114     { B_DOWN_ARROW,  KEY_DOWN },
00115     { B_SPACE,       KEY_SPACE },
00116     { B_ENTER,       KEY_ENTER },
00117     { B_F1_KEY,      KEY_F1 },
00118     { B_F2_KEY,      KEY_F2 },
00119     { B_F3_KEY,      KEY_F3 },
00120     { B_F4_KEY,      KEY_F4 },
00121     { B_F5_KEY,      KEY_F5 },
00122     { B_F6_KEY,      KEY_F6 },
00123     { B_F7_KEY,      KEY_F7 },
00124     { B_F8_KEY,      KEY_F8 },
00125     { B_F9_KEY,      KEY_F9 },
00126     { B_F10_KEY,     KEY_F10 },
00127     { B_F11_KEY,     KEY_F11 },
00128     { B_F12_KEY,     KEY_F12 },
00129     { B_HOME,        KEY_HOME },
00130     { B_END,         KEY_END },
00131     { B_ESCAPE,      KEY_ESC },
00132     { B_PAGE_UP,     KEY_PAGEUP },
00133     { B_PAGE_DOWN,   KEY_PAGEDOWN },
00134     { B_TAB,         KEY_TAB },
00135     { B_BACKSPACE,   KEY_BACKSPACE }
00136 };
00137 
00138 static int ConvertKeyFromVLC( int key )
00139 {
00140     for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
00141     {
00142         if( beos_keys[i][1] == key )
00143         {
00144             return beos_keys[i][0];
00145         }
00146     }
00147     return key;
00148 }
00149 
00150 static int ConvertKeyToVLC( int key )
00151 {
00152     for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ )
00153     {
00154         if( beos_keys[i][0] == key )
00155         {
00156             return beos_keys[i][1];
00157         }
00158     }
00159     return key;
00160 }
00161 
00162 /*****************************************************************************
00163  * get_interface_window
00164  *****************************************************************************/
00165 BWindow*
00166 get_interface_window()
00167 {
00168     return beos_GetAppWindow( "VLC " PACKAGE_VERSION );
00169 }
00170 
00171 class BackgroundView : public BView
00172 {
00173  public:
00174                             BackgroundView(BRect frame, VLCView* view)
00175                             : BView(frame, "background",
00176                                     B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
00177                               fVideoView(view)
00178                             {
00179                                 SetViewColor(kBlack);
00180                             }
00181     virtual                    ~BackgroundView() {}
00182 
00183     virtual    void            MouseDown(BPoint where)
00184                             {
00185                                 // convert coordinates
00186                                 where = fVideoView->ConvertFromParent(where);
00187                                 // let him handle it
00188                                 fVideoView->MouseDown(where);
00189                             }
00190     virtual    void            MouseMoved(BPoint where, uint32_t transit,
00191                                        const BMessage* dragMessage)
00192                             {
00193                                 // convert coordinates
00194                                 where = fVideoView->ConvertFromParent(where);
00195                                 // let him handle it
00196                                 fVideoView->MouseMoved(where, transit, dragMessage);
00197                                 // notice: It might look like transit should be
00198                                 // B_OUTSIDE_VIEW regardless, but leave it like this,
00199                                 // otherwise, unwanted things will happen!
00200                             }
00201 
00202  private:
00203     VLCView*                fVideoView;
00204 };
00205 
00206 
00207 /*****************************************************************************
00208  * VideoSettings constructor and destructor
00209  *****************************************************************************/
00210 VideoSettings::VideoSettings()
00211     : fVideoSize( SIZE_100 ),
00212       fFlags( FLAG_CORRECT_RATIO ),
00213       fSettings( new BMessage( 'sett' ) )
00214 {
00215     // read settings from disk
00216     status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" );
00217     if ( ret == B_OK )
00218     {
00219         uint32_t flags;
00220         if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK )
00221             SetFlags( flags );
00222         uint32_t size;
00223         if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK )
00224             SetVideoSize( size );
00225     }
00226     else
00227     {
00228         // figure out if we should use vertical sync by default
00229         BScreen screen(B_MAIN_SCREEN_ID);
00230         if (screen.IsValid())
00231         {
00232             display_mode mode;
00233             screen.GetMode(&mode);
00234             float refresh = (mode.timing.pixel_clock * 1000)
00235                             / ((mode.timing.h_total)* (mode.timing.v_total));
00236             if (refresh < MIN_AUTO_VSYNC_REFRESH)
00237                 AddFlags(FLAG_SYNC_RETRACE);
00238         }
00239     }
00240 }
00241 
00242 VideoSettings::VideoSettings( const VideoSettings& clone )
00243     : fVideoSize( clone.VideoSize() ),
00244       fFlags( clone.Flags() ),
00245       fSettings( NULL )
00246 {
00247 }
00248 
00249 
00250 VideoSettings::~VideoSettings()
00251 {
00252     if ( fSettings )
00253     {
00254         // we are the default settings
00255         // and write our settings to disk
00256         if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK)
00257             fSettings->AddInt32( "video size", VideoSize() );
00258         if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK)
00259             fSettings->AddInt32( "flags", Flags() );
00260 
00261         save_settings( fSettings, "video_settings", "VideoLAN Client" );
00262         delete fSettings;
00263     }
00264     else
00265     {
00266         // we are just a clone of the default settings
00267         fDefaultSettings.SetVideoSize( VideoSize() );
00268         fDefaultSettings.SetFlags( Flags() );
00269     }
00270 }
00271 
00272 /*****************************************************************************
00273  * VideoSettings::DefaultSettings
00274  *****************************************************************************/
00275 VideoSettings*
00276 VideoSettings::DefaultSettings()
00277 {
00278     return &fDefaultSettings;
00279 }
00280 
00281 /*****************************************************************************
00282  * VideoSettings::SetVideoSize
00283  *****************************************************************************/
00284 void
00285 VideoSettings::SetVideoSize( uint32_t mode )
00286 {
00287     fVideoSize = mode;
00288 }
00289 
00290 // static variable initialization
00291 VideoSettings
00292 VideoSettings::fDefaultSettings;
00293 
00294 
00295 /*****************************************************************************
00296  * VideoWindow constructor and destructor
00297  *****************************************************************************/
00298 VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
00299                          vout_thread_t *p_videoout)
00300     : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
00301       i_width(frame.IntegerWidth()),
00302       i_height(frame.IntegerHeight()),
00303       winSize(frame),
00304       i_buffer(0),
00305       teardownwindow(false),
00306       fTrueWidth(v_width),
00307       fTrueHeight(v_height),
00308       fCachedFeel(B_NORMAL_WINDOW_FEEL),
00309       fInterfaceShowing(false),
00310       fInitStatus(B_ERROR),
00311       fSettings(new VideoSettings(*VideoSettings::DefaultSettings()))
00312 {
00313     p_vout = p_videoout;
00314 
00315     // create the view to do the display
00316     view = new VLCView( Bounds(), p_vout );
00317 
00318     // create background view
00319     BView *mainView =  new BackgroundView( Bounds(), view );
00320     AddChild(mainView);
00321     mainView->AddChild(view);
00322 
00323     // allocate bitmap buffers
00324     for (int32_t i = 0; i < 3; i++)
00325         bitmap[i] = NULL;
00326     fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
00327 
00328     // make sure we layout the view correctly
00329     FrameResized(i_width, i_height);
00330 
00331     if (fInitStatus >= B_OK && mode == OVERLAY)
00332     {
00333        overlay_restrictions r;
00334 
00335        bitmap[0]->GetOverlayRestrictions(&r);
00336        SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
00337                      (i_height * r.min_height_scale), i_height * r.max_height_scale);
00338     }
00339 
00340     // vlc settings override settings from disk
00341     if (config_GetInt(p_vout, "fullscreen"))
00342         fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
00343 
00344     _SetToSettings();
00345 }
00346 
00347 VideoWindow::~VideoWindow()
00348 {
00349     int32 result;
00350 
00351     teardownwindow = true;
00352     wait_for_thread(fDrawThreadID, &result);
00353     _FreeBuffers();
00354     delete fSettings;
00355 }
00356 
00357 /*****************************************************************************
00358  * VideoWindow::MessageReceived
00359  *****************************************************************************/
00360 void
00361 VideoWindow::MessageReceived( BMessage *p_message )
00362 {
00363     switch( p_message->what )
00364     {
00365         case SHOW_INTERFACE:
00366             SetInterfaceShowing( true );
00367             break;
00368         case TOGGLE_FULL_SCREEN:
00369             BWindow::Zoom();
00370             break;
00371         case RESIZE_50:
00372         case RESIZE_100:
00373         case RESIZE_200:
00374             if (IsFullScreen())
00375                 BWindow::Zoom();
00376             _SetVideoSize(p_message->what);
00377             break;
00378         case VERT_SYNC:
00379             SetSyncToRetrace(!IsSyncedToRetrace());
00380             break;
00381         case WINDOW_FEEL:
00382             {
00383                 window_feel winFeel;
00384                 if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
00385                 {
00386                     SetFeel(winFeel);
00387                     fCachedFeel = winFeel;
00388                     if (winFeel == B_FLOATING_ALL_WINDOW_FEEL)
00389                         fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL);
00390                     else
00391                         fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL);
00392                 }
00393             }
00394             break;
00395         case ASPECT_CORRECT:
00396             SetCorrectAspectRatio(!CorrectAspectRatio());
00397             break;
00398 
00399         case B_KEY_DOWN:
00400         case B_UNMAPPED_KEY_DOWN:
00401         case B_KEY_UP:
00402         case B_UNMAPPED_KEY_UP:
00403         {
00404             key_map * keys;
00405             char    * chars;
00406             int32     key, modifiers;
00407 
00408             if( p_message->FindInt32( "key", &key ) != B_OK ||
00409                 p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
00410             {
00411                 /* Shouldn't happen */
00412                 break;
00413             }
00414 
00415             if( ( p_message->what == B_KEY_UP ||
00416                   p_message->what == B_UNMAPPED_KEY_UP ) &&
00417                 !( modifiers & B_COMMAND_KEY ) )
00418             {
00419                 /* We only use the KEY_UP messages to detect Alt+X
00420                    shortcuts (because the KEY_DOWN messages aren't
00421                    sent when Alt is pressed) */
00422                 break;
00423             }
00424 
00425             /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
00426                the character depends on the keymap, we use the key codes
00427                directly (18, 19, 20) */
00428             if( ( modifiers & B_COMMAND_KEY ) &&
00429                 key >= 18 && key <= 20 )
00430             {
00431                 if( key == 18 )
00432                     PostMessage( RESIZE_50 );
00433                 else if( key == 19 )
00434                     PostMessage( RESIZE_100 );
00435                 else
00436                     PostMessage( RESIZE_200 );
00437 
00438                 break;
00439             }
00440 
00441             /* Get the current keymap */
00442             get_key_map( &keys, &chars );
00443 
00444             if( key >= 128 || chars[keys->normal_map[key]] != 1 )
00445             {
00446                 /* Weird key or Unicode character */
00447                 free( keys );
00448                 free( chars );
00449                 break;
00450             }
00451 
00452             vlc_value_t val;
00453             val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
00454 
00455             if( modifiers & B_COMMAND_KEY )
00456             {
00457                 val.i_int |= KEY_MODIFIER_ALT;
00458             }
00459             if( modifiers & B_SHIFT_KEY )
00460             {
00461                 val.i_int |= KEY_MODIFIER_SHIFT;
00462             }
00463             if( modifiers & B_CONTROL_KEY )
00464             {
00465                 val.i_int |= KEY_MODIFIER_CTRL;
00466             }
00467             var_Set( p_vout->p_vlc, "key-pressed", val );
00468 
00469             free( keys );
00470             free( chars );
00471             break;
00472         }
00473 
00474         default:
00475             BWindow::MessageReceived( p_message );
00476             break;
00477     }
00478 }
00479 
00480 /*****************************************************************************
00481  * VideoWindow::Zoom
00482  *****************************************************************************/
00483 void
00484 VideoWindow::Zoom(BPoint origin, float width, float height )
00485 {
00486     ToggleFullScreen();
00487 }
00488 
00489 /*****************************************************************************
00490  * VideoWindow::FrameMoved
00491  *****************************************************************************/
00492 void
00493 VideoWindow::FrameMoved(BPoint origin)
00494 {
00495     if (IsFullScreen())
00496         return ;
00497     winSize = Frame();
00498 }
00499 
00500 /*****************************************************************************
00501  * VideoWindow::FrameResized
00502  *****************************************************************************/
00503 void
00504 VideoWindow::FrameResized( float width, float height )
00505 {
00506     int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth;
00507     int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight;
00508     float out_width, out_height;
00509     float out_left, out_top;
00510     float width_scale = width / useWidth;
00511     float height_scale = height / useHeight;
00512 
00513     if (width_scale <= height_scale)
00514     {
00515         out_width = (useWidth * width_scale);
00516         out_height = (useHeight * width_scale);
00517         out_left = 0;
00518         out_top = (height - out_height) / 2;
00519     }
00520     else   /* if the height is proportionally smaller */
00521     {
00522         out_width = (useWidth * height_scale);
00523         out_height = (useHeight * height_scale);
00524         out_top = 0;
00525         out_left = (width - out_width) / 2;
00526     }
00527     view->MoveTo(out_left,out_top);
00528     view->ResizeTo(out_width, out_height);
00529 
00530     if (!IsFullScreen())
00531         winSize = Frame();
00532 }
00533 
00534 /*****************************************************************************
00535  * VideoWindow::ScreenChanged
00536  *****************************************************************************/
00537 void
00538 VideoWindow::ScreenChanged(BRect frame, color_space format)
00539 {
00540     BScreen screen(this);
00541     display_mode mode;
00542     screen.GetMode(&mode);
00543     float refresh = (mode.timing.pixel_clock * 1000)
00544                     / ((mode.timing.h_total) * (mode.timing.v_total));
00545     SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH);
00546 }
00547 
00548 /*****************************************************************************
00549  * VideoWindow::Activate
00550  *****************************************************************************/
00551 void
00552 VideoWindow::WindowActivated(bool active)
00553 {
00554 }
00555 
00556 /*****************************************************************************
00557  * VideoWindow::drawBuffer
00558  *****************************************************************************/
00559 void
00560 VideoWindow::drawBuffer(int bufferIndex)
00561 {
00562     i_buffer = bufferIndex;
00563 
00564     // sync to the screen if required
00565     if (IsSyncedToRetrace())
00566     {
00567         BScreen screen(this);
00568         screen.WaitForRetrace(22000);
00569     }
00570     if (fInitStatus >= B_OK && LockLooper())
00571     {
00572        // switch the overlay bitmap
00573        if (mode == OVERLAY)
00574        {
00575           rgb_color key;
00576           view->SetViewOverlay(bitmap[i_buffer],
00577                             bitmap[i_buffer]->Bounds() ,
00578                             view->Bounds(),
00579                             &key, B_FOLLOW_ALL,
00580                             B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
00581                             B_OVERLAY_TRANSFER_CHANNEL);
00582            view->SetViewColor(key);
00583        }
00584        else
00585        {
00586          // switch the bitmap
00587          view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
00588        }
00589        UnlockLooper();
00590     }
00591 }
00592 
00593 /*****************************************************************************
00594  * VideoWindow::SetInterfaceShowing
00595  *****************************************************************************/
00596 void
00597 VideoWindow::ToggleInterfaceShowing()
00598 {
00599     SetInterfaceShowing(!fInterfaceShowing);
00600 }
00601 
00602 /*****************************************************************************
00603  * VideoWindow::SetInterfaceShowing
00604  *****************************************************************************/
00605 void
00606 VideoWindow::SetInterfaceShowing(bool showIt)
00607 {
00608     BWindow* window = get_interface_window();
00609     if (window)
00610     {
00611         if (showIt)
00612         {
00613             if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
00614                 SetFeel(B_NORMAL_WINDOW_FEEL);
00615             window->Activate(true);
00616             SendBehind(window);
00617         }
00618         else
00619         {
00620             SetFeel(fCachedFeel);
00621             Activate(true);
00622             window->SendBehind(this);
00623         }
00624         fInterfaceShowing = showIt;
00625     }
00626 }
00627 
00628 /*****************************************************************************
00629  * VideoWindow::SetCorrectAspectRatio
00630  *****************************************************************************/
00631 void
00632 VideoWindow::SetCorrectAspectRatio(bool doIt)
00633 {
00634     if (CorrectAspectRatio() != doIt)
00635     {
00636         if (doIt)
00637             fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO);
00638         else
00639             fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO);
00640         FrameResized(Bounds().Width(), Bounds().Height());
00641     }
00642 }
00643 
00644 /*****************************************************************************
00645  * VideoWindow::CorrectAspectRatio
00646  *****************************************************************************/
00647 bool
00648 VideoWindow::CorrectAspectRatio() const
00649 {
00650     return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO);
00651 }
00652 
00653 /*****************************************************************************
00654  * VideoWindow::ToggleFullScreen
00655  *****************************************************************************/
00656 void
00657 VideoWindow::ToggleFullScreen()
00658 {
00659     SetFullScreen(!IsFullScreen());
00660 }
00661 
00662 /*****************************************************************************
00663  * VideoWindow::SetFullScreen
00664  *****************************************************************************/
00665 void
00666 VideoWindow::SetFullScreen(bool doIt)
00667 {
00668     if (doIt)
00669     {
00670         SetLook( B_NO_BORDER_WINDOW_LOOK );
00671         BScreen screen( this );
00672         BRect rect = screen.Frame();
00673         Activate();
00674         MoveTo(0.0, 0.0);
00675         ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
00676         be_app->ObscureCursor();
00677         fInterfaceShowing = false;
00678         fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
00679     }
00680     else
00681     {
00682         SetLook( B_TITLED_WINDOW_LOOK );
00683         MoveTo(winSize.left, winSize.top);
00684         ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
00685         be_app->ShowCursor();
00686         fInterfaceShowing = true;
00687         fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
00688     }
00689 }
00690 
00691 /*****************************************************************************
00692  * VideoWindow::IsFullScreen
00693  *****************************************************************************/
00694 bool
00695 VideoWindow::IsFullScreen() const
00696 {
00697     return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN);
00698 }
00699 
00700 /*****************************************************************************
00701  * VideoWindow::SetSyncToRetrace
00702  *****************************************************************************/
00703 void
00704 VideoWindow::SetSyncToRetrace(bool doIt)
00705 {
00706     if (doIt)
00707         fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE);
00708     else
00709         fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE);
00710 }
00711 
00712 /*****************************************************************************
00713  * VideoWindow::IsSyncedToRetrace
00714  *****************************************************************************/
00715 bool
00716 VideoWindow::IsSyncedToRetrace() const
00717 {
00718     return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE);
00719 }
00720 
00721 
00722 /*****************************************************************************
00723  * VideoWindow::_AllocateBuffers
00724  *****************************************************************************/
00725 status_t
00726 VideoWindow::_AllocateBuffers(int width, int height, int* mode)
00727 {
00728     // clear any old buffers
00729     _FreeBuffers();
00730     // set default mode
00731     *mode = BITMAP;
00732     bitmap_count = 3;
00733 
00734     BRect bitmapFrame( 0, 0, width, height );
00735     // read from config, if we are supposed to use overlay at all
00736     int noOverlay = !config_GetInt( p_vout, "overlay" );
00737 
00738     /* Test for overlay capability: for every chroma in colspace,
00739        we try to do double-buffered overlay, single-buffered overlay
00740        or basic overlay. If nothing worked, we then have to work with
00741        a non-overlay BBitmap. */
00742     for( int i = 0; i < COLOR_COUNT; i++ )
00743     {
00744         if( noOverlay )
00745             break;
00746 
00747         bitmap[0] = new BBitmap( bitmapFrame,
00748                                  B_BITMAP_WILL_OVERLAY |
00749                                  B_BITMAP_RESERVE_OVERLAY_CHANNEL,
00750                                  colspace[i].colspace );
00751         if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
00752         {
00753             colspace_index = i;
00754 
00755             *mode = OVERLAY;
00756             rgb_color key;
00757             view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
00758                                   view->Bounds(), &key, B_FOLLOW_ALL,
00759                                   B_OVERLAY_FILTER_HORIZONTAL |
00760                                   B_OVERLAY_FILTER_VERTICAL );
00761             view->SetViewColor( key );
00762             SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
00763 
00764             bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
00765                                      colspace[colspace_index].colspace);
00766             if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
00767             {
00768 
00769                 bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
00770                                          colspace[colspace_index].colspace);
00771                 if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
00772                 {
00773                     msg_Dbg( p_vout, "using double-buffered overlay" );
00774                 }
00775                 else
00776                 {
00777                     msg_Dbg( p_vout, "using single-buffered overlay" );
00778                     bitmap_count = 2;
00779                     if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
00780                 }
00781             }
00782             else
00783             {
00784                 msg_Dbg( p_vout, "using simple overlay" );
00785                 bitmap_count = 1;
00786                 if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
00787             }
00788             break;
00789         }
00790         else
00791         {
00792             if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
00793         }
00794     }
00795 
00796     if (*mode == BITMAP)
00797     {
00798         msg_Warn( p_vout, "no possible overlay" );
00799 
00800         // fallback to RGB
00801         colspace_index = DEFAULT_COL;    // B_RGB32
00802         bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00803         bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00804         bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
00805         SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
00806     }
00807     // see if everything went well
00808     status_t status = B_ERROR;
00809     for (int32_t i = 0; i < bitmap_count; i++)
00810     {
00811         if (bitmap[i])
00812             status = bitmap[i]->InitCheck();
00813         if (status < B_OK)
00814             break;
00815     }
00816     if (status >= B_OK)
00817     {
00818         // clear bitmaps to black
00819         for (int32_t i = 0; i < bitmap_count; i++)
00820             _BlankBitmap(bitmap[i]);
00821     }
00822     return status;
00823 }
00824 
00825 /*****************************************************************************
00826  * VideoWindow::_FreeBuffers
00827  *****************************************************************************/
00828 void
00829 VideoWindow::_FreeBuffers()
00830 {
00831     if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
00832     if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
00833     if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
00834     fInitStatus = B_ERROR;
00835 }
00836 
00837 /*****************************************************************************
00838  * VideoWindow::_BlankBitmap
00839  *****************************************************************************/
00840 void
00841 VideoWindow::_BlankBitmap(BBitmap* bitmap) const
00842 {
00843     // no error checking (we do that earlier on and since it's a private function...
00844 
00845     // YCbCr:
00846     // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
00847 
00848     // YUV:
00849     // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
00850 
00851     // we only handle weird colorspaces with special care
00852     switch (bitmap->ColorSpace()) {
00853         case B_YCbCr422: {
00854             // Y0[7:0]  Cb0[7:0]  Y1[7:0]  Cr0[7:0]  Y2[7:0]  Cb2[7:0]  Y3[7:0]  Cr2[7:0]
00855             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00856             uint8_t* bits = (uint8_t*)bitmap->Bits();
00857             int32_t bpr = bitmap->BytesPerRow();
00858             for (int32_t y = 0; y < height; y++) {
00859                 // handle 2 bytes at a time
00860                 for (int32_t i = 0; i < bpr; i += 2) {
00861                     // offset into line
00862                     bits[i] = 16;
00863                     bits[i + 1] = 128;
00864                 }
00865                 // next line
00866                 bits += bpr;
00867             }
00868             break;
00869         }
00870         case B_YCbCr420: {
00871 // TODO: untested!!
00872             // Non-interlaced only, Cb0  Y0  Y1  Cb2 Y2  Y3  on even scan lines ...
00873             // Cr0  Y0  Y1  Cr2 Y2  Y3  on odd scan lines
00874             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00875             uint8_t* bits = (uint8_t*)bitmap->Bits();
00876             int32_t bpr = bitmap->BytesPerRow();
00877             for (int32_t y = 0; y < height; y += 1) {
00878                 // handle 3 bytes at a time
00879                 for (int32_t i = 0; i < bpr; i += 3) {
00880                     // offset into line
00881                     bits[i] = 128;
00882                     bits[i + 1] = 16;
00883                     bits[i + 2] = 16;
00884                 }
00885                 // next line
00886                 bits += bpr;
00887             }
00888             break;
00889         }
00890         case B_YUV422: {
00891 // TODO: untested!!
00892             // U0[7:0]  Y0[7:0]   V0[7:0]  Y1[7:0]  U2[7:0]  Y2[7:0]   V2[7:0]  Y3[7:0]
00893             int32_t height = bitmap->Bounds().IntegerHeight() + 1;
00894             uint8_t* bits = (uint8_t*)bitmap->Bits();
00895             int32_t bpr = bitmap->BytesPerRow();
00896             for (int32_t y = 0; y < height; y += 1) {
00897                 // handle 2 bytes at a time
00898                 for (int32_t i = 0; i < bpr; i += 2) {
00899                     // offset into line
00900                     bits[i] = 128;
00901                     bits[i + 1] = 0;
00902                 }
00903                 // next line
00904                 bits += bpr;
00905             }
00906             break;
00907         }
00908         default:
00909             memset(bitmap->Bits(), 0, bitmap->BitsLength());
00910             break;
00911     }
00912 }
00913 
00914 /*****************************************************************************
00915  * VideoWindow::_SetVideoSize
00916  *****************************************************************************/
00917 void
00918 VideoWindow::_SetVideoSize(uint32_t mode)
00919 {
00920     // let size depend on aspect correction
00921     int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth;
00922     int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight;
00923     switch (mode)
00924     {
00925         case RESIZE_50:
00926             width /= 2;
00927             height /= 2;
00928             break;
00929         case RESIZE_200:
00930             width *= 2;
00931             height *= 2;
00932             break;
00933         case RESIZE_100:
00934         default:
00935             break;
00936     }
00937     fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN);
00938     ResizeTo(width, height);
00939 }
00940 
00941 /*****************************************************************************
00942  * VideoWindow::_SetToSettings
00943  *****************************************************************************/
00944 void
00945 VideoWindow::_SetToSettings()
00946 {
00947     // adjust dimensions
00948     uint32_t mode = RESIZE_100;
00949     switch (fSettings->VideoSize())
00950     {
00951         case VideoSettings::SIZE_50:
00952             mode = RESIZE_50;
00953             break;
00954         case VideoSettings::SIZE_200:
00955             mode = RESIZE_200;
00956             break;
00957         case VideoSettings::SIZE_100:
00958         case VideoSettings::SIZE_OTHER:
00959         default:
00960             break;
00961     }
00962     bool fullscreen = IsFullScreen();    // remember settings
00963     _SetVideoSize(mode);                // because this will reset settings
00964     // the fullscreen status is reflected in the settings,
00965     // but not yet in the windows state
00966     if (fullscreen)
00967         SetFullScreen(true);
00968     if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL))
00969         fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL;
00970     else
00971         fCachedFeel = B_NORMAL_WINDOW_FEEL;
00972     SetFeel(fCachedFeel);
00973 }
00974 
00975 /*****************************************************************************
00976  * VLCView::VLCView
00977  *****************************************************************************/
00978 VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance )
00979     : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
00980       fLastMouseMovedTime(mdate()),
00981       fCursorHidden(false),
00982       fCursorInside(false),
00983       fIgnoreDoubleClick(false)
00984 {
00985     p_vout = p_vout_instance;
00986     SetViewColor(B_TRANSPARENT_32_BIT);
00987 }
00988 
00989 /*****************************************************************************
00990  * VLCView::~VLCView
00991  *****************************************************************************/
00992 VLCView::~VLCView()
00993 {
00994 }
00995 
00996 /*****************************************************************************
00997  * VLCVIew::AttachedToWindow
00998  *****************************************************************************/
00999 void
01000 VLCView::AttachedToWindow()
01001 {
01002     // periodically check if we want to hide the pointer
01003     Window()->SetPulseRate(1000000);
01004 }
01005 
01006 /*****************************************************************************
01007  * VLCVIew::MouseDown
01008  *****************************************************************************/
01009 void
01010 VLCView::MouseDown(BPoint where)
01011 {
01012     VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
01013     BMessage* msg = Window()->CurrentMessage();
01014     int32 clicks;
01015     uint32_t buttons;
01016     msg->FindInt32("clicks", &clicks);
01017     msg->FindInt32("buttons", (int32*)&buttons);
01018 
01019     if (videoWindow)
01020     {
01021         if (buttons & B_PRIMARY_MOUSE_BUTTON)
01022         {
01023             if (clicks == 2 && !fIgnoreDoubleClick)
01024                 Window()->Zoom();
01025             /* else
01026                 videoWindow->ToggleInterfaceShowing(); */
01027             fIgnoreDoubleClick = false;
01028         }
01029         else
01030         {
01031             if (buttons & B_SECONDARY_MOUSE_BUTTON)
01032             {
01033                 // clicks will be 2 next time (if interval short enough)
01034                 // even if the first click and the second
01035                 // have not been made with the same mouse button
01036                 fIgnoreDoubleClick = true;
01037                 // launch popup menu
01038                 BPopUpMenu *menu = new BPopUpMenu("context menu");
01039                 menu->SetRadioMode(false);
01040                 // In full screen, add an item to show/hide the interface
01041                 if( videoWindow->IsFullScreen() )
01042                 {
01043                     BMenuItem *intfItem =
01044                         new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) );
01045                     menu->AddItem( intfItem );
01046                 }
01047                 // Resize to 50%
01048                 BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50));
01049                 menu->AddItem(halfItem);
01050                 // Resize to 100%
01051                 BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100));
01052                 menu->AddItem(origItem);
01053                 // Resize to 200%
01054                 BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200));
01055                 menu->AddItem(doubleItem);
01056                 // Toggle FullScreen
01057                 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
01058                 zoomItem->SetMarked(videoWindow->IsFullScreen());
01059                 menu->AddItem(zoomItem);
01060     
01061                 menu->AddSeparatorItem();
01062     
01063                 // Toggle vSync
01064                 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
01065                 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
01066                 menu->AddItem(vsyncItem);
01067                 // Correct Aspect Ratio
01068                 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
01069                 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
01070                 menu->AddItem(aspectItem);
01071     
01072                 menu->AddSeparatorItem();
01073     
01074                 // Window Feel Items
01075 /*                BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
01076                 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
01077                 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
01078                 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
01079                 menu->AddItem(normWindItem);
01080                 
01081                 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
01082                 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
01083                 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
01084                 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
01085                 menu->AddItem(onTopWindItem);
01086                 
01087                 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
01088                 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
01089                 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
01090                 allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
01091                 menu->AddItem(allSpacesWindItem);*/
01092 
01093                 BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
01094                 bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
01095                 window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
01096                 windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel );
01097                 BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg );
01098                 windowFeelItem->SetMarked( onTop );
01099                 menu->AddItem( windowFeelItem );
01100 
01101                 menu->AddSeparatorItem();
01102 
01103                 BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"),
01104                                                            new BMessage( SCREEN_SHOT ) );
01105                 menu->AddItem( screenShotItem );
01106 
01107                 menu->SetTargetForItems( this );
01108                 ConvertToScreen( &where );
01109                 BRect mouseRect( where.x - 5, where.y - 5,
01110                                  where.x + 5, where.y + 5 );
01111                 menu->Go( where, true, false, mouseRect, true );
01112             }
01113         }
01114     }
01115     fLastMouseMovedTime = mdate();
01116     fCursorHidden = false;
01117 }
01118 
01119 /*****************************************************************************
01120  * VLCVIew::MouseUp
01121  *****************************************************************************/
01122 void
01123 VLCView::MouseUp( BPoint where )
01124 {
01125     vlc_value_t val;
01126     val.b_bool = VLC_TRUE;
01127     var_Set( p_vout, "mouse-clicked", val );
01128 }
01129 
01130 /*****************************************************************************
01131  * VLCVIew::MouseMoved
01132  *****************************************************************************/
01133 void
01134 VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
01135 {
01136     fLastMouseMovedTime = mdate();
01137     fCursorHidden = false;
01138     fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW );
01139 
01140     if( !fCursorInside )
01141     {
01142         return;
01143     }
01144 
01145     vlc_value_t val;
01146     unsigned int i_width, i_height, i_x, i_y;
01147     vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(),
01148                        (unsigned int)Bounds().Height(),
01149                        &i_x, &i_y, &i_width, &i_height );
01150     val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width;
01151     var_Set( p_vout, "mouse-x", val );
01152     val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height;
01153     var_Set( p_vout, "mouse-y", val );
01154     val.b_bool = VLC_TRUE;
01155     var_Set( p_vout, "mouse-moved", val );
01156 }
01157 
01158 /*****************************************************************************
01159  * VLCVIew::Pulse
01160  *****************************************************************************/
01161 void
01162 VLCView::Pulse()
01163 {
01164     // We are getting the pulse messages no matter if the mouse is over
01165     // this view. If we are in full screen mode, we want to hide the cursor
01166     // even if it is not.
01167     VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
01168     if (!fCursorHidden)
01169     {
01170         if (fCursorInside
01171             && mdate() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
01172         {
01173             be_app->ObscureCursor();
01174             fCursorHidden = true;
01175             
01176             // hide the interface window as well if full screen
01177             if (videoWindow && videoWindow->IsFullScreen())
01178                 videoWindow->SetInterfaceShowing(false);
01179         }
01180     }
01181 
01182     // Workaround to disable the screensaver in full screen:
01183     // we simulate an activity every 29 seconds    
01184     if( videoWindow && videoWindow->IsFullScreen() &&
01185         mdate() - fLastMouseMovedTime > 29000000 )
01186     {
01187         BPoint where;
01188         uint32 buttons;
01189         GetMouse(&where, &buttons, false);
01190         ConvertToScreen(&where);
01191         set_mouse_position((int32_t) where.x, (int32_t) where.y);
01192     }
01193 }
01194 
01195 /*****************************************************************************
01196  * VLCVIew::Draw
01197  *****************************************************************************/
01198 void
01199 VLCView::Draw(BRect updateRect)
01200 {
01201     VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
01202     if ( window && window->mode == BITMAP )
01203         FillRect( updateRect );
01204 }
01205 
01206 /*****************************************************************************
01207  * Local prototypes
01208  *****************************************************************************/
01209 static int  Init       ( vout_thread_t * );
01210 static void End        ( vout_thread_t * );
01211 static int  Manage     ( vout_thread_t * );
01212 static void Display    ( vout_thread_t *, picture_t * );
01213 static int  Control    ( vout_thread_t *, int, va_list );
01214 
01215 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
01216 static void BeosCloseDisplay( vout_thread_t *p_vout );
01217 
01218 /*****************************************************************************
01219  * OpenVideo: allocates BeOS video thread output method
01220  *****************************************************************************
01221  * This function allocates and initializes a BeOS vout method.
01222  *****************************************************************************/
01223 int E_(OpenVideo) ( vlc_object_t *p_this )
01224 {
01225     vout_thread_t * p_vout = (vout_thread_t *)p_this;
01226 
01227     /* Allocate structure */
01228     p_vout->p_sys = (vout_sys_t*) malloc( sizeof( vout_sys_t ) );
01229     if( p_vout->p_sys == NULL )
01230     {
01231         msg_Err( p_vout, "out of memory" );
01232         return( 1 );
01233     }
01234     p_vout->p_sys->i_width = p_vout->render.i_width;
01235     p_vout->p_sys->i_height = p_vout->render.i_height;
01236     p_vout->p_sys->source_chroma = p_vout->render.i_chroma;
01237 
01238     p_vout->pf_init = Init;
01239     p_vout->pf_end = End;
01240     p_vout->pf_manage = Manage;
01241     p_vout->pf_render = NULL;
01242     p_vout->pf_display = Display;
01243     p_vout->pf_control = Control;
01244 
01245     return( 0 );
01246 }
01247 
01248 /*****************************************************************************
01249  * Init: initialize BeOS video thread output method
01250  *****************************************************************************/
01251 int Init( vout_thread_t *p_vout )
01252 {
01253     int i_index;
01254     picture_t *p_pic;
01255 
01256     I_OUTPUTPICTURES = 0;
01257 
01258     /* Open and initialize device */
01259     if( BeosOpenDisplay( p_vout ) )
01260     {
01261         msg_Err(p_vout, "vout error: can't open display");
01262         return 0;
01263     }
01264     p_vout->output.i_width  = p_vout->render.i_width;
01265     p_vout->output.i_height = p_vout->render.i_height;
01266 
01267     /* Assume we have square pixels */
01268     p_vout->output.i_aspect = p_vout->p_sys->i_width
01269                                * VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
01270     p_vout->output.i_chroma = colspace[p_vout->p_sys->p_window->colspace_index].chroma;
01271     p_vout->p_sys->i_index = 0;
01272 
01273     p_vout->b_direct = 1;
01274 
01275     p_vout->output.i_rmask  = 0x00ff0000;
01276     p_vout->output.i_gmask  = 0x0000ff00;
01277     p_vout->output.i_bmask  = 0x000000ff;
01278 
01279     for( int buffer_index = 0 ;
01280          buffer_index < p_vout->p_sys->p_window->bitmap_count;
01281          buffer_index++ )
01282     {
01283        p_pic = NULL;
01284        /* Find an empty picture slot */
01285        for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
01286        {
01287            p_pic = NULL;
01288            if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
01289            {
01290                p_pic = p_vout->p_picture + i_index;
01291                break;
01292            }
01293        }
01294 
01295        if( p_pic == NULL )
01296        {
01297            return 0;
01298        }
01299        p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
01300        p_pic->p->i_lines = p_vout->p_sys->i_height;
01301        p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
01302 
01303        p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
01304        p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
01305        p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow();
01306        p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 );
01307 
01308        p_pic->i_status = DESTROYED_PICTURE;
01309        p_pic->i_type   = DIRECT_PICTURE;
01310 
01311        PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
01312 
01313        I_OUTPUTPICTURES++;
01314     }
01315 
01316     return( 0 );
01317 }
01318 
01319 /*****************************************************************************
01320  * End: terminate BeOS video thread output method
01321  *****************************************************************************/
01322 void End( vout_thread_t *p_vout )
01323 {
01324     BeosCloseDisplay( p_vout );
01325 }
01326 
01327 /*****************************************************************************
01328  * Manage
01329  *****************************************************************************/
01330 static int Manage( vout_thread_t * p_vout )
01331 {
01332     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
01333     {
01334         p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN );
01335         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
01336     }
01337 
01338     return 0;
01339 }
01340 
01341 /*****************************************************************************
01342  * CloseVideo: destroy BeOS video thread output method
01343  *****************************************************************************
01344  * Terminate an output method created by DummyCreateOutputMethod
01345  *****************************************************************************/
01346 void E_(CloseVideo) ( vlc_object_t *p_this )
01347 {
01348     vout_thread_t * p_vout = (vout_thread_t *)p_this;
01349 
01350     free( p_vout->p_sys );
01351 }
01352 
01353 /*****************************************************************************
01354  * Display: displays previously rendered output
01355  *****************************************************************************
01356  * This function send the currently rendered image to BeOS image, waits until
01357  * it is displayed and switch the two rendering buffers, preparing next frame.
01358  *****************************************************************************/
01359 void Display( vout_thread_t *p_vout, picture_t *p_pic )
01360 {
01361     VideoWindow * p_win = p_vout->p_sys->p_window;
01362 
01363     /* draw buffer if required */
01364     if (!p_win->teardownwindow)
01365     {
01366        p_win->drawBuffer(p_vout->p_sys->i_index);
01367     }
01368     /* change buffer */
01369     p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
01370         p_vout->p_sys->p_window->bitmap_count;
01371     p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
01372 }
01373 
01374 static int Control( vout_thread_t * p_vout, int i_query, va_list args )
01375 {
01376     return vout_vaControlDefault( p_vout, i_query, args );
01377 }
01378 
01379 /* following functions are local */
01380 
01381 /*****************************************************************************
01382  * BeosOpenDisplay: open and initialize BeOS device
01383  *****************************************************************************/
01384 static int BeosOpenDisplay( vout_thread_t *p_vout )
01385 {
01386 
01387     p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1,
01388                                                p_vout->p_sys->i_height - 1,
01389                                                BRect( 20, 50,
01390                                                       20 + p_vout->i_window_width - 1,
01391                                                       50 + p_vout->i_window_height - 1 ),
01392                                                p_vout );
01393     if( p_vout->p_sys->p_window == NULL )
01394     {
01395         msg_Err( p_vout, "cannot allocate VideoWindow" );
01396         return( 1 );
01397     }
01398     else
01399     {
01400         p_vout->p_sys->p_window->Show();
01401     }
01402 
01403     return( 0 );
01404 }
01405 
01406 /*****************************************************************************
01407  * BeosDisplay: close and reset BeOS device
01408  *****************************************************************************
01409  * Returns all resources allocated by BeosOpenDisplay and restore the original
01410  * state of the device.
01411  *****************************************************************************/
01412 static void BeosCloseDisplay( vout_thread_t *p_vout )
01413 {
01414     VideoWindow * p_win = p_vout->p_sys->p_window;
01415     /* Destroy the video window */
01416     if( p_win != NULL && !p_win->teardownwindow)
01417     {
01418         p_win->Lock();
01419         p_win->teardownwindow = true;
01420         p_win->Hide();
01421         p_win->Quit();
01422     }
01423     p_win = NULL;
01424 }

Generated on Tue Dec 20 10:14:38 2005 for vlc-0.8.4a by  doxygen 1.4.2