]> git.sesse.net Git - vlc/blobdiff - modules/gui/beos/VideoOutput.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / beos / VideoOutput.cpp
index 0e6f9034d1adecef438f5b9688f627cd2838b00a..24a30010345e48f2d550c031d9a83c428b6f3a8e 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * vout_beos.cpp: beos video output display method
  *****************************************************************************
- * Copyright (C) 2000, 2001 VideoLAN
+ * Copyright (C) 2000, 2001 the VideoLAN team
  * $Id$
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 #include <errno.h>                                                 /* ENOMEM */
-#include <stdlib.h>                                                /* free() */
-#include <stdio.h>
-#include <string.h>                                            /* strerror() */
 
 #include <Application.h>
 #include <BitmapStream.h>
@@ -47,8 +44,8 @@
 
 /* VLC headers */
 #include <vlc/vlc.h>
-#include <vlc/intf.h>
-#include <vlc/vout.h>
+#include <vlc_interface.h>
+#include <vlc_vout.h>
 #include <vlc_keys.h>
 
 #include "InterfaceWindow.h"    // for load/save_settings()
@@ -78,8 +75,6 @@ struct vout_sys_t
 
 #define MOUSE_IDLE_TIMEOUT 2000000    // two seconds
 #define MIN_AUTO_VSYNC_REFRESH 61    // Hz
-#define DEFAULT_SCREEN_SHOT_FORMAT 'PNG '
-#define DEFAULT_SCREEN_SHOT_PATH "/boot/home/vlc screenshot"
 
 /*****************************************************************************
  * beos_GetAppWindow : retrieve a BWindow pointer from the window name
@@ -334,7 +329,7 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
     {
        overlay_restrictions r;
 
-       bitmap[1]->GetOverlayRestrictions(&r);
+       bitmap[0]->GetOverlayRestrictions(&r);
        SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
                      (i_height * r.min_height_scale), i_height * r.max_height_scale);
     }
@@ -343,12 +338,6 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame,
     if (config_GetInt(p_vout, "fullscreen"))
         fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN);
 
-    // add a few useful shortcuts
-    // XXX works only with US keymap
-    AddShortcut( '1', 0, new BMessage( RESIZE_50 ) );
-    AddShortcut( '2', 0, new BMessage( RESIZE_100 ) );
-    AddShortcut( '3', 0, new BMessage( RESIZE_200 ) );
-
     _SetToSettings();
 }
 
@@ -403,62 +392,82 @@ VideoWindow::MessageReceived( BMessage *p_message )
         case ASPECT_CORRECT:
             SetCorrectAspectRatio(!CorrectAspectRatio());
             break;
-        case SCREEN_SHOT:
-            // save a screen shot
-            if ( BBitmap* current = bitmap[i_buffer] )
+
+        case B_KEY_DOWN:
+        case B_UNMAPPED_KEY_DOWN:
+        case B_KEY_UP:
+        case B_UNMAPPED_KEY_UP:
+        {
+            key_map * keys;
+            char    * chars;
+            int32     key, modifiers;
+
+            if( p_message->FindInt32( "key", &key ) != B_OK ||
+                p_message->FindInt32( "modifiers", &modifiers ) != B_OK )
             {
-// the following line might be tempting, but does not work for some overlay bitmaps!!!
-//                BBitmap* temp = new BBitmap( current );
-// so we clone the bitmap ourselves
-// however, we need to take care of potentially different padding!
-// memcpy() is slow when reading from grafix memory, but what the heck...
-                BBitmap* temp = new BBitmap( current->Bounds(), current->ColorSpace() );
-                if ( temp && temp->IsValid() )
-                {
-                    int32_t height = (int32_t)current->Bounds().Height();
-                    uint8_t* dst = (uint8_t*)temp->Bits();
-                    uint8_t* src = (uint8_t*)current->Bits();
-                    int32_t dstBpr = temp->BytesPerRow();
-                    int32_t srcBpr = current->BytesPerRow();
-                    int32_t validBytes = dstBpr > srcBpr ? srcBpr : dstBpr;
-                    for ( int32_t y = 0; y < height; y++ )
-                    {
-                        memcpy( dst, src, validBytes );
-                        dst += dstBpr;
-                        src += srcBpr;
-                    }
-                    char * path = config_GetPsz( p_vout, "beos-screenshotpath" );
-                    if ( !path )
-                        path = strdup( DEFAULT_SCREEN_SHOT_PATH );
-                    
-                    /* FIXME - we should check which translators are
-                       actually available */
-                    char * psz_format = config_GetPsz( p_vout, "beos-screenshotformat" );
-                    int32_t format = DEFAULT_SCREEN_SHOT_FORMAT;
-                    if( !strcmp( psz_format, "TGA" ) )
-                        format = 'TGA ';
-                    else if( !strcmp( psz_format, "PPM" ) )
-                        format = 'PPM ';
-                    else if( !strcmp( psz_format, "JPEG" ) )
-                        format = 'JPEG';
-                    else if( !strcmp( psz_format, "BMP" ) )
-                        format = 'BMP ';
-
-                    _SaveScreenShot( temp, path, format );
-                }
+                /* Shouldn't happen */
+                break;
+            }
+
+            if( ( p_message->what == B_KEY_UP ||
+                  p_message->what == B_UNMAPPED_KEY_UP ) &&
+                !( modifiers & B_COMMAND_KEY ) )
+            {
+                /* We only use the KEY_UP messages to detect Alt+X
+                   shortcuts (because the KEY_DOWN messages aren't
+                   sent when Alt is pressed) */
+                break;
+            }
+
+            /* Special case for Alt+1, Alt+2 and Alt+3 shortcuts: since
+               the character depends on the keymap, we use the key codes
+               directly (18, 19, 20) */
+            if( ( modifiers & B_COMMAND_KEY ) &&
+                key >= 18 && key <= 20 )
+            {
+                if( key == 18 )
+                    PostMessage( RESIZE_50 );
+                else if( key == 19 )
+                    PostMessage( RESIZE_100 );
                 else
-                {
-                    delete temp;
-                }
+                    PostMessage( RESIZE_200 );
+
+                break;
             }
