X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fbeos%2FVideoOutput.cpp;h=c8fcfc239a40914a567b5514c8cb597b3d29a689;hb=c361066fb94ae32ee2c94af3ad1ea06cd6c4d742;hp=384c732632f775fbca2b8f6bd20f1d3a86224761;hpb=7c80c87d871fa6d57aab75926a8e9a253465793e;p=vlc diff --git a/modules/gui/beos/VideoOutput.cpp b/modules/gui/beos/VideoOutput.cpp index 384c732632..c8fcfc239a 100644 --- a/modules/gui/beos/VideoOutput.cpp +++ b/modules/gui/beos/VideoOutput.cpp @@ -2,7 +2,7 @@ * vout_beos.cpp: beos video output display method ***************************************************************************** * Copyright (C) 2000, 2001 VideoLAN - * $Id: VideoOutput.cpp,v 1.8 2002/12/04 06:23:08 titer Exp $ + * $Id$ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -14,7 +14,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -36,22 +36,27 @@ #include #include #include +#include #include #include #include #include #include #include +#include /* VLC headers */ #include #include #include +#include -#include "VideoWindow.h" +#include "InterfaceWindow.h" // for load/save_settings() #include "DrawingTidbits.h" #include "MsgVals.h" +#include "VideoWindow.h" + /***************************************************************************** * vout_sys_t: BeOS video output method descriptor ***************************************************************************** @@ -62,17 +67,17 @@ struct vout_sys_t { VideoWindow * p_window; - s32 i_width; - s32 i_height; + int32_t i_width; + int32_t i_height; -// u8 *pp_buffer[3]; - u32 source_chroma; +// uint8_t *pp_buffer[3]; + uint32_t source_chroma; int i_index; }; -#define MOUSE_IDLE_TIMEOUT 2000000 // two seconds -#define MIN_AUTO_VSYNC_REFRESH 61 // Hz +#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" @@ -82,9 +87,9 @@ struct vout_sys_t BWindow* beos_GetAppWindow(char *name) { - int32 index; + int32_t index; BWindow *window; - + for (index = 0 ; ; index++) { window = be_app->WindowAt(index); @@ -100,7 +105,60 @@ beos_GetAppWindow(char *name) window->Unlock(); } } - return window; + return window; +} + +static const int beos_keys[][2] = +{ + { B_LEFT_ARROW, KEY_LEFT }, + { B_RIGHT_ARROW, KEY_RIGHT }, + { B_UP_ARROW, KEY_UP }, + { B_DOWN_ARROW, KEY_DOWN }, + { B_SPACE, KEY_SPACE }, + { B_ENTER, KEY_ENTER }, + { B_F1_KEY, KEY_F1 }, + { B_F2_KEY, KEY_F2 }, + { B_F3_KEY, KEY_F3 }, + { B_F4_KEY, KEY_F4 }, + { B_F5_KEY, KEY_F5 }, + { B_F6_KEY, KEY_F6 }, + { B_F7_KEY, KEY_F7 }, + { B_F8_KEY, KEY_F8 }, + { B_F9_KEY, KEY_F9 }, + { B_F10_KEY, KEY_F10 }, + { B_F11_KEY, KEY_F11 }, + { B_F12_KEY, KEY_F12 }, + { B_HOME, KEY_HOME }, + { B_END, KEY_END }, + { B_ESCAPE, KEY_ESC }, + { B_PAGE_UP, KEY_PAGEUP }, + { B_PAGE_DOWN, KEY_PAGEDOWN }, + { B_TAB, KEY_TAB }, + { B_BACKSPACE, KEY_BACKSPACE } +}; + +static int ConvertKeyFromVLC( int key ) +{ + for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ ) + { + if( beos_keys[i][1] == key ) + { + return beos_keys[i][0]; + } + } + return key; +} + +static int ConvertKeyToVLC( int key ) +{ + for( unsigned i = 0; i < sizeof( beos_keys ) / sizeof( int ) / 2; i++ ) + { + if( beos_keys[i][0] == key ) + { + return beos_keys[i][1]; + } + } + return key; } /***************************************************************************** @@ -109,90 +167,167 @@ beos_GetAppWindow(char *name) BWindow* get_interface_window() { - return beos_GetAppWindow(VOUT_TITLE); + return beos_GetAppWindow( "VLC " PACKAGE_VERSION ); } class BackgroundView : public BView { public: - BackgroundView(BRect frame, VLCView* view) - : BView(frame, "background", - B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE), - fVideoView(view) - { - SetViewColor(kBlack); - } - virtual ~BackgroundView() {} - - virtual void MouseDown(BPoint where) - { - // convert coordinates - where = fVideoView->ConvertFromParent(where); - // let him handle it - fVideoView->MouseDown(where); - } - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) - { - // convert coordinates - where = fVideoView->ConvertFromParent(where); - // let him handle it - fVideoView->MouseMoved(where, transit, dragMessage); - // notice: It might look like transit should be - // B_OUTSIDE_VIEW regardless, but leave it like this, - // otherwise, unwanted things will happen! - } + BackgroundView(BRect frame, VLCView* view) + : BView(frame, "background", + B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE), + fVideoView(view) + { + SetViewColor(kBlack); + } + virtual ~BackgroundView() {} + + virtual void MouseDown(BPoint where) + { + // convert coordinates + where = fVideoView->ConvertFromParent(where); + // let him handle it + fVideoView->MouseDown(where); + } + virtual void MouseMoved(BPoint where, uint32_t transit, + const BMessage* dragMessage) + { + // convert coordinates + where = fVideoView->ConvertFromParent(where); + // let him handle it + fVideoView->MouseMoved(where, transit, dragMessage); + // notice: It might look like transit should be + // B_OUTSIDE_VIEW regardless, but leave it like this, + // otherwise, unwanted things will happen! + } private: - VLCView* fVideoView; + VLCView* fVideoView; }; + +/***************************************************************************** + * VideoSettings constructor and destructor + *****************************************************************************/ +VideoSettings::VideoSettings() + : fVideoSize( SIZE_100 ), + fFlags( FLAG_CORRECT_RATIO ), + fSettings( new BMessage( 'sett' ) ) +{ + // read settings from disk + status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" ); + if ( ret == B_OK ) + { + uint32_t flags; + if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK ) + SetFlags( flags ); + uint32_t size; + if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK ) + SetVideoSize( size ); + } + else + { + // figure out if we should use vertical sync by default + BScreen screen(B_MAIN_SCREEN_ID); + if (screen.IsValid()) + { + display_mode mode; + screen.GetMode(&mode); + float refresh = (mode.timing.pixel_clock * 1000) + / ((mode.timing.h_total)* (mode.timing.v_total)); + if (refresh < MIN_AUTO_VSYNC_REFRESH) + AddFlags(FLAG_SYNC_RETRACE); + } + } +} + +VideoSettings::VideoSettings( const VideoSettings& clone ) + : fVideoSize( clone.VideoSize() ), + fFlags( clone.Flags() ), + fSettings( NULL ) +{ +} + + +VideoSettings::~VideoSettings() +{ + if ( fSettings ) + { + // we are the default settings + // and write our settings to disk + if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK) + fSettings->AddInt32( "video size", VideoSize() ); + if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK) + fSettings->AddInt32( "flags", Flags() ); + + save_settings( fSettings, "video_settings", "VideoLAN Client" ); + delete fSettings; + } + else + { + // we are just a clone of the default settings + fDefaultSettings.SetVideoSize( VideoSize() ); + fDefaultSettings.SetFlags( Flags() ); + } +} + +/***************************************************************************** + * VideoSettings::DefaultSettings + *****************************************************************************/ +VideoSettings* +VideoSettings::DefaultSettings() +{ + return &fDefaultSettings; +} + +/***************************************************************************** + * VideoSettings::SetVideoSize + *****************************************************************************/ +void +VideoSettings::SetVideoSize( uint32_t mode ) +{ + fVideoSize = mode; +} + +// static variable initialization +VideoSettings +VideoSettings::fDefaultSettings; + + /***************************************************************************** * VideoWindow constructor and destructor *****************************************************************************/ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame, vout_thread_t *p_videoout) - : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE), - i_width(frame.IntegerWidth()), - i_height(frame.IntegerHeight()), - is_zoomed(false), - vsync(false), - i_buffer(0), - teardownwindow(false), - fTrueWidth(v_width), - fTrueHeight(v_height), - fCorrectAspect(true), - fCachedFeel(B_NORMAL_WINDOW_FEEL), - fInterfaceShowing(false), - fInitStatus(B_ERROR) + : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE), + i_width(frame.IntegerWidth()), + i_height(frame.IntegerHeight()), + winSize(frame), + i_buffer(0), + teardownwindow(false), + fTrueWidth(v_width), + fTrueHeight(v_height), + fCachedFeel(B_NORMAL_WINDOW_FEEL), + fInterfaceShowing(false), + fInitStatus(B_ERROR), + fSettings(new VideoSettings(*VideoSettings::DefaultSettings())) { p_vout = p_videoout; - + // create the view to do the display view = new VLCView( Bounds(), p_vout ); - // create background view + // create background view BView *mainView = new BackgroundView( Bounds(), view ); AddChild(mainView); mainView->AddChild(view); - // figure out if we should use vertical sync by default - BScreen screen(this); - if (screen.IsValid()) - { - display_mode mode; - screen.GetMode(&mode); - float refresh = (mode.timing.pixel_clock * 1000) - / ((mode.timing.h_total)* (mode.timing.v_total)); - vsync = (refresh < MIN_AUTO_VSYNC_REFRESH); - } - - // allocate bitmap buffers - for (int32 i = 0; i < 3; i++) - bitmap[i] = NULL; - fInitStatus = _AllocateBuffers(v_width, v_height, &mode); - - // make sure we layout the view correctly + // allocate bitmap buffers + for (int32_t i = 0; i < 3; i++) + bitmap[i] = NULL; + fInitStatus = _AllocateBuffers(v_width, v_height, &mode); + + // make sure we layout the view correctly FrameResized(i_width, i_height); if (fInitStatus >= B_OK && mode == OVERLAY) @@ -203,11 +338,18 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame, 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); } - - if( config_GetInt( p_vout, "fullscreen" ) ) - { - BWindow::Zoom();; - } + + // vlc settings override settings from disk + 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(); } VideoWindow::~VideoWindow() @@ -217,6 +359,7 @@ VideoWindow::~VideoWindow() teardownwindow = true; wait_for_thread(fDrawThreadID, &result); _FreeBuffers(); + delete fSettings; } /***************************************************************************** @@ -225,73 +368,101 @@ VideoWindow::~VideoWindow() void VideoWindow::MessageReceived( BMessage *p_message ) { - switch( p_message->what ) - { - case TOGGLE_FULL_SCREEN: - BWindow::Zoom(); - break; - case RESIZE_50: - case RESIZE_100: - case RESIZE_200: - if (is_zoomed) - BWindow::Zoom(); - _SetVideoSize(p_message->what); - break; - case VERT_SYNC: - vsync = !vsync; - break; - case WINDOW_FEEL: - { - window_feel winFeel; - if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK) - { - SetFeel(winFeel); - fCachedFeel = winFeel; - } - } - break; - case ASPECT_CORRECT: - SetCorrectAspectRatio(!fCorrectAspect); - break; - case SCREEN_SHOT: - // save a screen shot - if ( BBitmap* current = bitmap[i_buffer] ) - { + switch( p_message->what ) + { + case SHOW_INTERFACE: + SetInterfaceShowing( true ); + break; + case TOGGLE_FULL_SCREEN: + BWindow::Zoom(); + break; + case RESIZE_50: + case RESIZE_100: + case RESIZE_200: + if (IsFullScreen()) + BWindow::Zoom(); + _SetVideoSize(p_message->what); + break; + case VERT_SYNC: + SetSyncToRetrace(!IsSyncedToRetrace()); + break; + case WINDOW_FEEL: + { + window_feel winFeel; + if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK) + { + SetFeel(winFeel); + fCachedFeel = winFeel; + if (winFeel == B_FLOATING_ALL_WINDOW_FEEL) + fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL); + else + fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL); + } + } + break; + case ASPECT_CORRECT: + SetCorrectAspectRatio(!CorrectAspectRatio()); + break; + case SCREEN_SHOT: + // save a screen shot + if ( BBitmap* current = bitmap[i_buffer] ) + { // the following line might be tempting, but does not work for some overlay bitmaps!!! -// BBitmap* temp = new BBitmap( current ); +// 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 height = (int32)current->Bounds().Height(); - uint8* dst = (uint8*)temp->Bits(); - uint8* src = (uint8*)current->Bits(); - int32 dstBpr = temp->BytesPerRow(); - int32 srcBpr = current->BytesPerRow(); - int32 validBytes = dstBpr > srcBpr ? srcBpr : dstBpr; - for ( int32 y = 0; y < height; y++ ) - { - memcpy( dst, src, validBytes ); - dst += dstBpr; - src += srcBpr; - } - _SaveScreenShot( temp, - strdup( DEFAULT_SCREEN_SHOT_PATH ), - DEFAULT_SCREEN_SHOT_FORMAT ); - } - else - { - delete temp; - fprintf( stderr, "error copying bitmaps\n" ); - } - } - break; - default: - BWindow::MessageReceived( p_message ); - break; - } + 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 ); + } + else + { + delete temp; + } + } + break; + case SHORTCUT: + { + vlc_value_t val; + p_message->FindInt32( "key", (int32*) &val.i_int ); + var_Set( p_vout->p_vlc, "key-pressed", val ); + break; + } + default: + BWindow::MessageReceived( p_message ); + break; + } } /***************************************************************************** @@ -300,33 +471,17 @@ VideoWindow::MessageReceived( BMessage *p_message ) void VideoWindow::Zoom(BPoint origin, float width, float height ) { - if(is_zoomed) - { - MoveTo(winSize.left, winSize.top); - ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight()); - be_app->ShowCursor(); - fInterfaceShowing = true; - } - else - { - BScreen screen(this); - BRect rect = screen.Frame(); - Activate(); - MoveTo(0.0, 0.0); - ResizeTo(rect.IntegerWidth(), rect.IntegerHeight()); - be_app->ObscureCursor(); - fInterfaceShowing = false; - } - is_zoomed = !is_zoomed; + ToggleFullScreen(); } /***************************************************************************** * VideoWindow::FrameMoved *****************************************************************************/ void -VideoWindow::FrameMoved(BPoint origin) +VideoWindow::FrameMoved(BPoint origin) { - if (is_zoomed) return ; + if (IsFullScreen()) + return ; winSize = Frame(); } @@ -336,8 +491,8 @@ VideoWindow::FrameMoved(BPoint origin) void VideoWindow::FrameResized( float width, float height ) { - int32 useWidth = fCorrectAspect ? i_width : fTrueWidth; - int32 useHeight = fCorrectAspect ? i_height : fTrueHeight; + int32_t useWidth = CorrectAspectRatio() ? i_width : fTrueWidth; + int32_t useHeight = CorrectAspectRatio() ? i_height : fTrueHeight; float out_width, out_height; float out_left, out_top; float width_scale = width / useWidth; @@ -347,7 +502,7 @@ VideoWindow::FrameResized( float width, float height ) { out_width = (useWidth * width_scale); out_height = (useHeight * width_scale); - out_left = 0; + out_left = 0; out_top = (height - out_height) / 2; } else /* if the height is proportionally smaller */ @@ -360,7 +515,7 @@ VideoWindow::FrameResized( float width, float height ) view->MoveTo(out_left,out_top); view->ResizeTo(out_width, out_height); - if (!is_zoomed) + if (!IsFullScreen()) winSize = Frame(); } @@ -370,13 +525,12 @@ VideoWindow::FrameResized( float width, float height ) void VideoWindow::ScreenChanged(BRect frame, color_space format) { - BScreen screen(this); - display_mode mode; - screen.GetMode(&mode); - float refresh = (mode.timing.pixel_clock * 1000) - / ((mode.timing.h_total) * (mode.timing.v_total)); - if (refresh < MIN_AUTO_VSYNC_REFRESH) - vsync = true; + BScreen screen(this); + display_mode mode; + screen.GetMode(&mode); + float refresh = (mode.timing.pixel_clock * 1000) + / ((mode.timing.h_total) * (mode.timing.v_total)); + SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH); } /***************************************************************************** @@ -396,7 +550,7 @@ VideoWindow::drawBuffer(int bufferIndex) i_buffer = bufferIndex; // sync to the screen if required - if (vsync) + if (IsSyncedToRetrace()) { BScreen screen(this); screen.WaitForRetrace(22000); @@ -407,14 +561,14 @@ VideoWindow::drawBuffer(int bufferIndex) if (mode == OVERLAY) { rgb_color key; - view->SetViewOverlay(bitmap[i_buffer], + view->SetViewOverlay(bitmap[i_buffer], bitmap[i_buffer]->Bounds() , view->Bounds(), &key, B_FOLLOW_ALL, - B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL| - B_OVERLAY_TRANSFER_CHANNEL); - view->SetViewColor(key); - } + B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL| + B_OVERLAY_TRANSFER_CHANNEL); + view->SetViewColor(key); + } else { // switch the bitmap @@ -430,7 +584,7 @@ VideoWindow::drawBuffer(int bufferIndex) void VideoWindow::ToggleInterfaceShowing() { - SetInterfaceShowing(!fInterfaceShowing); + SetInterfaceShowing(!fInterfaceShowing); } /***************************************************************************** @@ -439,24 +593,24 @@ VideoWindow::ToggleInterfaceShowing() void VideoWindow::SetInterfaceShowing(bool showIt) { - BWindow* window = get_interface_window(); - if (window) - { - if (showIt) - { - if (fCachedFeel != B_NORMAL_WINDOW_FEEL) - SetFeel(B_NORMAL_WINDOW_FEEL); - window->Activate(true); - SendBehind(window); - } - else - { - SetFeel(fCachedFeel); - Activate(true); - window->SendBehind(this); - } - fInterfaceShowing = showIt; - } + BWindow* window = get_interface_window(); + if (window) + { + if (showIt) + { + if (fCachedFeel != B_NORMAL_WINDOW_FEEL) + SetFeel(B_NORMAL_WINDOW_FEEL); + window->Activate(true); + SendBehind(window); + } + else + { + SetFeel(fCachedFeel); + Activate(true); + window->SendBehind(this); + } + fInterfaceShowing = showIt; + } } /***************************************************************************** @@ -465,94 +619,190 @@ VideoWindow::SetInterfaceShowing(bool showIt) void VideoWindow::SetCorrectAspectRatio(bool doIt) { - if (fCorrectAspect != doIt) - { - fCorrectAspect = doIt; - FrameResized(Bounds().Width(), Bounds().Height()); - } + if (CorrectAspectRatio() != doIt) + { + if (doIt) + fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO); + else + fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO); + FrameResized(Bounds().Width(), Bounds().Height()); + } +} + +/***************************************************************************** + * VideoWindow::CorrectAspectRatio + *****************************************************************************/ +bool +VideoWindow::CorrectAspectRatio() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO); +} + +/***************************************************************************** + * VideoWindow::ToggleFullScreen + *****************************************************************************/ +void +VideoWindow::ToggleFullScreen() +{ + SetFullScreen(!IsFullScreen()); } +/***************************************************************************** + * VideoWindow::SetFullScreen + *****************************************************************************/ +void +VideoWindow::SetFullScreen(bool doIt) +{ + if (doIt) + { + SetLook( B_NO_BORDER_WINDOW_LOOK ); + BScreen screen( this ); + BRect rect = screen.Frame(); + Activate(); + MoveTo(0.0, 0.0); + ResizeTo(rect.IntegerWidth(), rect.IntegerHeight()); + be_app->ObscureCursor(); + fInterfaceShowing = false; + fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN); + } + else + { + SetLook( B_TITLED_WINDOW_LOOK ); + MoveTo(winSize.left, winSize.top); + ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight()); + be_app->ShowCursor(); + fInterfaceShowing = true; + fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN); + } +} + +/***************************************************************************** + * VideoWindow::IsFullScreen + *****************************************************************************/ +bool +VideoWindow::IsFullScreen() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN); +} + +/***************************************************************************** + * VideoWindow::SetSyncToRetrace + *****************************************************************************/ +void +VideoWindow::SetSyncToRetrace(bool doIt) +{ + if (doIt) + fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE); + else + fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE); +} + +/***************************************************************************** + * VideoWindow::IsSyncedToRetrace + *****************************************************************************/ +bool +VideoWindow::IsSyncedToRetrace() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE); +} + + /***************************************************************************** * VideoWindow::_AllocateBuffers *****************************************************************************/ status_t VideoWindow::_AllocateBuffers(int width, int height, int* mode) { - // clear any old buffers - _FreeBuffers(); - // set default mode - *mode = BITMAP; + // clear any old buffers + _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 + 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, or we fallback on + single-buffered overlay. In 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(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; 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(VOUT_TITLE " (Overlay)"); - break; + *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[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; } + } + break; } else { - _FreeBuffers(); - *mode = BITMAP; // might want to try again with normal bitmaps + *mode = BITMAP; + _FreeBuffers(); } } else + { delete bitmap[0]; - } + } + } if (*mode == BITMAP) - { + { + msg_Warn( p_vout, "no possible overlay" ); + // fallback to RGB - colspace_index = DEFAULT_COL; // B_RGB16 -// FIXME: an error in the YUV->RGB32 module prevents this from being used! -/* BScreen screen( B_MAIN_SCREEN_ID ); - if ( screen.ColorSpace() == B_RGB32 ) - colspace_index = 3; // B_RGB32 (faster on 32 bit screen)*/ - SetTitle( VOUT_TITLE " (Bitmap)" ); + colspace_index = DEFAULT_COL; // B_RGB32 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 i = 0; i < 3; i++) + for (int32_t i = 0; i < bitmap_count; i++) { - if (bitmap[i]) - status = bitmap[i]->InitCheck(); - if (status < B_OK) - break; + if (bitmap[i]) + status = bitmap[i]->InitCheck(); + if (status < B_OK) + break; } if (status >= B_OK) { - // clear bitmaps to black - for (int32 i = 0; i < 3; i++) - _BlankBitmap(bitmap[i]); + // clear bitmaps to black + for (int32_t i = 0; i < bitmap_count; i++) + _BlankBitmap(bitmap[i]); } return status; } @@ -563,13 +813,10 @@ 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; - fInitStatus = B_ERROR; + 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; } /***************************************************************************** @@ -578,102 +825,136 @@ VideoWindow::_FreeBuffers() void VideoWindow::_BlankBitmap(BBitmap* bitmap) const { - // no error checking (we do that earlier on and since it's a private function... - - // YCbCr: - // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128) - - // YUV: - // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128) - - // we only handle weird colorspaces with special care - switch (bitmap->ColorSpace()) { - case B_YCbCr422: { - // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0] - int32 height = bitmap->Bounds().IntegerHeight() + 1; - uint8* bits = (uint8*)bitmap->Bits(); - int32 bpr = bitmap->BytesPerRow(); - for (int32 y = 0; y < height; y++) { - // handle 2 bytes at a time - for (int32 i = 0; i < bpr; i += 2) { - // offset into line - bits[i] = 16; - bits[i + 1] = 128; - } - // next line - bits += bpr; - } - break; - } - case B_YCbCr420: { + // no error checking (we do that earlier on and since it's a private function... + + // YCbCr: + // Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128) + + // YUV: + // Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128) + + // we only handle weird colorspaces with special care + switch (bitmap->ColorSpace()) { + case B_YCbCr422: { + // Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0] + int32_t height = bitmap->Bounds().IntegerHeight() + 1; + uint8_t* bits = (uint8_t*)bitmap->Bits(); + int32_t bpr = bitmap->BytesPerRow(); + for (int32_t y = 0; y < height; y++) { + // handle 2 bytes at a time + for (int32_t i = 0; i < bpr; i += 2) { + // offset into line + bits[i] = 16; + bits[i + 1] = 128; + } + // next line + bits += bpr; + } + break; + } + case B_YCbCr420: { // TODO: untested!! - // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ... - // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines - int32 height = bitmap->Bounds().IntegerHeight() + 1; - uint8* bits = (uint8*)bitmap->Bits(); - int32 bpr = bitmap->BytesPerRow(); - for (int32 y = 0; y < height; y += 1) { - // handle 3 bytes at a time - for (int32 i = 0; i < bpr; i += 3) { - // offset into line - bits[i] = 128; - bits[i + 1] = 16; - bits[i + 2] = 16; - } - // next line - bits += bpr; - } - break; - } - case B_YUV422: { + // Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ... + // Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines + int32_t height = bitmap->Bounds().IntegerHeight() + 1; + uint8_t* bits = (uint8_t*)bitmap->Bits(); + int32_t bpr = bitmap->BytesPerRow(); + for (int32_t y = 0; y < height; y += 1) { + // handle 3 bytes at a time + for (int32_t i = 0; i < bpr; i += 3) { + // offset into line + bits[i] = 128; + bits[i + 1] = 16; + bits[i + 2] = 16; + } + // next line + bits += bpr; + } + break; + } + case B_YUV422: { // TODO: untested!! - // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0] - int32 height = bitmap->Bounds().IntegerHeight() + 1; - uint8* bits = (uint8*)bitmap->Bits(); - int32 bpr = bitmap->BytesPerRow(); - for (int32 y = 0; y < height; y += 1) { - // handle 2 bytes at a time - for (int32 i = 0; i < bpr; i += 2) { - // offset into line - bits[i] = 128; - bits[i + 1] = 0; - } - // next line - bits += bpr; - } - break; - } - default: - memset(bitmap->Bits(), 0, bitmap->BitsLength()); - break; - } + // U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0] + int32_t height = bitmap->Bounds().IntegerHeight() + 1; + uint8_t* bits = (uint8_t*)bitmap->Bits(); + int32_t bpr = bitmap->BytesPerRow(); + for (int32_t y = 0; y < height; y += 1) { + // handle 2 bytes at a time + for (int32_t i = 0; i < bpr; i += 2) { + // offset into line + bits[i] = 128; + bits[i + 1] = 0; + } + // next line + bits += bpr; + } + break; + } + default: + memset(bitmap->Bits(), 0, bitmap->BitsLength()); + break; + } } /***************************************************************************** * VideoWindow::_SetVideoSize *****************************************************************************/ void -VideoWindow::_SetVideoSize(uint32 mode) +VideoWindow::_SetVideoSize(uint32_t mode) +{ + // let size depend on aspect correction + int32_t width = CorrectAspectRatio() ? i_width : fTrueWidth; + int32_t height = CorrectAspectRatio() ? i_height : fTrueHeight; + switch (mode) + { + case RESIZE_50: + width /= 2; + height /= 2; + break; + case RESIZE_200: + width *= 2; + height *= 2; + break; + case RESIZE_100: + default: + break; + } + fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN); + ResizeTo(width, height); +} + +/***************************************************************************** + * VideoWindow::_SetToSettings + *****************************************************************************/ +void +VideoWindow::_SetToSettings() { - // let size depend on aspect correction - int32 width = fCorrectAspect ? i_width : fTrueWidth; - int32 height = fCorrectAspect ? i_height : fTrueHeight; - switch (mode) - { - case RESIZE_50: - width /= 2; - height /= 2; - break; - case RESIZE_200: - width *= 2; - height *= 2; - break; - case RESIZE_100: - default: - break; - } - ResizeTo(width, height); - is_zoomed = false; + // adjust dimensions + uint32_t mode = RESIZE_100; + switch (fSettings->VideoSize()) + { + case VideoSettings::SIZE_50: + mode = RESIZE_50; + break; + case VideoSettings::SIZE_200: + mode = RESIZE_200; + break; + case VideoSettings::SIZE_100: + case VideoSettings::SIZE_OTHER: + default: + break; + } + bool fullscreen = IsFullScreen(); // remember settings + _SetVideoSize(mode); // because this will reset settings + // the fullscreen status is reflected in the settings, + // but not yet in the windows state + if (fullscreen) + SetFullScreen(true); + if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL)) + fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL; + else + fCachedFeel = B_NORMAL_WINDOW_FEEL; + SetFeel(fCachedFeel); } /***************************************************************************** @@ -681,22 +962,22 @@ VideoWindow::_SetVideoSize(uint32 mode) *****************************************************************************/ void VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path, - uint32 translatorID ) const + 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 = fCorrectAspect ? i_width : fTrueWidth; - info->height = fCorrectAspect ? 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 ); + // 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 ); } /***************************************************************************** @@ -705,157 +986,148 @@ VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path, 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 ); - BEntry entry( path.String() ); - int32 appendedNumber = 0; - if ( entry.Exists() && !entry.IsSymLink() ) - { - // we would clobber an existing entry - bool foundUniqueName = false; - appendedNumber = 1; - while ( !foundUniqueName ) { - BString newName( info->path ); - 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 ); -// if ( converted->IsValid() ) -// memset( converted->Bits(), 0, converted->BitsLength() ); - status_t status = convert_bitmap( info->bitmap, converted ); - if ( status == B_OK ) - { - BTranslatorRoster* roster = BTranslatorRoster::Default(); - uint32 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 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 ); - } - } - } else { - fprintf( stderr, " failed to write bitmap: %s\n", - strerror( status ) ); - } - } else { - fprintf( stderr, " failed to create output file: %s\n", - strerror( status ) ); - } - outStream.DetachBitmap( &converted ); - outFile.Unset(); - } - else - fprintf( stderr, " failed to find translator\n"); - } - else - fprintf( stderr, " failed to convert colorspace: %s\n", - strerror( status ) ); - delete converted; - } - if ( info ) - { - delete info->bitmap; - delete[] info->path; - } - delete info; - return B_OK; + 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; } @@ -863,11 +1135,11 @@ VideoWindow::_save_screen_shot( void* cookie ) * VLCView::VLCView *****************************************************************************/ VLCView::VLCView(BRect bounds, vout_thread_t *p_vout_instance ) - : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED), - fLastMouseMovedTime(system_time()), - fCursorHidden(false), - fCursorInside(false), - fIgnoreDoubleClick(false) + : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED), + fLastMouseMovedTime(mdate()), + fCursorHidden(false), + fCursorInside(false), + fIgnoreDoubleClick(false) { p_vout = p_vout_instance; SetViewColor(B_TRANSPARENT_32_BIT); @@ -886,10 +1158,10 @@ 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); + // in order to get keyboard events + MakeFocus(true); + // periodically check if we want to hide the pointer + Window()->SetPulseRate(1000000); } /***************************************************************************** @@ -898,102 +1170,111 @@ VLCView::AttachedToWindow() void VLCView::MouseDown(BPoint where) { - VideoWindow* videoWindow = dynamic_cast(Window()); - BMessage* msg = Window()->CurrentMessage(); - int32 clicks; - uint32 buttons; - msg->FindInt32("clicks", &clicks); - msg->FindInt32("buttons", (int32*)&buttons); - - if (videoWindow) - { - if (buttons & B_PRIMARY_MOUSE_BUTTON) - { - if (clicks == 2 && !fIgnoreDoubleClick) - Window()->Zoom(); - else - videoWindow->ToggleInterfaceShowing(); - fIgnoreDoubleClick = false; - } - else - { - if (buttons & B_SECONDARY_MOUSE_BUTTON) - { - // clicks will be 2 next time (if interval short enough) - // even if the first click and the second - // have not been made with the same mouse button - fIgnoreDoubleClick = true; - // launch popup menu - BPopUpMenu *menu = new BPopUpMenu("context menu"); - menu->SetRadioMode(false); - // Resize to 50% - BMenuItem *halfItem = new BMenuItem("50%", new BMessage(RESIZE_50)); - menu->AddItem(halfItem); - // Resize to 100% - BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100)); - menu->AddItem(origItem); - // Resize to 200% - BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200)); - menu->AddItem(doubleItem); - // Toggle FullScreen - BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN)); - zoomItem->SetMarked(videoWindow->is_zoomed); - menu->AddItem(zoomItem); - - menu->AddSeparatorItem(); - - // Toggle vSync - BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC)); - vsyncItem->SetMarked(videoWindow->vsync); - menu->AddItem(vsyncItem); - // Correct Aspect Ratio - BMenuItem *aspectItem = new BMenuItem("Correct Aspect Ratio", new BMessage(ASPECT_CORRECT)); - aspectItem->SetMarked(videoWindow->CorrectAspectRatio()); - menu->AddItem(aspectItem); - - menu->AddSeparatorItem(); - - // Windwo Feel Items -/* BMessage *winNormFeel = new BMessage(WINDOW_FEEL); - winNormFeel->AddInt32("WinFeel", (int32)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)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)B_FLOATING_ALL_WINDOW_FEEL); - BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel); - allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL); - menu->AddItem(allSpacesWindItem);*/ - - BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL ); - bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL; - window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL; - windowFeelMsg->AddInt32( "WinFeel", (int32)feel ); - BMenuItem *windowFeelItem = new BMenuItem( "Stay On Top", windowFeelMsg ); - windowFeelItem->SetMarked( onTop ); - menu->AddItem( windowFeelItem ); - - menu->AddSeparatorItem(); - - BMenuItem* screenShotItem = new BMenuItem( "Take Screen Shot", - new BMessage( SCREEN_SHOT ) ); - menu->AddItem( screenShotItem ); - - menu->SetTargetForItems( this ); - ConvertToScreen( &where ); - menu->Go( where, true, false, true ); - } - } - } - fLastMouseMovedTime = system_time(); - fCursorHidden = false; + VideoWindow* videoWindow = dynamic_cast(Window()); + BMessage* msg = Window()->CurrentMessage(); + int32 clicks; + uint32_t buttons; + msg->FindInt32("clicks", &clicks); + msg->FindInt32("buttons", (int32*)&buttons); + + if (videoWindow) + { + if (buttons & B_PRIMARY_MOUSE_BUTTON) + { + if (clicks == 2 && !fIgnoreDoubleClick) + Window()->Zoom(); + /* else + videoWindow->ToggleInterfaceShowing(); */ + fIgnoreDoubleClick = false; + } + else + { + if (buttons & B_SECONDARY_MOUSE_BUTTON) + { + // clicks will be 2 next time (if interval short enough) + // even if the first click and the second + // have not been made with the same mouse button + fIgnoreDoubleClick = true; + // launch popup menu + BPopUpMenu *menu = new BPopUpMenu("context menu"); + menu->SetRadioMode(false); + // In full screen, add an item to show/hide the interface + if( videoWindow->IsFullScreen() ) + { + BMenuItem *intfItem = + new BMenuItem( _("Show Interface"), new BMessage(SHOW_INTERFACE) ); + menu->AddItem( intfItem ); + } + // Resize to 50% + BMenuItem *halfItem = new BMenuItem(_("50%"), new BMessage(RESIZE_50)); + menu->AddItem(halfItem); + // Resize to 100% + BMenuItem *origItem = new BMenuItem(_("100%"), new BMessage(RESIZE_100)); + menu->AddItem(origItem); + // Resize to 200% + BMenuItem *doubleItem = new BMenuItem(_("200%"), new BMessage(RESIZE_200)); + menu->AddItem(doubleItem); + // Toggle FullScreen + 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()); + menu->AddItem(vsyncItem); + // Correct Aspect Ratio + 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); + allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL); + menu->AddItem(allSpacesWindItem);*/ + + BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL ); + bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL; + window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL; + windowFeelMsg->AddInt32( "WinFeel", (int32_t)feel ); + BMenuItem *windowFeelItem = new BMenuItem( _("Stay On Top"), windowFeelMsg ); + windowFeelItem->SetMarked( onTop ); + menu->AddItem( windowFeelItem ); + + menu->AddSeparatorItem(); + + BMenuItem* screenShotItem = new BMenuItem( _("Take Screen Shot"), + new BMessage( SCREEN_SHOT ) ); + menu->AddItem( screenShotItem ); + + menu->SetTargetForItems( this ); + ConvertToScreen( &where ); + BRect mouseRect( where.x - 5, where.y - 5, + where.x + 5, where.y + 5 ); + menu->Go( where, true, false, mouseRect, true ); + } + } + } + fLastMouseMovedTime = mdate(); + fCursorHidden = false; } /***************************************************************************** @@ -1013,125 +1294,103 @@ VLCView::MouseUp( BPoint where ) void VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage) { - fLastMouseMovedTime = system_time(); - fCursorHidden = false; - fCursorInside = (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW); - /* DVD navigation */ - unsigned int i_width, i_height, i_x, i_y; + fLastMouseMovedTime = mdate(); + fCursorHidden = false; + fCursorInside = ( transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW ); + + if( !fCursorInside ) + { + return; + } + + vlc_value_t val; + unsigned int i_width, i_height, i_x, i_y; vout_PlacePicture( p_vout, (unsigned int)Bounds().Width(), (unsigned int)Bounds().Height(), &i_x, &i_y, &i_width, &i_height ); - vlc_value_t val; - val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width; - var_Set( p_vout, "mouse-x", val ); - val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height; - var_Set( p_vout, "mouse-y", val ); - val.b_bool = VLC_TRUE; + val.i_int = ( (int)point.x - i_x ) * p_vout->render.i_width / i_width; + var_Set( p_vout, "mouse-x", val ); + val.i_int = ( (int)point.y - i_y ) * p_vout->render.i_height / i_height; + var_Set( p_vout, "mouse-y", val ); + val.b_bool = VLC_TRUE; var_Set( p_vout, "mouse-moved", val ); } /***************************************************************************** * VLCVIew::Pulse *****************************************************************************/ -void +void VLCView::Pulse() { - // We are getting the pulse messages no matter if the mouse is over - // this view. If we are in full screen mode, we want to hide the cursor - // even if it is not. - if (!fCursorHidden) - { - if (fCursorInside - && system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT) - { - be_app->ObscureCursor(); - fCursorHidden = true; - VideoWindow *videoWindow = dynamic_cast(Window()); - // hide the interface window as well if full screen - if (videoWindow && videoWindow->is_zoomed) - videoWindow->SetInterfaceShowing(false); - } - } + // We are getting the pulse messages no matter if the mouse is over + // this view. If we are in full screen mode, we want to hide the cursor + // even if it is not. + VideoWindow *videoWindow = dynamic_cast(Window()); + if (!fCursorHidden) + { + if (fCursorInside + && mdate() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT) + { + be_app->ObscureCursor(); + fCursorHidden = true; + + // hide the interface window as well if full screen + if (videoWindow && videoWindow->IsFullScreen()) + videoWindow->SetInterfaceShowing(false); + } + } + + // Workaround to disable the screensaver in full screen: + // we simulate an activity every 29 seconds + if( videoWindow && videoWindow->IsFullScreen() && + mdate() - fLastMouseMovedTime > 29000000 ) + { + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons, false); + ConvertToScreen(&where); + set_mouse_position((int32_t) where.x, (int32_t) where.y); + } } /***************************************************************************** - * VLCVIew::KeyDown + * VLCVIew::KeyUp *****************************************************************************/ -void -VLCView::KeyDown(const char *bytes, int32 numBytes) +void VLCView::KeyUp( const char *bytes, int32 numBytes ) { - VideoWindow *videoWindow = dynamic_cast(Window()); - BWindow* interfaceWindow = get_interface_window(); - if (videoWindow && numBytes > 0) { - uint32 mods = modifiers(); - switch (*bytes) { - case B_TAB: - // toggle window and full screen mode - // not passing on the tab key to the default KeyDown() - // implementation also avoids loosing the keyboard focus - videoWindow->PostMessage(TOGGLE_FULL_SCREEN); - break; - case B_ESCAPE: - // go back to window mode - if (videoWindow->is_zoomed) - videoWindow->PostMessage(TOGGLE_FULL_SCREEN); - break; - case B_SPACE: - // toggle playback - if (interfaceWindow) - interfaceWindow->PostMessage(PAUSE_PLAYBACK); - break; - case B_RIGHT_ARROW: - if (interfaceWindow) - { - if (mods & B_SHIFT_KEY) - // next title - interfaceWindow->PostMessage(NEXT_TITLE); - else - // next chapter - interfaceWindow->PostMessage(NEXT_CHAPTER); - } - break; - case B_LEFT_ARROW: - if (interfaceWindow) - { - if (mods & B_SHIFT_KEY) - // previous title - interfaceWindow->PostMessage(PREV_TITLE); - else - // previous chapter - interfaceWindow->PostMessage(PREV_CHAPTER); - } - break; - case B_UP_ARROW: - // previous file in playlist - interfaceWindow->PostMessage(PREV_FILE); - break; - case B_DOWN_ARROW: - // next file in playlist - interfaceWindow->PostMessage(NEXT_FILE); - break; - case B_PRINT_KEY: - case 's': - case 'S': - videoWindow->PostMessage( SCREEN_SHOT ); - break; - default: - BView::KeyDown(bytes, numBytes); - break; - } - } + 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 *****************************************************************************/ void -VLCView::Draw(BRect updateRect) +VLCView::Draw(BRect updateRect) { - VideoWindow* window = dynamic_cast( Window() ); - if ( window && window->mode == BITMAP ) - FillRect( updateRect ); + VideoWindow* window = dynamic_cast( Window() ); + if ( window && window->mode == BITMAP ) + FillRect( updateRect ); } /***************************************************************************** @@ -1139,7 +1398,7 @@ VLCView::Draw(BRect updateRect) *****************************************************************************/ static int Init ( vout_thread_t * ); static void End ( vout_thread_t * ); -// static int Manage ( vout_thread_t * ); +static int Manage ( vout_thread_t * ); static void Display ( vout_thread_t *, picture_t * ); static int BeosOpenDisplay ( vout_thread_t *p_vout ); @@ -1167,7 +1426,7 @@ int E_(OpenVideo) ( vlc_object_t *p_this ) p_vout->pf_init = Init; p_vout->pf_end = End; - p_vout->pf_manage = NULL; + p_vout->pf_manage = Manage; p_vout->pf_render = NULL; p_vout->pf_display = Display; @@ -1205,7 +1464,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 */ @@ -1223,17 +1484,18 @@ int Init( vout_thread_t *p_vout ) { return 0; } - p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[buffer_index]->Bits(); + 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; - p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow(); + p_pic->p->i_pitch = p_vout->p_sys->p_window->bitmap[buffer_index]->BytesPerRow(); p_pic->p->i_visible_pitch = p_pic->p->i_pixel_pitch * ( p_vout->p_sys->p_window->bitmap[buffer_index]->Bounds().IntegerWidth() + 1 ); p_pic->i_status = DESTROYED_PICTURE; p_pic->i_type = DIRECT_PICTURE; - + PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; I_OUTPUTPICTURES++; @@ -1250,6 +1512,20 @@ void End( vout_thread_t *p_vout ) BeosCloseDisplay( p_vout ); } +/***************************************************************************** + * Manage + *****************************************************************************/ +static int Manage( vout_thread_t * p_vout ) +{ + if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) + { + p_vout->p_sys->p_window->PostMessage( TOGGLE_FULL_SCREEN ); + p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; + } + + return 0; +} + /***************************************************************************** * CloseVideo: destroy BeOS video thread output method ***************************************************************************** @@ -1272,14 +1548,15 @@ void Display( vout_thread_t *p_vout, picture_t *p_pic ) { VideoWindow * p_win = p_vout->p_sys->p_window; - /* draw buffer if required */ + /* draw buffer if required */ if (!p_win->teardownwindow) - { + { 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_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits(); + 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(); } /* following functions are local */ @@ -1288,12 +1565,12 @@ void Display( vout_thread_t *p_vout, picture_t *p_pic ) * BeosOpenDisplay: open and initialize BeOS device *****************************************************************************/ static int BeosOpenDisplay( vout_thread_t *p_vout ) -{ +{ p_vout->p_sys->p_window = new VideoWindow( p_vout->p_sys->i_width - 1, p_vout->p_sys->i_height - 1, BRect( 20, 50, - 20 + p_vout->i_window_width - 1, + 20 + p_vout->i_window_width - 1, 50 + p_vout->i_window_height - 1 ), p_vout ); if( p_vout->p_sys->p_window == NULL ) @@ -1305,7 +1582,7 @@ static int BeosOpenDisplay( vout_thread_t *p_vout ) { p_vout->p_sys->p_window->Show(); } - + return( 0 ); } @@ -1316,7 +1593,7 @@ static int BeosOpenDisplay( vout_thread_t *p_vout ) * state of the device. *****************************************************************************/ static void BeosCloseDisplay( vout_thread_t *p_vout ) -{ +{ VideoWindow * p_win = p_vout->p_sys->p_window; /* Destroy the video window */ if( p_win != NULL && !p_win->teardownwindow)