1 /*****************************************************************************
2 * kva.c: KVA video output plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2010, 2011, 2012 VLC authors and VideoLAN
6 * Authors: KO Myung-Hun <komh@chollian.net>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_vout_display.h>
33 #include <vlc_picture_pool.h>
43 /*****************************************************************************
45 *****************************************************************************/
46 static int Open ( vlc_object_t
* );
47 static void Close( vlc_object_t
* );
49 #define KVA_FIXT23_TEXT N_( \
50 "Enable a workaround for T23" )
51 #define KVA_FIXT23_LONGTEXT N_( \
52 "Enable this option if the diagonal stripes are displayed " \
53 "when the window size is equal to or smaller than the movie size." )
54 #define KVA_VIDEO_MODE_TEXT N_( \
56 #define KVA_VIDEO_MODE_LONGTEXT N_( \
57 "Select a proper video mode to be used by KVA." )
59 static const char *const ppsz_kva_video_mode
[] = {
60 "auto", "snap", "wo", "vman", "dive" };
61 static const char *const ppsz_kva_video_mode_text
[] = {
62 N_("Auto"), N_("SNAP"), N_("WarpOverlay!"), N_("VMAN"), N_("DIVE") };
65 set_shortname( "KVA" )
66 set_category( CAT_VIDEO
)
67 set_subcategory( SUBCAT_VIDEO_VOUT
)
68 add_string( "kva-video-mode", ppsz_kva_video_mode
[0], KVA_VIDEO_MODE_TEXT
,
69 KVA_VIDEO_MODE_LONGTEXT
, false )
70 change_string_list( ppsz_kva_video_mode
, ppsz_kva_video_mode_text
)
71 add_bool( "kva-fixt23", false, KVA_FIXT23_TEXT
, KVA_FIXT23_LONGTEXT
, true )
72 set_description( N_("K Video Acceleration video output") )
73 set_capability( "vout display", 100 )
75 set_callbacks( Open
, Close
)
78 /*****************************************************************************
79 * vout_display_sys_t: video output method descriptor
80 *****************************************************************************
81 * This structure is part of the video output thread descriptor.
82 * It describes the module specific properties of an output thread.
83 *****************************************************************************/
84 struct vout_display_sys_t
100 vout_window_t
*parent_window
;
103 picture_pool_t
*pool
;
104 unsigned button_pressed
;
105 bool is_mouse_hidden
;
114 /*****************************************************************************
116 *****************************************************************************/
117 static picture_pool_t
*Pool (vout_display_t
*, unsigned);
118 static void Display(vout_display_t
*, picture_t
*, subpicture_t
* );
119 static int Control(vout_display_t
*, int, va_list);
120 static void Manage (vout_display_t
*);
122 static int OpenDisplay ( vout_display_t
*, video_format_t
* );
123 static void CloseDisplay( vout_display_t
* );
125 static int KVALock( picture_t
* );
126 static void KVAUnlock( picture_t
* );
128 static void MorphToPM ( void );
129 static int ConvertKey ( USHORT
);
130 static MRESULT EXPENTRY
MyFrameWndProc( HWND
, ULONG
, MPARAM
, MPARAM
);
131 static MRESULT EXPENTRY
WndProc ( HWND
, ULONG
, MPARAM
, MPARAM
);
133 #define WC_VLC_KVA "WC_VLC_KVA"
135 #define COLOR_KEY 0x0F0F0F
137 #define WM_VLC_MANAGE ( WM_USER + 1 )
138 #define WM_VLC_FULLSCREEN_CHANGE ( WM_USER + 2 )
139 #define WM_VLC_SIZE_CHANGE ( WM_USER + 3 )
141 static const char *psz_video_mode
[ 4 ] = {"DIVE", "WarpOverlay!", "SNAP",
144 static void PMThread( void *arg
)
146 vout_display_t
*vd
= ( vout_display_t
* )arg
;
147 vout_display_sys_t
* sys
= vd
->sys
;
155 video_format_ApplyRotation(&fmt
, &vd
->fmt
);
158 vout_display_info_t info
= vd
->info
;
159 info
.is_slow
= false;
160 info
.has_double_click
= true;
161 info
.has_hide_mouse
= false;
162 info
.has_pictures_invalid
= false;
166 sys
->hab
= WinInitialize( 0 );
167 sys
->hmq
= WinCreateMsgQueue( sys
->hab
, 0);
169 WinRegisterClass( sys
->hab
,
172 CS_SIZEREDRAW
| CS_MOVENOTIFY
,
175 sys
->b_fixt23
= var_CreateGetBool( vd
, "kva-fixt23");
178 /* If an external window was specified, we'll draw in it. */
180 vout_display_NewWindow( vd
, VOUT_WINDOW_TYPE_HWND
);
182 if( sys
->parent_window
)
184 sys
->parent
= ( HWND
)sys
->parent_window
->handle
.hwnd
;
186 ULONG i_style
= WinQueryWindowULong( sys
->parent
, QWL_STYLE
);
187 WinSetWindowULong( sys
->parent
, QWL_STYLE
,
188 i_style
| WS_CLIPCHILDREN
);
190 i_frame_flags
= FCF_TITLEBAR
;
194 sys
->parent
= HWND_DESKTOP
;
196 i_frame_flags
= FCF_SYSMENU
| FCF_TITLEBAR
| FCF_MINMAX
|
197 FCF_SIZEBORDER
| FCF_TASKLIST
;
201 WinCreateStdWindow( sys
->parent
, /* parent window handle */
202 WS_VISIBLE
, /* frame window style */
203 &i_frame_flags
, /* window style */
204 WC_VLC_KVA
, /* class name */
205 "", /* window title */
206 0L, /* default client style */
207 NULLHANDLE
, /* resource in exe file */
208 1, /* frame window id */
209 &sys
->client
); /* client window handle */
211 if( sys
->frame
== NULLHANDLE
)
213 msg_Err( vd
, "cannot create a frame window");
218 WinSetWindowPtr( sys
->client
, 0, vd
);
220 if( !sys
->parent_window
)
222 WinSetWindowPtr( sys
->frame
, 0, vd
);
223 sys
->p_old_frame
= WinSubclassWindow( sys
->frame
, MyFrameWndProc
);
226 psz_mode
= var_CreateGetString( vd
, "kva-video-mode" );
228 i_kva_mode
= KVAM_AUTO
;
229 if( strcmp( psz_mode
, "snap" ) == 0 )
230 i_kva_mode
= KVAM_SNAP
;
231 else if( strcmp( psz_mode
, "wo" ) == 0 )
232 i_kva_mode
= KVAM_WO
;
233 else if( strcmp( psz_mode
, "vman" ) == 0 )
234 i_kva_mode
= KVAM_VMAN
;
235 else if( strcmp( psz_mode
, "dive" ) == 0 )
236 i_kva_mode
= KVAM_DIVE
;
240 if( kvaInit( i_kva_mode
, sys
->client
, COLOR_KEY
))
242 msg_Err( vd
, "cannot initialize KVA");
247 kvaCaps( &sys
->kvac
);
249 msg_Dbg( vd
, "selected video mode = %s",
250 psz_video_mode
[ sys
->kvac
.ulMode
- 1 ]);
252 if( OpenDisplay( vd
, &fmt
) )
254 msg_Err( vd
, "cannot open display");
256 goto exit_open_display
;
259 if( vd
->cfg
->is_fullscreen
&& !sys
->parent_window
)
260 WinPostMsg( sys
->client
, WM_VLC_FULLSCREEN_CHANGE
,
261 MPFROMLONG( true ), 0 );
263 kvaDisableScreenSaver();
265 /* Setup vout_display now that everything is fine */
271 vd
->display
= Display
;
272 vd
->control
= Control
;
275 /* Prevent SIG_FPE */
276 _control87(MCW_EM
, MCW_EM
);
278 sys
->i_result
= VLC_SUCCESS
;
279 DosPostEventSem( sys
->ack_event
);
281 if( !sys
->parent_window
)
282 WinSetVisibleRegionNotify( sys
->frame
, TRUE
);
284 while( WinGetMsg( sys
->hab
, &qm
, NULLHANDLE
, 0, 0 ))
285 WinDispatchMsg( sys
->hab
, &qm
);
287 if( !sys
->parent_window
)
288 WinSetVisibleRegionNotify( sys
->frame
, FALSE
);
290 kvaEnableScreenSaver();
300 if( !sys
->parent_window
)
301 WinSubclassWindow( sys
->frame
, sys
->p_old_frame
);
303 WinDestroyWindow( sys
->frame
);
306 vout_display_DeleteWindow( vd
, sys
->parent_window
);
308 if( sys
->is_mouse_hidden
)
309 WinShowPointer( HWND_DESKTOP
, TRUE
);
311 WinDestroyMsgQueue( sys
->hmq
);
312 WinTerminate( sys
->hab
);
314 sys
->i_result
= VLC_EGENERIC
;
315 DosPostEventSem( sys
->ack_event
);
319 * This function initializes KVA vout method.
321 static int Open ( vlc_object_t
*object
)
323 vout_display_t
*vd
= (vout_display_t
*)object
;
324 vout_display_sys_t
*sys
;
326 vd
->sys
= sys
= calloc( 1, sizeof( *sys
));
330 DosCreateEventSem( NULL
, &sys
->ack_event
, 0, FALSE
);
332 sys
->tid
= _beginthread( PMThread
, NULL
, 1024 * 1024, vd
);
333 DosWaitEventSem( sys
->ack_event
, SEM_INDEFINITE_WAIT
);
335 if( sys
->i_result
!= VLC_SUCCESS
)
337 DosCloseEventSem( sys
->ack_event
);
347 /*****************************************************************************
348 * Close: destroy KVA video thread output method
349 *****************************************************************************
350 * Terminate an output method created by Open
351 *****************************************************************************/
352 static void Close ( vlc_object_t
*object
)
354 vout_display_t
* vd
= (vout_display_t
*)object
;
355 vout_display_sys_t
* sys
= vd
->sys
;
357 WinPostQueueMsg( sys
->hmq
, WM_QUIT
, 0, 0 );
359 DosWaitThread( &sys
->tid
, DCWW_WAIT
);
362 picture_pool_Release( sys
->pool
);
364 DosCloseEventSem( sys
->ack_event
);
370 * Return a pool of direct buffers
372 static picture_pool_t
*Pool(vout_display_t
*vd
, unsigned count
)
374 vout_display_sys_t
*sys
= vd
->sys
;
380 /*****************************************************************************
381 * Display: displays previously rendered output
382 *****************************************************************************
383 * This function sends the currently rendered image to the display.
384 *****************************************************************************/
385 static void Display( vout_display_t
*vd
, picture_t
*picture
,
386 subpicture_t
*subpicture
)
389 VLC_UNUSED( subpicture
);
391 picture_Release( picture
);
394 /*****************************************************************************
395 * Manage: handle Sys events
396 *****************************************************************************
397 * This function should be called regularly by video output thread. It returns
398 * a non null value if an error occurred.
399 *****************************************************************************/
400 static void Manage( vout_display_t
*vd
)
402 vout_display_sys_t
* sys
= vd
->sys
;
404 /* Let a window procedure manage instead because if resizing a frame window
405 * here, WM_SIZE is not sent to its child window.
406 * Maybe, is this due to the different threads ? */
407 WinPostMsg( sys
->client
, WM_VLC_MANAGE
, 0, 0 );
410 /*****************************************************************************
411 * Control: control facility for the vout
412 *****************************************************************************/
413 static int Control( vout_display_t
*vd
, int query
, va_list args
)
415 vout_display_sys_t
*sys
= vd
->sys
;
419 case VOUT_DISPLAY_HIDE_MOUSE
:
423 WinQueryPointerPos( HWND_DESKTOP
, &ptl
);
424 if( !sys
->is_mouse_hidden
&&
425 WinWindowFromPoint( HWND_DESKTOP
, &ptl
, TRUE
) == sys
->client
)
427 WinShowPointer( HWND_DESKTOP
, FALSE
);
428 sys
->is_mouse_hidden
= true;
434 case VOUT_DISPLAY_CHANGE_FULLSCREEN
:
436 bool fs
= va_arg(args
, int);
438 WinPostMsg( sys
->client
, WM_VLC_FULLSCREEN_CHANGE
, MPFROMLONG(fs
), 0 );
442 case VOUT_DISPLAY_CHANGE_WINDOW_STATE
:
444 const unsigned state
= va_arg( args
, unsigned );
445 const bool is_on_top
= (state
& VOUT_WINDOW_STATE_ABOVE
) != 0;
448 WinSetWindowPos( sys
->frame
, HWND_TOP
, 0, 0, 0, 0, SWP_ZORDER
);
450 sys
->is_on_top
= is_on_top
;
455 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE
:
456 case VOUT_DISPLAY_CHANGE_ZOOM
:
458 const vout_display_cfg_t
*cfg
= va_arg(args
, const vout_display_cfg_t
*);
460 WinPostMsg( sys
->client
, WM_VLC_SIZE_CHANGE
,
461 MPFROMLONG( cfg
->display
.width
),
462 MPFROMLONG( cfg
->display
.height
));
466 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
:
467 case VOUT_DISPLAY_CHANGE_SOURCE_CROP
:
469 const video_format_t
*src
= va_arg(args
, const video_format_t
*);
471 if( query
== VOUT_DISPLAY_CHANGE_SOURCE_ASPECT
)
473 vout_display_place_t place
;
474 vout_display_PlacePicture(&place
, src
, vd
->cfg
, false);
476 sys
->kvas
.ulAspectWidth
= place
.width
;
477 sys
->kvas
.ulAspectHeight
= place
.height
;
481 video_format_t src_rot
;
482 video_format_ApplyRotation(&src_rot
, src
);
484 sys
->kvas
.rclSrcRect
.xLeft
= src_rot
.i_x_offset
;
485 sys
->kvas
.rclSrcRect
.yTop
= src_rot
.i_y_offset
;
486 sys
->kvas
.rclSrcRect
.xRight
= src_rot
.i_x_offset
+
487 src_rot
.i_visible_width
;
488 sys
->kvas
.rclSrcRect
.yBottom
= src_rot
.i_y_offset
+
489 src_rot
.i_visible_height
;
492 kvaSetup( &sys
->kvas
);
497 case VOUT_DISPLAY_RESET_PICTURES
:
498 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED
:
503 msg_Err(vd
, "Unsupported query(=%d) in vout display KVA", query
);
507 /* following functions are local */
509 /*****************************************************************************
510 * OpenDisplay: open and initialize KVA device
511 *****************************************************************************
512 * Open and initialize display according to preferences specified in the vout
514 *****************************************************************************/
515 static int OpenDisplay( vout_display_t
*vd
, video_format_t
*fmt
)
517 vout_display_sys_t
* sys
= vd
->sys
;
518 const vlc_fourcc_t
*fallback
;
522 char sz_title
[ 256 ];
526 msg_Dbg( vd
, "render chroma = %4.4s", ( const char * )&fmt
->i_chroma
);
528 for( int pass
= 0; pass
< 2 && !b_hw_accel
; pass
++ )
530 fallback
= ( pass
== 0 ) ? vlc_fourcc_GetYUVFallback( fmt
->i_chroma
) :
531 vlc_fourcc_GetRGBFallback( fmt
->i_chroma
);
533 for( int i
= 0; fallback
[ i
]; i
++ )
535 switch( fallback
[ i
])
538 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_YV12
;
539 i_kva_fourcc
= FOURCC_YV12
;
544 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_YUY2
;
545 i_kva_fourcc
= FOURCC_Y422
;
550 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_YVU9
;
551 i_kva_fourcc
= FOURCC_YVU9
;
555 case VLC_CODEC_RGB32
:
556 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_BGR32
;
557 i_kva_fourcc
= FOURCC_BGR4
;
561 case VLC_CODEC_RGB24
:
562 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_BGR24
;
563 i_kva_fourcc
= FOURCC_BGR3
;
567 case VLC_CODEC_RGB16
:
568 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_BGR16
;
569 i_kva_fourcc
= FOURCC_R565
;
573 case VLC_CODEC_RGB15
:
574 b_hw_accel
= sys
->kvac
.ulInputFormatFlags
& KVAF_BGR15
;
575 i_kva_fourcc
= FOURCC_R555
;
582 fmt
->i_chroma
= fallback
[ i
];
590 msg_Err( vd
, "Ooops. There is no fourcc supported by KVA at all.");
595 /* Set the RGB masks */
596 fmt
->i_rmask
= sys
->kvac
.ulRMask
;
597 fmt
->i_gmask
= sys
->kvac
.ulGMask
;
598 fmt
->i_bmask
= sys
->kvac
.ulBMask
;
600 msg_Dbg( vd
, "output chroma = %4.4s", ( const char * )&fmt
->i_chroma
);
601 msg_Dbg( vd
, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc
);
606 sys
->kvas
.ulLength
= sizeof( KVASETUP
);
607 sys
->kvas
.szlSrcSize
.cx
= w
;
608 sys
->kvas
.szlSrcSize
.cy
= h
;
609 sys
->kvas
.rclSrcRect
.xLeft
= fmt
->i_x_offset
;
610 sys
->kvas
.rclSrcRect
.yTop
= fmt
->i_y_offset
;
611 sys
->kvas
.rclSrcRect
.xRight
= fmt
->i_x_offset
+ fmt
->i_visible_width
;
612 sys
->kvas
.rclSrcRect
.yBottom
= fmt
->i_y_offset
+ fmt
->i_visible_height
;
613 sys
->kvas
.ulRatio
= KVAR_FORCEANY
;
614 sys
->kvas
.ulAspectWidth
= w
;
615 sys
->kvas
.ulAspectHeight
= h
;
616 sys
->kvas
.fccSrcColor
= i_kva_fourcc
;
617 sys
->kvas
.fDither
= TRUE
;
619 if( kvaSetup( &sys
->kvas
))
621 msg_Err( vd
, "cannot set up KVA");
626 /* Create the associated picture */
627 picture_sys_t
*picsys
= malloc( sizeof( *picsys
) );
630 picsys
->i_chroma_shift
= i_chroma_shift
;
632 picture_resource_t resource
= { .p_sys
= picsys
};
633 picture_t
*picture
= picture_NewFromResource( fmt
, &resource
);
640 /* Wrap it into a picture pool */
641 picture_pool_configuration_t pool_cfg
;
642 memset( &pool_cfg
, 0, sizeof( pool_cfg
));
643 pool_cfg
.picture_count
= 1;
644 pool_cfg
.picture
= &picture
;
645 pool_cfg
.lock
= KVALock
;
646 pool_cfg
.unlock
= KVAUnlock
;
648 sys
->pool
= picture_pool_NewExtended( &pool_cfg
);
651 picture_Release( picture
);
655 if (vd
->cfg
->display
.title
)
656 snprintf( sz_title
, sizeof( sz_title
), "%s", vd
->cfg
->display
.title
);
658 snprintf( sz_title
, sizeof( sz_title
),
659 "%s (%4.4s to %4.4s - %s mode KVA output)",
661 ( char * )&vd
->fmt
.i_chroma
,
662 ( char * )&sys
->kvas
.fccSrcColor
,
663 psz_video_mode
[ sys
->kvac
.ulMode
- 1 ]);
664 WinSetWindowText( sys
->frame
, sz_title
);
666 sys
->i_screen_width
= WinQuerySysValue( HWND_DESKTOP
, SV_CXSCREEN
);
667 sys
->i_screen_height
= WinQuerySysValue( HWND_DESKTOP
, SV_CYSCREEN
);
669 if( sys
->parent_window
)
670 WinQueryWindowRect( sys
->parent
, &sys
->client_rect
);
673 sys
->client_rect
.xLeft
= ( sys
->i_screen_width
- w
) / 2;
674 sys
->client_rect
.yBottom
= ( sys
->i_screen_height
- h
) / 2 ;
675 sys
->client_rect
.xRight
= sys
->client_rect
.xLeft
+ w
;
676 sys
->client_rect
.yTop
= sys
->client_rect
.yBottom
+ h
;
679 rcl
= sys
->client_rect
;
681 WinCalcFrameRect( sys
->frame
, &rcl
, FALSE
);
683 WinSetWindowPos( sys
->frame
, HWND_TOP
,
684 rcl
.xLeft
, rcl
.yBottom
,
685 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
686 SWP_MOVE
| SWP_SIZE
| SWP_ZORDER
| SWP_SHOW
|
692 /*****************************************************************************
693 * CloseDisplay: close and reset KVA device
694 *****************************************************************************
695 * This function returns all resources allocated by OpenDisplay and restore
696 * the original state of the device.
697 *****************************************************************************/
698 static void CloseDisplay( vout_display_t
*vd
)
703 static int KVALock( picture_t
*picture
)
705 picture_sys_t
*picsys
= picture
->p_sys
;
709 if( kvaLockBuffer( &kva_buffer
, &kva_bpl
))
712 /* Packed or Y plane */
713 picture
->p
->p_pixels
= ( uint8_t * )kva_buffer
;
714 picture
->p
->i_pitch
= kva_bpl
;
715 picture
->p
->i_lines
= picture
->format
.i_height
;
718 for( int n
= 1; n
< picture
->i_planes
; n
++ )
720 const plane_t
*o
= &picture
->p
[n
-1];
721 plane_t
*p
= &picture
->p
[n
];
723 p
->p_pixels
= o
->p_pixels
+ o
->i_lines
* o
->i_pitch
;
724 p
->i_pitch
= kva_bpl
>> picsys
->i_chroma_shift
;
725 p
->i_lines
= picture
->format
.i_height
>> picsys
->i_chroma_shift
;
731 static void KVAUnlock( picture_t
*picture
)
733 VLC_UNUSED( picture
);
738 static void MorphToPM( void )
742 DosGetInfoBlocks(NULL
, &pib
);
744 /* Change flag from VIO to PM */
745 if (pib
->pib_ultype
== 2)
749 /*****************************************************************************
750 * Key events handling
751 *****************************************************************************/
756 } pmkeys_to_vlckeys
[] =
758 { VK_LEFT
, KEY_LEFT
},
759 { VK_RIGHT
, KEY_RIGHT
},
761 { VK_DOWN
, KEY_DOWN
},
763 { VK_NEWLINE
, KEY_ENTER
},
764 { VK_ENTER
, KEY_ENTER
},
777 { VK_HOME
, KEY_HOME
},
779 { VK_INSERT
, KEY_INSERT
},
780 { VK_DELETE
, KEY_DELETE
},
786 { VK_PAGEUP
, KEY_PAGEUP
},
787 { VK_PAGEDOWN
, KEY_PAGEDOWN
},
789 { VK_BACKSPACE
, KEY_BACKSPACE
},
792 {, KEY_MOUSEWHEELUP },
793 {, KEY_MOUSEWHEELDOWN },
794 {, KEY_MOUSEWHEELLEFT },
795 {, KEY_MOUSEWHEELRIGHT },
797 {, KEY_BROWSER_BACK },
798 {, KEY_BROWSER_FORWARD },
799 {, KEY_BROWSER_REFRESH },
800 {, KEY_BROWSER_STOP },
801 {, KEY_BROWSER_SEARCH },
802 {, KEY_BROWSER_FAVORITES },
803 {, KEY_BROWSER_HOME },
804 {, KEY_VOLUME_MUTE },
805 {, KEY_VOLUME_DOWN },
807 {, KEY_MEDIA_NEXT_TRACK },
808 {, KEY_MEDIA_PREV_TRACK },
810 {, KEY_MEDIA_PLAY_PAUSE },
816 static int ConvertKey( USHORT i_pmkey
)
819 for( i
= 0; pmkeys_to_vlckeys
[ i
].i_pmkey
!= 0; i
++ )
821 if( pmkeys_to_vlckeys
[ i
].i_pmkey
== i_pmkey
)
822 return pmkeys_to_vlckeys
[ i
].i_vlckey
;
827 static MRESULT EXPENTRY
MyFrameWndProc( HWND hwnd
, ULONG msg
, MPARAM mp1
,
830 vout_display_t
*vd
= WinQueryWindowPtr( hwnd
, 0 );
831 vout_display_sys_t
*sys
= vd
->sys
;
835 case WM_QUERYTRACKINFO
:
839 mr
= sys
->p_old_frame( hwnd
, msg
, mp1
, mp2
);
843 PTRACKINFO pti
= ( PTRACKINFO
)mp2
;
846 pti
->rclBoundary
.xLeft
= 0;
847 pti
->rclBoundary
.yBottom
= 0;
848 pti
->rclBoundary
.xRight
= sys
->i_screen_width
;
849 pti
->rclBoundary
.yTop
= sys
->i_screen_height
;
851 WinCalcFrameRect( hwnd
, &pti
->rclBoundary
, FALSE
);
853 pti
->ptlMaxTrackSize
.x
= pti
->rclBoundary
.xRight
-
854 pti
->rclBoundary
.xLeft
;
855 pti
->ptlMaxTrackSize
.y
= pti
->rclBoundary
.yTop
-
856 pti
->rclBoundary
.yBottom
;
860 rcl
.xRight
= sys
->kvas
.szlSrcSize
.cx
+ 1;
861 rcl
.yTop
= sys
->kvas
.szlSrcSize
.cy
+ 1;
863 WinCalcFrameRect( hwnd
, &rcl
, FALSE
);
865 pti
->ptlMinTrackSize
.x
= rcl
.xRight
- rcl
.xLeft
;
866 pti
->ptlMinTrackSize
.y
= rcl
.yTop
- rcl
.yBottom
;
868 return MRFROMLONG( TRUE
);
871 case WM_ADJUSTWINDOWPOS
:
876 PSWP pswp
= ( PSWP
)mp1
;
878 if( pswp
->fl
& SWP_SIZE
)
883 rcl
.yBottom
= pswp
->y
;
884 rcl
.xRight
= rcl
.xLeft
+ pswp
->cx
;
885 rcl
.yTop
= rcl
.yBottom
+ pswp
->cy
;
887 WinCalcFrameRect( hwnd
, &rcl
, TRUE
);
889 if( rcl
.xRight
- rcl
.xLeft
<= sys
->kvas
.szlSrcSize
.cx
)
890 rcl
.xRight
= rcl
.xLeft
+ ( sys
->kvas
.szlSrcSize
.cx
+ 1 );
892 if( rcl
.yTop
- rcl
.yBottom
<= sys
->kvas
.szlSrcSize
.cy
)
893 rcl
.yTop
= rcl
.yBottom
+ ( sys
->kvas
.szlSrcSize
.cy
+ 1 );
895 if( rcl
.xRight
- rcl
.xLeft
> sys
->i_screen_width
)
898 rcl
.xRight
= sys
->i_screen_width
;
901 if( rcl
.yTop
- rcl
.yBottom
> sys
->i_screen_height
)
904 rcl
.yTop
= sys
->i_screen_height
;
907 WinCalcFrameRect( hwnd
, &rcl
, FALSE
);
909 if( pswp
->x
!= rcl
.xLeft
|| pswp
->y
!= rcl
.yBottom
)
910 pswp
->fl
|= SWP_MOVE
;
913 pswp
->y
= rcl
.yBottom
;
915 pswp
->cx
= rcl
.xRight
- rcl
.xLeft
;
916 pswp
->cy
= rcl
.yTop
- rcl
.yBottom
;
922 //case WM_VRNDISABLED :
924 if( !vd
->cfg
->is_fullscreen
&& sys
->is_on_top
)
925 WinSetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_ZORDER
);
929 return sys
->p_old_frame( hwnd
, msg
, mp1
, mp2
);
932 static void MousePressed( vout_display_t
*vd
, HWND hwnd
, unsigned button
)
934 if( WinQueryFocus( HWND_DESKTOP
) != hwnd
)
935 WinSetFocus( HWND_DESKTOP
, hwnd
);
937 if( !vd
->sys
->button_pressed
)
938 WinSetCapture( HWND_DESKTOP
, hwnd
);
940 vd
->sys
->button_pressed
|= 1 << button
;
942 vout_display_SendEventMousePressed( vd
, button
);
945 static void MouseReleased( vout_display_t
*vd
, unsigned button
)
947 vd
->sys
->button_pressed
&= ~(1 << button
);
948 if( !vd
->sys
->button_pressed
)
949 WinSetCapture( HWND_DESKTOP
, NULLHANDLE
);
951 vout_display_SendEventMouseReleased( vd
, button
);
954 #define WM_MOUSELEAVE 0x41F
956 static MRESULT EXPENTRY
WndProc( HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
)
958 vout_display_t
* vd
= WinQueryWindowPtr( hwnd
, 0 );
959 MRESULT result
= ( MRESULT
)TRUE
;
962 return WinDefWindowProc( hwnd
, msg
, mp1
, mp2
);
964 vout_display_sys_t
* sys
= vd
->sys
;
968 if ( sys
->is_mouse_hidden
&&
969 ((msg
>= WM_MOUSEFIRST
&& msg
<= WM_MOUSELAST
) ||
970 (msg
>= WM_EXTMOUSEFIRST
&& msg
<= WM_EXTMOUSELAST
) ||
971 msg
== WM_MOUSELEAVE
))
973 WinShowPointer(HWND_DESKTOP
, TRUE
);
974 sys
->is_mouse_hidden
= false;
979 /* the user wants to close the window */
981 vout_display_SendEventClose(vd
);
987 SHORT i_mouse_x
= SHORT1FROMMP( mp1
);
988 SHORT i_mouse_y
= SHORT2FROMMP( mp1
);
990 int i_movie_width
, i_movie_height
;
991 int i_src_width
, i_src_height
;
993 /* Get a current movie area */
994 kvaAdjustDstRect( &sys
->kvas
.rclSrcRect
, &movie_rect
);
995 i_movie_width
= movie_rect
.xRight
- movie_rect
.xLeft
;
996 i_movie_height
= movie_rect
.yTop
- movie_rect
.yBottom
;
998 i_src_width
= sys
->kvas
.rclSrcRect
.xRight
-
999 sys
->kvas
.rclSrcRect
.xLeft
;
1000 i_src_height
= sys
->kvas
.rclSrcRect
.yBottom
-
1001 sys
->kvas
.rclSrcRect
.yTop
;
1003 int x
= ( i_mouse_x
- movie_rect
.xLeft
) *
1004 i_src_width
/ i_movie_width
+
1005 sys
->kvas
.rclSrcRect
.xLeft
;
1006 int y
= ( i_mouse_y
- movie_rect
.yBottom
) *
1007 i_src_height
/ i_movie_height
;
1009 /* Invert Y coordinate and add y offset */
1010 y
= ( i_src_height
- y
) + sys
->kvas
.rclSrcRect
.yTop
;;
1012 vout_display_SendEventMouseMoved(vd
, x
, y
);
1014 result
= WinDefWindowProc( hwnd
, msg
, mp1
,mp2
);
1018 case WM_BUTTON1DOWN
:
1019 MousePressed( vd
, hwnd
, MOUSE_BUTTON_LEFT
);
1022 case WM_BUTTON2DOWN
:
1023 MousePressed( vd
, hwnd
, MOUSE_BUTTON_RIGHT
);
1026 case WM_BUTTON3DOWN
:
1027 MousePressed( vd
, hwnd
, MOUSE_BUTTON_CENTER
);
1031 MouseReleased( vd
, MOUSE_BUTTON_LEFT
);
1035 MouseReleased( vd
, MOUSE_BUTTON_RIGHT
);
1039 MouseReleased( vd
, MOUSE_BUTTON_CENTER
);
1042 case WM_BUTTON1DBLCLK
:
1043 vout_display_SendEventMouseDoubleClick(vd
);
1046 case WM_TRANSLATEACCEL
:
1047 /* We have no accelerator table at all */
1048 result
= ( MRESULT
)FALSE
;
1053 USHORT i_flags
= SHORT1FROMMP( mp1
);
1054 USHORT i_ch
= SHORT1FROMMP( mp2
);
1055 USHORT i_vk
= SHORT2FROMMP( mp2
);
1058 /* If embedded window, let the parent process keys */
1059 if( sys
->parent_window
)
1061 WinPostMsg( sys
->parent
, msg
, mp1
, mp2
);
1065 if( !( i_flags
& KC_KEYUP
))
1067 if( i_flags
& KC_VIRTUALKEY
)
1068 /* convert the key if possible */
1069 i_key
= ConvertKey( i_vk
);
1070 else if(( i_flags
& KC_CHAR
) && !HIBYTE( i_ch
))
1071 i_key
= tolower( i_ch
);
1075 if( i_flags
& KC_SHIFT
)
1076 i_key
|= KEY_MODIFIER_SHIFT
;
1078 if( i_flags
& KC_CTRL
)
1079 i_key
|= KEY_MODIFIER_CTRL
;
1081 if( i_flags
& KC_ALT
)
1082 i_key
|= KEY_MODIFIER_ALT
;
1084 vout_display_SendEventKey(vd
, i_key
);
1090 /* Process Manage() call */
1091 case WM_VLC_MANAGE
:
1094 /* Fullscreen change */
1095 case WM_VLC_FULLSCREEN_CHANGE
:
1096 if( LONGFROMMP( mp1
))
1098 WinQueryWindowPos( sys
->frame
, &swp
);
1099 sys
->client_rect
.xLeft
= swp
.x
;
1100 sys
->client_rect
.yBottom
= swp
.y
;
1101 sys
->client_rect
.xRight
= sys
->client_rect
.xLeft
+ swp
.cx
;
1102 sys
->client_rect
.yTop
= sys
->client_rect
.yBottom
+ swp
.cy
;
1103 WinCalcFrameRect( sys
->frame
, &sys
->client_rect
, TRUE
);
1107 rcl
.xRight
= sys
->i_screen_width
;
1108 rcl
.yTop
= sys
->i_screen_height
;
1111 rcl
= sys
->client_rect
;
1113 WinCalcFrameRect( sys
->frame
, &rcl
, FALSE
);
1115 WinSetWindowPos( sys
->frame
, HWND_TOP
,
1116 rcl
.xLeft
, rcl
.yBottom
,
1117 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
1118 SWP_MOVE
| SWP_SIZE
| SWP_ZORDER
| SWP_SHOW
|
1123 case WM_VLC_SIZE_CHANGE
:
1126 rcl
.xRight
= LONGFROMMP( mp1
);
1127 rcl
.yTop
= LONGFROMMP( mp2
);
1128 WinCalcFrameRect( sys
->frame
, &rcl
, FALSE
);
1130 WinSetWindowPos( sys
->frame
, NULLHANDLE
,
1132 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
1135 WinQueryWindowPos( sys
->frame
, &swp
);
1136 sys
->client_rect
.xLeft
= swp
.x
;
1137 sys
->client_rect
.yBottom
= swp
.y
;
1138 sys
->client_rect
.xRight
= sys
->client_rect
.xLeft
+ swp
.cx
;
1139 sys
->client_rect
.yTop
= sys
->client_rect
.yBottom
+ swp
.cy
;
1140 WinCalcFrameRect( sys
->frame
, &sys
->client_rect
, TRUE
);
1144 return WinDefWindowProc( hwnd
, msg
, mp1
, mp2
);
1147 /* If embedded window, we need to change our window size according to a
1148 * parent window size */
1149 if( sys
->parent_window
)
1151 WinQueryWindowRect( sys
->parent
, &rcl
);
1153 if( rcl
.xLeft
!= sys
->parent_rect
.xLeft
||
1154 rcl
.yBottom
!= sys
->parent_rect
.yBottom
||
1155 rcl
.xRight
!= sys
->parent_rect
.xRight
||
1156 rcl
.yTop
!= sys
->parent_rect
.yTop
)
1158 sys
->parent_rect
= rcl
;
1160 WinCalcFrameRect( sys
->frame
, &rcl
, FALSE
);
1162 WinSetWindowPos( sys
->frame
, NULLHANDLE
,
1163 rcl
.xLeft
, rcl
.yBottom
,
1164 rcl
.xRight
- rcl
.xLeft
, rcl
.yTop
- rcl
.yBottom
,
1165 SWP_SIZE
| SWP_MOVE
);