From e54cc504833e241107edd85a568338e6c3fbdccf Mon Sep 17 00:00:00 2001 From: Damien Fouilleul Date: Mon, 14 May 2007 12:23:55 +0000 Subject: [PATCH 1/1] vout: merged all Microsoft Windows specific vouts under msw directory in order to leverage common event handling --- configure.ac | 2 +- modules/video_output/Modules.am | 2 - .../video_output/{directx => msw}/Modules.am | 12 + .../video_output/{directx => msw}/direct3d.c | 32 +- .../video_output/{directx => msw}/directx.c | 40 +- .../video_output/{directx => msw}/events.c | 90 +- .../video_output/{directx => msw}/glwin32.c | 23 +- modules/video_output/{directx => msw}/vout.h | 66 +- modules/video_output/msw/wingdi.c | 919 +++++++++++ modules/video_output/wingdi.c | 1362 ----------------- 10 files changed, 1115 insertions(+), 1433 deletions(-) rename modules/video_output/{directx => msw}/Modules.am (61%) rename modules/video_output/{directx => msw}/direct3d.c (98%) rename modules/video_output/{directx => msw}/directx.c (98%) rename modules/video_output/{directx => msw}/events.c (94%) rename modules/video_output/{directx => msw}/glwin32.c (95%) rename modules/video_output/{directx => msw}/vout.h (82%) create mode 100755 modules/video_output/msw/wingdi.c delete mode 100644 modules/video_output/wingdi.c diff --git a/configure.ac b/configure.ac index 9082d62060..222cd7f728 100644 --- a/configure.ac +++ b/configure.ac @@ -5916,7 +5916,7 @@ AC_CONFIG_FILES([ modules/video_chroma/Makefile modules/video_filter/Makefile modules/video_output/Makefile - modules/video_output/directx/Makefile + modules/video_output/msw/Makefile modules/video_output/qte/Makefile modules/video_output/x11/Makefile modules/visualization/Makefile diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am index 21dcb6381f..de69658934 100644 --- a/modules/video_output/Modules.am +++ b/modules/video_output/Modules.am @@ -5,8 +5,6 @@ SOURCES_ggi = ggi.c SOURCES_glide = glide.c SOURCES_vout_sdl = sdl.c SOURCES_svgalib = svgalib.c -SOURCES_wingdi = wingdi.c -SOURCES_wingapi = wingdi.c SOURCES_mga = mga.c SOURCES_hd1000v = hd1000v.cpp SOURCES_snapshot = snapshot.c diff --git a/modules/video_output/directx/Modules.am b/modules/video_output/msw/Modules.am similarity index 61% rename from modules/video_output/directx/Modules.am rename to modules/video_output/msw/Modules.am index 2db1b1e809..ba1636b614 100644 --- a/modules/video_output/directx/Modules.am +++ b/modules/video_output/msw/Modules.am @@ -15,3 +15,15 @@ SOURCES_glwin32 = \ vout.h \ events.c \ $(NULL) + +SOURCES_wingdi = \ + wingdi.c \ + vout.h \ + events.c \ + $(NULL) + +SOURCES_wingapi = \ + windi.c \ + vout.h \ + events.c \ + $(NULL) diff --git a/modules/video_output/directx/direct3d.c b/modules/video_output/msw/direct3d.c similarity index 98% rename from modules/video_output/directx/direct3d.c rename to modules/video_output/msw/direct3d.c index ae3f3502a3..5077c7a421 100644 --- a/modules/video_output/directx/direct3d.c +++ b/modules/video_output/msw/direct3d.c @@ -138,7 +138,7 @@ typedef struct #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) /***************************************************************************** - * OpenVideo: allocate DirectX video thread output method + * OpenVideo: allocate Vout video thread output method ***************************************************************************** * This function allocates and initialize the Direct3D vout method. *****************************************************************************/ @@ -172,15 +172,12 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL; p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL; p_vout->p_sys->i_changes = 0; - p_vout->p_sys->b_wallpaper = 0; vlc_mutex_init( p_vout, &p_vout->p_sys->lock ); SetRectEmpty( &p_vout->p_sys->rect_display ); SetRectEmpty( &p_vout->p_sys->rect_parent ); var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_vout, "directx-device", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); - var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); p_vout->p_sys->b_cursor_hidden = 0; p_vout->p_sys->i_lastmoved = mdate(); @@ -192,21 +189,21 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->i_window_width = p_vout->i_window_width; p_vout->p_sys->i_window_height = p_vout->i_window_height; - /* Create the DirectXEventThread, this thread is created by us to isolate + /* Create the Vout EventThread, this thread is created by us to isolate * the Win32 PeekMessage function calls. We want to do this because * Windows can stay blocked inside this call for a long time, and when * this happens it thus blocks vlc's video_output thread. - * DirectXEventThread will take care of the creation of the video + * Vout EventThread will take care of the creation of the video * window (because PeekMessage has to be called from the same thread which * created the window). */ - msg_Dbg( p_vout, "creating DirectXEventThread" ); + msg_Dbg( p_vout, "creating Vout EventThread" ); p_vout->p_sys->p_event = vlc_object_create( p_vout, sizeof(event_thread_t) ); p_vout->p_sys->p_event->p_vout = p_vout; - if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread", - E_(DirectXEventThread), 0, 1 ) ) + if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread", + E_(EventThread), 0, 1 ) ) { - msg_Err( p_vout, "cannot create DirectXEventThread" ); + msg_Err( p_vout, "cannot create Vout EventThread" ); vlc_object_destroy( p_vout->p_sys->p_event ); p_vout->p_sys->p_event = NULL; goto error; @@ -214,13 +211,13 @@ static int OpenVideo( vlc_object_t *p_this ) if( p_vout->p_sys->p_event->b_error ) { - msg_Err( p_vout, "DirectXEventThread failed" ); + msg_Err( p_vout, "Vout EventThread failed" ); goto error; } vlc_object_attach( p_vout->p_sys->p_event, p_vout ); - msg_Dbg( p_vout, "DirectXEventThread running" ); + msg_Dbg( p_vout, "Vout EventThread running" ); /* Variable to indicate if the window should be on top of others */ /* Trigger a callback right now */ @@ -272,10 +269,10 @@ static void CloseVideo( vlc_object_t *p_this ) { vlc_object_detach( p_vout->p_sys->p_event ); - /* Kill DirectXEventThread */ + /* Kill Vout EventThread */ p_vout->p_sys->p_event->b_die = VLC_TRUE; - /* we need to be sure DirectXEventThread won't stay stuck in + /* we need to be sure Vout EventThread won't stay stuck in * GetMessage, so we send a fake message */ if( p_vout->p_sys->hwnd ) { @@ -334,7 +331,7 @@ static int Init( vout_thread_t *p_vout ) p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->fmt_out = p_vout->fmt_in; - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); /* create picture pool */ i_ret = Direct3DVoutCreatePictures(p_vout, 1); @@ -451,7 +448,7 @@ static int Manage( vout_thread_t *p_vout ) p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); } /* We used to call the Win32 PeekMessage function here to read the window @@ -708,7 +705,8 @@ static int Direct3DVoutOpen( vout_thread_t *p_vout ) // Create the D3DDevice hr = IDirect3D9_CreateDevice(p_d3dobj, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, p_vout->p_sys->hvideownd, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, + D3DCREATE_SOFTWARE_VERTEXPROCESSING| + D3DCREATE_MULTITHREADED, &d3dpp, &p_d3ddev ); if( FAILED(hr) ) { diff --git a/modules/video_output/directx/directx.c b/modules/video_output/msw/directx.c similarity index 98% rename from modules/video_output/directx/directx.c rename to modules/video_output/msw/directx.c index 9c86356532..e6500b7260 100644 --- a/modules/video_output/directx/directx.c +++ b/modules/video_output/msw/directx.c @@ -264,7 +264,7 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->i_window_width = p_vout->i_window_width; p_vout->p_sys->i_window_height = p_vout->i_window_height; - /* Create the DirectXEventThread, this thread is created by us to isolate + /* Create the Vout EventThread, this thread is created by us to isolate * the Win32 PeekMessage function calls. We want to do this because * Windows can stay blocked inside this call for a long time, and when * this happens it thus blocks vlc's video_output thread. @@ -275,10 +275,10 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->p_event = vlc_object_create( p_vout, sizeof(event_thread_t) ); p_vout->p_sys->p_event->p_vout = p_vout; - if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread", - E_(DirectXEventThread), 0, 1 ) ) + if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread", + E_(EventThread), 0, 1 ) ) { - msg_Err( p_vout, "cannot create DirectXEventThread" ); + msg_Err( p_vout, "cannot create Vout EventThread" ); vlc_object_destroy( p_vout->p_sys->p_event ); p_vout->p_sys->p_event = NULL; goto error; @@ -286,25 +286,25 @@ static int OpenVideo( vlc_object_t *p_this ) if( p_vout->p_sys->p_event->b_error ) { - msg_Err( p_vout, "DirectXEventThread failed" ); + msg_Err( p_vout, "Vout EventThread failed" ); goto error; } vlc_object_attach( p_vout->p_sys->p_event, p_vout ); - msg_Dbg( p_vout, "DirectXEventThread running" ); + msg_Dbg( p_vout, "Vout EventThread running" ); /* Initialise DirectDraw */ if( DirectXInitDDraw( p_vout ) ) { - msg_Err( p_vout, "cannot initialize DirectDraw" ); + msg_Err( p_vout, "cannot initialize DirectX DirectDraw" ); goto error; } /* Create the directx display */ if( DirectXCreateDisplay( p_vout ) ) { - msg_Err( p_vout, "cannot initialize DirectDraw" ); + msg_Err( p_vout, "cannot initialize DirectX DirectDraw" ); goto error; } @@ -399,7 +399,7 @@ static int Init( vout_thread_t *p_vout ) p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->fmt_out = p_vout->fmt_in; - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); #define MAX_DIRECTBUFFERS 1 /* Right now we use only 1 directbuffer because we don't want the @@ -492,10 +492,10 @@ static void CloseVideo( vlc_object_t *p_this ) { vlc_object_detach( p_vout->p_sys->p_event ); - /* Kill DirectXEventThread */ + /* Kill Vout EventThread */ p_vout->p_sys->p_event->b_die = VLC_TRUE; - /* we need to be sure DirectXEventThread won't stay stuck in + /* we need to be sure Vout EventThread won't stay stuck in * GetMessage, so we send a fake message */ if( p_vout->p_sys->hwnd ) { @@ -608,7 +608,7 @@ static int Manage( vout_thread_t *p_vout ) p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); } /* We used to call the Win32 PeekMessage function here to read the window @@ -620,7 +620,7 @@ static int Manage( vout_thread_t *p_vout ) { SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper ); p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE; - E_(DirectXUpdateOverlay)( p_vout ); + DirectDrawUpdateOverlay( p_vout ); } /* @@ -722,7 +722,7 @@ static void Display( vout_thread_t *p_vout, picture_t *p_pic ) { if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK && p_vout->p_sys->b_using_overlay ) - E_(DirectXUpdateOverlay)( p_vout ); + DirectDrawUpdateOverlay( p_vout ); } if( !p_vout->p_sys->b_using_overlay ) @@ -1056,7 +1056,7 @@ static int DirectXCreateDisplay( vout_thread_t *p_vout ) p_vout->p_sys->i_rgb_colorkey = DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey ); - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); return VLC_SUCCESS; } @@ -1224,7 +1224,7 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, /* Check the overlay is useable as some graphics cards allow creating * several overlays but only one can be used at one time. */ p_vout->p_sys->p_current_surface = *pp_surface_final; - if( E_(DirectXUpdateOverlay)( p_vout ) != VLC_SUCCESS ) + if( DirectDrawUpdateOverlay( p_vout ) != VLC_SUCCESS ) { IDirectDrawSurface2_Release( *pp_surface_final ); *pp_surface_final = NULL; @@ -1237,13 +1237,13 @@ static int DirectXCreateSurface( vout_thread_t *p_vout, } /***************************************************************************** - * DirectXUpdateOverlay: Move or resize overlay surface on video display. + * DirectDrawUpdateOverlay: Move or resize overlay surface on video display. ***************************************************************************** * This function is used to move or resize an overlay surface on the screen. * Ususally the overlay is moved by the user and thus, by a move or resize * event (in Manage). *****************************************************************************/ -int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout ) +int DirectDrawUpdateOverlay( vout_thread_t *p_vout ) { DDOVERLAYFX ddofx; DWORD dwFlags; @@ -1299,7 +1299,7 @@ int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout ) if(dxresult != DD_OK) { - msg_Warn( p_vout, "DirectXUpdateOverlay cannot move/resize overlay" ); + msg_Warn( p_vout, "DirectDrawUpdateOverlay cannot move/resize overlay" ); return VLC_EGENERIC; } @@ -1465,7 +1465,7 @@ static int NewPictureVec( vout_thread_t *p_vout, picture_t *p_pic, DirectXUnlockSurface( p_vout, &front_pic ); } - E_(DirectXUpdateOverlay)( p_vout ); + DirectDrawUpdateOverlay( p_vout ); I_OUTPUTPICTURES = 1; msg_Dbg( p_vout, "YUV overlay created successfully" ); } diff --git a/modules/video_output/directx/events.c b/modules/video_output/msw/events.c similarity index 94% rename from modules/video_output/directx/events.c rename to modules/video_output/msw/events.c index 646563ed83..bbed9dbceb 100644 --- a/modules/video_output/directx/events.c +++ b/modules/video_output/msw/events.c @@ -57,6 +57,13 @@ #include "vlc_keys.h" #include "vout.h" +#if defined(UNDER_CE) && !defined(__PLUGIN__) /*FIXME*/ +# define SHFS_SHOWSIPBUTTON 0x0004 +# define SHFS_HIDESIPBUTTON 0x0008 +# define MENU_HEIGHT 26 + BOOL SHFullScreen(HWND hwndRequester, DWORD dwState); +#endif + /***************************************************************************** * Local prototypes. *****************************************************************************/ @@ -82,14 +89,14 @@ static void DirectXPopupMenu( event_thread_t *p_event, vlc_bool_t b_open ) static int DirectXConvertKey( int i_key ); /***************************************************************************** - * DirectXEventThread: Create video window & handle its messages + * EventThread: Create video window & handle its messages ***************************************************************************** * This function creates a video window and then enters an infinite loop * that handles the messages sent to that window. * The main goal of this thread is to isolate the Win32 PeekMessage function * because this one can block for a long time. *****************************************************************************/ -void E_(DirectXEventThread)( event_thread_t *p_event ) +void E_(EventThread)( event_thread_t *p_event ) { MSG msg; POINT old_mouse_pos = {0,0}, mouse_pos; @@ -112,6 +119,7 @@ void E_(DirectXEventThread)( event_thread_t *p_event ) /* Signal the creation of the window */ vlc_thread_ready( p_event ); +#ifndef UNDER_CE /* Set power management stuff */ if( (hkernel32 = GetModuleHandle( _T("KERNEL32") ) ) ) { @@ -126,6 +134,7 @@ void E_(DirectXEventThread)( event_thread_t *p_event ) else msg_Dbg( p_event, "no support for SetThreadExecutionState()" ); } +#endif /* Main loop */ /* GetMessage will sleep if there's no message in the queue */ @@ -307,6 +316,12 @@ void E_(DirectXEventThread)( event_thread_t *p_event ) { if( val.psz_string ) free( val.psz_string ); +#ifdef MODULE_NAME_IS_wingdi + val.psz_string = strdup( VOUT_TITLE " (WinGDI output)" ); +#endif +#ifdef MODULE_NAME_IS_wingapi + val.psz_string = strdup( VOUT_TITLE " (WinGAPI output)" ); +#endif #ifdef MODULE_NAME_IS_glwin32 val.psz_string = strdup( VOUT_TITLE " (OpenGL output)" ); #endif @@ -315,11 +330,11 @@ void E_(DirectXEventThread)( event_thread_t *p_event ) #endif #ifdef MODULE_NAME_IS_vout_directx if( p_event->p_vout->p_sys->b_using_overlay ) val.psz_string = - strdup( VOUT_TITLE " (hardware YUV overlay DirectX output)" ); + strdup( VOUT_TITLE " (hardware YUV overlay DirectX output)" ); else if( p_event->p_vout->p_sys->b_hw_yuv ) val.psz_string = - strdup( VOUT_TITLE " (hardware YUV DirectX output)" ); + strdup( VOUT_TITLE " (hardware YUV DirectX output)" ); else val.psz_string = - strdup( VOUT_TITLE " (software RGB DirectX output)" ); + strdup( VOUT_TITLE " (software RGB DirectX output)" ); #endif } @@ -585,13 +600,13 @@ static void DirectXCloseWindow( vout_thread_t *p_vout ) } /***************************************************************************** - * DirectXUpdateRects: update clipping rectangles + * UpdateRects: update clipping rectangles ***************************************************************************** * This function is called when the window position or size are changed, and * its job is to update the source and destination RECTs used to display the * picture. *****************************************************************************/ -void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force ) +void E_(UpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force ) { #define rect_src p_vout->p_sys->rect_src #define rect_src_clipped p_vout->p_sys->rect_src_clipped @@ -682,7 +697,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force ) } #else /* MODULE_NAME_IS_vout_directx */ - /* AFAIK, there are no clipping constraints in Direct3D or OpenGL */ + /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */ rect_dest_clipped = rect_dest; #endif @@ -742,7 +757,7 @@ void E_(DirectXUpdateRects)( vout_thread_t *p_vout, vlc_bool_t b_force ) rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top; if( p_vout->p_sys->b_using_overlay ) - E_(DirectXUpdateOverlay)( p_vout ); + DirectDrawUpdateOverlay( p_vout ); #endif /* Signal the change in size/position */ @@ -788,6 +803,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, } } +#ifndef UNDER_CE /* Catch the screensaver and the monitor turn-off */ if( message == WM_SYSCOMMAND && ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) ) @@ -795,6 +811,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, //if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" ); return 0; /* this stops them from happening */ } +#endif if( hwnd == p_vout->p_sys->hvideownd ) { @@ -841,7 +858,7 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, { case WM_WINDOWPOSCHANGED: - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); return 0; /* the user wants to close the window */ @@ -889,6 +906,50 @@ static long FAR PASCAL DirectXEventProc( HWND hwnd, UINT message, case WM_ERASEBKGND: return DefWindowProc(hwnd, message, wParam, lParam); + case WM_KILLFOCUS: +#ifdef MODULE_NAME_IS_wingapi + p_vout->p_sys->b_focus = VLC_FALSE; + if( !p_vout->p_sys->b_parent_focus ) GXSuspend(); +#endif +#ifdef UNDER_CE + if( hWnd == p_vout->p_sys->hfswnd ) + { + HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); + ShowWindow( htbar, SW_SHOW ); + } + + if( !p_vout->p_sys->hparent || + hWnd == p_vout->p_sys->hfswnd ) + { + SHFullScreen( hWnd, SHFS_SHOWSIPBUTTON ); + } +#endif + return 0; + + case WM_SETFOCUS: +#ifdef MODULE_NAME_IS_wingapi + p_vout->p_sys->b_focus = VLC_TRUE; + GXResume(); +#endif +#ifdef UNDER_CE + if( p_vout->p_sys->hparent && + hWnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen ) + p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE; + + if( hWnd == p_vout->p_sys->hfswnd ) + { + HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); + ShowWindow( htbar, SW_HIDE ); + } + + if( !p_vout->p_sys->hparent || + hWnd == p_vout->p_sys->hfswnd ) + { + SHFullScreen( hWnd, SHFS_HIDESIPBUTTON ); + } +#endif + return 0; + default: //msg_Dbg( p_vout, "WinProc WM Default %i", message ); break; @@ -1063,6 +1124,15 @@ static int Control( vout_thread_t *p_vout, int i_query, va_list args ) p_vout->p_sys->b_on_top_change = VLC_TRUE; return VLC_SUCCESS; +#ifdef MODULE_NAME_IS_wingapi + case VOUT_SET_FOCUS: + b_bool = va_arg( args, vlc_bool_t ); + p_vout->p_sys->b_parent_focus = b_bool; + if( b_bool ) GXResume(); + else if( !p_vout->p_sys->b_focus ) GXSuspend(); + return VLC_SUCCESS; +#endif + default: return vout_vaControlDefault( p_vout, i_query, args ); } diff --git a/modules/video_output/directx/glwin32.c b/modules/video_output/msw/glwin32.c similarity index 95% rename from modules/video_output/directx/glwin32.c rename to modules/video_output/msw/glwin32.c index 14fe9b2aea..b2549fa131 100644 --- a/modules/video_output/directx/glwin32.c +++ b/modules/video_output/msw/glwin32.c @@ -108,7 +108,6 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL; p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL; p_vout->p_sys->i_changes = 0; - p_vout->p_sys->b_wallpaper = 0; vlc_mutex_init( p_vout, &p_vout->p_sys->lock ); SetRectEmpty( &p_vout->p_sys->rect_display ); SetRectEmpty( &p_vout->p_sys->rect_parent ); @@ -122,21 +121,21 @@ static int OpenVideo( vlc_object_t *p_this ) p_vout->p_sys->i_window_width = p_vout->i_window_width; p_vout->p_sys->i_window_height = p_vout->i_window_height; - /* Create the DirectXEventThread, this thread is created by us to isolate + /* Create the Vout EventThread, this thread is created by us to isolate * the Win32 PeekMessage function calls. We want to do this because * Windows can stay blocked inside this call for a long time, and when * this happens it thus blocks vlc's video_output thread. - * DirectXEventThread will take care of the creation of the video + * Vout EventThread will take care of the creation of the video * window (because PeekMessage has to be called from the same thread which * created the window). */ - msg_Dbg( p_vout, "creating DirectXEventThread" ); + msg_Dbg( p_vout, "creating Vout EventThread" ); p_vout->p_sys->p_event = vlc_object_create( p_vout, sizeof(event_thread_t) ); p_vout->p_sys->p_event->p_vout = p_vout; - if( vlc_thread_create( p_vout->p_sys->p_event, "DirectX Events Thread", - E_(DirectXEventThread), 0, 1 ) ) + if( vlc_thread_create( p_vout->p_sys->p_event, "Vout Events Thread", + E_(EventThread), 0, 1 ) ) { - msg_Err( p_vout, "cannot create DirectXEventThread" ); + msg_Err( p_vout, "cannot create Vout EventThread" ); vlc_object_destroy( p_vout->p_sys->p_event ); p_vout->p_sys->p_event = NULL; goto error; @@ -144,13 +143,13 @@ static int OpenVideo( vlc_object_t *p_this ) if( p_vout->p_sys->p_event->b_error ) { - msg_Err( p_vout, "DirectXEventThread failed" ); + msg_Err( p_vout, "Vout EventThread failed" ); goto error; } vlc_object_attach( p_vout->p_sys->p_event, p_vout ); - msg_Dbg( p_vout, "DirectXEventThread running" ); + msg_Dbg( p_vout, "Vout EventThread running" ); /* Variable to indicate if the window should be on top of others */ /* Trigger a callback right now */ @@ -225,10 +224,10 @@ static void CloseVideo( vlc_object_t *p_this ) { vlc_object_detach( p_vout->p_sys->p_event ); - /* Kill DirectXEventThread */ + /* Kill Vout EventThread */ p_vout->p_sys->p_event->b_die = VLC_TRUE; - /* we need to be sure DirectXEventThread won't stay stuck in + /* we need to be sure Vout EventThread won't stay stuck in * GetMessage, so we send a fake message */ if( p_vout->p_sys->hwnd ) { @@ -312,7 +311,7 @@ static int Manage( vout_thread_t *p_vout ) p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; - E_(DirectXUpdateRects)( p_vout, VLC_TRUE ); + E_(UpdateRects)( p_vout, VLC_TRUE ); } /* We used to call the Win32 PeekMessage function here to read the window diff --git a/modules/video_output/directx/vout.h b/modules/video_output/msw/vout.h similarity index 82% rename from modules/video_output/directx/vout.h rename to modules/video_output/msw/vout.h index 5fe7d9880b..05b4afb65c 100644 --- a/modules/video_output/directx/vout.h +++ b/modules/video_output/msw/vout.h @@ -1,10 +1,11 @@ /***************************************************************************** - * vout.h: Windows DirectX video output header file + * vout.h: Windows video output header file ***************************************************************************** * Copyright (C) 2001-2004 the VideoLAN team * $Id$ * * Authors: Gildas Bazin + * Damien Fouilleul * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +23,7 @@ *****************************************************************************/ /***************************************************************************** - * event_thread_t: DirectX event thread + * event_thread_t: event thread *****************************************************************************/ typedef struct event_thread_t { @@ -33,10 +34,10 @@ typedef struct event_thread_t } event_thread_t; /***************************************************************************** - * vout_sys_t: video output DirectX method descriptor + * vout_sys_t: video output method descriptor ***************************************************************************** * This structure is part of the video output thread descriptor. - * It describes the DirectX specific properties of an output thread. + * It describes the module specific properties of an output thread. *****************************************************************************/ struct vout_sys_t { @@ -75,13 +76,15 @@ struct vout_sys_t /* Misc */ vlc_bool_t b_on_top_change; - vlc_bool_t b_wallpaper; +#ifndef UNDER_CE /* screensaver system settings to be restored when vout is closed */ UINT i_spi_lowpowertimeout; UINT i_spi_powerofftimeout; UINT i_spi_screensavetimeout; +#endif + /* Coordinates of src and dest images (used when blitting to display) */ RECT rect_src; RECT rect_src_clipped; @@ -90,6 +93,7 @@ struct vout_sys_t vlc_bool_t b_hw_yuv; /* Should we use hardware YUV->RGB conversions */ + #ifdef MODULE_NAME_IS_vout_directx /* Overlay alignment restrictions */ int i_align_src_boundary; @@ -97,6 +101,8 @@ struct vout_sys_t int i_align_dest_boundary; int i_align_dest_size; + vlc_bool_t b_wallpaper; /* show as desktop wallpaper ? */ + vlc_bool_t b_using_overlay; /* Are we using an overlay surface */ vlc_bool_t b_use_sysmem; /* Should we use system memory for surfaces */ vlc_bool_t b_3buf_overlay; /* Should we use triple buffered overlays */ @@ -133,20 +139,62 @@ struct vout_sys_t LPDIRECT3DVERTEXBUFFER9 p_d3dvtc; #endif +#ifdef MODULE_NAME_IS_wingdi + + int i_depth; + + /* Our offscreen bitmap and its framebuffer */ + HDC off_dc; + HBITMAP off_bitmap; + uint8_t * p_pic_buffer; + int i_pic_pitch; + int i_pic_pixel_pitch; + + BITMAPINFO bitmapinfo; + RGBQUAD red; + RGBQUAD green; + RGBQUAD blue; +#endif + +#ifdef MODULE_NAME_IS_wingapi + int i_depth; + int render_width; + int render_height; + + vlc_bool_t b_focus; + vlc_bool_t b_parent_focus; + + HINSTANCE gapi_dll; /* handle of the opened gapi dll */ + + /* GAPI functions */ + int (*GXOpenDisplay)( HWND hWnd, DWORD dwFlags ); + int (*GXCloseDisplay)(); + void *(*GXBeginDraw)(); + int (*GXEndDraw)(); + GXDisplayProperties (*GXGetDisplayProperties)(); + int (*GXSuspend)(); + int (*GXResume)(); +#endif + +#ifndef UNDER_CE + /* suspend display */ + vlc_bool_t b_suspend_display; +#endif + event_thread_t *p_event; vlc_mutex_t lock; }; /***************************************************************************** - * Prototypes from vout.c + * Prototypes from directx.c *****************************************************************************/ -int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout ); +int DirectDrawUpdateOverlay( vout_thread_t *p_vout ); /***************************************************************************** * Prototypes from events.c *****************************************************************************/ -void E_(DirectXEventThread) ( event_thread_t *p_event ); -void E_(DirectXUpdateRects) ( vout_thread_t *p_vout, vlc_bool_t b_force ); +void E_(EventThread) ( event_thread_t *p_event ); +void E_(UpdateRects) ( vout_thread_t *p_vout, vlc_bool_t b_force ); void Win32ToggleFullscreen ( vout_thread_t *p_vout ); /***************************************************************************** diff --git a/modules/video_output/msw/wingdi.c b/modules/video_output/msw/wingdi.c new file mode 100755 index 0000000000..ba2367be7f --- /dev/null +++ b/modules/video_output/msw/wingdi.c @@ -0,0 +1,919 @@ +/***************************************************************************** + * wingdi.c : Win32 / WinCE GDI video output plugin for vlc + ***************************************************************************** + * Copyright (C) 2002 the VideoLAN team + * $Id: wingdi.c 18074 2006-11-26 16:26:44Z zorglub $ + * + * Authors: Gildas Bazin + * Samuel Hocevar + * + * This program is free software; you can redistribute it and/or modify + * 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 + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include /* malloc(), free() */ +#include + +#include +#include +#include +#include + +#include + +#include "vout.h" + +#ifdef MODULE_NAME_IS_wingapi + typedef struct GXDisplayProperties { + DWORD cxWidth; + DWORD cyHeight; + long cbxPitch; + long cbyPitch; + long cBPP; + DWORD ffFormat; + } GXDisplayProperties; + + typedef struct GXScreenRect { + DWORD dwTop; + DWORD dwLeft; + DWORD dwWidth; + DWORD dwHeight; + } GXScreenRect; + +# define GX_FULLSCREEN 0x01 +# define GX_NORMALKEYS 0x02 +# define GX_LANDSCAPEKEYS 0x03 + +# ifndef kfLandscape +# define kfLandscape 0x8 +# define kfPalette 0x10 +# define kfDirect 0x20 +# define kfDirect555 0x40 +# define kfDirect565 0x80 +# define kfDirect888 0x100 +# define kfDirect444 0x200 +# define kfDirectInverted 0x400 +# endif +#endif /* MODULE_NAME_IS_wingapi */ + +#define MAX_DIRECTBUFFERS 10 + +#ifdef UNDER_CE +#ifndef WS_OVERLAPPEDWINDOW +# define WS_OVERLAPPEDWINDOW 0xcf0000 +#endif +#ifndef WS_EX_NOPARENTNOTIFY +# define WS_EX_NOPARENTNOTIFY 4 +#endif +#ifndef WS_EX_APPWINDOW +#define WS_EX_APPWINDOW 0x40000 +#endif +#define SetWindowLongPtr SetWindowLong +#define GetWindowLongPtr GetWindowLong +#define GWLP_USERDATA GWL_USERDATA +#define AdjustWindowRect(a,b,c) +#endif //UNDER_CE + +#ifndef WS_NONAVDONEBUTTON +#define WS_NONAVDONEBUTTON 0 +#endif +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +static int OpenVideo ( vlc_object_t * ); +static void CloseVideo ( vlc_object_t * ); + +static int Init ( vout_thread_t * ); +static void End ( vout_thread_t * ); +static int Manage ( vout_thread_t * ); +static void Render ( vout_thread_t *, picture_t * ); +#ifdef MODULE_NAME_IS_wingapi +static void FirstDisplayGAPI( vout_thread_t *, picture_t * ); +static void DisplayGAPI( vout_thread_t *, picture_t * ); +static int GAPILockSurface( vout_thread_t *, picture_t * ); +static int GAPIUnlockSurface( vout_thread_t *, picture_t * ); +#else +static void FirstDisplayGDI( vout_thread_t *, picture_t * ); +static void DisplayGDI( vout_thread_t *, picture_t * ); +#endif +static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * ); + +static void InitBuffers ( vout_thread_t * ); + +#ifdef MODULE_NAME_IS_wingapi +# define GXOpenDisplay p_vout->p_sys->GXOpenDisplay +# define GXCloseDisplay p_vout->p_sys->GXCloseDisplay +# define GXBeginDraw p_vout->p_sys->GXBeginDraw +# define GXEndDraw p_vout->p_sys->GXEndDraw +# define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties +# define GXSuspend p_vout->p_sys->GXSuspend +# define GXResume p_vout->p_sys->GXResume +#endif + +#define DX_POSITION_CHANGE 0x1000 + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ +vlc_module_begin(); + set_category( CAT_VIDEO ); + set_subcategory( SUBCAT_VIDEO_VOUT ); +#ifdef MODULE_NAME_IS_wingapi + set_shortname( "Windows GAPI" ); + set_description( _("Windows GAPI video output") ); + set_capability( "video output", 20 ); +#else + set_shortname( "Windows GDI" ); + set_description( _("Windows GDI video output") ); + set_capability( "video output", 10 ); +#endif + set_callbacks( OpenVideo, CloseVideo ); +vlc_module_end(); + +/***************************************************************************** + * OpenVideo: activate GDI video thread output method + *****************************************************************************/ +static int OpenVideo ( vlc_object_t *p_this ) +{ + vout_thread_t * p_vout = (vout_thread_t *)p_this; + vlc_value_t val; + + p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) ); + if( !p_vout->p_sys ) return VLC_ENOMEM; + memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) ); + +#ifdef MODULE_NAME_IS_wingapi + /* Load GAPI */ + p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") ); + if( p_vout->p_sys->gapi_dll == NULL ) + { + msg_Warn( p_vout, "failed loading gx.dll" ); + free( p_vout->p_sys ); + return VLC_EGENERIC; + } + + GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") ); + GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXCloseDisplay@@YAHXZ") ); + GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXBeginDraw@@YAPAXXZ") ); + GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXEndDraw@@YAHXZ") ); + GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") ); + GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXSuspend@@YAHXZ") ); + GXResume = GetProcAddress( p_vout->p_sys->gapi_dll, + _T("?GXResume@@YAHXZ") ); + + if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw || + !GXGetDisplayProperties || !GXSuspend || !GXResume ) + { + msg_Err( p_vout, "failed GetProcAddress on gapi.dll" ); + free( p_vout->p_sys ); + return VLC_EGENERIC; + } + + msg_Dbg( p_vout, "GAPI DLL loaded" ); + + p_vout->p_sys->render_width = p_vout->render.i_width; + p_vout->p_sys->render_height = p_vout->render.i_height; +#endif + + p_vout->p_sys->p_event = (vlc_object_t *) + vlc_object_create( p_vout, VLC_OBJECT_GENERIC ); + if( !p_vout->p_sys->p_event ) + { + free( p_vout->p_sys ); + return VLC_ENOMEM; + } + + p_vout->pf_init = Init; + p_vout->pf_end = End; + p_vout->pf_manage = Manage; + p_vout->pf_render = Render; +#ifdef MODULE_NAME_IS_wingapi + p_vout->pf_display = FirstDisplayGAPI; + + p_vout->p_sys->b_focus = 0; + p_vout->p_sys->b_parent_focus = 0; + +#else + p_vout->pf_display = FirstDisplayGDI; +#endif + + p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL; + p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL; + p_vout->p_sys->i_changes = 0; + vlc_mutex_init( p_vout, &p_vout->p_sys->lock ); + SetRectEmpty( &p_vout->p_sys->rect_display ); + SetRectEmpty( &p_vout->p_sys->rect_parent ); + + var_Create( p_vout, "video-title", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); + var_Create( p_vout, "disable-screensaver", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + + p_vout->p_sys->b_cursor_hidden = 0; + p_vout->p_sys->i_lastmoved = mdate(); + + /* Set main window's size */ + p_vout->p_sys->i_window_width = p_vout->i_window_width; + p_vout->p_sys->i_window_height = p_vout->i_window_height; + + /* Create the EventThread, this thread is created by us to isolate + * the Win32 PeekMessage function calls. We want to do this because + * Windows can stay blocked inside this call for a long time, and when + * this happens it thus blocks vlc's video_output thread. + * Vout EventThread will take care of the creation of the video + * window (because PeekMessage has to be called from the same thread which + * created the window). */ + msg_Dbg( p_vout, "creating Vout EventThread" ); + p_vout->p_sys->p_event = + vlc_object_create( p_vout, sizeof(event_thread_t) ); + p_vout->p_sys->p_event->p_vout = p_vout; + if( vlc_thread_create( p_vout->p_sys->p_event, "VLC Vout Events Thread", + E_(EventThread), 0, 1 ) ) + { + msg_Err( p_vout, "cannot create Vout EventThread" ); + vlc_object_destroy( p_vout->p_sys->p_event ); + p_vout->p_sys->p_event = NULL; + goto error; + } + + if( p_vout->p_sys->p_event->b_error ) + { + msg_Err( p_vout, "Vout EventThread failed" ); + goto error; + } + + vlc_object_attach( p_vout->p_sys->p_event, p_vout ); + + msg_Dbg( p_vout, "Vout EventThread running" ); + +#ifndef UNDER_CE + /* Variable to indicate if the window should be on top of others */ + /* Trigger a callback right now */ + var_Get( p_vout, "video-on-top", &val ); + var_Set( p_vout, "video-on-top", val ); + + /* disable screensaver by temporarily changing system settings */ + p_vout->p_sys->i_spi_lowpowertimeout = 0; + p_vout->p_sys->i_spi_powerofftimeout = 0; + p_vout->p_sys->i_spi_screensavetimeout = 0; + var_Get( p_vout, "disable-screensaver", &val); + if( val.b_bool ) { + msg_Dbg(p_vout, "disabling screen saver"); + SystemParametersInfo(SPI_GETLOWPOWERTIMEOUT, + 0, &(p_vout->p_sys->i_spi_lowpowertimeout), 0); + if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) { + SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, 0, NULL, 0); + } + SystemParametersInfo(SPI_GETPOWEROFFTIMEOUT, 0, + &(p_vout->p_sys->i_spi_powerofftimeout), 0); + if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) { + SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, 0, NULL, 0); + } + SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, + &(p_vout->p_sys->i_spi_screensavetimeout), 0); + if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) { + SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 0, NULL, 0); + } + } +#endif + return VLC_SUCCESS; + +error: + CloseVideo( VLC_OBJECT(p_vout) ); + return VLC_EGENERIC; +} + +/***************************************************************************** + * CloseVideo: deactivate the GDI video output + *****************************************************************************/ +static void CloseVideo ( vlc_object_t *p_this ) +{ + vout_thread_t * p_vout = (vout_thread_t *)p_this; + + if( p_vout->p_sys->p_event ) + { + vlc_object_detach( p_vout->p_sys->p_event ); + + /* Kill Vout EventThread */ + p_vout->p_sys->p_event->b_die = VLC_TRUE; + + /* we need to be sure Vout EventThread won't stay stuck in + * GetMessage, so we send a fake message */ + if( p_vout->p_sys->hwnd ) + { + PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0); + } + + vlc_thread_join( p_vout->p_sys->p_event ); + vlc_object_destroy( p_vout->p_sys->p_event ); + } + vlc_mutex_destroy( &p_vout->p_sys->lock ); + +#ifndef UNDER_CE + /* restore screensaver system settings */ + if( 0 != p_vout->p_sys->i_spi_lowpowertimeout ) { + SystemParametersInfo(SPI_SETLOWPOWERTIMEOUT, + p_vout->p_sys->i_spi_lowpowertimeout, NULL, 0); + } + if( 0 != p_vout->p_sys->i_spi_powerofftimeout ) { + SystemParametersInfo(SPI_SETPOWEROFFTIMEOUT, + p_vout->p_sys->i_spi_powerofftimeout, NULL, 0); + } + if( 0 != p_vout->p_sys->i_spi_screensavetimeout ) { + SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, + p_vout->p_sys->i_spi_screensavetimeout, NULL, 0); + } +#endif + +#ifdef MODULE_NAME_IS_wingapi + FreeLibrary( p_vout->p_sys->gapi_dll ); +#endif + + if( p_vout->p_sys ) + { + free( p_vout->p_sys ); + p_vout->p_sys = NULL; + } +} + +/***************************************************************************** + * Init: initialize video thread output method + *****************************************************************************/ +static int Init( vout_thread_t *p_vout ) +{ + picture_t *p_pic; + + /* Initialize offscreen buffer */ + InitBuffers( p_vout ); + + p_vout->p_sys->rect_display.left = 0; + p_vout->p_sys->rect_display.top = 0; + p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN); + p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN); + + I_OUTPUTPICTURES = 0; + + /* Initialize the output structure */ + switch( p_vout->p_sys->i_depth ) + { + case 8: + p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); + p_vout->output.pf_setpalette = SetPalette; + break; + case 15: + p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); + p_vout->output.i_rmask = 0x7c00; + p_vout->output.i_gmask = 0x03e0; + p_vout->output.i_bmask = 0x001f; + break; + case 16: + p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); + p_vout->output.i_rmask = 0xf800; + p_vout->output.i_gmask = 0x07e0; + p_vout->output.i_bmask = 0x001f; + break; + case 24: + p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); + p_vout->output.i_rmask = 0x00ff0000; + p_vout->output.i_gmask = 0x0000ff00; + p_vout->output.i_bmask = 0x000000ff; + break; + case 32: + p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); + p_vout->output.i_rmask = 0x00ff0000; + p_vout->output.i_gmask = 0x0000ff00; + p_vout->output.i_bmask = 0x000000ff; + break; + default: + msg_Err( p_vout, "screen depth %i not supported", + p_vout->p_sys->i_depth ); + return VLC_EGENERIC; + break; + } + + p_pic = &p_vout->p_picture[0]; + +#ifdef MODULE_NAME_IS_wingapi + p_vout->output.i_width = 0; + p_vout->output.i_height = 0; + p_pic->pf_lock = GAPILockSurface; + p_pic->pf_unlock = GAPIUnlockSurface; + Manage( p_vout ); + GAPILockSurface( p_vout, p_pic ); + p_vout->i_changes = 0; + p_vout->output.i_width = p_vout->p_sys->render_width; + p_vout->output.i_height = p_vout->p_sys->render_height; + +#else + p_vout->output.i_width = p_vout->render.i_width; + p_vout->output.i_height = p_vout->render.i_height; + + p_vout->fmt_out = p_vout->fmt_in; + p_vout->fmt_out.i_chroma = p_vout->output.i_chroma; +#endif + + p_vout->output.i_aspect = p_vout->render.i_aspect; + + p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer; + p_pic->p->i_lines = p_vout->output.i_height; + p_pic->p->i_visible_lines = p_vout->output.i_height; + p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch; + p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch; + p_pic->p->i_visible_pitch = p_vout->output.i_width * + p_pic->p->i_pixel_pitch; + p_pic->i_planes = 1; + p_pic->i_status = DESTROYED_PICTURE; + p_pic->i_type = DIRECT_PICTURE; + + PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic; + + /* Change the window title bar text */ + PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 ); + E_(UpdateRects)( p_vout, VLC_TRUE ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * End: terminate video thread output method + *****************************************************************************/ +static void End( vout_thread_t *p_vout ) +{ +#ifdef MODULE_NAME_IS_wingapi + GXCloseDisplay(); +#else + DeleteDC( p_vout->p_sys->off_dc ); + DeleteObject( p_vout->p_sys->off_bitmap ); +#endif +} + +/***************************************************************************** + * Manage: handle events + ***************************************************************************** + * This function should be called regularly by video output thread. It manages + * console events. It returns a non null value on error. + *****************************************************************************/ +static int Manage( vout_thread_t *p_vout ) +{ + /* If we do not control our window, we check for geometry changes + * ourselves because the parent might not send us its events. */ + vlc_mutex_lock( &p_vout->p_sys->lock ); + if( p_vout->p_sys->hparent && !p_vout->b_fullscreen ) + { + RECT rect_parent; + POINT point; + + vlc_mutex_unlock( &p_vout->p_sys->lock ); + + GetClientRect( p_vout->p_sys->hparent, &rect_parent ); + point.x = point.y = 0; + ClientToScreen( p_vout->p_sys->hparent, &point ); + OffsetRect( &rect_parent, point.x, point.y ); + + if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) ) + { + int i_x, i_y, i_width, i_height; + p_vout->p_sys->rect_parent = rect_parent; + + /* This one is to force the update even if only + * the position has changed */ + SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1, + rect_parent.right - rect_parent.left, + rect_parent.bottom - rect_parent.top, 0 ); + + SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, + rect_parent.right - rect_parent.left, + rect_parent.bottom - rect_parent.top, 0 ); + + vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left, + rect_parent.bottom - rect_parent.top, + &i_x, &i_y, &i_width, &i_height ); + + SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, + i_x, i_y, i_width, i_height, 0 ); + } + } + else + { + vlc_mutex_unlock( &p_vout->p_sys->lock ); + } + + /* Check for cropping / aspect changes */ + if( p_vout->i_changes & VOUT_CROP_CHANGE || + p_vout->i_changes & VOUT_ASPECT_CHANGE ) + { + p_vout->i_changes &= ~VOUT_CROP_CHANGE; + p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; + + p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset; + p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset; + p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width; + p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height; + p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect; + p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; + p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; + p_vout->output.i_aspect = p_vout->fmt_in.i_aspect; + E_(UpdateRects)( p_vout, VLC_TRUE ); + } + + /* + * Position Change + */ + if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE ) + { + p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE; + } + + /* We used to call the Win32 PeekMessage function here to read the window + * messages. But since window can stay blocked into this function for a + * long time (for example when you move your window on the screen), I + * decided to isolate PeekMessage in another thread. */ + + /* + * Fullscreen change + */ + if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE + || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) + { + Win32ToggleFullscreen( p_vout ); + + p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; + p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; + } + + /* + * Pointer change + */ + if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden && + (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) + { + POINT point; + HWND hwnd; + + /* Hide the cursor only if it is inside our window */ + GetCursorPos( &point ); + hwnd = WindowFromPoint(point); + if( hwnd == p_vout->p_sys->hwnd || hwnd == p_vout->p_sys->hvideownd ) + { + PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 ); + } + else + { + p_vout->p_sys->i_lastmoved = mdate(); + } + } + + /* + * "Always on top" status change + */ + if( p_vout->p_sys->b_on_top_change ) + { + vlc_value_t val; + HMENU hMenu = GetSystemMenu( p_vout->p_sys->hwnd, FALSE ); + + var_Get( p_vout, "video-on-top", &val ); + + /* Set the window on top if necessary */ + if( val.b_bool && !( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE ) + & WS_EX_TOPMOST ) ) + { + CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP, + MF_BYCOMMAND | MFS_CHECKED ); + SetWindowPos( p_vout->p_sys->hwnd, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE ); + } + else + /* The window shouldn't be on top */ + if( !val.b_bool && ( GetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE ) + & WS_EX_TOPMOST ) ) + { + CheckMenuItem( hMenu, IDM_TOGGLE_ON_TOP, + MF_BYCOMMAND | MFS_UNCHECKED ); + SetWindowPos( p_vout->p_sys->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE ); + } + + p_vout->p_sys->b_on_top_change = VLC_FALSE; + } + + /* Check if the event thread is still running */ + if( p_vout->p_sys->p_event->b_die ) + { + return VLC_EGENERIC; /* exit */ + } + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Render: render previously calculated output + *****************************************************************************/ +static void Render( vout_thread_t *p_vout, picture_t *p_pic ) +{ + /* No need to do anything, the fake direct buffers stay as they are */ +} + +/***************************************************************************** + * Display: displays previously rendered output + *****************************************************************************/ +#define rect_src p_vout->p_sys->rect_src +#define rect_src_clipped p_vout->p_sys->rect_src_clipped +#define rect_dest p_vout->p_sys->rect_dest +#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped + +#ifndef MODULE_NAME_IS_wingapi +static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic ) +{ + vout_sys_t *p_sys = p_vout->p_sys; + RECT rect_dst = rect_dest_clipped; + HDC hdc = GetDC( p_sys->hvideownd ); + + OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top ); + SelectObject( p_sys->off_dc, p_sys->off_bitmap ); + + if( rect_dest_clipped.right - rect_dest_clipped.left != + rect_src_clipped.right - rect_src_clipped.left || + rect_dest_clipped.bottom - rect_dest_clipped.top != + rect_src_clipped.bottom - rect_src_clipped.top ) + { + StretchBlt( hdc, rect_dst.left, rect_dst.top, + rect_dst.right, rect_dst.bottom, + p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top, + rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY ); + } + else + { + BitBlt( hdc, rect_dst.left, rect_dst.top, + rect_dst.right, rect_dst.bottom, + p_sys->off_dc, rect_src_clipped.left, + rect_src_clipped.top, SRCCOPY ); + } + + ReleaseDC( p_sys->hvideownd, hdc ); +} + +static void FirstDisplayGDI( vout_thread_t *p_vout, picture_t *p_pic ) +{ + /* + ** Video window is initially hidden, show it now since we got a + ** picture to show. + */ + SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, + SWP_ASYNCWINDOWPOS| + SWP_FRAMECHANGED| + SWP_SHOWWINDOW| + SWP_NOMOVE| + SWP_NOSIZE| + SWP_NOZORDER ); + + /* get initial picture presented */ + DisplayGDI(p_vout, p_pic); + + /* use and restores proper display function for further pictures */ + p_vout->pf_display = DisplayGDI; +} + +#else + +static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic ) +{ + vout_sys_t *p_sys = p_vout->p_sys; + int i_x, i_y, i_width, i_height; + RECT video_rect; + POINT point; + + GetClientRect( p_sys->hwnd, &video_rect); + vout_PlacePicture( p_vout, video_rect.right - video_rect.left, + video_rect.bottom - video_rect.top, + &i_x, &i_y, &i_width, &i_height ); + point.x = point.y = 0; + ClientToScreen( p_sys->hwnd, &point ); + i_x += point.x + video_rect.left; + i_y += point.y + video_rect.top; + + if( i_width != p_vout->output.i_width || + i_height != p_vout->output.i_height ) + { + GXDisplayProperties gxdisplayprop = GXGetDisplayProperties(); + + p_sys->render_width = i_width; + p_sys->render_height = i_height; + p_vout->i_changes |= VOUT_SIZE_CHANGE; + + msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)", + i_width, i_height, p_vout->output.i_width, + p_vout->output.i_height ); + + p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch; + p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch; + return VLC_EGENERIC; + } + else + { + GXDisplayProperties gxdisplayprop; + RECT display_rect, dest_rect; + uint8_t *p_dest, *p_src = p_pic->p->p_pixels; + + video_rect.left = i_x; video_rect.top = i_y; + video_rect.right = i_x + i_width; + video_rect.bottom = i_y + i_height; + + gxdisplayprop = GXGetDisplayProperties(); + display_rect.left = 0; display_rect.top = 0; + display_rect.right = gxdisplayprop.cxWidth; + display_rect.bottom = gxdisplayprop.cyHeight; + + if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) ) + { + return VLC_EGENERIC; + } + +#if 0 + msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) " + "dest (%d,%d,%d,%d)", + video_rect.left, video_rect.right, + video_rect.top, video_rect.bottom, + display_rect.left, display_rect.right, + display_rect.top, display_rect.bottom, + dest_rect.left, dest_rect.right, + dest_rect.top, dest_rect.bottom ); +#endif + + if( !(p_dest = GXBeginDraw()) ) + { +#if 0 + msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() ); +#endif + return VLC_EGENERIC; + } + + p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch + + (dest_rect.top - video_rect.top) * p_pic->p->i_pitch; + p_dest += dest_rect.left * gxdisplayprop.cbxPitch + + dest_rect.top * gxdisplayprop.cbyPitch; + i_width = dest_rect.right - dest_rect.left; + i_height = dest_rect.bottom - dest_rect.top; + + p_pic->p->p_pixels = p_dest; + } + + return VLC_SUCCESS; +} + +static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic ) +{ + GXEndDraw(); + return VLC_SUCCESS; +} + +static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic ) +{ +} + +static void FirstDisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic ) +{ + /* get initial picture presented through D3D */ + DisplayGAPI(p_vout, p_pic); + + /* + ** Video window is initially hidden, show it now since we got a + ** picture to show. + */ + SetWindowPos( p_vout->p_sys->hvideownd, 0, 0, 0, 0, 0, + SWP_ASYNCWINDOWPOS| + SWP_FRAMECHANGED| + SWP_SHOWWINDOW| + SWP_NOMOVE| + SWP_NOSIZE| + SWP_NOZORDER ); + + /* use and restores proper display function for further pictures */ + p_vout->pf_display = DisplayGAPI; +} + +#endif + +#undef rect_src +#undef rect_src_clipped +#undef rect_dest +#undef rect_dest_clipped +/***************************************************************************** + * SetPalette: sets an 8 bpp palette + *****************************************************************************/ +static void SetPalette( vout_thread_t *p_vout, + uint16_t *red, uint16_t *green, uint16_t *blue ) +{ + msg_Err( p_vout, "FIXME: SetPalette unimplemented" ); +} + +/***************************************************************************** + * InitBuffers: initialize an offscreen bitmap for direct buffer operations. + *****************************************************************************/ +static void InitBuffers( vout_thread_t *p_vout ) +{ + BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader; + BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo; + int i_pixels = p_vout->render.i_height * p_vout->render.i_width; + HDC window_dc = GetDC( p_vout->p_sys->hvideownd ); + + /* Get screen properties */ +#ifdef MODULE_NAME_IS_wingapi + GXDisplayProperties gx_displayprop = GXGetDisplayProperties(); + p_vout->p_sys->i_depth = gx_displayprop.cBPP; +#else + p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) * + GetDeviceCaps( window_dc, BITSPIXEL ); +#endif + msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth ); + +#ifdef MODULE_NAME_IS_wingapi + GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN ); + +#else + + /* Initialize offscreen bitmap */ + memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) ); + + p_header->biSize = sizeof( BITMAPINFOHEADER ); + p_header->biSizeImage = 0; + p_header->biPlanes = 1; + switch( p_vout->p_sys->i_depth ) + { + case 8: + p_header->biBitCount = 8; + p_header->biCompression = BI_RGB; + /* FIXME: we need a palette here */ + break; + case 15: + p_header->biBitCount = 15; + p_header->biCompression = BI_BITFIELDS;//BI_RGB; + ((DWORD*)p_info->bmiColors)[0] = 0x00007c00; + ((DWORD*)p_info->bmiColors)[1] = 0x000003e0; + ((DWORD*)p_info->bmiColors)[2] = 0x0000001f; + break; + case 16: + p_header->biBitCount = 16; + p_header->biCompression = BI_BITFIELDS;//BI_RGB; + ((DWORD*)p_info->bmiColors)[0] = 0x0000f800; + ((DWORD*)p_info->bmiColors)[1] = 0x000007e0; + ((DWORD*)p_info->bmiColors)[2] = 0x0000001f; + break; + case 24: + p_header->biBitCount = 24; + p_header->biCompression = BI_RGB; + ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000; + ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00; + ((DWORD*)p_info->bmiColors)[2] = 0x000000ff; + break; + case 32: + p_header->biBitCount = 32; + p_header->biCompression = BI_RGB; + ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000; + ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00; + ((DWORD*)p_info->bmiColors)[2] = 0x000000ff; + break; + default: + msg_Err( p_vout, "screen depth %i not supported", + p_vout->p_sys->i_depth ); + return; + break; + } + p_header->biWidth = p_vout->render.i_width; + p_header->biHeight = -p_vout->render.i_height; + p_header->biClrImportant = 0; + p_header->biClrUsed = 0; + p_header->biXPelsPerMeter = 0; + p_header->biYPelsPerMeter = 0; + + p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8; + p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8; + + p_vout->p_sys->off_bitmap = + CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS, + (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 ); + + p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc ); + + SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap ); + ReleaseDC( p_vout->p_sys->hvideownd, window_dc ); +#endif +} + diff --git a/modules/video_output/wingdi.c b/modules/video_output/wingdi.c deleted file mode 100644 index 25585071fd..0000000000 --- a/modules/video_output/wingdi.c +++ /dev/null @@ -1,1362 +0,0 @@ -/***************************************************************************** - * wingdi.c : Win32 / WinCE GDI video output plugin for vlc - ***************************************************************************** - * Copyright (C) 2002 the VideoLAN team - * $Id$ - * - * Authors: Gildas Bazin - * Samuel Hocevar - * - * This program is free software; you can redistribute it and/or modify - * 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 - * GNU General Public License for more details. - * - * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. - *****************************************************************************/ - -/***************************************************************************** - * Preamble - *****************************************************************************/ -#include /* malloc(), free() */ -#include - -#include -#include -#include -#include - -#include - -#define SHFS_SHOWSIPBUTTON 0x0004 -#define SHFS_HIDESIPBUTTON 0x0008 - -#if defined(UNDER_CE) && !defined(__PLUGIN__) /*FIXME*/ -# define MENU_HEIGHT 26 - BOOL SHFullScreen(HWND hwndRequester, DWORD dwState); -#else -# define MENU_HEIGHT 0 -# define SHFullScreen(a,b) -#endif - -#ifdef MODULE_NAME_IS_wingapi - typedef struct GXDisplayProperties { - DWORD cxWidth; - DWORD cyHeight; - long cbxPitch; - long cbyPitch; - long cBPP; - DWORD ffFormat; - } GXDisplayProperties; - - typedef struct GXScreenRect { - DWORD dwTop; - DWORD dwLeft; - DWORD dwWidth; - DWORD dwHeight; - } GXScreenRect; - -# define GX_FULLSCREEN 0x01 -# define GX_NORMALKEYS 0x02 -# define GX_LANDSCAPEKEYS 0x03 - -# ifndef kfLandscape -# define kfLandscape 0x8 -# define kfPalette 0x10 -# define kfDirect 0x20 -# define kfDirect555 0x40 -# define kfDirect565 0x80 -# define kfDirect888 0x100 -# define kfDirect444 0x200 -# define kfDirectInverted 0x400 -# endif -#endif /* MODULE_NAME_IS_wingapi */ - -#define MAX_DIRECTBUFFERS 10 - -#ifdef UNDER_CE -#ifndef WS_OVERLAPPEDWINDOW -# define WS_OVERLAPPEDWINDOW 0xcf0000 -#endif -#ifndef WS_EX_NOPARENTNOTIFY -# define WS_EX_NOPARENTNOTIFY 4 -#endif -#ifndef WS_EX_APPWINDOW -#define WS_EX_APPWINDOW 0x40000 -#endif -#define SetWindowLongPtr SetWindowLong -#define GetWindowLongPtr GetWindowLong -#define GWLP_USERDATA GWL_USERDATA -#define AdjustWindowRect(a,b,c) -#endif //UNDER_CE - -#ifndef WS_NONAVDONEBUTTON -#define WS_NONAVDONEBUTTON 0 -#endif -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int OpenVideo ( vlc_object_t * ); -static void CloseVideo ( vlc_object_t * ); - -static int Init ( vout_thread_t * ); -static void End ( vout_thread_t * ); -static int Manage ( vout_thread_t * ); -static void Render ( vout_thread_t *, picture_t * ); -#ifdef MODULE_NAME_IS_wingapi -static void DisplayGAPI( vout_thread_t *, picture_t * ); -static int GAPILockSurface( vout_thread_t *, picture_t * ); -static int GAPIUnlockSurface( vout_thread_t *, picture_t * ); -#else -static void DisplayGDI( vout_thread_t *, picture_t * ); -#endif -static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * ); - -static void EventThread ( vlc_object_t * ); -static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM ); -static void InitBuffers ( vout_thread_t * ); -static void UpdateRects ( vout_thread_t *, vlc_bool_t ); - -static int Control( vout_thread_t *p_vout, int i_query, va_list args ); - -/***************************************************************************** - * Private structure - *****************************************************************************/ -struct vout_sys_t -{ - /* The event thread */ - vlc_object_t * p_event; - - /* Our video output window */ - HWND hwnd; - HWND hvideownd; - HWND hfswnd; - int i_depth; - HWND hparent; /* Handle of the parent window */ - WNDPROC pf_wndproc; /* Window handling callback */ - volatile uint16_t i_changes; /* changes made to the video display */ - RECT window_placement; - - /* Window position and size */ - int i_window_x; - int i_window_y; - int i_window_width; - int i_window_height; - int i_window_style; - int render_width; - int render_height; - - /* Coordinates of src and dest images (used when blitting to display) */ - RECT rect_src; - RECT rect_src_clipped; - RECT rect_dest; - RECT rect_dest_clipped; - RECT rect_parent; - RECT rect_display; - - /* Our offscreen bitmap and its framebuffer */ - HDC off_dc; - HBITMAP off_bitmap; - uint8_t * p_pic_buffer; - int i_pic_pitch; - int i_pic_pixel_pitch; - - BITMAPINFO bitmapinfo; - RGBQUAD red; - RGBQUAD green; - RGBQUAD blue; - - /* WINCE stuff */ - vlc_bool_t b_video_display; - - /* Window focus states */ - vlc_bool_t b_focus; - vlc_bool_t b_parent_focus; - -#ifdef MODULE_NAME_IS_wingapi - HINSTANCE gapi_dll; /* handle of the opened gapi dll */ - - /* GAPI functions */ - int (*GXOpenDisplay)( HWND hWnd, DWORD dwFlags ); - int (*GXCloseDisplay)(); - void *(*GXBeginDraw)(); - int (*GXEndDraw)(); - GXDisplayProperties (*GXGetDisplayProperties)(); - int (*GXSuspend)(); - int (*GXResume)(); -#endif -}; - -#define GXOpenDisplay p_vout->p_sys->GXOpenDisplay -#define GXCloseDisplay p_vout->p_sys->GXCloseDisplay -#define GXBeginDraw p_vout->p_sys->GXBeginDraw -#define GXEndDraw p_vout->p_sys->GXEndDraw -#define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties - -#ifdef MODULE_NAME_IS_wingapi -# define GXSuspend p_vout->p_sys->GXSuspend -# define GXResume p_vout->p_sys->GXResume -#else -# define GXSuspend() -# define GXResume() -#endif - -#define DX_POSITION_CHANGE 0x1000 - -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -vlc_module_begin(); - set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_VOUT ); -#ifdef MODULE_NAME_IS_wingapi - set_shortname( "Windows GAPI" ); - set_description( _("Windows GAPI video output") ); - set_capability( "video output", 20 ); -#else - set_shortname( "Windows GDI" ); - set_description( _("Windows GDI video output") ); - set_capability( "video output", 10 ); -#endif - set_callbacks( OpenVideo, CloseVideo ); -vlc_module_end(); - -/***************************************************************************** - * OpenVideo: activate GDI video thread output method - *****************************************************************************/ -static int OpenVideo ( vlc_object_t *p_this ) -{ - vout_thread_t * p_vout = (vout_thread_t *)p_this; - vlc_value_t val; - - p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) ); - if( !p_vout->p_sys ) return VLC_ENOMEM; - -#ifdef MODULE_NAME_IS_wingapi - /* Load GAPI */ - p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") ); - if( p_vout->p_sys->gapi_dll == NULL ) - { - msg_Warn( p_vout, "failed loading gx.dll" ); - free( p_vout->p_sys ); - return VLC_EGENERIC; - } - - GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") ); - GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXCloseDisplay@@YAHXZ") ); - GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXBeginDraw@@YAPAXXZ") ); - GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXEndDraw@@YAHXZ") ); - GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") ); - GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXSuspend@@YAHXZ") ); - GXResume = GetProcAddress( p_vout->p_sys->gapi_dll, - _T("?GXResume@@YAHXZ") ); - - if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw || - !GXGetDisplayProperties || !GXSuspend || !GXResume ) - { - msg_Err( p_vout, "failed GetProcAddress on gapi.dll" ); - free( p_vout->p_sys ); - return VLC_EGENERIC; - } - - msg_Dbg( p_vout, "GAPI DLL loaded" ); - - p_vout->p_sys->render_width = p_vout->render.i_width; - p_vout->p_sys->render_height = p_vout->render.i_height; -#endif - - p_vout->p_sys->p_event = (vlc_object_t *) - vlc_object_create( p_vout, VLC_OBJECT_GENERIC ); - if( !p_vout->p_sys->p_event ) - { - free( p_vout->p_sys ); - return VLC_ENOMEM; - } - - var_Create( p_vout->p_sys->p_event, "p_vout", VLC_VAR_ADDRESS ); - val.p_address = (void *)p_vout; - var_Set( p_vout->p_sys->p_event, "p_vout", val ); - - SetRectEmpty( &p_vout->p_sys->rect_display ); - SetRectEmpty( &p_vout->p_sys->rect_parent ); - - if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread", - EventThread, 0, 1 ) ) - { - msg_Err( p_vout, "cannot spawn EventThread" ); - return VLC_ETHREAD; - } - - p_vout->pf_init = Init; - p_vout->pf_end = End; - p_vout->pf_manage = Manage; - p_vout->pf_render = Render; -#ifdef MODULE_NAME_IS_wingapi - p_vout->pf_display = DisplayGAPI; -#else - p_vout->pf_display = DisplayGDI; -#endif - p_vout->p_sys->i_changes = 0; - - p_vout->p_sys->b_focus = 0; - p_vout->p_sys->b_parent_focus = 0; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * CloseVideo: deactivate the GDI video output - *****************************************************************************/ -static void CloseVideo ( vlc_object_t *p_this ) -{ - vout_thread_t * p_vout = (vout_thread_t *)p_this; - - p_vout->p_sys->p_event->b_die = VLC_TRUE; - PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0 ); - vlc_thread_join( p_vout->p_sys->p_event ); - -#ifdef MODULE_NAME_IS_wingapi - FreeLibrary( p_vout->p_sys->gapi_dll ); -#endif - - var_Destroy( p_vout->p_sys->p_event, "p_vout" ); - vlc_object_destroy( p_vout->p_sys->p_event ); - free( p_vout->p_sys ); -} - -/***************************************************************************** - * Init: initialize video thread output method - *****************************************************************************/ -static int Init( vout_thread_t *p_vout ) -{ - picture_t *p_pic; - - p_vout->p_sys->rect_display.left = 0; - p_vout->p_sys->rect_display.top = 0; - p_vout->p_sys->rect_display.right = GetSystemMetrics(SM_CXSCREEN); - p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN); - - p_vout->p_sys->b_video_display = VLC_TRUE; - p_vout->p_sys->p_event->b_die = VLC_FALSE; - - I_OUTPUTPICTURES = 0; - - /* Initialize the output structure */ - switch( p_vout->p_sys->i_depth ) - { - case 8: - p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2'); - p_vout->output.pf_setpalette = SetPalette; - break; - case 15: - p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5'); - p_vout->output.i_rmask = 0x7c00; - p_vout->output.i_gmask = 0x03e0; - p_vout->output.i_bmask = 0x001f; - break; - case 16: - p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6'); - p_vout->output.i_rmask = 0xf800; - p_vout->output.i_gmask = 0x07e0; - p_vout->output.i_bmask = 0x001f; - break; - case 24: - p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4'); - p_vout->output.i_rmask = 0x00ff0000; - p_vout->output.i_gmask = 0x0000ff00; - p_vout->output.i_bmask = 0x000000ff; - break; - case 32: - p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2'); - p_vout->output.i_rmask = 0x00ff0000; - p_vout->output.i_gmask = 0x0000ff00; - p_vout->output.i_bmask = 0x000000ff; - break; - default: - msg_Err( p_vout, "screen depth %i not supported", - p_vout->p_sys->i_depth ); - return VLC_EGENERIC; - break; - } - - p_pic = &p_vout->p_picture[0]; - -#ifdef MODULE_NAME_IS_wingapi - p_vout->output.i_width = 0; - p_vout->output.i_height = 0; - p_pic->pf_lock = GAPILockSurface; - p_pic->pf_unlock = GAPIUnlockSurface; - Manage( p_vout ); - GAPILockSurface( p_vout, p_pic ); - p_vout->i_changes = 0; - p_vout->output.i_width = p_vout->p_sys->render_width; - p_vout->output.i_height = p_vout->p_sys->render_height; - -#else - p_vout->output.i_width = p_vout->render.i_width; - p_vout->output.i_height = p_vout->render.i_height; - - p_vout->fmt_out = p_vout->fmt_in; - p_vout->fmt_out.i_chroma = p_vout->output.i_chroma; -#endif - - p_vout->output.i_aspect = p_vout->render.i_aspect; - - p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer; - p_pic->p->i_lines = p_vout->output.i_height; - p_pic->p->i_visible_lines = p_vout->output.i_height; - p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch; - p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch; - p_pic->p->i_visible_pitch = p_vout->output.i_width * - p_pic->p->i_pixel_pitch; - p_pic->i_planes = 1; - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; - - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic; - - return VLC_SUCCESS; -} - -/***************************************************************************** - * End: terminate video thread output method - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) -{ -} - -/***************************************************************************** - * Manage: handle events - ***************************************************************************** - * This function should be called regularly by video output thread. It manages - * console events. It returns a non null value on error. - *****************************************************************************/ -static int Manage( vout_thread_t *p_vout ) -{ -#ifndef UNDER_CE - WINDOWPLACEMENT window_placement; -#endif - - /* If we do not control our window, we check for geometry changes - * ourselves because the parent might not send us its events. */ - if( p_vout->p_sys->hparent && !p_vout->b_fullscreen ) - { - RECT rect_parent; - POINT point; - - GetClientRect( p_vout->p_sys->hparent, &rect_parent ); - point.x = point.y = 0; - ClientToScreen( p_vout->p_sys->hparent, &point ); - OffsetRect( &rect_parent, point.x, point.y ); - - if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) ) - { - int i_x, i_y, i_width, i_height; - p_vout->p_sys->rect_parent = rect_parent; - - /* This one is to force the update even if only - * the position has changed */ - SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1, - rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, 0 ); - - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, 0 ); - - vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left, - rect_parent.bottom - rect_parent.top, - &i_x, &i_y, &i_width, &i_height ); - - SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, - i_x, i_y, i_width, i_height, 0 ); - } - } - - /* We used to call the Win32 PeekMessage function here to read the window - * messages. But since window can stay blocked into this function for a - * long time (for example when you move your window on the screen), I - * decided to isolate PeekMessage in another thread. */ - - /* - * Fullscreen change - */ - if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE - || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE ) - { - int i_style = 0; - vlc_value_t val; - - HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ? - p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd; - - p_vout->b_fullscreen = ! p_vout->b_fullscreen; - - /* We need to switch between Maximized and Normal sized window */ -#ifndef UNDER_CE - window_placement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement( hwnd, &window_placement ); -#endif - if( p_vout->b_fullscreen ) - { -#ifndef UNDER_CE - /* Change window style, no borders and no title bar */ - int i_style = WS_CLIPCHILDREN | WS_VISIBLE; - SetWindowLong( hwnd, GWL_STYLE, i_style ); - - if( p_vout->p_sys->hparent ) - { - /* Retrieve current window position so fullscreen will happen - * on the right screen */ - POINT point = {0,0}; - RECT rect; - ClientToScreen( p_vout->p_sys->hwnd, &point ); - GetClientRect( p_vout->p_sys->hwnd, &rect ); - SetWindowPos( hwnd, 0, point.x, point.y, - rect.right, rect.bottom, - SWP_NOZORDER|SWP_FRAMECHANGED ); - GetWindowPlacement( hwnd, &window_placement ); - } - - /* Maximize window */ - window_placement.showCmd = SW_SHOWMAXIMIZED; - SetWindowPlacement( hwnd, &window_placement ); - SetWindowPos( hwnd, 0, 0, 0, 0, 0, - SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); -#endif - - if( p_vout->p_sys->hparent ) - { - RECT rect; - GetClientRect( hwnd, &rect ); - SetParent( p_vout->p_sys->hwnd, hwnd ); - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect.right, rect.bottom, - SWP_NOZORDER|SWP_FRAMECHANGED ); - } - - ShowWindow( hwnd, SW_SHOW ); - SetForegroundWindow( hwnd ); - } - else - { - /* Change window style, no borders and no title bar */ - //SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style ); - -#ifndef UNDER_CE - /* Normal window */ - window_placement.showCmd = SW_SHOWNORMAL; - SetWindowPlacement( hwnd, &window_placement ); - SetWindowPos( hwnd, 0, 0, 0, 0, 0, - SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); -#endif - - if( p_vout->p_sys->hparent ) - { - RECT rect; - GetClientRect( p_vout->p_sys->hparent, &rect ); - SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent ); - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect.right, rect.bottom, - SWP_NOZORDER|SWP_FRAMECHANGED ); - - ShowWindow( hwnd, SW_HIDE ); - SetForegroundWindow( p_vout->p_sys->hparent ); - } - - /* Make sure the mouse cursor is displayed */ - //PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 ); - } - - /* Change window style, borders and title bar */ - ShowWindow( p_vout->p_sys->hwnd, SW_SHOW ); - UpdateWindow( p_vout->p_sys->hwnd ); - - /* Update the object variable and trigger callback */ - val.b_bool = p_vout->b_fullscreen; - var_Set( p_vout, "fullscreen", val ); - - p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE; - } - - return VLC_SUCCESS; -} - -/***************************************************************************** - * Render: render previously calculated output - *****************************************************************************/ -static void Render( vout_thread_t *p_vout, picture_t *p_pic ) -{ - /* No need to do anything, the fake direct buffers stay as they are */ -} - -/***************************************************************************** - * Display: displays previously rendered output - *****************************************************************************/ -#define rect_src p_vout->p_sys->rect_src -#define rect_src_clipped p_vout->p_sys->rect_src_clipped -#define rect_dest p_vout->p_sys->rect_dest -#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped - -#ifndef MODULE_NAME_IS_wingapi -static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic ) -{ - vout_sys_t *p_sys = p_vout->p_sys; - RECT rect_dst = rect_dest_clipped; - HDC hdc = GetDC( p_sys->hvideownd ); - - OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top ); - SelectObject( p_sys->off_dc, p_sys->off_bitmap ); - - if( rect_dest_clipped.right - rect_dest_clipped.left != - rect_src_clipped.right - rect_src_clipped.left || - rect_dest_clipped.bottom - rect_dest_clipped.top != - rect_src_clipped.bottom - rect_src_clipped.top ) - { - StretchBlt( hdc, rect_dst.left, rect_dst.top, - rect_dst.right, rect_dst.bottom, - p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top, - rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY ); - } - else - { - BitBlt( hdc, rect_dst.left, rect_dst.top, - rect_dst.right, rect_dst.bottom, - p_sys->off_dc, rect_src_clipped.left, - rect_src_clipped.top, SRCCOPY ); - } - - ReleaseDC( p_sys->hwnd, hdc ); -} -#else - -static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic ) -{ - vout_sys_t *p_sys = p_vout->p_sys; - int i_x, i_y, i_width, i_height; - RECT video_rect; - POINT point; - - /* Undo the display */ - if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) || - ( p_sys->b_video_display == VLC_FALSE ) ) - { - //return VLC_EGENERIC; - } - - GetClientRect( p_sys->hwnd, &video_rect); - vout_PlacePicture( p_vout, video_rect.right - video_rect.left, - video_rect.bottom - video_rect.top, - &i_x, &i_y, &i_width, &i_height ); - point.x = point.y = 0; - ClientToScreen( p_sys->hwnd, &point ); - i_x += point.x + video_rect.left; - i_y += point.y + video_rect.top; - - if( i_width != p_vout->output.i_width || - i_height != p_vout->output.i_height ) - { - GXDisplayProperties gxdisplayprop = GXGetDisplayProperties(); - - p_sys->render_width = i_width; - p_sys->render_height = i_height; - p_vout->i_changes |= VOUT_SIZE_CHANGE; - - msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)", - i_width, i_height, p_vout->output.i_width, - p_vout->output.i_height ); - - p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch; - p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch; - return VLC_EGENERIC; - } - else - { - GXDisplayProperties gxdisplayprop; - RECT display_rect, dest_rect; - uint8_t *p_dest, *p_src = p_pic->p->p_pixels; - - video_rect.left = i_x; video_rect.top = i_y; - video_rect.right = i_x + i_width; - video_rect.bottom = i_y + i_height; - - gxdisplayprop = GXGetDisplayProperties(); - display_rect.left = 0; display_rect.top = 0; - display_rect.right = gxdisplayprop.cxWidth; - display_rect.bottom = gxdisplayprop.cyHeight; - - if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) ) - { - return VLC_EGENERIC; - } - -#if 0 - msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) " - "dest (%d,%d,%d,%d)", - video_rect.left, video_rect.right, - video_rect.top, video_rect.bottom, - display_rect.left, display_rect.right, - display_rect.top, display_rect.bottom, - dest_rect.left, dest_rect.right, - dest_rect.top, dest_rect.bottom ); -#endif - - if( !(p_dest = GXBeginDraw()) ) - { -#if 0 - msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() ); -#endif - return VLC_EGENERIC; - } - - p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch + - (dest_rect.top - video_rect.top) * p_pic->p->i_pitch; - p_dest += dest_rect.left * gxdisplayprop.cbxPitch + - dest_rect.top * gxdisplayprop.cbyPitch; - i_width = dest_rect.right - dest_rect.left; - i_height = dest_rect.bottom - dest_rect.top; - - p_pic->p->p_pixels = p_dest; - } - - return VLC_SUCCESS; -} - -static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic ) -{ - GXEndDraw(); - return VLC_SUCCESS; -} - -static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic ) -{ -} -#endif - -#undef rect_src -#undef rect_src_clipped -#undef rect_dest -#undef rect_dest_clipped -/***************************************************************************** - * SetPalette: sets an 8 bpp palette - *****************************************************************************/ -static void SetPalette( vout_thread_t *p_vout, - uint16_t *red, uint16_t *green, uint16_t *blue ) -{ - msg_Err( p_vout, "FIXME: SetPalette unimplemented" ); -} - -/***************************************************************************** - * EventThread: Event handling thread - *****************************************************************************/ -static void EventThread ( vlc_object_t *p_event ) -{ - vout_thread_t *p_vout; - vlc_value_t val; - - int i_style; - WNDCLASS wc; - MSG msg; - - /* Initialisations */ - var_Get( p_event, "p_vout", &val ); - p_vout = (vout_thread_t *)val.p_address; - - /* Register window class */ - memset( &wc, 0, sizeof(wc) ); - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpfnWndProc = (WNDPROC)WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(NULL); - wc.hIcon = 0; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); - wc.lpszMenuName = 0; - wc.lpszClassName = _T("VLC WinGDI"); - RegisterClass( &wc ); - - /* Register the video sub-window class */ - wc.lpszClassName = _T("VLC WinGDI video"); wc.hIcon = 0; - RegisterClass(&wc); - - /* Create output window */ - p_vout->p_sys->hparent = (HWND) - vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x, - &p_vout->p_sys->i_window_y, - (unsigned int *)&p_vout->p_sys->i_window_width, - (unsigned int *)&p_vout->p_sys->i_window_height ); - - if( p_vout->p_sys->hparent ) - ShowWindow( p_vout->p_sys->hparent, SW_SHOW ); - - if( p_vout->p_sys->hparent ) - i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD; - else - i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN; - - p_vout->p_sys->i_window_style = i_style; - - p_vout->p_sys->hwnd = - CreateWindow( _T("VLC WinGDI"), _T(VOUT_TITLE), i_style, - (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT : - p_vout->p_sys->i_window_x, /* default X coordinate */ - (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT : - p_vout->p_sys->i_window_y, /* default Y coordinate */ - p_vout->p_sys->i_window_width, - p_vout->p_sys->i_window_height + 10, - p_vout->p_sys->hparent, NULL, - GetModuleHandle(NULL), (LPVOID)p_vout ); - - if( !p_vout->p_sys->hwnd ) - { - msg_Warn( p_vout, "couldn't create window" ); - return; - } - msg_Warn( p_vout, "Created WinGDI window" ); - - if( p_vout->p_sys->hparent ) - { - LONG i_style; - - /* We don't want the window owner to overwrite our client area */ - i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE ); - - if( !(i_style & WS_CLIPCHILDREN) ) - /* Hmmm, apparently this is a blocking call... */ - SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE, - i_style | WS_CLIPCHILDREN ); - - /* Create our fullscreen window */ - p_vout->p_sys->hfswnd = - CreateWindowEx( WS_EX_APPWINDOW, _T("VLC WinGDI"), - _T(VOUT_TITLE), - WS_NONAVDONEBUTTON|WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, GetModuleHandle(NULL), (LPVOID)p_vout); - } - - /* Display our window */ - ShowWindow( p_vout->p_sys->hwnd, SW_SHOW ); - UpdateWindow( p_vout->p_sys->hwnd ); - - /* Create video sub-window */ - p_vout->p_sys->hvideownd = - CreateWindow( _T("VLC WinGDI video"), _T(""), /* window class */ - WS_CHILD | WS_VISIBLE, /* window style */ - CW_USEDEFAULT, CW_USEDEFAULT, /* default coordinates */ - CW_USEDEFAULT, CW_USEDEFAULT, - p_vout->p_sys->hwnd, /* parent window */ - NULL, GetModuleHandle(NULL), - (LPVOID)p_vout ); /* send p_vout to WM_CREATE */ - - /* Initialize offscreen buffer */ - InitBuffers( p_vout ); - - p_vout->pf_control = Control; - - /* Tell the video output we're ready to receive data */ - vlc_thread_ready( p_event ); - - while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) ) - { - /* Check if we are asked to exit */ - if( p_event->b_die ) break; - - switch( msg.message ) - { - case WM_KEYDOWN: - switch( msg.wParam ) - { - case VK_ESCAPE: - p_event->p_libvlc->b_die = VLC_TRUE; - break; - } - TranslateMessage( &msg ); - break; - - case WM_CHAR: - switch( msg.wParam ) - { - case 'q': - case 'Q': - p_event->p_libvlc->b_die = VLC_TRUE; - break; - } - break; - - default: - TranslateMessage( &msg ); - DispatchMessage( &msg ); - break; - } - } - - msg_Dbg( p_vout, "CloseWindow" ); - -#ifdef MODULE_NAME_IS_wingapi - GXCloseDisplay(); -#else - DeleteDC( p_vout->p_sys->off_dc ); - DeleteObject( p_vout->p_sys->off_bitmap ); -#endif - - DestroyWindow( p_vout->p_sys->hwnd ); - if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd ); - - if( p_vout->p_sys->hparent ) - vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent ); -} - -/***************************************************************************** - * UpdateRects: update clipping rectangles - ***************************************************************************** - * This function is called when the window position or size are changed, and - * its job is to update the source and destination RECTs used to display the - * picture. - *****************************************************************************/ -static void UpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force ) -{ -#define rect_src p_vout->p_sys->rect_src -#define rect_src_clipped p_vout->p_sys->rect_src_clipped -#define rect_dest p_vout->p_sys->rect_dest -#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped - - int i_width, i_height, i_x, i_y; - - RECT rect; - POINT point; - - /* Retrieve the window size */ - GetClientRect( p_vout->p_sys->hwnd, &rect ); - - /* Retrieve the window position */ - point.x = point.y = 0; - ClientToScreen( p_vout->p_sys->hwnd, &point ); - - /* If nothing changed, we can return */ - if( !b_force - && p_vout->p_sys->i_window_width == rect.right - && p_vout->p_sys->i_window_height == rect.bottom - && p_vout->p_sys->i_window_x == point.x - && p_vout->p_sys->i_window_y == point.y ) - { - return; - } - - /* Update the window position and size */ - p_vout->p_sys->i_window_x = point.x; - p_vout->p_sys->i_window_y = point.y; - p_vout->p_sys->i_window_width = rect.right; - p_vout->p_sys->i_window_height = rect.bottom; - - vout_PlacePicture( p_vout, rect.right, rect.bottom, - &i_x, &i_y, &i_width, &i_height ); - - if( p_vout->p_sys->hvideownd ) - SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP, - i_x, i_y, i_width, i_height, 0 ); - - /* Destination image position and dimensions */ - rect_dest.left = point.x + i_x; - rect_dest.right = rect_dest.left + i_width; - rect_dest.top = point.y + i_y; - rect_dest.bottom = rect_dest.top + i_height; - - /* Clip the destination window */ - if( !IntersectRect( &rect_dest_clipped, &rect_dest, - &p_vout->p_sys->rect_display ) ) - { - SetRectEmpty( &rect_src_clipped ); - return; - } - -#if 0 - msg_Dbg( p_vout, "image_dst_clipped coords: %i,%i,%i,%i", - rect_dest_clipped.left, rect_dest_clipped.top, - rect_dest_clipped.right, rect_dest_clipped.bottom ); -#endif - - /* the 2 following lines are to fix a bug when clicking on the desktop */ - if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 || - (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 ) - { - SetRectEmpty( &rect_src_clipped ); - return; - } - - /* src image dimensions */ - rect_src.left = 0; - rect_src.top = 0; - rect_src.right = p_vout->output.i_width; - rect_src.bottom = p_vout->output.i_height; - - /* Clip the source image */ - rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) * - p_vout->output.i_width / (rect_dest.right - rect_dest.left); - rect_src_clipped.right = p_vout->output.i_width - - (rect_dest.right - rect_dest_clipped.right) * p_vout->output.i_width / - (rect_dest.right - rect_dest.left); - rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) * - p_vout->output.i_height / (rect_dest.bottom - rect_dest.top); - rect_src_clipped.bottom = p_vout->output.i_height - - (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->output.i_height / - (rect_dest.bottom - rect_dest.top); - -#if 0 - msg_Dbg( p_vout, "image_src_clipped coords: %i,%i,%i,%i", - rect_src_clipped.left, rect_src_clipped.top, - rect_src_clipped.right, rect_src_clipped.bottom ); -#endif - - /* The destination coordinates need to be relative to the current - * directdraw primary surface (display) */ - rect_dest_clipped.left -= p_vout->p_sys->rect_display.left; - rect_dest_clipped.right -= p_vout->p_sys->rect_display.left; - rect_dest_clipped.top -= p_vout->p_sys->rect_display.top; - rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top; - - /* Signal the change in size/position */ - p_vout->p_sys->i_changes |= DX_POSITION_CHANGE; - -#undef rect_src -#undef rect_src_clipped -#undef rect_dest -#undef rect_dest_clipped -} - -/***************************************************************************** - * Message handler for the main window - *****************************************************************************/ -static long FAR PASCAL WndProc( HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam ) -{ - vout_thread_t *p_vout; - - if( message == WM_CREATE ) - { - /* Store p_vout for future use */ - p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams; - SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)p_vout ); - if( p_vout ) msg_Dbg( p_vout, "create: %p", hWnd ); - } - else - { - p_vout = (vout_thread_t *)GetWindowLongPtr( hWnd, GWLP_USERDATA ); - } - -#ifndef UNDER_CE - /* Catch the screensaver and the monitor turn-off */ - if( message == WM_SYSCOMMAND && - ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) ) - { - //if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" ); - return 0; /* this stops them from happening */ - } -#endif - - if( !p_vout ) - { - /* Hmmm mozilla does manage somehow to save the pointer to our - * windowproc and still calls it after the vout has been closed. */ - return DefWindowProc(hWnd, message, wParam, lParam); - } - - if( hWnd != p_vout->p_sys->hwnd && - hWnd != p_vout->p_sys->hfswnd && - hWnd != p_vout->p_sys->hvideownd ) - return DefWindowProc(hWnd, message, wParam, lParam); - - switch( message ) - { - case WM_WINDOWPOSCHANGED: - if( hWnd == p_vout->p_sys->hwnd ) - UpdateRects( p_vout, VLC_TRUE ); - break; - -#if 0 - case WM_ACTIVATE: - msg_Err( p_vout, "WM_ACTIVATE: %i", wParam ); - if( wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE ) - GXResume(); - else if( wParam == WA_INACTIVE ) - GXSuspend(); - break; -#endif - - case WM_KILLFOCUS: - p_vout->p_sys->b_focus = VLC_FALSE; - if( !p_vout->p_sys->b_parent_focus ) GXSuspend(); - - if( hWnd == p_vout->p_sys->hfswnd ) - { -#ifdef UNDER_CE - HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); - ShowWindow( htbar, SW_SHOW ); -#endif - } - - if( !p_vout->p_sys->hparent || - hWnd == p_vout->p_sys->hfswnd ) - { - SHFullScreen( hWnd, SHFS_SHOWSIPBUTTON ); - } - break; - - case WM_SETFOCUS: - p_vout->p_sys->b_focus = VLC_TRUE; - GXResume(); - - if( p_vout->p_sys->hparent && - hWnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen ) - p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE; - - if( hWnd == p_vout->p_sys->hfswnd ) - { -#ifdef UNDER_CE - HWND htbar = FindWindow( _T("HHTaskbar"), NULL ); - ShowWindow( htbar, SW_HIDE ); -#endif - } - - if( !p_vout->p_sys->hparent || - hWnd == p_vout->p_sys->hfswnd ) - { - SHFullScreen( hWnd, SHFS_HIDESIPBUTTON ); - } - break; - - case WM_LBUTTONDOWN: - p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE; - break; - case WM_MOUSEMOVE: - break; - case WM_LBUTTONUP: - break; - - case WM_INITMENUPOPUP: - p_vout->p_sys->b_video_display = VLC_FALSE; - break; - - case WM_NOTIFY: - // Redo the video display because menu can be closed - // FIXME verify if p_child_window exits - if( (((NMHDR *)lParam)->code) == NM_CUSTOMDRAW ) - p_vout->p_sys->b_video_display = VLC_TRUE; - break; - - /* the user wants to close the window */ - case WM_CLOSE: - { - playlist_t * p_playlist = - (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); - if( p_playlist == NULL ) return 0; - - playlist_Stop( p_playlist ); - vlc_object_release( p_playlist ); - return 0; - } - - case WM_DESTROY: - msg_Dbg( p_vout, "WinProc WM_DESTROY" ); - PostQuitMessage( 0 ); - break; - - default: - return DefWindowProc( hWnd, message, wParam, lParam ); - } - - return 0; -} - -/***************************************************************************** - * InitBuffers: initialize an offscreen bitmap for direct buffer operations. - *****************************************************************************/ -static void InitBuffers( vout_thread_t *p_vout ) -{ - BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader; - BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo; - int i_pixels = p_vout->render.i_height * p_vout->render.i_width; - HDC window_dc = GetDC( p_vout->p_sys->hvideownd ); - - /* Get screen properties */ -#ifdef MODULE_NAME_IS_wingapi - GXDisplayProperties gx_displayprop = GXGetDisplayProperties(); - p_vout->p_sys->i_depth = gx_displayprop.cBPP; -#else - p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) * - GetDeviceCaps( window_dc, BITSPIXEL ); -#endif - msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth ); - -#ifdef MODULE_NAME_IS_wingapi - GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN ); - -#else - - /* Initialize offscreen bitmap */ - memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) ); - - p_header->biSize = sizeof( BITMAPINFOHEADER ); - p_header->biSizeImage = 0; - p_header->biPlanes = 1; - switch( p_vout->p_sys->i_depth ) - { - case 8: - p_header->biBitCount = 8; - p_header->biCompression = BI_RGB; - /* FIXME: we need a palette here */ - break; - case 15: - p_header->biBitCount = 15; - p_header->biCompression = BI_BITFIELDS;//BI_RGB; - ((DWORD*)p_info->bmiColors)[0] = 0x00007c00; - ((DWORD*)p_info->bmiColors)[1] = 0x000003e0; - ((DWORD*)p_info->bmiColors)[2] = 0x0000001f; - break; - case 16: - p_header->biBitCount = 16; - p_header->biCompression = BI_BITFIELDS;//BI_RGB; - ((DWORD*)p_info->bmiColors)[0] = 0x0000f800; - ((DWORD*)p_info->bmiColors)[1] = 0x000007e0; - ((DWORD*)p_info->bmiColors)[2] = 0x0000001f; - break; - case 24: - p_header->biBitCount = 24; - p_header->biCompression = BI_RGB; - ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000; - ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00; - ((DWORD*)p_info->bmiColors)[2] = 0x000000ff; - break; - case 32: - p_header->biBitCount = 32; - p_header->biCompression = BI_RGB; - ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000; - ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00; - ((DWORD*)p_info->bmiColors)[2] = 0x000000ff; - break; - default: - msg_Err( p_vout, "screen depth %i not supported", - p_vout->p_sys->i_depth ); - return; - break; - } - p_header->biWidth = p_vout->render.i_width; - p_header->biHeight = -p_vout->render.i_height; - p_header->biClrImportant = 0; - p_header->biClrUsed = 0; - p_header->biXPelsPerMeter = 0; - p_header->biYPelsPerMeter = 0; - - p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8; - p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8; - - p_vout->p_sys->off_bitmap = - CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS, - (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 ); - - p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc ); - - SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap ); - ReleaseDC( 0, window_dc ); -#endif -} - -/***************************************************************************** - * Control: control facility for the vout - *****************************************************************************/ -static int Control( vout_thread_t *p_vout, int i_query, va_list args ) -{ - unsigned int *pi_width, *pi_height; - vlc_bool_t b_bool; - RECT rect_window; - POINT point; - - switch( i_query ) - { - case VOUT_GET_SIZE: - if( p_vout->p_sys->hparent ) - return vout_ControlWindow( p_vout, - (void *)p_vout->p_sys->hparent, i_query, args ); - - pi_width = va_arg( args, unsigned int * ); - pi_height = va_arg( args, unsigned int * ); - - GetClientRect( p_vout->p_sys->hwnd, &rect_window ); - - *pi_width = rect_window.right - rect_window.left; - *pi_height = rect_window.bottom - rect_window.top; - return VLC_SUCCESS; - - case VOUT_SET_SIZE: - if( p_vout->p_sys->hparent ) - return vout_ControlWindow( p_vout, - (void *)p_vout->p_sys->hparent, i_query, args ); - - /* Update dimensions */ - rect_window.top = rect_window.left = 0; - rect_window.right = va_arg( args, unsigned int ); - rect_window.bottom = va_arg( args, unsigned int ); - if( !rect_window.right ) rect_window.right = p_vout->i_window_width; - if( !rect_window.bottom ) rect_window.bottom = p_vout->i_window_height; - AdjustWindowRect( &rect_window, p_vout->p_sys->i_window_style, 0 ); - - SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0, - rect_window.right - rect_window.left, - rect_window.bottom - rect_window.top, SWP_NOMOVE ); - - return VLC_SUCCESS; - - case VOUT_CLOSE: - ShowWindow( p_vout->p_sys->hwnd, SW_HIDE ); - case VOUT_REPARENT: - /* Change window style, borders and title bar */ - //vlc_mutex_lock( &p_vout->p_sys->lock ); - p_vout->p_sys->hparent = 0; - //vlc_mutex_unlock( &p_vout->p_sys->lock ); - - /* Retrieve the window position */ - point.x = point.y = 0; - ClientToScreen( p_vout->p_sys->hwnd, &point ); - - SetParent( p_vout->p_sys->hwnd, 0 ); - p_vout->p_sys->i_window_style = - WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX; - SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, - p_vout->p_sys->i_window_style | - (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) ); - SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW ); - SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0, - SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED ); - - return vout_vaControlDefault( p_vout, i_query, args ); - - case VOUT_SET_FOCUS: - b_bool = va_arg( args, vlc_bool_t ); - - p_vout->p_sys->b_parent_focus = b_bool; - if( b_bool ) GXResume(); - else if( !p_vout->p_sys->b_focus ) GXSuspend(); - - return VLC_SUCCESS; - - default: - return vout_vaControlDefault( p_vout, i_query, args ); - } -} -- 2.20.1