-            break;
-        case SHORTCUT:
-        {
+
+            /* Get the current keymap */
+            get_key_map( &keys, &chars );
+
+            if( key >= 128 || chars[keys->normal_map[key]] != 1 )
+            {
+                /* Weird key or Unicode character */
+                free( keys );
+                free( chars );
+                break;
+            }
+
             vlc_value_t val;
-            p_message->FindInt32( "key", (int32*) &val.i_int );
-            var_Set( p_vout->p_vlc, "key-pressed", val );
+            val.i_int = ConvertKeyToVLC( chars[keys->normal_map[key]+1] );
+
+            if( modifiers & B_COMMAND_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_ALT;
+            }
+            if( modifiers & B_SHIFT_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_SHIFT;
+            }
+            if( modifiers & B_CONTROL_KEY )
+            {
+                val.i_int |= KEY_MODIFIER_CTRL;
+            }
+            var_Set( p_vout->p_libvlc, "key-pressed", val );
+
+            free( keys );
+            free( chars );
             break;
         }
+
         default:
             BWindow::MessageReceived( p_message );
             break;
@@ -717,62 +726,84 @@ VideoWindow::_AllocateBuffers(int width, int height, int* mode)
     _FreeBuffers();
     // set default mode
     *mode = BITMAP;
+    bitmap_count = 3;
 
     BRect bitmapFrame( 0, 0, width, height );
     // read from config, if we are supposed to use overlay at all
     int noOverlay = !config_GetInt( p_vout, "overlay" );
