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
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
vout.h \
events.c \
$(NULL)
+
+SOURCES_wingdi = \
+ wingdi.c \
+ vout.h \
+ events.c \
+ $(NULL)
+
+SOURCES_wingapi = \
+ windi.c \
+ vout.h \
+ events.c \
+ $(NULL)
#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.
*****************************************************************************/
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();
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;
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 */
{
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 )
{
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);
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
// 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) )
{
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.
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;
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;
}
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
{
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 )
{
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
{
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 );
}
/*
{
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 )
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;
}
/* 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;
}
/*****************************************************************************
- * 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;
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;
}
DirectXUnlockSurface( p_vout, &front_pic );
}
- E_(DirectXUpdateOverlay)( p_vout );
+ DirectDrawUpdateOverlay( p_vout );
I_OUTPUTPICTURES = 1;
msg_Dbg( p_vout, "YUV overlay created successfully" );
}
#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.
*****************************************************************************/
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;
/* Signal the creation of the window */
vlc_thread_ready( p_event );
+#ifndef UNDER_CE
/* Set power management stuff */
if( (hkernel32 = GetModuleHandle( _T("KERNEL32") ) ) )
{
else
msg_Dbg( p_event, "no support for SetThreadExecutionState()" );
}
+#endif
/* Main loop */
/* GetMessage will sleep if there's no message in the queue */
{
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
#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
}
}
/*****************************************************************************
- * 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
}
#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
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 */
}
}
+#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( hwnd == p_vout->p_sys->hvideownd )
{
{
case WM_WINDOWPOSCHANGED:
- E_(DirectXUpdateRects)( p_vout, VLC_TRUE );
+ E_(UpdateRects)( p_vout, VLC_TRUE );
return 0;
/* the user wants to close the window */
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;
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 );
}
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 );
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;
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 */
{
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 )
{
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
/*****************************************************************************
- * 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 <gbazin@videolan.org>
+ * Damien Fouilleul <damienf@videolan.org>
*
* 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
*****************************************************************************/
/*****************************************************************************
- * event_thread_t: DirectX event thread
+ * event_thread_t: event thread
*****************************************************************************/
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
{
/* 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;
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;
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 */
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 );
/*****************************************************************************
--- /dev/null
+/*****************************************************************************
+ * 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 <gbazin@videolan.org>
+ * Samuel Hocevar <sam@zoy.org>
+ *
+ * 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 <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc_interface.h>
+#include <vlc_playlist.h>
+#include <vlc_vout.h>
+
+#include <commctrl.h>
+
+#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
+}
+
+++ /dev/null
-/*****************************************************************************
- * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
- *****************************************************************************
- * Copyright (C) 2002 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- * Samuel Hocevar <sam@zoy.org>
- *
- * 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 <stdlib.h> /* malloc(), free() */
-#include <string.h>
-
-#include <vlc/vlc.h>
-#include <vlc_interface.h>
-#include <vlc_playlist.h>
-#include <vlc_vout.h>
-
-#include <commctrl.h>
-
-#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 );
- }
-}