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 picture_resource_t resource;
105 unsigned button_pressed;
106 bool is_mouse_hidden;
115 /*****************************************************************************
117 *****************************************************************************/
118 static picture_pool_t *Pool (vout_display_t *, unsigned);
119 static void Display(vout_display_t *, picture_t *, subpicture_t * );
120 static int Control(vout_display_t *, int, va_list);
121 static void Manage (vout_display_t *);
123 static int OpenDisplay ( vout_display_t *, video_format_t * );
124 static void CloseDisplay( vout_display_t * );
126 static int KVALock( picture_t * );
127 static void KVAUnlock( picture_t * );
129 static void MorphToPM ( void );
130 static int ConvertKey ( USHORT );
131 static MRESULT EXPENTRY MyFrameWndProc( HWND, ULONG, MPARAM, MPARAM );
132 static MRESULT EXPENTRY WndProc ( HWND, ULONG, MPARAM, MPARAM );
134 #define WC_VLC_KVA "WC_VLC_KVA"
136 #define COLOR_KEY 0x0F0F0F
138 #define WM_VLC_MANAGE ( WM_USER + 1 )
139 #define WM_VLC_FULLSCREEN_CHANGE ( WM_USER + 2 )
140 #define WM_VLC_SIZE_CHANGE ( WM_USER + 3 )
142 static const char *psz_video_mode[ 4 ] = {"DIVE", "WarpOverlay!", "SNAP",
145 static void PMThread( void *arg )
147 vout_display_t *vd = ( vout_display_t * )arg;
148 vout_display_sys_t * sys = vd->sys;
155 video_format_t 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");
179 vout_window_cfg_t wnd_cfg;
181 wnd_cfg.is_standalone = false;
182 wnd_cfg.type = VOUT_WINDOW_TYPE_HWND;
183 wnd_cfg.x = var_InheritInteger(vd, "video-x");
184 wnd_cfg.y = var_InheritInteger(vd, "video-y");
185 wnd_cfg.width = vd->cfg->display.width;
186 wnd_cfg.height = vd->cfg->display.height;
188 /* If an external window was specified, we'll draw in it. */
190 vout_display_NewWindow( vd, &wnd_cfg );
193 if( sys->parent_window )
195 sys->parent = ( HWND )sys->parent_window->handle.hwnd;
198 * When an embedded window opened first, it is not positioned
199 * correctly. So reposition it here, again.
201 WinSetWindowPos( WinQueryWindow( sys->parent, QW_PARENT ),
202 HWND_TOP, 0, 0, 0, 0, SWP_MOVE );
204 ULONG i_style = WinQueryWindowULong( sys->parent, QWL_STYLE );
205 WinSetWindowULong( sys->parent, QWL_STYLE,
206 i_style | WS_CLIPCHILDREN );
208 i_frame_flags = FCF_TITLEBAR;
212 sys->parent = HWND_DESKTOP;
214 i_frame_flags = FCF_SYSMENU | FCF_TITLEBAR | FCF_MINMAX |
215 FCF_SIZEBORDER | FCF_TASKLIST;
219 WinCreateStdWindow( sys->parent, /* parent window handle */
220 WS_VISIBLE, /* frame window style */
221 &i_frame_flags, /* window style */
222 WC_VLC_KVA, /* class name */
223 "", /* window title */
224 0L, /* default client style */
225 NULLHANDLE, /* resource in exe file */
226 1, /* frame window id */
227 &sys->client ); /* client window handle */
229 if( sys->frame == NULLHANDLE )
231 msg_Err( vd, "cannot create a frame window");
236 WinSetWindowPtr( sys->client, 0, vd );
238 if( !sys->parent_window )
240 WinSetWindowPtr( sys->frame, 0, vd );
241 sys->p_old_frame = WinSubclassWindow( sys->frame, MyFrameWndProc );
244 psz_mode = var_CreateGetString( vd, "kva-video-mode" );
246 i_kva_mode = KVAM_AUTO;
247 if( strcmp( psz_mode, "snap" ) == 0 )
248 i_kva_mode = KVAM_SNAP;
249 else if( strcmp( psz_mode, "wo" ) == 0 )
250 i_kva_mode = KVAM_WO;
251 else if( strcmp( psz_mode, "vman" ) == 0 )
252 i_kva_mode = KVAM_VMAN;
253 else if( strcmp( psz_mode, "dive" ) == 0 )
254 i_kva_mode = KVAM_DIVE;
258 if( kvaInit( i_kva_mode, sys->client, COLOR_KEY ))
260 msg_Err( vd, "cannot initialize KVA");
265 kvaCaps( &sys->kvac );
267 msg_Dbg( vd, "selected video mode = %s",
268 psz_video_mode[ sys->kvac.ulMode - 1 ]);
270 if( OpenDisplay( vd, &fmt ) )
272 msg_Err( vd, "cannot open display");
274 goto exit_open_display;
277 if( vd->cfg->is_fullscreen )
279 if( sys->parent_window )
280 vout_window_SetFullScreen(sys->parent_window, true);
282 WinPostMsg( sys->client, WM_VLC_FULLSCREEN_CHANGE,
283 MPFROMLONG( true ), 0 );
286 kvaDisableScreenSaver();
288 /* Setup vout_display now that everything is fine */
294 vd->display = Display;
295 vd->control = Control;
298 /* Prevent SIG_FPE */
299 _control87(MCW_EM, MCW_EM);
301 sys->i_result = VLC_SUCCESS;
302 DosPostEventSem( sys->ack_event );
304 if( !sys->parent_window )
305 WinSetVisibleRegionNotify( sys->frame, TRUE );
307 while( WinGetMsg( sys->hab, &qm, NULLHANDLE, 0, 0 ))
308 WinDispatchMsg( sys->hab, &qm );
310 if( !sys->parent_window )
311 WinSetVisibleRegionNotify( sys->frame, FALSE );
313 kvaEnableScreenSaver();
323 if( !sys->parent_window )
324 WinSubclassWindow( sys->frame, sys->p_old_frame );
326 WinDestroyWindow( sys->frame );
329 vout_display_DeleteWindow( vd, sys->parent_window );
331 if( sys->is_mouse_hidden )
332 WinShowPointer( HWND_DESKTOP, TRUE );
334 WinDestroyMsgQueue( sys->hmq );
335 WinTerminate( sys->hab );
337 sys->i_result = VLC_EGENERIC;
338 DosPostEventSem( sys->ack_event );
342 * This function initializes KVA vout method.
344 static int Open ( vlc_object_t *object )
346 vout_display_t *vd = (vout_display_t *)object;
347 vout_display_sys_t *sys;
349 vd->sys = sys = calloc( 1, sizeof( *sys ));
353 DosCreateEventSem( NULL, &sys->ack_event, 0, FALSE );
355 sys->tid = _beginthread( PMThread, NULL, 1024 * 1024, vd );
356 DosWaitEventSem( sys->ack_event, SEM_INDEFINITE_WAIT );
358 if( sys->i_result != VLC_SUCCESS )
360 DosCloseEventSem( sys->ack_event );
370 /*****************************************************************************
371 * Close: destroy KVA video thread output method
372 *****************************************************************************
373 * Terminate an output method created by Open
374 *****************************************************************************/
375 static void Close ( vlc_object_t *object )
377 vout_display_t * vd = (vout_display_t *)object;
378 vout_display_sys_t * sys = vd->sys;
380 WinPostQueueMsg( sys->hmq, WM_QUIT, 0, 0 );
382 DosWaitThread( &sys->tid, DCWW_WAIT );
385 picture_pool_Delete( sys->pool );
387 DosCloseEventSem( sys->ack_event );
393 * Return a pool of direct buffers
395 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
397 vout_display_sys_t *sys = vd->sys;
403 /*****************************************************************************
404 * Display: displays previously rendered output
405 *****************************************************************************
406 * This function sends the currently rendered image to the display.
407 *****************************************************************************/
408 static void Display( vout_display_t *vd, picture_t *picture,
409 subpicture_t *subpicture )
412 VLC_UNUSED( subpicture );
414 picture_Release( picture );
417 /*****************************************************************************
418 * Manage: handle Sys events
419 *****************************************************************************
420 * This function should be called regularly by video output thread. It returns
421 * a non null value if an error occurred.
422 *****************************************************************************/
423 static void Manage( vout_display_t *vd )
425 vout_display_sys_t * sys = vd->sys;
427 /* Let a window procedure manage instead because if resizing a frame window
428 * here, WM_SIZE is not sent to its child window.
429 * Maybe, is this due to the different threads ? */
430 WinPostMsg( sys->client, WM_VLC_MANAGE, 0, 0 );
433 /*****************************************************************************
434 * Control: control facility for the vout
435 *****************************************************************************/
436 static int Control( vout_display_t *vd, int query, va_list args )
438 vout_display_sys_t *sys = vd->sys;
442 case VOUT_DISPLAY_HIDE_MOUSE:
446 WinQueryPointerPos( HWND_DESKTOP, &ptl );
447 if( !sys->is_mouse_hidden &&
448 WinWindowFromPoint( HWND_DESKTOP, &ptl, TRUE ) == sys->client )
450 WinShowPointer( HWND_DESKTOP, FALSE );
451 sys->is_mouse_hidden = true;
457 case VOUT_DISPLAY_CHANGE_FULLSCREEN:
459 vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *);
461 if( sys->parent_window )
462 vout_window_SetFullScreen(sys->parent_window, cfg.is_fullscreen);
464 WinPostMsg( sys->client, WM_VLC_FULLSCREEN_CHANGE,
465 MPFROMLONG( cfg.is_fullscreen ), 0 );
470 case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
472 const unsigned state = va_arg( args, unsigned );
473 const bool is_on_top = (state & VOUT_WINDOW_STATE_ABOVE) != 0;
475 if( sys->parent_window )
477 if( vout_window_SetState( sys->parent_window, state ))
481 WinSetWindowPos( sys->frame, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
483 sys->is_on_top = is_on_top;
488 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
490 const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
491 bool is_forced = va_arg(args, int);
495 if( sys->parent_window )
497 vout_window_SetSize(sys->parent_window,
498 cfg->display.width, cfg->display.height);
501 * If changing aspect ratio after resizing a main window,
502 * an embedded window is misplaced. So reposition it, here.
504 WinSetWindowPos( WinQueryWindow( sys->parent, QW_PARENT ),
505 HWND_TOP, 0, 1, 0, 0, SWP_MOVE );
506 WinSetWindowPos( WinQueryWindow( sys->parent, QW_PARENT ),
507 HWND_TOP, 0, 0, 0, 0, SWP_MOVE );
510 WinPostMsg( sys->client, WM_VLC_SIZE_CHANGE,
511 MPFROMLONG( cfg->display.width ),
512 MPFROMLONG( cfg->display.height ));
518 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
519 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
521 const video_format_t *source = va_arg(args, const video_format_t *);
523 if( query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT )
525 sys->kvas.ulAspectWidth = ( int64_t )source->i_width *
526 source->i_sar_num / source->i_sar_den;
527 sys->kvas.ulAspectHeight = source->i_height;
531 sys->kvas.rclSrcRect.xLeft = source->i_x_offset;
532 sys->kvas.rclSrcRect.yTop = source->i_y_offset;
533 sys->kvas.rclSrcRect.xRight = source->i_x_offset +
534 source->i_visible_width;
535 sys->kvas.rclSrcRect.yBottom = source->i_y_offset +
536 source->i_visible_height;
539 kvaSetup( &sys->kvas );
544 case VOUT_DISPLAY_RESET_PICTURES:
545 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
546 case VOUT_DISPLAY_CHANGE_ZOOM:
547 case VOUT_DISPLAY_GET_OPENGL:
552 msg_Err(vd, "Unsupported query(=%d) in vout display KVA", query);
556 /* following functions are local */
558 /*****************************************************************************
559 * OpenDisplay: open and initialize KVA device
560 *****************************************************************************
561 * Open and initialize display according to preferences specified in the vout
563 *****************************************************************************/
564 static int OpenDisplay( vout_display_t *vd, video_format_t *fmt )
566 vout_display_sys_t * sys = vd->sys;
567 const vlc_fourcc_t *fallback;
571 char sz_title[ 256 ];
575 msg_Dbg( vd, "render chroma = %4.4s", ( const char * )&fmt->i_chroma );
577 for( int pass = 0; pass < 2 && !b_hw_accel; pass++ )
579 fallback = ( pass == 0 ) ? vlc_fourcc_GetYUVFallback( fmt->i_chroma ) :
580 vlc_fourcc_GetRGBFallback( fmt->i_chroma );
582 for( int i = 0; fallback[ i ]; i++ )
584 switch( fallback[ i ])
587 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YV12;
588 i_kva_fourcc = FOURCC_YV12;
593 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YUY2;
594 i_kva_fourcc = FOURCC_Y422;
599 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_YVU9;
600 i_kva_fourcc = FOURCC_YVU9;
604 case VLC_CODEC_RGB32:
605 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR32;
606 i_kva_fourcc = FOURCC_BGR4;
610 case VLC_CODEC_RGB24:
611 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR24;
612 i_kva_fourcc = FOURCC_BGR3;
616 case VLC_CODEC_RGB16:
617 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR16;
618 i_kva_fourcc = FOURCC_R565;
622 case VLC_CODEC_RGB15:
623 b_hw_accel = sys->kvac.ulInputFormatFlags & KVAF_BGR15;
624 i_kva_fourcc = FOURCC_R555;
631 fmt->i_chroma = fallback[ i ];
639 msg_Err( vd, "Ooops. There is no fourcc supported by KVA at all.");
644 /* Set the RGB masks */
645 fmt->i_rmask = sys->kvac.ulRMask;
646 fmt->i_gmask = sys->kvac.ulGMask;
647 fmt->i_bmask = sys->kvac.ulBMask;
649 msg_Dbg( vd, "output chroma = %4.4s", ( const char * )&fmt->i_chroma );
650 msg_Dbg( vd, "KVA chroma = %4.4s", ( const char * )&i_kva_fourcc );
652 w = vd->source.i_width;
653 h = vd->source.i_height;
655 sys->kvas.ulLength = sizeof( KVASETUP );
656 sys->kvas.szlSrcSize.cx = w;
657 sys->kvas.szlSrcSize.cy = h;
658 sys->kvas.rclSrcRect.xLeft = 0;
659 sys->kvas.rclSrcRect.yTop = 0;
660 sys->kvas.rclSrcRect.xRight = w;
661 sys->kvas.rclSrcRect.yBottom = h;
662 sys->kvas.ulRatio = KVAR_FORCEANY;
663 sys->kvas.ulAspectWidth = w;
664 sys->kvas.ulAspectHeight = h;
665 sys->kvas.fccSrcColor = i_kva_fourcc;
666 sys->kvas.fDither = TRUE;
668 if( kvaSetup( &sys->kvas ))
670 msg_Err( vd, "cannot set up KVA");
675 /* Create the associated picture */
676 picture_resource_t *rsc = &sys->resource;
677 rsc->p_sys = malloc( sizeof( *rsc->p_sys ));
681 rsc->p_sys->i_chroma_shift = i_chroma_shift;
683 for( int i = 0; i < PICTURE_PLANE_MAX; i++ )
685 rsc->p[ i ].p_pixels = NULL;
686 rsc->p[ i ].i_pitch = 0;
687 rsc->p[ i ].i_lines = 0;
690 picture_t *picture = picture_NewFromResource( fmt, rsc );
694 /* Wrap it into a picture pool */
695 picture_pool_configuration_t pool_cfg;
696 memset( &pool_cfg, 0, sizeof( pool_cfg ));
697 pool_cfg.picture_count = 1;
698 pool_cfg.picture = &picture;
699 pool_cfg.lock = KVALock;
700 pool_cfg.unlock = KVAUnlock;
702 sys->pool = picture_pool_NewExtended( &pool_cfg );
705 picture_Release( picture );
710 if (vd->cfg->display.title)
711 snprintf( sz_title, sizeof( sz_title ), "%s", vd->cfg->display.title );
713 snprintf( sz_title, sizeof( sz_title ),
714 "%s (%4.4s to %4.4s - %s mode KVA output)",
716 ( char * )&vd->fmt.i_chroma,
717 ( char * )&sys->kvas.fccSrcColor,
718 psz_video_mode[ sys->kvac.ulMode - 1 ]);
719 WinSetWindowText( sys->frame, sz_title );
721 sys->i_screen_width = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
722 sys->i_screen_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
724 if( sys->parent_window )
725 WinQueryWindowRect( sys->parent, &sys->client_rect );
728 sys->client_rect.xLeft = ( sys->i_screen_width - w ) / 2;
729 sys->client_rect.yBottom = ( sys->i_screen_height - h ) / 2 ;
730 sys->client_rect.xRight = sys->client_rect.xLeft + w;
731 sys->client_rect.yTop = sys->client_rect.yBottom + h;
734 rcl = sys->client_rect;
736 WinCalcFrameRect( sys->frame, &rcl, FALSE);
738 WinSetWindowPos( sys->frame, HWND_TOP,
739 rcl.xLeft, rcl.yBottom,
740 rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
741 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW |
752 /*****************************************************************************
753 * CloseDisplay: close and reset KVA device
754 *****************************************************************************
755 * This function returns all resources allocated by OpenDisplay and restore
756 * the original state of the device.
757 *****************************************************************************/
758 static void CloseDisplay( vout_display_t *vd )
763 static int KVALock( picture_t *picture )
765 picture_sys_t *picsys = picture->p_sys;
769 if( kvaLockBuffer( &kva_buffer, &kva_bpl ))
772 /* Packed or Y plane */
773 picture->p->p_pixels = ( uint8_t * )kva_buffer;
774 picture->p->i_pitch = kva_bpl;
775 picture->p->i_lines = picture->format.i_height;
778 for( int n = 1; n < picture->i_planes; n++ )
780 const plane_t *o = &picture->p[n-1];
781 plane_t *p = &picture->p[n];
783 p->p_pixels = o->p_pixels + o->i_lines * o->i_pitch;
784 p->i_pitch = kva_bpl >> picsys->i_chroma_shift;
785 p->i_lines = picture->format.i_height >> picsys->i_chroma_shift;
791 static void KVAUnlock( picture_t *picture )
793 VLC_UNUSED( picture );
798 static void MorphToPM( void )
802 DosGetInfoBlocks(NULL, &pib);
804 /* Change flag from VIO to PM */
805 if (pib->pib_ultype == 2)
809 /*****************************************************************************
810 * Key events handling
811 *****************************************************************************/
816 } pmkeys_to_vlckeys[] =
818 { VK_LEFT, KEY_LEFT },
819 { VK_RIGHT, KEY_RIGHT },
821 { VK_DOWN, KEY_DOWN },
823 { VK_NEWLINE, KEY_ENTER },
824 { VK_ENTER, KEY_ENTER },
837 { VK_HOME, KEY_HOME },
839 { VK_INSERT, KEY_INSERT },
840 { VK_DELETE, KEY_DELETE },
846 { VK_PAGEUP, KEY_PAGEUP },
847 { VK_PAGEDOWN, KEY_PAGEDOWN },
849 { VK_BACKSPACE, KEY_BACKSPACE },
852 {, KEY_MOUSEWHEELUP },
853 {, KEY_MOUSEWHEELDOWN },
854 {, KEY_MOUSEWHEELLEFT },
855 {, KEY_MOUSEWHEELRIGHT },
857 {, KEY_BROWSER_BACK },
858 {, KEY_BROWSER_FORWARD },
859 {, KEY_BROWSER_REFRESH },
860 {, KEY_BROWSER_STOP },
861 {, KEY_BROWSER_SEARCH },
862 {, KEY_BROWSER_FAVORITES },
863 {, KEY_BROWSER_HOME },
864 {, KEY_VOLUME_MUTE },
865 {, KEY_VOLUME_DOWN },
867 {, KEY_MEDIA_NEXT_TRACK },
868 {, KEY_MEDIA_PREV_TRACK },
870 {, KEY_MEDIA_PLAY_PAUSE },
876 static int ConvertKey( USHORT i_pmkey )
879 for( i = 0; pmkeys_to_vlckeys[ i ].i_pmkey != 0; i++ )
881 if( pmkeys_to_vlckeys[ i ].i_pmkey == i_pmkey )
882 return pmkeys_to_vlckeys[ i ].i_vlckey;
887 static MRESULT EXPENTRY MyFrameWndProc( HWND hwnd, ULONG msg, MPARAM mp1,
890 vout_display_t *vd = WinQueryWindowPtr( hwnd, 0 );
891 vout_display_sys_t *sys = vd->sys;
895 case WM_QUERYTRACKINFO :
899 mr = sys->p_old_frame( hwnd, msg, mp1, mp2 );
903 PTRACKINFO pti = ( PTRACKINFO )mp2;
906 pti->rclBoundary.xLeft = 0;
907 pti->rclBoundary.yBottom = 0;
908 pti->rclBoundary.xRight = sys->i_screen_width;
909 pti->rclBoundary.yTop = sys->i_screen_height;
911 WinCalcFrameRect( hwnd, &pti->rclBoundary, FALSE );
913 pti->ptlMaxTrackSize.x = pti->rclBoundary.xRight -
914 pti->rclBoundary.xLeft;
915 pti->ptlMaxTrackSize.y = pti->rclBoundary.yTop -
916 pti->rclBoundary.yBottom;
920 rcl.xRight = sys->kvas.szlSrcSize.cx + 1;
921 rcl.yTop = sys->kvas.szlSrcSize.cy + 1;
923 WinCalcFrameRect( hwnd, &rcl, FALSE );
925 pti->ptlMinTrackSize.x = rcl.xRight - rcl.xLeft;
926 pti->ptlMinTrackSize.y = rcl.yTop - rcl.yBottom;
928 return MRFROMLONG( TRUE );
931 case WM_ADJUSTWINDOWPOS :
936 PSWP pswp = ( PSWP )mp1;
938 if( pswp->fl & SWP_SIZE )
943 rcl.yBottom = pswp->y;
944 rcl.xRight = rcl.xLeft + pswp->cx;
945 rcl.yTop = rcl.yBottom + pswp->cy;
947 WinCalcFrameRect( hwnd, &rcl, TRUE );
949 if( rcl.xRight - rcl.xLeft <= sys->kvas.szlSrcSize.cx )
950 rcl.xRight = rcl.xLeft + ( sys->kvas.szlSrcSize.cx + 1 );
952 if( rcl.yTop - rcl.yBottom <= sys->kvas.szlSrcSize.cy )
953 rcl.yTop = rcl.yBottom + ( sys->kvas.szlSrcSize.cy + 1 );
955 if( rcl.xRight - rcl.xLeft > sys->i_screen_width )
958 rcl.xRight = sys->i_screen_width;
961 if( rcl.yTop - rcl.yBottom > sys->i_screen_height )
964 rcl.yTop = sys->i_screen_height;
967 WinCalcFrameRect( hwnd, &rcl, FALSE );
969 if( pswp->x != rcl.xLeft || pswp->y != rcl.yBottom )
970 pswp->fl |= SWP_MOVE;
973 pswp->y = rcl.yBottom;
975 pswp->cx = rcl.xRight - rcl.xLeft;
976 pswp->cy = rcl.yTop - rcl.yBottom;
982 //case WM_VRNDISABLED :
984 if( !vd->cfg->is_fullscreen && sys->is_on_top )
985 WinSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
989 return sys->p_old_frame( hwnd, msg, mp1, mp2 );
992 static void MousePressed( vout_display_t *vd, HWND hwnd, unsigned button )
994 if( WinQueryFocus( HWND_DESKTOP ) != hwnd )
995 WinSetFocus( HWND_DESKTOP, hwnd );
997 if( !vd->sys->button_pressed )
998 WinSetCapture( HWND_DESKTOP, hwnd );
1000 vd->sys->button_pressed |= 1 << button;
1002 vout_display_SendEventMousePressed( vd, button );
1005 static void MouseReleased( vout_display_t *vd, unsigned button )
1007 vd->sys->button_pressed &= ~(1 << button);
1008 if( !vd->sys->button_pressed )
1009 WinSetCapture( HWND_DESKTOP, NULLHANDLE );
1011 vout_display_SendEventMouseReleased( vd, button );
1014 #define WM_MOUSELEAVE 0x41F
1016 static MRESULT EXPENTRY WndProc( HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 )
1018 vout_display_t * vd = WinQueryWindowPtr( hwnd, 0 );
1019 MRESULT result = ( MRESULT )TRUE;
1022 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1024 vout_display_sys_t * sys = vd->sys;
1028 if ( sys->is_mouse_hidden &&
1029 ((msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) ||
1030 (msg >= WM_EXTMOUSEFIRST && msg <= WM_EXTMOUSELAST) ||
1031 msg == WM_MOUSELEAVE))
1033 WinShowPointer(HWND_DESKTOP, TRUE);
1034 sys->is_mouse_hidden = false;
1039 /* the user wants to close the window */
1041 vout_display_SendEventClose(vd);
1047 SHORT i_mouse_x = SHORT1FROMMP( mp1 );
1048 SHORT i_mouse_y = SHORT2FROMMP( mp1 );
1050 int i_movie_width, i_movie_height;
1051 int i_src_width, i_src_height;
1053 /* Get a current movie area */
1054 kvaAdjustDstRect( &sys->kvas.rclSrcRect, &movie_rect );
1055 i_movie_width = movie_rect.xRight - movie_rect.xLeft;
1056 i_movie_height = movie_rect.yTop - movie_rect.yBottom;
1058 i_src_width = sys->kvas.rclSrcRect.xRight -
1059 sys->kvas.rclSrcRect.xLeft;
1060 i_src_height = sys->kvas.rclSrcRect.yBottom -
1061 sys->kvas.rclSrcRect.yTop;
1063 int x = ( i_mouse_x - movie_rect.xLeft ) *
1064 i_src_width / i_movie_width +
1065 sys->kvas.rclSrcRect.xLeft;
1066 int y = ( i_mouse_y - movie_rect.yBottom ) *
1067 i_src_height / i_movie_height;
1069 /* Invert Y coordinate and add y offset */
1070 y = ( i_src_height - y ) + sys->kvas.rclSrcRect.yTop;;
1072 vout_display_SendEventMouseMoved(vd, x, y);
1074 result = WinDefWindowProc( hwnd, msg, mp1,mp2 );
1078 case WM_BUTTON1DOWN :
1079 MousePressed( vd, hwnd, MOUSE_BUTTON_LEFT );
1082 case WM_BUTTON2DOWN :
1083 MousePressed( vd, hwnd, MOUSE_BUTTON_RIGHT );
1086 case WM_BUTTON3DOWN :
1087 MousePressed( vd, hwnd, MOUSE_BUTTON_CENTER );
1091 MouseReleased( vd, MOUSE_BUTTON_LEFT );
1095 MouseReleased( vd, MOUSE_BUTTON_RIGHT );
1099 MouseReleased( vd, MOUSE_BUTTON_CENTER );
1102 case WM_BUTTON1DBLCLK :
1103 vout_display_SendEventMouseDoubleClick(vd);
1106 case WM_TRANSLATEACCEL :
1107 /* We have no accelerator table at all */
1108 result = ( MRESULT )FALSE;
1113 USHORT i_flags = SHORT1FROMMP( mp1 );
1114 USHORT i_ch = SHORT1FROMMP( mp2 );
1115 USHORT i_vk = SHORT2FROMMP( mp2 );
1118 /* If embedded window, let the parent process keys */
1119 if( sys->parent_window )
1121 WinPostMsg( sys->parent, msg, mp1, mp2 );
1125 if( !( i_flags & KC_KEYUP ))
1127 if( i_flags & KC_VIRTUALKEY )
1128 /* convert the key if possible */
1129 i_key = ConvertKey( i_vk );
1130 else if(( i_flags & KC_CHAR ) && !HIBYTE( i_ch ))
1131 i_key = tolower( i_ch );
1135 if( i_flags & KC_SHIFT )
1136 i_key |= KEY_MODIFIER_SHIFT;
1138 if( i_flags & KC_CTRL )
1139 i_key |= KEY_MODIFIER_CTRL;
1141 if( i_flags & KC_ALT )
1142 i_key |= KEY_MODIFIER_ALT;
1144 vout_display_SendEventKey(vd, i_key);
1150 /* Process Manage() call */
1151 case WM_VLC_MANAGE :
1154 /* Fullscreen change */
1155 case WM_VLC_FULLSCREEN_CHANGE :
1156 if( LONGFROMMP( mp1 ))
1158 WinQueryWindowPos( sys->frame, &swp );
1159 sys->client_rect.xLeft = swp.x;
1160 sys->client_rect.yBottom = swp.y;
1161 sys->client_rect.xRight = sys->client_rect.xLeft + swp.cx;
1162 sys->client_rect.yTop = sys->client_rect.yBottom + swp.cy;
1163 WinCalcFrameRect( sys->frame, &sys->client_rect, TRUE );
1167 rcl.xRight = sys->i_screen_width;
1168 rcl.yTop = sys->i_screen_height;
1171 rcl = sys->client_rect;
1173 WinCalcFrameRect( sys->frame, &rcl, FALSE );
1175 WinSetWindowPos( sys->frame, HWND_TOP,
1176 rcl.xLeft, rcl.yBottom,
1177 rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
1178 SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW |
1183 case WM_VLC_SIZE_CHANGE :
1186 rcl.xRight = LONGFROMMP( mp1 );
1187 rcl.yTop = LONGFROMMP( mp2 );
1188 WinCalcFrameRect( sys->frame, &rcl, FALSE );
1190 WinSetWindowPos( sys->frame, NULLHANDLE,
1192 rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
1195 WinQueryWindowPos( sys->frame, &swp );
1196 sys->client_rect.xLeft = swp.x;
1197 sys->client_rect.yBottom = swp.y;
1198 sys->client_rect.xRight = sys->client_rect.xLeft + swp.cx;
1199 sys->client_rect.yTop = sys->client_rect.yBottom + swp.cy;
1200 WinCalcFrameRect( sys->frame, &sys->client_rect, TRUE );
1204 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1207 /* If embedded window, we need to change our window size according to a
1208 * parent window size */
1209 if( sys->parent_window )
1211 WinQueryWindowRect( sys->parent, &rcl );
1213 if( rcl.xLeft != sys->parent_rect.xLeft ||
1214 rcl.yBottom != sys->parent_rect.yBottom ||
1215 rcl.xRight != sys->parent_rect.xRight ||
1216 rcl.yTop != sys->parent_rect.yTop)
1218 sys->parent_rect = rcl;
1220 WinCalcFrameRect( sys->frame, &rcl, FALSE );
1222 WinSetWindowPos( sys->frame, NULLHANDLE,
1223 rcl.xLeft, rcl.yBottom,
1224 rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom,
1225 SWP_SIZE | SWP_MOVE );