Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

wingdi.c

00001 /*****************************************************************************
00002  * wingdi.c : Win32 / WinCE GDI video output plugin for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2002 the VideoLAN team
00005  * $Id: wingdi.c 13380 2005-11-25 17:56:49Z xtophe $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *          Samuel Hocevar <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <stdlib.h>                                      /* malloc(), free() */
00029 #include <string.h>
00030 
00031 #include <vlc/vlc.h>
00032 #include <vlc/intf.h>
00033 #include <vlc/vout.h>
00034 
00035 #include <commctrl.h>
00036 
00037 #define SHFS_SHOWSIPBUTTON 0x0004
00038 #define SHFS_HIDESIPBUTTON 0x0008
00039 
00040 #if defined(UNDER_CE) && !defined(__PLUGIN__) /*FIXME*/
00041 #   define MENU_HEIGHT 26
00042     BOOL SHFullScreen(HWND hwndRequester, DWORD dwState);
00043 #else
00044 #   define MENU_HEIGHT 0
00045 #   define SHFullScreen(a,b)
00046 #endif
00047 
00048 #ifdef MODULE_NAME_IS_wingapi
00049     typedef struct GXDisplayProperties {
00050         DWORD cxWidth;
00051         DWORD cyHeight;
00052         long cbxPitch;
00053         long cbyPitch;
00054         long cBPP;
00055         DWORD ffFormat;
00056     } GXDisplayProperties;
00057 
00058     typedef struct GXScreenRect {
00059         DWORD dwTop;
00060         DWORD dwLeft;
00061         DWORD dwWidth;
00062         DWORD dwHeight;
00063     } GXScreenRect;
00064 
00065 #   define GX_FULLSCREEN    0x01
00066 #   define GX_NORMALKEYS    0x02
00067 #   define GX_LANDSCAPEKEYS 0x03
00068 
00069 #   ifndef kfLandscape
00070 #       define kfLandscape      0x8
00071 #       define kfPalette        0x10
00072 #       define kfDirect         0x20
00073 #       define kfDirect555      0x40
00074 #       define kfDirect565      0x80
00075 #       define kfDirect888      0x100
00076 #       define kfDirect444      0x200
00077 #       define kfDirectInverted 0x400
00078 #   endif
00079 #endif /* MODULE_NAME_IS_wingapi */
00080 
00081 #define MAX_DIRECTBUFFERS 10
00082 
00083 #ifdef UNDER_CE
00084 #ifndef WS_OVERLAPPEDWINDOW
00085 #   define WS_OVERLAPPEDWINDOW 0xcf0000
00086 #endif
00087 #ifndef WS_EX_NOPARENTNOTIFY
00088 #   define WS_EX_NOPARENTNOTIFY 4
00089 #endif
00090 #ifndef WS_EX_APPWINDOW
00091 #define WS_EX_APPWINDOW 0x40000
00092 #endif
00093 #define SetWindowLongPtr SetWindowLong
00094 #define GetWindowLongPtr GetWindowLong
00095 #define GWLP_USERDATA GWL_USERDATA
00096 #define AdjustWindowRect(a,b,c)
00097 #endif //UNDER_CE
00098 
00099 #ifndef WS_NONAVDONEBUTTON
00100 #define WS_NONAVDONEBUTTON 0
00101 #endif
00102 /*****************************************************************************
00103  * Local prototypes
00104  *****************************************************************************/
00105 static int  OpenVideo  ( vlc_object_t * );
00106 static void CloseVideo ( vlc_object_t * );
00107 
00108 static int  Init      ( vout_thread_t * );
00109 static void End       ( vout_thread_t * );
00110 static int  Manage    ( vout_thread_t * );
00111 static void Render    ( vout_thread_t *, picture_t * );
00112 #ifdef MODULE_NAME_IS_wingapi
00113 static void DisplayGAPI( vout_thread_t *, picture_t * );
00114 static int GAPILockSurface( vout_thread_t *, picture_t * );
00115 static int GAPIUnlockSurface( vout_thread_t *, picture_t * );
00116 #else
00117 static void DisplayGDI( vout_thread_t *, picture_t * );
00118 #endif
00119 static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
00120 
00121 static void EventThread        ( vlc_object_t * );
00122 static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM );
00123 static void InitBuffers        ( vout_thread_t * );
00124 static void UpdateRects        ( vout_thread_t *, vlc_bool_t );
00125 
00126 static int Control( vout_thread_t *p_vout, int i_query, va_list args );
00127 
00128 /*****************************************************************************
00129  * Private structure
00130  *****************************************************************************/
00131 struct vout_sys_t
00132 {
00133     /* The event thread */
00134     vlc_object_t * p_event;
00135 
00136     /* Our video output window */
00137     HWND hwnd;
00138     HWND hvideownd;
00139     HWND hfswnd;
00140     int  i_depth;
00141     HWND                 hparent;             /* Handle of the parent window */
00142     WNDPROC              pf_wndproc;             /* Window handling callback */
00143     volatile uint16_t    i_changes;     /* changes made to the video display */
00144     RECT window_placement;
00145 
00146     /* Window position and size */
00147     int          i_window_x;
00148     int          i_window_y;
00149     int          i_window_width;
00150     int          i_window_height;
00151     int          i_window_style;
00152     int          render_width;
00153     int          render_height;
00154 
00155     /* Coordinates of src and dest images (used when blitting to display) */
00156     RECT         rect_src;
00157     RECT         rect_src_clipped;
00158     RECT         rect_dest;
00159     RECT         rect_dest_clipped;
00160     RECT         rect_parent;
00161     RECT         rect_display;
00162 
00163     /* Our offscreen bitmap and its framebuffer */
00164     HDC        off_dc;
00165     HBITMAP    off_bitmap;
00166     uint8_t *  p_pic_buffer;
00167     int        i_pic_pitch;
00168     int        i_pic_pixel_pitch;
00169 
00170     BITMAPINFO bitmapinfo;
00171     RGBQUAD    red;
00172     RGBQUAD    green;
00173     RGBQUAD    blue;
00174 
00175     /* WINCE stuff */
00176     vlc_bool_t   b_video_display;
00177 
00178     /* Window focus states */
00179     vlc_bool_t b_focus;
00180     vlc_bool_t b_parent_focus;
00181 
00182 #ifdef MODULE_NAME_IS_wingapi
00183     HINSTANCE  gapi_dll;                    /* handle of the opened gapi dll */
00184 
00185     /* GAPI functions */
00186     int (*GXOpenDisplay)( HWND hWnd, DWORD dwFlags );
00187     int (*GXCloseDisplay)();
00188     void *(*GXBeginDraw)();
00189     int (*GXEndDraw)();
00190     GXDisplayProperties (*GXGetDisplayProperties)();
00191     int (*GXSuspend)();
00192     int (*GXResume)();
00193 #endif
00194 };
00195 
00196 #define GXOpenDisplay p_vout->p_sys->GXOpenDisplay
00197 #define GXCloseDisplay p_vout->p_sys->GXCloseDisplay
00198 #define GXBeginDraw p_vout->p_sys->GXBeginDraw
00199 #define GXEndDraw p_vout->p_sys->GXEndDraw
00200 #define GXGetDisplayProperties p_vout->p_sys->GXGetDisplayProperties
00201 
00202 #ifdef MODULE_NAME_IS_wingapi
00203 #   define GXSuspend p_vout->p_sys->GXSuspend
00204 #   define GXResume p_vout->p_sys->GXResume
00205 #else
00206 #   define GXSuspend()
00207 #   define GXResume()
00208 #endif
00209 
00210 #define DX_POSITION_CHANGE 0x1000
00211 
00212 /*****************************************************************************
00213  * Module descriptor
00214  *****************************************************************************/
00215 vlc_module_begin();
00216     set_category( CAT_VIDEO );
00217     set_subcategory( SUBCAT_VIDEO_VOUT );
00218 #ifdef MODULE_NAME_IS_wingapi
00219     set_shortname( _("Windows GAPI") );
00220     set_description( _("Windows GAPI video output") );
00221     set_capability( "video output", 20 );
00222 #else
00223     set_shortname( _("Windows GDI") );
00224     set_description( _("Windows GDI video output") );
00225     set_capability( "video output", 10 );
00226 #endif
00227     set_callbacks( OpenVideo, CloseVideo );
00228 vlc_module_end();
00229 
00230 /*****************************************************************************
00231  * OpenVideo: activate GDI video thread output method
00232  *****************************************************************************/
00233 static int OpenVideo ( vlc_object_t *p_this )
00234 {
00235     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00236     vlc_value_t val;
00237 
00238     p_vout->p_sys = (vout_sys_t *)malloc( sizeof(vout_sys_t) );
00239     if( !p_vout->p_sys ) return VLC_ENOMEM;
00240 
00241 #ifdef MODULE_NAME_IS_wingapi
00242     /* Load GAPI */
00243     p_vout->p_sys->gapi_dll = LoadLibrary( _T("GX.DLL") );
00244     if( p_vout->p_sys->gapi_dll == NULL )
00245     {
00246         msg_Warn( p_vout, "failed loading gx.dll" );
00247         free( p_vout->p_sys );
00248         return VLC_EGENERIC;
00249     }
00250 
00251     GXOpenDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00252         _T("?GXOpenDisplay@@YAHPAUHWND__@@K@Z") );
00253     GXCloseDisplay = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00254         _T("?GXCloseDisplay@@YAHXZ") );
00255     GXBeginDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00256         _T("?GXBeginDraw@@YAPAXXZ") );
00257     GXEndDraw = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00258         _T("?GXEndDraw@@YAHXZ") );
00259     GXGetDisplayProperties = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00260         _T("?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ") );
00261     GXSuspend = (void *)GetProcAddress( p_vout->p_sys->gapi_dll,
00262         _T("?GXSuspend@@YAHXZ") );
00263     GXResume = GetProcAddress( p_vout->p_sys->gapi_dll,
00264         _T("?GXResume@@YAHXZ") );
00265 
00266     if( !GXOpenDisplay || !GXCloseDisplay || !GXBeginDraw || !GXEndDraw ||
00267         !GXGetDisplayProperties || !GXSuspend || !GXResume )
00268     {
00269         msg_Err( p_vout, "failed GetProcAddress on gapi.dll" );
00270         free( p_vout->p_sys );
00271         return VLC_EGENERIC;
00272     }
00273 
00274     msg_Dbg( p_vout, "GAPI DLL loaded" );
00275 
00276     p_vout->p_sys->render_width = p_vout->render.i_width;
00277     p_vout->p_sys->render_height = p_vout->render.i_height;
00278 #endif
00279 
00280     p_vout->p_sys->p_event = (vlc_object_t *)
00281         vlc_object_create( p_vout, VLC_OBJECT_GENERIC );
00282     if( !p_vout->p_sys->p_event )
00283     {
00284         free( p_vout->p_sys );
00285         return VLC_ENOMEM;
00286     }
00287 
00288     var_Create( p_vout->p_sys->p_event, "p_vout", VLC_VAR_ADDRESS );
00289     val.p_address = (void *)p_vout;
00290     var_Set( p_vout->p_sys->p_event, "p_vout", val );
00291 
00292     SetRectEmpty( &p_vout->p_sys->rect_display );
00293     SetRectEmpty( &p_vout->p_sys->rect_parent );
00294 
00295     if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread",
00296                            EventThread, 0, 1 ) )
00297     {
00298         msg_Err( p_vout, "cannot spawn EventThread" );
00299         return VLC_ETHREAD;
00300     }
00301 
00302     p_vout->pf_init = Init;
00303     p_vout->pf_end = End;
00304     p_vout->pf_manage = Manage;
00305     p_vout->pf_render = Render;
00306 #ifdef MODULE_NAME_IS_wingapi
00307     p_vout->pf_display = DisplayGAPI;
00308 #else
00309     p_vout->pf_display = DisplayGDI;
00310 #endif
00311     p_vout->p_sys->i_changes = 0;
00312 
00313     p_vout->p_sys->b_focus = 0;
00314     p_vout->p_sys->b_parent_focus = 0;
00315 
00316     return VLC_SUCCESS;
00317 }
00318 
00319 /*****************************************************************************
00320  * CloseVideo: deactivate the GDI video output
00321  *****************************************************************************/
00322 static void CloseVideo ( vlc_object_t *p_this )
00323 {
00324     vout_thread_t * p_vout = (vout_thread_t *)p_this;
00325 
00326     p_vout->p_sys->p_event->b_die = VLC_TRUE;
00327     PostMessage( p_vout->p_sys->hwnd, WM_NULL, 0, 0 );
00328     vlc_thread_join( p_vout->p_sys->p_event );
00329 
00330 #ifdef MODULE_NAME_IS_wingapi
00331     FreeLibrary( p_vout->p_sys->gapi_dll );
00332 #endif
00333 
00334     var_Destroy( p_vout->p_sys->p_event, "p_vout" );
00335     vlc_object_destroy( p_vout->p_sys->p_event );
00336     free( p_vout->p_sys );
00337 }
00338 
00339 /*****************************************************************************
00340  * Init: initialize video thread output method
00341  *****************************************************************************/
00342 static int Init( vout_thread_t *p_vout )
00343 {
00344     picture_t *p_pic;
00345 
00346     p_vout->p_sys->rect_display.left = 0;
00347     p_vout->p_sys->rect_display.top = 0;
00348     p_vout->p_sys->rect_display.right  = GetSystemMetrics(SM_CXSCREEN);
00349     p_vout->p_sys->rect_display.bottom = GetSystemMetrics(SM_CYSCREEN);
00350 
00351     p_vout->p_sys->b_video_display = VLC_TRUE;
00352     p_vout->p_sys->p_event->b_die = VLC_FALSE;
00353 
00354     I_OUTPUTPICTURES = 0;
00355 
00356     /* Initialize the output structure */
00357     switch( p_vout->p_sys->i_depth )
00358     {
00359     case 8:
00360         p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
00361         p_vout->output.pf_setpalette = SetPalette;
00362         break;
00363     case 15:
00364         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00365         p_vout->output.i_rmask  = 0x7c00;
00366         p_vout->output.i_gmask  = 0x03e0;
00367         p_vout->output.i_bmask  = 0x001f;
00368         break;
00369     case 16:
00370         p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00371         p_vout->output.i_rmask  = 0xf800;
00372         p_vout->output.i_gmask  = 0x07e0;
00373         p_vout->output.i_bmask  = 0x001f;
00374         break;
00375     case 24:
00376         p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
00377         p_vout->output.i_rmask  = 0x00ff0000;
00378         p_vout->output.i_gmask  = 0x0000ff00;
00379         p_vout->output.i_bmask  = 0x000000ff;
00380         break;
00381     case 32:
00382         p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00383         p_vout->output.i_rmask  = 0x00ff0000;
00384         p_vout->output.i_gmask  = 0x0000ff00;
00385         p_vout->output.i_bmask  = 0x000000ff;
00386         break;
00387     default:
00388         msg_Err( p_vout, "screen depth %i not supported",
00389                  p_vout->p_sys->i_depth );
00390         return VLC_EGENERIC;
00391         break;
00392     }
00393 
00394     p_pic = &p_vout->p_picture[0];
00395 
00396 #ifdef MODULE_NAME_IS_wingapi
00397     p_vout->output.i_width  = 0;
00398     p_vout->output.i_height = 0;
00399     p_pic->pf_lock  = GAPILockSurface;
00400     p_pic->pf_unlock = GAPIUnlockSurface;
00401     Manage( p_vout );
00402     GAPILockSurface( p_vout, p_pic );
00403     p_vout->i_changes = 0;
00404     p_vout->output.i_width  = p_vout->p_sys->render_width;
00405     p_vout->output.i_height = p_vout->p_sys->render_height;
00406 
00407 #else
00408     p_vout->output.i_width  = p_vout->render.i_width;
00409     p_vout->output.i_height = p_vout->render.i_height;
00410 
00411     p_vout->fmt_out = p_vout->fmt_in;
00412     p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;
00413 #endif
00414 
00415     p_vout->output.i_aspect = p_vout->render.i_aspect;
00416 
00417     p_pic->p->p_pixels = p_vout->p_sys->p_pic_buffer;
00418     p_pic->p->i_lines = p_vout->output.i_height;
00419     p_pic->p->i_visible_lines = p_vout->output.i_height;
00420     p_pic->p->i_pitch = p_vout->p_sys->i_pic_pitch;
00421     p_pic->p->i_pixel_pitch = p_vout->p_sys->i_pic_pixel_pitch;
00422     p_pic->p->i_visible_pitch = p_vout->output.i_width *
00423         p_pic->p->i_pixel_pitch;
00424     p_pic->i_planes = 1;
00425     p_pic->i_status = DESTROYED_PICTURE;
00426     p_pic->i_type   = DIRECT_PICTURE;
00427 
00428     PP_OUTPUTPICTURE[ I_OUTPUTPICTURES++ ] = p_pic;
00429 
00430     return VLC_SUCCESS;
00431 }
00432 
00433 /*****************************************************************************
00434  * End: terminate video thread output method
00435  *****************************************************************************/
00436 static void End( vout_thread_t *p_vout )
00437 {
00438 }
00439 
00440 /*****************************************************************************
00441  * Manage: handle events
00442  *****************************************************************************
00443  * This function should be called regularly by video output thread. It manages
00444  * console events. It returns a non null value on error.
00445  *****************************************************************************/
00446 static int Manage( vout_thread_t *p_vout )
00447 {
00448 #ifndef UNDER_CE
00449     WINDOWPLACEMENT window_placement;
00450 #endif
00451 
00452     /* If we do not control our window, we check for geometry changes
00453      * ourselves because the parent might not send us its events. */
00454     if( p_vout->p_sys->hparent && !p_vout->b_fullscreen )
00455     {
00456         RECT rect_parent;
00457         POINT point;
00458 
00459         GetClientRect( p_vout->p_sys->hparent, &rect_parent );
00460         point.x = point.y = 0;
00461         ClientToScreen( p_vout->p_sys->hparent, &point );
00462         OffsetRect( &rect_parent, point.x, point.y );
00463 
00464         if( !EqualRect( &rect_parent, &p_vout->p_sys->rect_parent ) )
00465         {
00466             int i_x, i_y, i_width, i_height;
00467             p_vout->p_sys->rect_parent = rect_parent;
00468 
00469             /* This one is to force the update even if only
00470              * the position has changed */
00471             SetWindowPos( p_vout->p_sys->hwnd, 0, 1, 1,
00472                           rect_parent.right - rect_parent.left,
00473                           rect_parent.bottom - rect_parent.top, 0 );
00474 
00475             SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00476                           rect_parent.right - rect_parent.left,
00477                           rect_parent.bottom - rect_parent.top, 0 );
00478 
00479             vout_PlacePicture( p_vout, rect_parent.right - rect_parent.left,
00480                                rect_parent.bottom - rect_parent.top,
00481                                &i_x, &i_y, &i_width, &i_height );
00482 
00483             SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
00484                           i_x, i_y, i_width, i_height, 0 );
00485         }
00486     }
00487 
00488     /* We used to call the Win32 PeekMessage function here to read the window
00489      * messages. But since window can stay blocked into this function for a
00490      * long time (for example when you move your window on the screen), I
00491      * decided to isolate PeekMessage in another thread. */
00492 
00493     /*
00494      * Fullscreen change
00495      */
00496     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE
00497         || p_vout->p_sys->i_changes & VOUT_FULLSCREEN_CHANGE )
00498     {
00499         int i_style = 0;
00500         vlc_value_t val;
00501 
00502         HWND hwnd = (p_vout->p_sys->hparent && p_vout->p_sys->hfswnd) ?
00503             p_vout->p_sys->hfswnd : p_vout->p_sys->hwnd;
00504 
00505         p_vout->b_fullscreen = ! p_vout->b_fullscreen;
00506 
00507         /* We need to switch between Maximized and Normal sized window */
00508 #ifndef UNDER_CE
00509         window_placement.length = sizeof(WINDOWPLACEMENT);
00510         GetWindowPlacement( hwnd, &window_placement );
00511 #endif
00512         if( p_vout->b_fullscreen )
00513         {
00514 #ifndef UNDER_CE
00515             /* Change window style, no borders and no title bar */
00516             int i_style = WS_CLIPCHILDREN | WS_VISIBLE;
00517             SetWindowLong( hwnd, GWL_STYLE, i_style );
00518 
00519             if( p_vout->p_sys->hparent )
00520             {
00521                 /* Retrieve current window position so fullscreen will happen
00522                  * on the right screen */
00523                 POINT point = {0,0};
00524                 RECT rect;
00525                 ClientToScreen( p_vout->p_sys->hwnd, &point );
00526                 GetClientRect( p_vout->p_sys->hwnd, &rect );
00527                 SetWindowPos( hwnd, 0, point.x, point.y,
00528                               rect.right, rect.bottom,
00529                               SWP_NOZORDER|SWP_FRAMECHANGED );
00530                 GetWindowPlacement( hwnd, &window_placement );
00531             }
00532 
00533             /* Maximize window */
00534             window_placement.showCmd = SW_SHOWMAXIMIZED;
00535             SetWindowPlacement( hwnd, &window_placement );
00536             SetWindowPos( hwnd, 0, 0, 0, 0, 0,
00537                           SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
00538 #endif
00539 
00540             if( p_vout->p_sys->hparent )
00541             {
00542                 RECT rect;
00543                 GetClientRect( hwnd, &rect );
00544                 SetParent( p_vout->p_sys->hwnd, hwnd );
00545                 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00546                               rect.right, rect.bottom,
00547                               SWP_NOZORDER|SWP_FRAMECHANGED );
00548             }
00549 
00550             ShowWindow( hwnd, SW_SHOW );
00551             SetForegroundWindow( hwnd );
00552         }
00553         else
00554         {
00555             /* Change window style, no borders and no title bar */
00556             //SetWindowLong( hwnd, GWL_STYLE, p_vout->p_sys->i_window_style );
00557 
00558 #ifndef UNDER_CE
00559             /* Normal window */
00560             window_placement.showCmd = SW_SHOWNORMAL;
00561             SetWindowPlacement( hwnd, &window_placement );
00562             SetWindowPos( hwnd, 0, 0, 0, 0, 0,
00563                           SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);
00564 #endif
00565 
00566             if( p_vout->p_sys->hparent )
00567             {
00568                 RECT rect;
00569                 GetClientRect( p_vout->p_sys->hparent, &rect );
00570                 SetParent( p_vout->p_sys->hwnd, p_vout->p_sys->hparent );
00571                 SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
00572                               rect.right, rect.bottom,
00573                               SWP_NOZORDER|SWP_FRAMECHANGED );
00574 
00575                 ShowWindow( hwnd, SW_HIDE );
00576                 SetForegroundWindow( p_vout->p_sys->hparent );
00577             }
00578 
00579             /* Make sure the mouse cursor is displayed */
00580             //PostMessage( p_vout->p_sys->hwnd, WM_VLC_SHOW_MOUSE, 0, 0 );
00581         }
00582 
00583         /* Change window style, borders and title bar */
00584         ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
00585         UpdateWindow( p_vout->p_sys->hwnd );
00586 
00587         /* Update the object variable and trigger callback */
00588         val.b_bool = p_vout->b_fullscreen;
00589         var_Set( p_vout, "fullscreen", val );
00590 
00591         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00592         p_vout->p_sys->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00593     }
00594 
00595     return VLC_SUCCESS;
00596 }
00597 
00598 /*****************************************************************************
00599  * Render: render previously calculated output
00600  *****************************************************************************/
00601 static void Render( vout_thread_t *p_vout, picture_t *p_pic )
00602 {
00603     /* No need to do anything, the fake direct buffers stay as they are */
00604 }
00605 
00606 /*****************************************************************************
00607  * Display: displays previously rendered output
00608  *****************************************************************************/
00609 #define rect_src p_vout->p_sys->rect_src
00610 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
00611 #define rect_dest p_vout->p_sys->rect_dest
00612 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
00613 
00614 #ifndef MODULE_NAME_IS_wingapi
00615 static void DisplayGDI( vout_thread_t *p_vout, picture_t *p_pic )
00616 {
00617     vout_sys_t *p_sys = p_vout->p_sys;
00618     RECT rect_dst = rect_dest_clipped;
00619     HDC hdc = GetDC( p_sys->hvideownd );
00620 
00621     OffsetRect( &rect_dst, -rect_dest.left, -rect_dest.top );
00622     SelectObject( p_sys->off_dc, p_sys->off_bitmap );
00623 
00624     if( rect_dest_clipped.right - rect_dest_clipped.left !=
00625         rect_src_clipped.right - rect_src_clipped.left ||
00626         rect_dest_clipped.bottom - rect_dest_clipped.top !=
00627         rect_src_clipped.bottom - rect_src_clipped.top )
00628     {
00629         StretchBlt( hdc, rect_dst.left, rect_dst.top,
00630                     rect_dst.right, rect_dst.bottom,
00631                     p_sys->off_dc, rect_src_clipped.left, rect_src_clipped.top,
00632                     rect_src_clipped.right, rect_src_clipped.bottom, SRCCOPY );
00633     }
00634     else
00635     {
00636         BitBlt( hdc, rect_dst.left, rect_dst.top,
00637                 rect_dst.right, rect_dst.bottom,
00638                 p_sys->off_dc, rect_src_clipped.left,
00639                 rect_src_clipped.top, SRCCOPY );
00640     }
00641 
00642     ReleaseDC( p_sys->hwnd, hdc );
00643 }
00644 #else
00645 
00646 static int GAPILockSurface( vout_thread_t *p_vout, picture_t *p_pic )
00647 {
00648     vout_sys_t *p_sys = p_vout->p_sys;
00649     int i_x, i_y, i_width, i_height;
00650     RECT video_rect;
00651     POINT point;
00652 
00653     /* Undo the display */
00654     if( ( GetForegroundWindow() != GetParent(p_sys->hwnd) ) ||
00655         ( p_sys->b_video_display == VLC_FALSE ) )
00656     {
00657         //return VLC_EGENERIC;
00658     }
00659 
00660     GetClientRect( p_sys->hwnd, &video_rect);
00661     vout_PlacePicture( p_vout, video_rect.right - video_rect.left,
00662                        video_rect.bottom - video_rect.top,
00663                        &i_x, &i_y, &i_width, &i_height );
00664     point.x = point.y = 0;
00665     ClientToScreen( p_sys->hwnd, &point );
00666     i_x += point.x + video_rect.left;
00667     i_y += point.y + video_rect.top;
00668 
00669     if( i_width != p_vout->output.i_width ||
00670         i_height != p_vout->output.i_height )
00671     {
00672         GXDisplayProperties gxdisplayprop = GXGetDisplayProperties();
00673 
00674         p_sys->render_width = i_width;
00675         p_sys->render_height = i_height;
00676         p_vout->i_changes |= VOUT_SIZE_CHANGE;
00677 
00678         msg_Dbg( p_vout, "vout size change (%ix%i -> %ix%i)",
00679                  i_width, i_height, p_vout->output.i_width,
00680                  p_vout->output.i_height );
00681 
00682         p_vout->p_sys->i_pic_pixel_pitch = gxdisplayprop.cbxPitch;
00683         p_vout->p_sys->i_pic_pitch = gxdisplayprop.cbyPitch;
00684         return VLC_EGENERIC;
00685     }
00686     else
00687     {
00688         GXDisplayProperties gxdisplayprop;
00689         RECT display_rect, dest_rect;
00690         uint8_t *p_dest, *p_src = p_pic->p->p_pixels;
00691 
00692         video_rect.left = i_x; video_rect.top = i_y;
00693         video_rect.right = i_x + i_width;
00694         video_rect.bottom = i_y + i_height;
00695 
00696         gxdisplayprop = GXGetDisplayProperties();
00697         display_rect.left = 0; display_rect.top = 0;
00698         display_rect.right = gxdisplayprop.cxWidth;
00699         display_rect.bottom = gxdisplayprop.cyHeight;
00700 
00701         if( !IntersectRect( &dest_rect, &video_rect, &display_rect ) )
00702         {
00703             return VLC_EGENERIC;
00704         }
00705 
00706 #if 0
00707         msg_Err( p_vout, "video (%d,%d,%d,%d) display (%d,%d,%d,%d) "
00708                  "dest (%d,%d,%d,%d)",
00709                  video_rect.left, video_rect.right,
00710                  video_rect.top, video_rect.bottom,
00711                  display_rect.left, display_rect.right,
00712                  display_rect.top, display_rect.bottom,
00713                  dest_rect.left, dest_rect.right,
00714                  dest_rect.top, dest_rect.bottom );
00715 #endif
00716 
00717         if( !(p_dest = GXBeginDraw()) )
00718         {
00719 #if 0
00720             msg_Err( p_vout, "GXBeginDraw error %d ", GetLastError() );
00721 #endif
00722             return VLC_EGENERIC;
00723         }
00724 
00725         p_src += (dest_rect.left - video_rect.left) * gxdisplayprop.cbxPitch +
00726             (dest_rect.top - video_rect.top) * p_pic->p->i_pitch;
00727         p_dest += dest_rect.left * gxdisplayprop.cbxPitch +
00728             dest_rect.top * gxdisplayprop.cbyPitch;
00729         i_width = dest_rect.right - dest_rect.left;
00730         i_height = dest_rect.bottom - dest_rect.top;
00731 
00732         p_pic->p->p_pixels = p_dest;
00733     }
00734 
00735     return VLC_SUCCESS;
00736 }
00737 
00738 static int GAPIUnlockSurface( vout_thread_t *p_vout, picture_t *p_pic )
00739 {
00740     GXEndDraw();
00741     return VLC_SUCCESS;
00742 }
00743 
00744 static void DisplayGAPI( vout_thread_t *p_vout, picture_t *p_pic )
00745 {
00746 }
00747 #endif
00748 
00749 #undef rect_src
00750 #undef rect_src_clipped
00751 #undef rect_dest
00752 #undef rect_dest_clipped
00753 /*****************************************************************************
00754  * SetPalette: sets an 8 bpp palette
00755  *****************************************************************************/
00756 static void SetPalette( vout_thread_t *p_vout,
00757                         uint16_t *red, uint16_t *green, uint16_t *blue )
00758 {
00759     msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
00760 }
00761 
00762 /*****************************************************************************
00763  * EventThread: Event handling thread
00764  *****************************************************************************/
00765 static void EventThread ( vlc_object_t *p_event )
00766 {
00767     vout_thread_t *p_vout;
00768     vlc_value_t   val;
00769 
00770     int        i_style;
00771     WNDCLASS   wc;
00772     MSG        msg;
00773 
00774     /* Initialisations */
00775     var_Get( p_event, "p_vout", &val );
00776     p_vout = (vout_thread_t *)val.p_address;
00777 
00778     /* Register window class */
00779     memset( &wc, 0, sizeof(wc) );
00780     wc.style          = CS_HREDRAW | CS_VREDRAW;
00781     wc.lpfnWndProc    = (WNDPROC)WndProc;
00782     wc.cbClsExtra     = 0;
00783     wc.cbWndExtra     = 0;
00784     wc.hInstance      = GetModuleHandle(NULL);
00785     wc.hIcon          = 0;
00786     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
00787     wc.hbrBackground  = (HBRUSH)GetStockObject( BLACK_BRUSH );
00788     wc.lpszMenuName   = 0;
00789     wc.lpszClassName  = _T("VLC WinGDI");
00790     RegisterClass( &wc );
00791 
00792     /* Register the video sub-window class */
00793     wc.lpszClassName = _T("VLC WinGDI video"); wc.hIcon = 0;
00794     RegisterClass(&wc);
00795 
00796     /* Create output window */
00797     p_vout->p_sys->hparent = (HWND)
00798         vout_RequestWindow( p_vout, &p_vout->p_sys->i_window_x,
00799                             &p_vout->p_sys->i_window_y,
00800                             (unsigned int *)&p_vout->p_sys->i_window_width,
00801                             (unsigned int *)&p_vout->p_sys->i_window_height );
00802 
00803     if( p_vout->p_sys->hparent )
00804         ShowWindow( p_vout->p_sys->hparent, SW_SHOW );
00805 
00806     if( p_vout->p_sys->hparent )
00807         i_style = WS_VISIBLE|WS_CLIPCHILDREN|WS_CHILD;
00808     else
00809         i_style = WS_OVERLAPPEDWINDOW|WS_SIZEBOX|WS_VISIBLE|WS_CLIPCHILDREN;
00810 
00811     p_vout->p_sys->i_window_style = i_style;
00812 
00813     p_vout->p_sys->hwnd =
00814         CreateWindow( _T("VLC WinGDI"), _T(VOUT_TITLE), i_style,
00815                       (p_vout->p_sys->i_window_x < 0) ? CW_USEDEFAULT :
00816                       p_vout->p_sys->i_window_x,   /* default X coordinate */
00817                       (p_vout->p_sys->i_window_y < 0) ? CW_USEDEFAULT :
00818                       p_vout->p_sys->i_window_y,   /* default Y coordinate */
00819                       p_vout->p_sys->i_window_width,
00820                       p_vout->p_sys->i_window_height + 10,
00821                       p_vout->p_sys->hparent, NULL,
00822                       GetModuleHandle(NULL), (LPVOID)p_vout );
00823 
00824     if( !p_vout->p_sys->hwnd )
00825     {
00826         msg_Warn( p_vout, "couldn't create window" );
00827         return;
00828     }
00829     msg_Warn( p_vout, "Created WinGDI window" );
00830 
00831     if( p_vout->p_sys->hparent )
00832     {
00833         LONG i_style;
00834 
00835         /* We don't want the window owner to overwrite our client area */
00836         i_style = GetWindowLong( p_vout->p_sys->hparent, GWL_STYLE );
00837 
00838         if( !(i_style & WS_CLIPCHILDREN) )
00839             /* Hmmm, apparently this is a blocking call... */
00840             SetWindowLong( p_vout->p_sys->hparent, GWL_STYLE,
00841                            i_style | WS_CLIPCHILDREN );
00842 
00843         /* Create our fullscreen window */
00844         p_vout->p_sys->hfswnd =
00845             CreateWindowEx( WS_EX_APPWINDOW, _T("VLC WinGDI"),
00846                             _T(VOUT_TITLE),
00847                             WS_NONAVDONEBUTTON|WS_CLIPCHILDREN,
00848                             CW_USEDEFAULT, CW_USEDEFAULT,
00849                             CW_USEDEFAULT, CW_USEDEFAULT,
00850                             NULL, NULL, GetModuleHandle(NULL), (LPVOID)p_vout);
00851     }
00852 
00853     /* Display our window */
00854     ShowWindow( p_vout->p_sys->hwnd, SW_SHOW );
00855     UpdateWindow( p_vout->p_sys->hwnd );
00856 
00857     /* Create video sub-window */
00858     p_vout->p_sys->hvideownd =
00859         CreateWindow( _T("VLC WinGDI video"), _T(""),   /* window class */
00860                     WS_CHILD | WS_VISIBLE,                   /* window style */
00861                     CW_USEDEFAULT, CW_USEDEFAULT,     /* default coordinates */
00862                     CW_USEDEFAULT, CW_USEDEFAULT,
00863                     p_vout->p_sys->hwnd,                  /* parent window */
00864                     NULL, GetModuleHandle(NULL),
00865                     (LPVOID)p_vout );            /* send p_vout to WM_CREATE */
00866 
00867     /* Initialize offscreen buffer */
00868     InitBuffers( p_vout );
00869 
00870     p_vout->pf_control = Control;
00871 
00872     /* Tell the video output we're ready to receive data */
00873     vlc_thread_ready( p_event );
00874 
00875     while( !p_event->b_die && GetMessage( &msg, 0, 0, 0 ) )
00876     {
00877         /* Check if we are asked to exit */
00878         if( p_event->b_die ) break;
00879 
00880         switch( msg.message )
00881         {
00882         case WM_KEYDOWN:
00883             switch( msg.wParam )
00884             {
00885             case VK_ESCAPE:
00886                 p_event->p_vlc->b_die = VLC_TRUE;
00887                 break;
00888             }
00889             TranslateMessage( &msg );
00890             break;
00891 
00892         case WM_CHAR:
00893             switch( msg.wParam )
00894             {
00895             case 'q':
00896             case 'Q':
00897                 p_event->p_vlc->b_die = VLC_TRUE;
00898                 break;
00899             }
00900             break;
00901 
00902         default:
00903             TranslateMessage( &msg );
00904             DispatchMessage( &msg );
00905             break;
00906         }
00907     }
00908 
00909     msg_Dbg( p_vout, "CloseWindow" );
00910 
00911 #ifdef MODULE_NAME_IS_wingapi
00912     GXCloseDisplay();
00913 #else
00914     DeleteDC( p_vout->p_sys->off_dc );
00915     DeleteObject( p_vout->p_sys->off_bitmap );
00916 #endif
00917 
00918     DestroyWindow( p_vout->p_sys->hwnd );
00919     if( p_vout->p_sys->hfswnd ) DestroyWindow( p_vout->p_sys->hfswnd );
00920 
00921     if( p_vout->p_sys->hparent )
00922         vout_ReleaseWindow( p_vout, (void *)p_vout->p_sys->hparent );
00923 }
00924 
00925 /*****************************************************************************
00926  * UpdateRects: update clipping rectangles
00927  *****************************************************************************
00928  * This function is called when the window position or size are changed, and
00929  * its job is to update the source and destination RECTs used to display the
00930  * picture.
00931  *****************************************************************************/
00932 static void UpdateRects( vout_thread_t *p_vout, vlc_bool_t b_force )
00933 {
00934 #define rect_src p_vout->p_sys->rect_src
00935 #define rect_src_clipped p_vout->p_sys->rect_src_clipped
00936 #define rect_dest p_vout->p_sys->rect_dest
00937 #define rect_dest_clipped p_vout->p_sys->rect_dest_clipped
00938 
00939     int i_width, i_height, i_x, i_y;
00940 
00941     RECT  rect;
00942     POINT point;
00943 
00944     /* Retrieve the window size */
00945     GetClientRect( p_vout->p_sys->hwnd, &rect );
00946 
00947     /* Retrieve the window position */
00948     point.x = point.y = 0;
00949     ClientToScreen( p_vout->p_sys->hwnd, &point );
00950 
00951     /* If nothing changed, we can return */
00952     if( !b_force
00953          && p_vout->p_sys->i_window_width == rect.right
00954          && p_vout->p_sys->i_window_height == rect.bottom
00955          && p_vout->p_sys->i_window_x == point.x
00956          && p_vout->p_sys->i_window_y == point.y )
00957     {
00958         return;
00959     }
00960 
00961     /* Update the window position and size */
00962     p_vout->p_sys->i_window_x = point.x;
00963     p_vout->p_sys->i_window_y = point.y;
00964     p_vout->p_sys->i_window_width = rect.right;
00965     p_vout->p_sys->i_window_height = rect.bottom;
00966 
00967     vout_PlacePicture( p_vout, rect.right, rect.bottom,
00968                        &i_x, &i_y, &i_width, &i_height );
00969 
00970     if( p_vout->p_sys->hvideownd )
00971         SetWindowPos( p_vout->p_sys->hvideownd, HWND_TOP,
00972                       i_x, i_y, i_width, i_height, 0 );
00973 
00974     /* Destination image position and dimensions */
00975     rect_dest.left = point.x + i_x;
00976     rect_dest.right = rect_dest.left + i_width;
00977     rect_dest.top = point.y + i_y;
00978     rect_dest.bottom = rect_dest.top + i_height;
00979 
00980     /* Clip the destination window */
00981     if( !IntersectRect( &rect_dest_clipped, &rect_dest,
00982                         &p_vout->p_sys->rect_display ) )
00983     {
00984         SetRectEmpty( &rect_src_clipped );
00985         return;
00986     }
00987 
00988 #if 0
00989     msg_Dbg( p_vout, "image_dst_clipped coords: %i,%i,%i,%i",
00990                      rect_dest_clipped.left, rect_dest_clipped.top,
00991                      rect_dest_clipped.right, rect_dest_clipped.bottom );
00992 #endif
00993 
00994     /* the 2 following lines are to fix a bug when clicking on the desktop */
00995     if( (rect_dest_clipped.right - rect_dest_clipped.left)==0 ||
00996         (rect_dest_clipped.bottom - rect_dest_clipped.top)==0 )
00997     {
00998         SetRectEmpty( &rect_src_clipped );
00999         return;
01000     }
01001 
01002     /* src image dimensions */
01003     rect_src.left = 0;
01004     rect_src.top = 0;
01005     rect_src.right = p_vout->output.i_width;
01006     rect_src.bottom = p_vout->output.i_height;
01007 
01008     /* Clip the source image */
01009     rect_src_clipped.left = (rect_dest_clipped.left - rect_dest.left) *
01010       p_vout->output.i_width / (rect_dest.right - rect_dest.left);
01011     rect_src_clipped.right = p_vout->output.i_width -
01012       (rect_dest.right - rect_dest_clipped.right) * p_vout->output.i_width /
01013       (rect_dest.right - rect_dest.left);
01014     rect_src_clipped.top = (rect_dest_clipped.top - rect_dest.top) *
01015       p_vout->output.i_height / (rect_dest.bottom - rect_dest.top);
01016     rect_src_clipped.bottom = p_vout->output.i_height -
01017       (rect_dest.bottom - rect_dest_clipped.bottom) * p_vout->output.i_height /
01018       (rect_dest.bottom - rect_dest.top);
01019 
01020 #if 0
01021     msg_Dbg( p_vout, "image_src_clipped coords: %i,%i,%i,%i",
01022                      rect_src_clipped.left, rect_src_clipped.top,
01023                      rect_src_clipped.right, rect_src_clipped.bottom );
01024 #endif
01025 
01026     /* The destination coordinates need to be relative to the current
01027      * directdraw primary surface (display) */
01028     rect_dest_clipped.left -= p_vout->p_sys->rect_display.left;
01029     rect_dest_clipped.right -= p_vout->p_sys->rect_display.left;
01030     rect_dest_clipped.top -= p_vout->p_sys->rect_display.top;
01031     rect_dest_clipped.bottom -= p_vout->p_sys->rect_display.top;
01032 
01033     /* Signal the change in size/position */
01034     p_vout->p_sys->i_changes |= DX_POSITION_CHANGE;
01035 
01036 #undef rect_src
01037 #undef rect_src_clipped
01038 #undef rect_dest
01039 #undef rect_dest_clipped
01040 }
01041 
01042 /*****************************************************************************
01043  * Message handler for the main window
01044  *****************************************************************************/
01045 static long FAR PASCAL WndProc( HWND hWnd, UINT message,
01046                                 WPARAM wParam, LPARAM lParam )
01047 {
01048     vout_thread_t *p_vout;
01049 
01050     if( message == WM_CREATE )
01051     {
01052         /* Store p_vout for future use */
01053         p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
01054         SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)p_vout );
01055         if( p_vout ) msg_Dbg( p_vout, "create: %p", hWnd );
01056     }
01057     else
01058     {
01059         p_vout = (vout_thread_t *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
01060     }
01061 
01062 #ifndef UNDER_CE
01063     /* Catch the screensaver and the monitor turn-off */
01064     if( message == WM_SYSCOMMAND &&
01065         ( (wParam & 0xFFF0) == SC_SCREENSAVE || (wParam & 0xFFF0) == SC_MONITORPOWER ) )
01066     {
01067         //if( p_vout ) msg_Dbg( p_vout, "WinProc WM_SYSCOMMAND screensaver" );
01068         return 0; /* this stops them from happening */
01069     }
01070 #endif
01071 
01072     if( !p_vout )
01073     {
01074         /* Hmmm mozilla does manage somehow to save the pointer to our
01075          * windowproc and still calls it after the vout has been closed. */
01076         return DefWindowProc(hWnd, message, wParam, lParam);
01077     }
01078 
01079     if( hWnd != p_vout->p_sys->hwnd &&
01080         hWnd != p_vout->p_sys->hfswnd &&
01081         hWnd != p_vout->p_sys->hvideownd )
01082         return DefWindowProc(hWnd, message, wParam, lParam);
01083 
01084     switch( message )
01085     {
01086     case WM_WINDOWPOSCHANGED:
01087         if( hWnd == p_vout->p_sys->hwnd )
01088             UpdateRects( p_vout, VLC_TRUE );
01089         break;
01090 
01091 #if 0
01092     case WM_ACTIVATE:
01093         msg_Err( p_vout, "WM_ACTIVATE: %i", wParam );
01094         if( wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE )
01095             GXResume();
01096         else if( wParam == WA_INACTIVE )
01097             GXSuspend();
01098         break;
01099 #endif
01100 
01101     case WM_KILLFOCUS:
01102         p_vout->p_sys->b_focus = VLC_FALSE;
01103         if( !p_vout->p_sys->b_parent_focus ) GXSuspend();
01104 
01105         if( hWnd == p_vout->p_sys->hfswnd )
01106         {
01107 #ifdef UNDER_CE
01108             HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
01109             ShowWindow( htbar, SW_SHOW );
01110 #endif
01111         }
01112 
01113         if( !p_vout->p_sys->hparent ||
01114             hWnd == p_vout->p_sys->hfswnd )
01115         {
01116             SHFullScreen( hWnd, SHFS_SHOWSIPBUTTON );
01117         }
01118         break;
01119 
01120     case WM_SETFOCUS:
01121         p_vout->p_sys->b_focus = VLC_TRUE;
01122         GXResume();
01123 
01124         if( p_vout->p_sys->hparent &&
01125             hWnd != p_vout->p_sys->hfswnd && p_vout->b_fullscreen )
01126             p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
01127 
01128         if( hWnd == p_vout->p_sys->hfswnd )
01129         {
01130 #ifdef UNDER_CE
01131             HWND htbar = FindWindow( _T("HHTaskbar"), NULL );
01132             ShowWindow( htbar, SW_HIDE );
01133 #endif
01134         }
01135 
01136         if( !p_vout->p_sys->hparent ||
01137             hWnd == p_vout->p_sys->hfswnd )
01138         {
01139             SHFullScreen( hWnd, SHFS_HIDESIPBUTTON );
01140         }
01141         break;
01142 
01143     case WM_LBUTTONDOWN:
01144         p_vout->p_sys->i_changes |= VOUT_FULLSCREEN_CHANGE;
01145         break;
01146     case WM_MOUSEMOVE:
01147         break;
01148     case WM_LBUTTONUP:
01149         break;
01150 
01151     case WM_INITMENUPOPUP:
01152         p_vout->p_sys->b_video_display = VLC_FALSE;
01153         break;
01154 
01155     case WM_NOTIFY:
01156         // Redo the video display because menu can be closed
01157         // FIXME verify if p_child_window exits
01158         if( (((NMHDR *)lParam)->code) == NM_CUSTOMDRAW )
01159             p_vout->p_sys->b_video_display = VLC_TRUE;
01160         break;
01161 
01162     /* the user wants to close the window */
01163     case WM_CLOSE:
01164     {
01165         playlist_t * p_playlist =
01166             (playlist_t *)vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,
01167                                            FIND_ANYWHERE );
01168         if( p_playlist == NULL ) return 0;
01169 
01170         playlist_Stop( p_playlist );
01171         vlc_object_release( p_playlist );
01172         return 0;
01173     }
01174 
01175     case WM_DESTROY:
01176         msg_Dbg( p_vout, "WinProc WM_DESTROY" );
01177         PostQuitMessage( 0 );
01178         break;
01179 
01180     default:
01181         return DefWindowProc( hWnd, message, wParam, lParam );
01182     }
01183 
01184     return 0;
01185 }
01186 
01187 /*****************************************************************************
01188  * InitBuffers: initialize an offscreen bitmap for direct buffer operations.
01189  *****************************************************************************/
01190 static void InitBuffers( vout_thread_t *p_vout )
01191 {
01192     BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
01193     BITMAPINFO *p_info = &p_vout->p_sys->bitmapinfo;
01194     int i_pixels = p_vout->render.i_height * p_vout->render.i_width;
01195     HDC window_dc = GetDC( p_vout->p_sys->hvideownd );
01196 
01197     /* Get screen properties */
01198 #ifdef MODULE_NAME_IS_wingapi
01199     GXDisplayProperties gx_displayprop = GXGetDisplayProperties();
01200     p_vout->p_sys->i_depth = gx_displayprop.cBPP;
01201 #else
01202     p_vout->p_sys->i_depth = GetDeviceCaps( window_dc, PLANES ) *
01203         GetDeviceCaps( window_dc, BITSPIXEL );
01204 #endif
01205     msg_Dbg( p_vout, "GDI depth is %i", p_vout->p_sys->i_depth );
01206 
01207 #ifdef MODULE_NAME_IS_wingapi
01208     GXOpenDisplay( p_vout->p_sys->hvideownd, GX_FULLSCREEN );
01209 
01210 #else
01211 
01212     /* Initialize offscreen bitmap */
01213     memset( p_info, 0, sizeof( BITMAPINFO ) + 3 * sizeof( RGBQUAD ) );
01214 
01215     p_header->biSize = sizeof( BITMAPINFOHEADER );
01216     p_header->biSizeImage = 0;
01217     p_header->biPlanes = 1;
01218     switch( p_vout->p_sys->i_depth )
01219     {
01220     case 8:
01221         p_header->biBitCount = 8;
01222         p_header->biCompression = BI_RGB;
01223         /* FIXME: we need a palette here */
01224         break;
01225     case 15:
01226         p_header->biBitCount = 15;
01227         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
01228         ((DWORD*)p_info->bmiColors)[0] = 0x00007c00;
01229         ((DWORD*)p_info->bmiColors)[1] = 0x000003e0;
01230         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
01231         break;
01232     case 16:
01233         p_header->biBitCount = 16;
01234         p_header->biCompression = BI_BITFIELDS;//BI_RGB;
01235         ((DWORD*)p_info->bmiColors)[0] = 0x0000f800;
01236         ((DWORD*)p_info->bmiColors)[1] = 0x000007e0;
01237         ((DWORD*)p_info->bmiColors)[2] = 0x0000001f;
01238         break;
01239     case 24:
01240         p_header->biBitCount = 24;
01241         p_header->biCompression = BI_RGB;
01242         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
01243         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
01244         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
01245         break;
01246     case 32:
01247         p_header->biBitCount = 32;
01248         p_header->biCompression = BI_RGB;
01249         ((DWORD*)p_info->bmiColors)[0] = 0x00ff0000;
01250         ((DWORD*)p_info->bmiColors)[1] = 0x0000ff00;
01251         ((DWORD*)p_info->bmiColors)[2] = 0x000000ff;
01252         break;
01253     default:
01254         msg_Err( p_vout, "screen depth %i not supported",
01255                  p_vout->p_sys->i_depth );
01256         return;
01257         break;
01258     }
01259     p_header->biWidth = p_vout->render.i_width;
01260     p_header->biHeight = -p_vout->render.i_height;
01261     p_header->biClrImportant = 0;
01262     p_header->biClrUsed = 0;
01263     p_header->biXPelsPerMeter = 0;
01264     p_header->biYPelsPerMeter = 0;
01265 
01266     p_vout->p_sys->i_pic_pixel_pitch = p_header->biBitCount / 8;
01267     p_vout->p_sys->i_pic_pitch = p_header->biBitCount * p_header->biWidth / 8;
01268 
01269     p_vout->p_sys->off_bitmap =
01270         CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
01271                           (void**)&p_vout->p_sys->p_pic_buffer, NULL, 0 );
01272 
01273     p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
01274 
01275     SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
01276     ReleaseDC( 0, window_dc );
01277 #endif
01278 }
01279 
01280 /*****************************************************************************
01281  * Control: control facility for the vout
01282  *****************************************************************************/
01283 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
01284 {
01285     vlc_bool_t b_bool;
01286     double f_arg;
01287     RECT rect_window;
01288     POINT point;
01289 
01290     switch( i_query )
01291     {
01292     case VOUT_SET_ZOOM:
01293         if( p_vout->p_sys->hparent )
01294             return vout_ControlWindow( p_vout,
01295                     (void *)p_vout->p_sys->hparent, i_query, args );
01296 
01297         /* Update dimensions */
01298         rect_window.top = rect_window.left = 0;
01299         rect_window.right  = p_vout->i_window_width;
01300         rect_window.bottom = p_vout->i_window_height;
01301         AdjustWindowRect( &rect_window, p_vout->p_sys->i_window_style, 0 );
01302 
01303         SetWindowPos( p_vout->p_sys->hwnd, 0, 0, 0,
01304                       rect_window.right - rect_window.left,
01305                       rect_window.bottom - rect_window.top, SWP_NOMOVE );
01306 
01307         return VLC_SUCCESS;
01308 
01309     case VOUT_CLOSE:
01310         ShowWindow( p_vout->p_sys->hwnd, SW_HIDE );
01311     case VOUT_REPARENT:
01312         /* Change window style, borders and title bar */
01313         //vlc_mutex_lock( &p_vout->p_sys->lock );
01314         p_vout->p_sys->hparent = 0;
01315         //vlc_mutex_unlock( &p_vout->p_sys->lock );
01316 
01317         /* Retrieve the window position */
01318         point.x = point.y = 0;
01319         ClientToScreen( p_vout->p_sys->hwnd, &point );
01320 
01321         SetParent( p_vout->p_sys->hwnd, 0 );
01322         p_vout->p_sys->i_window_style =
01323             WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
01324         SetWindowLong( p_vout->p_sys->hwnd, GWL_STYLE,
01325                        p_vout->p_sys->i_window_style |
01326                        (i_query == VOUT_CLOSE ? 0 : WS_VISIBLE) );
01327         SetWindowLong( p_vout->p_sys->hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW );
01328         SetWindowPos( p_vout->p_sys->hwnd, 0, point.x, point.y, 0, 0,
01329                       SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED );
01330 
01331         return vout_vaControlDefault( p_vout, i_query, args );
01332 
01333     case VOUT_SET_FOCUS:
01334         b_bool = va_arg( args, vlc_bool_t );
01335 
01336         p_vout->p_sys->b_parent_focus = b_bool;
01337         if( b_bool ) GXResume();
01338         else if( !p_vout->p_sys->b_focus ) GXSuspend();
01339 
01340         return VLC_SUCCESS;
01341 
01342     default:
01343         return vout_vaControlDefault( p_vout, i_query, args );
01344     }
01345 }

Generated on Tue Dec 20 10:14:55 2005 for vlc-0.8.4a by  doxygen 1.4.2