-    // test for overlay capability
-    for (int i = 0; i < COLOR_COUNT; i++)
+
+    /* Test for overlay capability: for every chroma in colspace,
+       we try to do double-buffered overlay, single-buffered overlay
+       or basic overlay. If nothing worked, we then have to work with
+       a non-overlay BBitmap. */
+    for( int i = 0; i < COLOR_COUNT; i++ )
     {
-        if (noOverlay) break;
-        bitmap[0] = new BBitmap ( bitmapFrame,
-                                  B_BITMAP_WILL_OVERLAY |
-                                  B_BITMAP_RESERVE_OVERLAY_CHANNEL,
-                                  colspace[i].colspace);
+        if( noOverlay )
+            break;
 
-        if(bitmap[0] && bitmap[0]->InitCheck() == B_OK)
+        bitmap[0] = new BBitmap( bitmapFrame,
+                                 B_BITMAP_WILL_OVERLAY |
+                                 B_BITMAP_RESERVE_OVERLAY_CHANNEL,
+                                 colspace[i].colspace );
+        if( bitmap[0] && bitmap[0]->InitCheck() == B_OK )
         {
             colspace_index = i;
 
+            *mode = OVERLAY;
+            rgb_color key;
+            view->SetViewOverlay( bitmap[0], bitmap[0]->Bounds(),
+                                  view->Bounds(), &key, B_FOLLOW_ALL,
+                                  B_OVERLAY_FILTER_HORIZONTAL |
+                                  B_OVERLAY_FILTER_VERTICAL );
+            view->SetViewColor( key );
+            SetTitle( "VLC " PACKAGE_VERSION " (Overlay)" );
+
             bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
                                      colspace[colspace_index].colspace);
-            bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
-                                     colspace[colspace_index].colspace);
-            if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
+            if( bitmap[1] && bitmap[1]->InitCheck() == B_OK )
             {
-               *mode = OVERLAY;
-               rgb_color key;
-               view->SetViewOverlay(bitmap[0],
-                                    bitmap[0]->Bounds() ,
-                                    view->Bounds(),
-                                    &key, B_FOLLOW_ALL,
-                                    B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL);
-               view->SetViewColor(key);
-               SetTitle("VLC " PACKAGE_VERSION " (Overlay)");
-               break;
+
+                bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
+                                         colspace[colspace_index].colspace);
+                if( bitmap[2] && bitmap[2]->InitCheck() == B_OK )
+                {
+                    msg_Dbg( p_vout, "using double-buffered overlay" );
+                }
+                else
+                {
+                    msg_Dbg( p_vout, "using single-buffered overlay" );
+                    bitmap_count = 2;
+                    if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
+                }
             }
             else
             {
-               _FreeBuffers();
-               *mode = BITMAP; // might want to try again with normal bitmaps
+                msg_Dbg( p_vout, "using simple overlay" );
+                bitmap_count = 1;
+                if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
             }
+            break;
         }
         else
-            delete bitmap[0];
+        {
+            if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
+        }
     }
 
     if (*mode == BITMAP)
     {
+        msg_Warn( p_vout, "no possible overlay" );
+
         // fallback to RGB
         colspace_index = DEFAULT_COL;    // B_RGB32
-        SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
         bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
         bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
         bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
+        SetTitle( "VLC " PACKAGE_VERSION " (Bitmap)" );
     }
     // see if everything went well
     status_t status = B_ERROR;
-    for (int32_t i = 0; i < 3; i++)
+    for (int32_t i = 0; i < bitmap_count; i++)
     {
         if (bitmap[i])
             status = bitmap[i]->InitCheck();
@@ -782,7 +813,7 @@ VideoWindow::_AllocateBuffers(int width, int height, int* mode)
     if (status >= B_OK)
     {
         // clear bitmaps to black
-        for (int32_t i = 0; i < 3; i++)
+        for (int32_t i = 0; i < bitmap_count; i++)
             _BlankBitmap(bitmap[i]);
     }
     return status;
@@ -794,12 +825,9 @@ VideoWindow::_AllocateBuffers(int width, int height, int* mode)
 void
 VideoWindow::_FreeBuffers()
 {
-    delete bitmap[0];
-    bitmap[0] = NULL;
-    delete bitmap[1];
-    bitmap[1] = NULL;
-    delete bitmap[2];
-    bitmap[2] = NULL;
+    if( bitmap[0] ) { delete bitmap[0]; bitmap[0] = NULL; }
+    if( bitmap[1] ) { delete bitmap[1]; bitmap[1] = NULL; }
+    if( bitmap[2] ) { delete bitmap[2]; bitmap[2] = NULL; }
     fInitStatus = B_ERROR;
 }
 
@@ -941,180 +969,6 @@ VideoWindow::_SetToSettings()
     SetFeel(fCachedFeel);
 }
 
