/*****************************************************************************
* wingdi.c : Win32 / WinCE GDI video output plugin for vlc
*****************************************************************************
- * Copyright (C) 2002 VideoLAN
+ * Copyright (C) 2002 the VideoLAN team
* $Id$
*
- * Authors: Samuel Hocevar <sam@zoy.org>
- * Gildas Bazin <gbazin@videolan.org>
+ * 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
#include <commctrl.h>
+#define SHFS_SHOWSIPBUTTON 0x0004
+#define SHFS_HIDESIPBUTTON 0x0008
+
#ifdef UNDER_CE
-# define SHFS_HIDESIPBUTTON 0x0008
# define MENU_HEIGHT 26
+ BOOL SHFullScreen(HWND hwndRequester, DWORD dwState);
#else
-# define SHFS_HIDESIPBUTTON 0
# define MENU_HEIGHT 0
+# define SHFullScreen(a,b)
#endif
-#undef MODULE_NAME_IS_gapi
-#ifdef MODULE_NAME_IS_gapi
+#ifdef MODULE_NAME_IS_wingapi
typedef struct GXDisplayProperties {
DWORD cxWidth;
DWORD cyHeight;
# define kfDirect444 0x200
# define kfDirectInverted 0x400
# endif
-#endif /* MODULE_NAME_IS_gapi */
+#endif /* MODULE_NAME_IS_wingapi */
#define MAX_DIRECTBUFFERS 10
static void End ( vout_thread_t * );
static int Manage ( vout_thread_t * );
static void Render ( vout_thread_t *, picture_t * );
-#ifdef MODULE_NAME_IS_gapi
+#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 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
*****************************************************************************/
/* Our offscreen bitmap and its framebuffer */
HDC off_dc;
HBITMAP off_bitmap;
- uint8_t * p_buffer;
+ uint8_t * p_pic_buffer;
+ int i_pic_pitch;
+ int i_pic_pixel_pitch;
BITMAPINFO bitmapinfo;
RGBQUAD red;
RGBQUAD blue;
/* WINCE stuff */
- HWND hMenu;
- HWND hTaskBar;
vlc_bool_t b_video_display;
-#ifdef MODULE_NAME_IS_gapi
+ /* 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 */
#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
+
+#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();
-#ifdef MODULE_NAME_IS_gapi
+ 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
p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) );
if( !p_vout->p_sys ) return VLC_ENOMEM;
-#ifdef MODULE_NAME_IS_gapi
+#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 )
p_vout->pf_end = End;
p_vout->pf_manage = Manage;
p_vout->pf_render = Render;
-#ifdef MODULE_NAME_IS_gapi
+#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;
}
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
-#ifdef MODULE_NAME_IS_gapi
- GXCloseDisplay();
- FreeLibrary( p_vout->p_sys->gapi_dll );
-#endif
-
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 );
*****************************************************************************/
static int Init( vout_thread_t *p_vout )
{
- int i_index;
picture_t *p_pic;
p_vout->p_sys->rect_display.left = 0;
break;
}
-#ifdef MODULE_NAME_IS_gapi
+ 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;
#endif
p_vout->output.i_aspect = p_vout->render.i_aspect;
- /* Try to initialize MAX_DIRECTBUFFERS direct buffers */
- while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
- {
- p_pic = NULL;
-
- /* Find an empty picture slot */
- for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
- {
- if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
- {
- p_pic = p_vout->p_picture + i_index;
- break;
- }
- }
-
- /* Allocate the picture */
- if( p_pic == NULL ) break;
-
- vout_AllocatePicture( VLC_OBJECT(p_vout), p_pic,
- p_vout->output.i_chroma,
- p_vout->output.i_width, p_vout->output.i_height,
- p_vout->output.i_aspect );
-
- if( p_pic->i_planes == 0 ) break;
-
- p_pic->i_status = DESTROYED_PICTURE;
- p_pic->i_type = DIRECT_PICTURE;
+ 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;
-
- I_OUTPUTPICTURES++;
- }
+ PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
return VLC_SUCCESS;
}
*****************************************************************************/
static void End( vout_thread_t *p_vout )
{
- int i_index;
-
- /* Free the fake output buffers we allocated */
- for( i_index = I_OUTPUTPICTURES ; i_index ; )
- {
- i_index--;
- free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
- }
}
/*****************************************************************************
//PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
}
-#ifdef MODULE_NAME_IS_gapi
- GXCloseDisplay();
-#endif
-
/* Change window style, borders and title bar */
ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
UpdateWindow( p_vout->p_sys->hwnd );
-#ifdef MODULE_NAME_IS_gapi
- GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
-#endif
-
/* Update the object variable and trigger callback */
val.b_bool = p_vout->b_fullscreen;
var_Set( p_vout, "fullscreen", val );
#define rect_dest p_vout->p_sys->rect_dest
#define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
-#ifndef MODULE_NAME_IS_gapi
+#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;
- int i_src_bytes, i_dest_bytes;
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 1
- /* Stupid GDI is upside-down */
- i_src_bytes = p_pic->p->i_lines * p_pic->p->i_pitch;
- i_dest_bytes = 0;
-
- while( i_src_bytes )
- {
- i_src_bytes -= p_pic->p->i_pitch;
-
- p_vout->p_vlc->pf_memcpy( p_sys->p_buffer + i_dest_bytes,
- p_pic->p->p_pixels + i_src_bytes,
- p_pic->p->i_visible_pitch );
-
- i_dest_bytes += p_pic->p->i_pitch;
- }
-#endif
-
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 !=
}
#else
-static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
+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;
if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) ||
( p_sys->b_video_display == VLC_FALSE ) )
{
- return;
+ //return VLC_EGENERIC;
}
GetClientRect( p_sys->hwnd, &video_rect);
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
{
if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
{
- return;
+ return VLC_EGENERIC;
}
#if 0
if( !(p_dest = GXBeginDraw()) )
{
+#if 0
msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
- return;
+#endif
+ return VLC_EGENERIC;
}
p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
i_width = dest_rect.right - dest_rect.left;
i_height = dest_rect.bottom - dest_rect.top;
- while( i_height-- )
- {
- p_vout->p_vlc->pf_memcpy( p_dest, p_src,
- i_width * gxdisplayprop.cbxPitch );
- p_src += p_pic->p->i_pitch;
- p_dest += gxdisplayprop.cbyPitch;
- }
+ 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
WNDCLASS wc;
MSG msg;
+ /* Initialisations */
var_Get( p_event, "p_vout", &val );
p_vout = (vout_thread_t *)val.p_address;
RegisterClass(&wc);
/* Create output window */
- p_vout->p_sys->hparent = p_vout->p_sys->hwnd = (HWND)
+ 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 );
- ShowWindow( p_vout->p_sys->hparent, SW_SHOW );
+ 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;
WS_NONAVDONEBUTTON|WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, GetModuleHandle(NULL), NULL );
+ NULL, NULL, GetModuleHandle(NULL), (LPVOID)p_vout);
}
/* Display our window */
NULL, GetModuleHandle(NULL),
(LPVOID)p_vout ); /* send p_vout to WM_CREATE */
- ShowWindow( p_vout->p_sys->hvideownd, SW_SHOW );
-
/* 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 );
}
break;
-#ifdef MODULE_NAME_IS_gapi
- case WM_KILLFOCUS:
- GXSuspend();
- break;
-
- case WM_SETFOCUS:
- GXResume();
- break;
-#endif
-
default:
TranslateMessage( &msg );
DispatchMessage( &msg );
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 );
-
- DeleteDC( p_vout->p_sys->off_dc );
- DeleteObject( p_vout->p_sys->off_bitmap );
}
/*****************************************************************************
/*****************************************************************************
* Message handler for the main window
*****************************************************************************/
-static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
- WPARAM wParam, LPARAM lParam )
+static long FAR PASCAL WndProc( HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam )
{
vout_thread_t *p_vout;
return DefWindowProc(hWnd, message, wParam, lParam);
}
- if( hWnd != p_vout->p_sys->hwnd )
+ 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:
- UpdateRects( p_vout, VLC_TRUE );
+ 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_LBUTTONUP:
break;
- case WM_CREATE:
- break;
-
case WM_INITMENUPOPUP:
p_vout->p_sys->b_video_display = VLC_FALSE;
break;
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;
-
- window_dc = GetDC( p_vout->p_sys->hvideownd );
+ HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
/* Get screen properties */
-#ifdef MODULE_NAME_IS_gapi
- {
+#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_gapi
- if( p_vout->b_fullscreen )
- {
- /* We need to restore Maximized sized window */
- GetWindowRect( p_vout->p_sys->hwnd,
- &p_vout->p_sys->window_placement );
-
- /* Maximized window */
- if( p_vout->p_sys->hparent )
- {
- SetWindowPos( GetParent( p_vout->p_sys->hwnd ), HWND_TOP,
- 0, 0, GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
- SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
- 0, 0, GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW );
-
-#ifdef UNDER_CE
- /* Hide SIP button, taskbar and menubar */
- SHFullScreen( GetParent(p_vout->p_sys->hwnd),
- SHFS_HIDESIPBUTTON );
- p_vout->p_sys->hTaskBar = FindWindow(_T("HHTaskbar"),NULL);
- ShowWindow( p_vout->p_sys->hTaskBar, SW_HIDE);
- p_vout->p_sys->hMenu =
- SHFindMenuBar( GetParent( p_vout->p_sys->hwnd ) );
- ShowWindow( p_vout->p_sys->hMenu,SW_HIDE );
-#endif
- }
- else
- {
- SetWindowPos( p_vout->p_sys->hwnd, HWND_TOP,
- 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, SWP_SHOWWINDOW );
- }
-
- GXCloseDisplay();
- }
-
+#ifdef MODULE_NAME_IS_wingapi
GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
+
#else
/* Initialize offscreen bitmap */
break;
}
p_header->biWidth = p_vout->render.i_width;
- p_header->biHeight = p_vout->render.i_height;
+ 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_buffer, NULL, 0 );
+ (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
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 )
+{
+ vlc_bool_t b_bool;
+
+ switch( i_query )
+ {
+ 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 );
+ }
+}