/*****************************************************************************
* vout.c: Windows DirectX video output display method
*****************************************************************************
- * Copyright (C) 2001-2004 VideoLAN
+ * Copyright (C) 2001-2004 the VideoLAN team
* $Id$
*
- * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ * Authors: Gildas Bazin <gbazin@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
#include <windows.h>
#include <ddraw.h>
+#include <commctrl.h>
-#include <multimon.h>
+#ifndef UNDER_CE
+# include <multimon.h>
+#endif
#undef GetSystemMetrics
#ifndef MONITOR_DEFAULTTONEAREST
static void End ( vout_thread_t * );
static int Manage ( vout_thread_t * );
static void Display ( vout_thread_t *, picture_t * );
+static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
static int NewPictureVec ( vout_thread_t *, picture_t *, int );
static void FreePictureVec ( vout_thread_t *, picture_t *, int );
static int DirectXLockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
static int DirectXUnlockSurface ( vout_thread_t *p_vout, picture_t *p_pic );
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color );
+static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *i_color );
+
+void SwitchWallpaperMode( vout_thread_t *, vlc_bool_t );
/* Object variables callbacks */
-static int OnTopCallback( vlc_object_t *, char const *,
- vlc_value_t, vlc_value_t, void * );
static int FindDevicesCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
+static int WallpaperCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
/*****************************************************************************
* Module descriptor
#define TRIPLEBUF_TEXT N_("Use triple buffering for overlays")
#define TRIPLEBUF_LONGTEXT N_( \
- "Try to use triple bufferring when using YUV overlays. That results in " \
+ "Try to use triple buffering when using YUV overlays. That results in " \
"much better video quality (no flickering)." )
#define DEVICE_TEXT N_("Name of desired display device")
-#define DEVICE_LONGTEXT N_("In a multimonitor configuration, you can specify "\
- "the Windows device name of the display that you want the video window " \
- "to open on. For example, \"\\\\.\\DISPLAY1\" or \"\\\\.\\DISPLAY2\"." )
+#define DEVICE_LONGTEXT N_("In a multiple monitor configuration, you can " \
+ "specify the Windows device name of the display that you want the video " \
+ "window to open on. For example, \"\\\\.\\DISPLAY1\" or " \
+ "\"\\\\.\\DISPLAY2\"." )
+
+#define WALLPAPER_TEXT N_("Enable wallpaper mode ")
+#define WALLPAPER_LONGTEXT N_( \
+ "The wallpaper mode allows you to display the video as the desktop " \
+ "background. Note that this feature only works in overlay mode and " \
+ "the desktop must not already have a wallpaper." )
static char *ppsz_dev[] = { "" };
static char *ppsz_dev_text[] = { N_("Default") };
vlc_module_begin();
+ set_shortname( "DirectX" );
+ set_category( CAT_VIDEO );
+ set_subcategory( SUBCAT_VIDEO_VOUT );
add_bool( "directx-hw-yuv", 1, NULL, HW_YUV_TEXT, HW_YUV_LONGTEXT,
VLC_TRUE );
add_bool( "directx-use-sysmem", 0, NULL, SYSMEM_TEXT, SYSMEM_LONGTEXT,
change_string_list( ppsz_dev, ppsz_dev_text, FindDevicesCallback );
change_action_add( FindDevicesCallback, N_("Refresh list") );
+ add_bool( "directx-wallpaper", 0, NULL, WALLPAPER_TEXT, WALLPAPER_LONGTEXT,
+ VLC_TRUE );
+
set_description( _("DirectX video output") );
set_capability( "video output", 100 );
add_shortcut( "directx" );
set_callbacks( OpenVideo, CloseVideo );
+
+ /* FIXME: Hack to avoid unregistering our window class */
+ linked_with_a_crap_library_which_uses_atexit( );
vlc_module_end();
#if 0 /* FIXME */
static int OpenVideo( vlc_object_t *p_this )
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
- vlc_value_t val, text;
+ vlc_value_t val;
HMODULE huser32;
/* Allocate structure */
p_vout->p_sys->p_current_surface = NULL;
p_vout->p_sys->p_clipper = NULL;
p_vout->p_sys->hwnd = p_vout->p_sys->hvideownd = NULL;
- p_vout->p_sys->hparent = NULL;
+ p_vout->p_sys->hparent = p_vout->p_sys->hfswnd = NULL;
p_vout->p_sys->i_changes = 0;
- SetRectEmpty( &p_vout->p_sys->rect_display );
+ 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 );
/* Multimonitor stuff */
p_vout->p_sys->hmonitor = NULL;
p_vout->p_sys->p_display_driver = NULL;
p_vout->p_sys->MonitorFromWindow = NULL;
p_vout->p_sys->GetMonitorInfo = NULL;
- if( (huser32 = GetModuleHandle( "USER32" ) ) )
+ if( (huser32 = GetModuleHandle( _T("USER32") ) ) )
{
- p_vout->p_sys->MonitorFromWindow =
- GetProcAddress( huser32, "MonitorFromWindow" );
+ p_vout->p_sys->MonitorFromWindow = (HMONITOR (WINAPI *)( HWND, DWORD ))
+ GetProcAddress( huser32, _T("MonitorFromWindow") );
p_vout->p_sys->GetMonitorInfo =
+#ifndef UNICODE
GetProcAddress( huser32, "GetMonitorInfoA" );
+#else
+ GetProcAddress( huser32, _T("GetMonitorInfoW") );
+#endif
}
var_Create( p_vout, "overlay", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
var_Create( p_vout, "directx-hw-yuv", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
var_Create( p_vout, "directx-3buffering", 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 );
p_vout->p_sys->b_cursor_hidden = 0;
p_vout->p_sys->i_lastmoved = mdate();
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",
- DirectXEventThread, 0, 1 ) )
+ E_(DirectXEventThread), 0, 1 ) )
{
msg_Err( p_vout, "cannot create DirectXEventThread" );
vlc_object_destroy( p_vout->p_sys->p_event );
goto error;
}
- /* Add a variable to indicate if the window should be on top of others */
- var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
- text.psz_string = _("Always on top");
- var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT, &text, NULL );
+ /* 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 );
- p_vout->p_sys->b_on_top_change = val.b_bool;
- var_AddCallback( p_vout, "video-on-top", OnTopCallback, NULL );
+ var_Set( p_vout, "video-on-top", val );
+
+ /* Variable to indicate if the window should be on top of others */
+ /* Trigger a callback right now */
+ var_Create( p_vout, "directx-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+ val.psz_string = _("Wallpaper");
+ var_Change( p_vout, "directx-wallpaper", VLC_VAR_SETTEXT, &val, NULL );
+ var_AddCallback( p_vout, "directx-wallpaper", WallpaperCallback, NULL );
+ var_Get( p_vout, "directx-wallpaper", &val );
+ var_Set( p_vout, "directx-wallpaper", val );
return VLC_SUCCESS;
p_vout->output.i_width = p_vout->render.i_width;
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 );
#define MAX_DIRECTBUFFERS 1
/* Right now we use only 1 directbuffer because we don't want the
if( !I_OUTPUTPICTURES )
{
/* hmmm, it didn't work! Let's try commonly supported chromas */
- if( p_vout->output.i_chroma != VLC_FOURCC('Y','V','1','2') )
+ if( p_vout->output.i_chroma != VLC_FOURCC('I','4','2','0') )
{
p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
NewPictureVec( p_vout, p_vout->p_picture, MAX_DIRECTBUFFERS );
}
/* Change the window title bar text */
- if( p_vout->p_sys->hparent ) ; /* Do nothing */
- else PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+ PostMessage( p_vout->p_sys->hwnd, WM_VLC_CHANGE_TEXT, 0, 0 );
+ p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
return VLC_SUCCESS;
}
msg_Dbg( p_vout, "CloseVideo" );
- var_Destroy( p_vout, "video-on-top" );
-
if( p_vout->p_sys->p_event )
{
vlc_object_detach( p_vout->p_sys->p_event );
vlc_object_destroy( p_vout->p_sys->p_event );
}
+ vlc_mutex_destroy( &p_vout->p_sys->lock );
+
+ /* Make sure the wallpaper is restored */
+ SwitchWallpaperMode( p_vout, VLC_FALSE );
+
if( p_vout->p_sys )
{
free( p_vout->p_sys );
* Manage: handle Sys events
*****************************************************************************
* This function should be called regularly by the video output thread.
- * It returns a non null value if an error occured.
+ * It returns a non null value if an error occurred.
*****************************************************************************/
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. */
- if( p_vout->p_sys->hparent )
+ 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 ) )
+ {
+ 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 );
+ }
+ }
+ else
{
- DirectXUpdateRects( p_vout, VLC_FALSE );
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
}
/*
*/
if( p_vout->p_sys->i_changes & DX_POSITION_CHANGE )
{
- if( p_vout->p_sys->b_using_overlay )
- DirectXUpdateOverlay( p_vout );
+ p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
/* Check if we are still on the same monitor */
if( p_vout->p_sys->MonitorFromWindow &&
/* This will force the vout core to recreate the picture buffers */
p_vout->i_changes |= VOUT_PICTURE_BUFFERS_CHANGE;
}
+ }
- p_vout->p_sys->i_changes &= ~DX_POSITION_CHANGE;
+ /* 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_(DirectXUpdateRects)( p_vout, VLC_TRUE );
}
/* We used to call the Win32 PeekMessage function here to read the window
* long time (for example when you move your window on the screen), I
* decided to isolate PeekMessage in another thread. */
+ if( p_vout->p_sys->i_changes & DX_WALLPAPER_CHANGE )
+ {
+ SwitchWallpaperMode( p_vout, !p_vout->p_sys->b_wallpaper );
+ p_vout->p_sys->i_changes &= ~DX_WALLPAPER_CHANGE;
+ E_(DirectXUpdateOverlay)( p_vout );
+ }
+
/*
* Fullscreen change
*/
|| p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
{
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 */
window_placement.length = sizeof(WINDOWPLACEMENT);
- GetWindowPlacement( p_vout->p_sys->hwnd, &window_placement );
+ GetWindowPlacement( hwnd, &window_placement );
if( p_vout->b_fullscreen )
{
- /* Maximized window */
- window_placement.showCmd = SW_SHOWMAXIMIZED;
/* Change window style, no borders and no title bar */
- SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, WS_CLIPCHILDREN );
+ 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);
+ 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 );
+ }
+
+ SetForegroundWindow( hwnd );
}
else
{
+ /* Change window style, no borders and no title bar */
+ SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
+
/* Normal window */
window_placement.showCmd = SW_SHOWNORMAL;
- /* Change window style, borders and title bar */
- SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE, WS_CLIPCHILDREN |
- WS_OVERLAPPEDWINDOW | WS_SIZEBOX | WS_VISIBLE );
- }
+ SetWindowPlacement( hwnd, &window_placement );
+ SetWindowPos( hwnd, 0, 0, 0, 0, 0,
+ SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
- SetWindowPlacement( p_vout->p_sys->hwnd, &window_placement );
+ 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 );
+ }
/* Update the object variable and trigger callback */
val.b_bool = p_vout->b_fullscreen;
/*
* Pointer change
*/
- if( (!p_vout->p_sys->b_cursor_hidden) &&
- ( (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 ) )
+ if( p_vout->b_fullscreen && !p_vout->p_sys->b_cursor_hidden &&
+ (mdate() - p_vout->p_sys->i_lastmoved) > 5000000 )
{
- /* Hide the mouse automatically */
- if( p_vout->p_sys->hwnd != p_vout->p_sys->hparent )
+ 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 )
{
- p_vout->p_sys->b_cursor_hidden = VLC_TRUE;
PostMessage( p_vout->p_sys->hwnd, WM_VLC_HIDE_MOUSE, 0, 0 );
}
+ else
+ {
+ p_vout->p_sys->i_lastmoved = mdate();
+ }
}
/*
{
if( IDirectDrawSurface2_Restore( p_vout->p_sys->p_display ) == DD_OK &&
p_vout->p_sys->b_using_overlay )
- DirectXUpdateOverlay( p_vout );
+ E_(DirectXUpdateOverlay)( p_vout );
}
if( !p_vout->p_sys->b_using_overlay )
msg_Dbg( p_vout, "DirectXInitDDraw" );
/* Load direct draw DLL */
- p_vout->p_sys->hddraw_dll = LoadLibrary("DDRAW.DLL");
+ p_vout->p_sys->hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
if( p_vout->p_sys->hddraw_dll == NULL )
{
msg_Warn( p_vout, "DirectXInitDDraw failed loading ddraw.dll" );
}
OurDirectDrawCreate =
- (void *)GetProcAddress(p_vout->p_sys->hddraw_dll, "DirectDrawCreate");
+ (void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
+ _T("DirectDrawCreate") );
if( OurDirectDrawCreate == NULL )
{
msg_Err( p_vout, "DirectXInitDDraw failed GetProcAddress" );
OurDirectDrawEnumerateEx =
(void *)GetProcAddress( p_vout->p_sys->hddraw_dll,
+#ifndef UNICODE
"DirectDrawEnumerateExA" );
+#else
+ _T("DirectDrawEnumerateExW") );
+#endif
if( OurDirectDrawEnumerateEx && p_vout->p_sys->MonitorFromWindow )
{
/* Make sure the colorkey will be painted */
p_vout->p_sys->i_colorkey = 1;
p_vout->p_sys->i_rgb_colorkey =
- DirectXFindColorkey( p_vout, p_vout->p_sys->i_colorkey );
+ DirectXFindColorkey( p_vout, &p_vout->p_sys->i_colorkey );
/* Create the actual brush */
SetClassLong( p_vout->p_sys->hvideownd, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush( p_vout->p_sys->i_rgb_colorkey ) );
InvalidateRect( p_vout->p_sys->hvideownd, NULL, TRUE );
- DirectXUpdateRects( p_vout, VLC_TRUE );
+ E_(DirectXUpdateRects)( 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( DirectXUpdateOverlay( p_vout ) != VLC_SUCCESS )
+ if( E_(DirectXUpdateOverlay)( p_vout ) != VLC_SUCCESS )
{
IDirectDrawSurface2_Release( *pp_surface_final );
*pp_surface_final = NULL;
* Ususally the overlay is moved by the user and thus, by a move or resize
* event (in Manage).
*****************************************************************************/
-int DirectXUpdateOverlay( vout_thread_t *p_vout )
+int E_(DirectXUpdateOverlay)( vout_thread_t *p_vout )
{
DDOVERLAYFX ddofx;
DWORD dwFlags;
HRESULT dxresult;
+ RECT rect_src = p_vout->p_sys->rect_src_clipped;
+ RECT rect_dest = p_vout->p_sys->rect_dest_clipped;
+
+ if( !p_vout->p_sys->b_using_overlay ) return VLC_EGENERIC;
- if( p_vout->p_sys->p_current_surface == NULL ||
- !p_vout->p_sys->b_using_overlay )
+ if( p_vout->p_sys->b_wallpaper )
+ {
+ int i_x, i_y, i_width, i_height;
+
+ rect_src.left = p_vout->fmt_out.i_x_offset;
+ rect_src.top = p_vout->fmt_out.i_y_offset;
+ rect_src.right = rect_src.left + p_vout->fmt_out.i_visible_width;
+ rect_src.bottom = rect_src.top + p_vout->fmt_out.i_visible_height;
+
+ rect_dest = p_vout->p_sys->rect_display;
+ vout_PlacePicture( p_vout, rect_dest.right, rect_dest.bottom,
+ &i_x, &i_y, &i_width, &i_height );
+
+ rect_dest.left += i_x;
+ rect_dest.right = rect_dest.left + i_width;
+ rect_dest.top += i_y;
+ rect_dest.bottom = rect_dest.top + i_height;
+ }
+
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ if( p_vout->p_sys->p_current_surface == NULL )
+ {
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
return VLC_EGENERIC;
+ }
/* The new window dimensions should already have been computed by the
* caller of this function */
dwFlags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;
dxresult = IDirectDrawSurface2_UpdateOverlay(
- p_vout->p_sys->p_current_surface,
- &p_vout->p_sys->rect_src_clipped,
- p_vout->p_sys->p_display,
- &p_vout->p_sys->rect_dest_clipped,
- dwFlags, &ddofx );
+ p_vout->p_sys->p_current_surface,
+ &rect_src, p_vout->p_sys->p_display, &rect_dest,
+ dwFlags, &ddofx );
+
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+
if(dxresult != DD_OK)
{
- msg_Warn( p_vout,
- "DirectXUpdateOverlay cannot move or resize overlay" );
+ msg_Warn( p_vout, "DirectXUpdateOverlay cannot move/resize overlay" );
return VLC_EGENERIC;
}
{
int i,j;
for( i = 0; i < front_pic.i_planes; i++ )
- for( j = 0; j < front_pic.p[i].i_lines; j++)
+ for( j = 0; j < front_pic.p[i].i_visible_lines; j++)
memset( front_pic.p[i].p_pixels + j *
front_pic.p[i].i_pitch, 127,
front_pic.p[i].i_visible_pitch );
DirectXUnlockSurface( p_vout, &front_pic );
}
- DirectXUpdateOverlay( p_vout );
+ E_(DirectXUpdateOverlay)( p_vout );
I_OUTPUTPICTURES = 1;
msg_Dbg( p_vout, "YUV overlay created successfully" );
}
{
switch( ddpfPixelFormat.dwRGBBitCount )
{
- case 8: /* FIXME: set the palette */
+ 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_pic[i].i_status = DESTROYED_PICTURE;
p_pic[i].i_type = DIRECT_PICTURE;
+ p_pic[i].b_slow = VLC_TRUE;
p_pic[i].pf_lock = DirectXLockSurface;
p_pic[i].pf_unlock = DirectXUnlockSurface;
PP_OUTPUTPICTURE[i] = &p_pic[i];
{
int i;
+ vlc_mutex_lock( &p_vout->p_sys->lock );
+ p_vout->p_sys->p_current_surface = 0;
+ vlc_mutex_unlock( &p_vout->p_sys->lock );
+
for( i = 0; i < i_num_pics; i++ )
{
DirectXCloseSurface( p_vout, p_pic[i].p_sys->p_front_surface );
free( p_pic[i].p_sys );
}
}
-
- p_vout->p_sys->p_current_surface = 0;
}
/*****************************************************************************
case VLC_FOURCC('R','V','3','2'):
p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
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_pic->p_sys->ddsd.lPitch;
switch( p_vout->output.i_chroma )
{
break;
case VLC_FOURCC('Y','V','1','2'):
+ case VLC_FOURCC('I','4','2','0'):
+
+ /* U and V inverted compared to I420
+ * Fixme: this should be handled by the vout core */
+ p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
p_pic->p[Y_PLANE].i_pixel_pitch = 1;
p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
p_pic->V_PIXELS = p_pic->Y_PIXELS
+ p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
p_pic->p[V_PLANE].i_pixel_pitch = 1;
p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
p_pic->U_PIXELS = p_pic->V_PIXELS
+ p_pic->p[V_PLANE].i_lines * p_pic->p[V_PLANE].i_pitch;
p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
p_pic->p[U_PLANE].i_pixel_pitch = 1;
p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
p_pic->Y_PIXELS = p_pic->p_sys->ddsd.lpSurface;
p_pic->p[Y_PLANE].i_lines = p_vout->output.i_height;
+ p_pic->p[Y_PLANE].i_visible_lines = p_vout->output.i_height;
p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->ddsd.lPitch;
p_pic->p[Y_PLANE].i_pixel_pitch = 1;
p_pic->p[Y_PLANE].i_visible_pitch = p_vout->output.i_width *
p_pic->U_PIXELS = p_pic->Y_PIXELS
+ p_pic->p[Y_PLANE].i_lines * p_pic->p[Y_PLANE].i_pitch;
p_pic->p[U_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[U_PLANE].i_visible_lines = p_vout->output.i_height / 2;
p_pic->p[U_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
p_pic->p[U_PLANE].i_pixel_pitch = 1;
p_pic->p[U_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
p_pic->V_PIXELS = p_pic->U_PIXELS
+ p_pic->p[U_PLANE].i_lines * p_pic->p[U_PLANE].i_pitch;
p_pic->p[V_PLANE].i_lines = p_vout->output.i_height / 2;
+ p_pic->p[V_PLANE].i_visible_lines = p_vout->output.i_height / 2;
p_pic->p[V_PLANE].i_pitch = p_pic->p[Y_PLANE].i_pitch / 2;
p_pic->p[V_PLANE].i_pixel_pitch = 1;
p_pic->p[V_PLANE].i_visible_pitch = p_vout->output.i_width / 2 *
p_pic->i_planes = 3;
break;
+ case VLC_FOURCC('U','Y','V','Y'):
case VLC_FOURCC('Y','U','Y','2'):
p_pic->p->p_pixels = p_pic->p_sys->ddsd.lpSurface;
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_pic->p_sys->ddsd.lPitch;
p_pic->p->i_pixel_pitch = 2;
p_pic->p->i_visible_pitch = p_vout->output.i_width *
dxresult = IDirectDrawSurface2_Lock( p_pic->p_sys->p_surface, NULL,
&p_pic->p_sys->ddsd,
DDLOCK_WAIT, NULL);
+#if 0
if( dxresult == DDERR_SURFACELOST )
msg_Dbg( p_vout, "DirectXLockSurface: DDERR_SURFACELOST" );
+#endif
}
if( dxresult != DD_OK )
{
/*****************************************************************************
* DirectXFindColorkey: Finds out the 32bits RGB pixel value of the colorkey
*****************************************************************************/
-static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t i_color )
+static DWORD DirectXFindColorkey( vout_thread_t *p_vout, uint32_t *pi_color )
{
DDSURFACEDESC ddsd;
HRESULT dxresult;
switch( ddsd.ddpfPixelFormat.dwRGBBitCount )
{
case 4:
- *(uint8_t *)ddsd.lpSurface = 0x11;
+ *(uint8_t *)ddsd.lpSurface = *pi_color | (*pi_color << 4);
break;
case 8:
- *(uint8_t *)ddsd.lpSurface = 0x01;
+ *(uint8_t *)ddsd.lpSurface = *pi_color;
break;
+ case 15:
case 16:
- *(uint16_t *)ddsd.lpSurface = 0x01;
+ *(uint16_t *)ddsd.lpSurface = *pi_color;
break;
+ case 24:
+ /* Seems to be problematic so we'll just put black as the colorkey */
+ *pi_color = 0;
default:
- *(uint32_t *)ddsd.lpSurface = 0x01;
+ *(uint32_t *)ddsd.lpSurface = *pi_color;
break;
}
}
/*****************************************************************************
- * object variables callbacks: a bunch of object variables are used by the
- * interfaces to interact with the vout.
+ * A few toolbox functions
*****************************************************************************/
-static int OnTopCallback( vlc_object_t *p_this, char const *psz_cmd,
- vlc_value_t oldval, vlc_value_t newval, void *p_data )
+void SwitchWallpaperMode( vout_thread_t *p_vout, vlc_bool_t b_on )
{
- vout_thread_t *p_vout = (vout_thread_t *)p_this;
- p_vout->p_sys->b_on_top_change = VLC_TRUE;
- return VLC_SUCCESS;
+ HWND hwnd;
+
+ if( p_vout->p_sys->b_wallpaper == b_on ) return; /* Nothing to do */
+
+ hwnd = FindWindow( _T("Progman"), NULL );
+ if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SHELLDLL_DefView"), NULL );
+ if( hwnd ) hwnd = FindWindowEx( hwnd, NULL, _T("SysListView32"), NULL );
+ if( !hwnd )
+ {
+ msg_Warn( p_vout, "couldn't find \"SysListView32\" window, "
+ "wallpaper mode not supported" );
+ return;
+ }
+
+ p_vout->p_sys->b_wallpaper = b_on;
+
+ msg_Dbg( p_vout, "wallpaper mode %s", b_on ? "enabled" : "disabled" );
+
+ if( p_vout->p_sys->b_wallpaper )
+ {
+ p_vout->p_sys->color_bkg = ListView_GetBkColor( hwnd );
+ p_vout->p_sys->color_bkgtxt = ListView_GetTextBkColor( hwnd );
+
+ ListView_SetBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
+ ListView_SetTextBkColor( hwnd, p_vout->p_sys->i_rgb_colorkey );
+ }
+ else if( hwnd )
+ {
+ ListView_SetBkColor( hwnd, p_vout->p_sys->color_bkg );
+ ListView_SetTextBkColor( hwnd, p_vout->p_sys->color_bkgtxt );
+ }
+
+ /* Update desktop */
+ InvalidateRect( hwnd, NULL, TRUE );
+ UpdateWindow( hwnd );
}
/*****************************************************************************
p_item->i_list = 1;
/* Load direct draw DLL */
- hddraw_dll = LoadLibrary("DDRAW.DLL");
+ hddraw_dll = LoadLibrary(_T("DDRAW.DLL"));
if( hddraw_dll == NULL ) return VLC_SUCCESS;
OurDirectDrawEnumerateEx =
+#ifndef UNICODE
(void *)GetProcAddress( hddraw_dll, "DirectDrawEnumerateExA" );
+#else
+ (void *)GetProcAddress( hddraw_dll, _T("DirectDrawEnumerateExW") );
+#endif
if( OurDirectDrawEnumerateEx )
{
FreeLibrary( hddraw_dll );
+ /* Signal change to the interface */
+ p_item->b_dirty = VLC_TRUE;
+
return VLC_SUCCESS;
}
+
+static int WallpaperCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+
+ if( (newval.b_bool && !p_vout->p_sys->b_wallpaper) ||
+ (!newval.b_bool && p_vout->p_sys->b_wallpaper) )
+ {
+ playlist_t *p_playlist;
+
+ p_playlist =
+ (playlist_t *)vlc_object_find( p_this, VLC_OBJECT_PLAYLIST,
+ FIND_PARENT );
+ if( p_playlist )
+ {
+ /* Modify playlist as well because the vout might have to be
+ * restarted */
+ var_Create( p_playlist, "directx-wallpaper", VLC_VAR_BOOL );
+ var_Set( p_playlist, "directx-wallpaper", newval );
+
+ vlc_object_release( p_playlist );
+ }
+
+ p_vout->p_sys->i_changes |= DX_WALLPAPER_CHANGE;
+ }
+
+ return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * 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" );
+}