-/*****************************************************************************
- * VideoWindow::_SaveScreenShot
- *****************************************************************************/
-void
-VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path,
-                          uint32_t translatorID ) const
-{
-    // make the info object from the parameters
-    screen_shot_info* info = new screen_shot_info;
-    info->bitmap = bitmap;
-    info->path = path;
-    info->translatorID = translatorID;
-    info->width = CorrectAspectRatio() ? i_width : fTrueWidth;
-    info->height = CorrectAspectRatio() ? i_height : fTrueHeight;
-    // spawn a new thread to take care of the actual saving to disk
-    thread_id thread = spawn_thread( _save_screen_shot,
-                                     "screen shot saver",
-                                     B_LOW_PRIORITY, (void*)info );
-    // start thread or do the job ourself if something went wrong
-    if ( thread < B_OK || resume_thread( thread ) < B_OK )
-        _save_screen_shot( (void*)info );
-}
-
-/*****************************************************************************
- * VideoWindow::_save_screen_shot
- *****************************************************************************/
-int32
-VideoWindow::_save_screen_shot( void* cookie )
-{
-    screen_shot_info* info = (screen_shot_info*)cookie;
-    if ( info && info->bitmap && info->bitmap->IsValid() && info->path )
-    {
-        // try to be as quick as possible creating the file (the user might have
-        // taken the next screen shot already!)
-        // make sure we have a unique name for the screen shot
-        BString path( info->path );
-        // create the folder if it doesn't exist
-        BString folder( info->path );
-        create_directory( folder.String(), 0777 );
-        path << "/vlc screenshot";
-        BEntry entry( path.String() );
-        int32_t appendedNumber = 0;
-        if ( entry.Exists() && !entry.IsSymLink() )
-        {
-            // we would clobber an existing entry
-            bool foundUniqueName = false;
-            appendedNumber = 1;
-            while ( !foundUniqueName ) {
-                BString newName( path.String() );
-                newName << " " << appendedNumber;
-                BEntry possiblyClobberedEntry( newName.String() );
-                if ( possiblyClobberedEntry.Exists()
-                    && !possiblyClobberedEntry.IsSymLink() )
-                    appendedNumber++;
-                else
-                    foundUniqueName = true;
-            }
-        }
-        if ( appendedNumber > 0 )
-            path << " " << appendedNumber;
-        // there is still a slight chance to clobber an existing
-        // file (if it was created in the "meantime"), but we take it...
-        BFile outFile( path.String(),
-                       B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE );
-
-        // make colorspace converted copy of bitmap
-        BBitmap* converted = new BBitmap( BRect( 0.0, 0.0, info->width, info->height ),
-                                          B_RGB32 );
-        status_t status = convert_bitmap( info->bitmap, converted );
-        if ( status == B_OK )
-        {
-            BTranslatorRoster* roster = BTranslatorRoster::Default();
-            uint32_t imageFormat = 0;
-            translator_id translator = 0;
-            bool found = false;
-
-            // find suitable translator
-            translator_id* ids = NULL;
-            int32 count = 0;
-        
-            status = roster->GetAllTranslators( &ids, &count );
-            if ( status >= B_OK )
-            {
-                for ( int tix = 0; tix < count; tix++ )
-                {
-                    const translation_format *formats = NULL;
-                    int32 num_formats = 0;
-                    bool ok = false;
-                    status = roster->GetInputFormats( ids[tix],
-                                                      &formats, &num_formats );
-                    if (status >= B_OK)
-                    {
-                        for ( int iix = 0; iix < num_formats; iix++ )
-                        {
-                            if ( formats[iix].type == B_TRANSLATOR_BITMAP )
-                            {
-                                ok = true;
-                                break;
-                            }
-                        }
-                    }
-                    if ( !ok )
-                        continue;
-                    status = roster->GetOutputFormats( ids[tix],
-                                                       &formats, &num_formats);
-                    if ( status >= B_OK )
-                    {
-                        for ( int32_t oix = 0; oix < num_formats; oix++ )
-                        {
-                             if ( formats[oix].type != B_TRANSLATOR_BITMAP )
-                             {
-                                 if ( formats[oix].type == info->translatorID )
-                                 {
-                                     found = true;
-                                     imageFormat = formats[oix].type;
-                                     translator = ids[tix];
-                                     break;
-                                 }
-                             }
-                        }
-                    }
-                }
-            }
-            delete[] ids;
-            if ( found )
-            {
-                // make bitmap stream
-                BBitmapStream outStream( converted );
-
-                status = outFile.InitCheck();
-                if (status == B_OK) {
-                    status = roster->Translate( &outStream, NULL, NULL,
-                                                &outFile, imageFormat );
-                    if ( status == B_OK )
-                    {
-                        BNodeInfo nodeInfo( &outFile );
-                        if ( nodeInfo.InitCheck() == B_OK )
-                        {
-                            translation_format* formats;
-                            int32 count;
-                            status = roster->GetOutputFormats( translator,
-                                                               (const translation_format **) &formats,
-                                                               &count);
-                            if ( status >= B_OK )
-                            {
-                                const char * mime = NULL;
-                                for ( int ix = 0; ix < count; ix++ ) {
-                                    if ( formats[ix].type == imageFormat ) {
-                                        mime = formats[ix].MIME;
-                                        break;
-                                    }
-                                }
-                                if ( mime )
-                                    nodeInfo.SetType( mime );
-                            }
-                        }
-                    }
-                }
-                outStream.DetachBitmap( &converted );
-                outFile.Unset();
-            }
-        }
-        delete converted;
-    }
-    if ( info )
-    {
-        delete info->bitmap;
-        free( info->path );
-    }
-    delete info;
-    return B_OK;
-}
-
-
 /*****************************************************************************
  * VLCView::VLCView
  *****************************************************************************/
@@ -1142,8 +996,6 @@ VLCView::~VLCView()
 void
 VLCView::AttachedToWindow()
 {
-    // in order to get keyboard events
-    MakeFocus(true);
     // periodically check if we want to hide the pointer
     Window()->SetPulseRate(1000000);
 }
@@ -1202,9 +1054,9 @@ VLCView::MouseDown(BPoint where)
                 BMenuItem *zoomItem = new BMenuItem(_("Fullscreen"), new BMessage(TOGGLE_FULL_SCREEN));
                 zoomItem->SetMarked(videoWindow->IsFullScreen());
                 menu->AddItem(zoomItem);
-    
                 menu->AddSeparatorItem();
-    
                 // Toggle vSync
                 BMenuItem *vsyncItem = new BMenuItem(_("Vertical Sync"), new BMessage(VERT_SYNC));
                 vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace());
@@ -1213,22 +1065,22 @@ VLCView::MouseDown(BPoint where)
                 BMenuItem *aspectItem = new BMenuItem(_("Correct Aspect Ratio"), new BMessage(ASPECT_CORRECT));
                 aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
                 menu->AddItem(aspectItem);
-    
                 menu->AddSeparatorItem();
-    
                 // Window Feel Items
 /*                BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
                 winNormFeel->AddInt32("WinFeel", (int32_t)B_NORMAL_WINDOW_FEEL);
                 BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
                 normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
                 menu->AddItem(normWindItem);
-                
                 BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
                 winFloatFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_APP_WINDOW_FEEL);
                 BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
                 onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
                 menu->AddItem(onTopWindItem);
-                
                 BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
                 winAllFeel->AddInt32("WinFeel", (int32_t)B_FLOATING_ALL_WINDOW_FEEL);
                 BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
@@ -1317,7 +1169,7 @@ VLCView::Pulse()
         {
             be_app->ObscureCursor();
             fCursorHidden = true;
-            
             // hide the interface window as well if full screen
             if (videoWindow && videoWindow->IsFullScreen())
                 videoWindow->SetInterfaceShowing(false);
@@ -1325,7 +1177,7 @@ VLCView::Pulse()
     }
 
     // Workaround to disable the screensaver in full screen:
-    // we simulate an activity every 29 seconds    
+    // we simulate an activity every 29 seconds
     if( videoWindow && videoWindow->IsFullScreen() &&
         mdate() - fLastMouseMovedTime > 29000000 )
     {
@@ -1337,35 +1189,6 @@ VLCView::Pulse()
     }
 }
 
-/*****************************************************************************
- * VLCVIew::KeyUp
- *****************************************************************************/
-void VLCView::KeyUp( const char *bytes, int32 numBytes )
-{
-    if( numBytes < 1 )
-    {
-        return;
-    }
-
-    uint32_t mods = modifiers();
-
-    vlc_value_t val;
-    val.i_int = ConvertKeyToVLC( *bytes );
-    if( mods & B_COMMAND_KEY )
-    {
-        val.i_int |= KEY_MODIFIER_ALT;
-    }
-    if( mods & B_SHIFT_KEY )
-    {
-        val.i_int |= KEY_MODIFIER_SHIFT;
-    }
-    if( mods & B_CONTROL_KEY )
-    {
-        val.i_int |= KEY_MODIFIER_CTRL;
-    }
-    var_Set( p_vout->p_vlc, "key-pressed", val );
-}
-
 /*****************************************************************************
  * VLCVIew::Draw
  *****************************************************************************/
@@ -1384,6 +1207,7 @@ static int  Init       ( vout_thread_t * );
 static void End        ( vout_thread_t * );
 static int  Manage     ( vout_thread_t * );
 static void Display    ( vout_thread_t *, picture_t * );
+static int  Control    ( vout_thread_t *, int, va_list );
 
 static int  BeosOpenDisplay ( vout_thread_t *p_vout );
 static void BeosCloseDisplay( vout_thread_t *p_vout );
@@ -1413,6 +1237,7 @@ int E_(OpenVideo) ( vlc_object_t *p_this )
     p_vout->pf_manage = Manage;
     p_vout->pf_render = NULL;
     p_vout->pf_display = Display;
+    p_vout->pf_control = Control;
 
     return( 0 );
 }
@@ -1448,7 +1273,9 @@ int Init( vout_thread_t *p_vout )
     p_vout->output.i_gmask  = 0x0000ff00;
     p_vout->output.i_bmask  = 0x000000ff;
 
-    for (int buffer_index = 0 ; buffer_index < 3; buffer_index++)
+    for( int buffer_index = 0 ;
+         buffer_index < p_vout->p_sys->p_window->bitmap_count;
+         buffer_index++ )
     {
        p_pic = NULL;
        /* Find an empty picture slot */
@@ -1468,6 +1295,7 @@ int Init( vout_thread_t *p_vout )
        }
        p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits();
        p_pic->p->i_lines = p_vout->p_sys->i_height;
+       p_pic->p->i_visible_lines = p_vout->p_sys->i_height;
 
        p_pic->p->i_pixel_pitch = colspace[p_vout->p_sys->p_window->colspace_index].pixel_bytes;
        p_pic->i_planes = colspace[p_vout->p_sys->p_window->colspace_index].planes;
@@ -1535,10 +1363,16 @@ void Display( vout_thread_t *p_vout, picture_t *p_pic )
        p_win->drawBuffer(p_vout->p_sys->i_index);
     }
     /* change buffer */
-    p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
+    p_vout->p_sys->i_index = ++p_vout->p_sys->i_index %
+        p_vout->p_sys->p_window->bitmap_count;
     p_pic->p->p_pixels = (uint8_t*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
 }
 
+static int Control( vout_thread_t * p_vout, int i_query, va_list args )
+{
+    return vout_vaControlDefault( p_vout, i_query, args );
+}
+
 /* following functions are local */
 
 /*****************************************************************************