2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 \author Nicolas Plourde <nicolasplourde@gmail.com>
22 Copyright (c) Nicolas Plourde - April 2004
24 YUV support Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
26 \brief MPlayer Mac OSX Quartz video out module.
28 \todo: -screen overlay output
29 -fit osd in black bar when available
38 #include <Carbon/Carbon.h>
39 #include <QuickTime/QuickTime.h>
43 #include "fastmemcpy.h"
44 #include "video_out.h"
45 #include "video_out_internal.h"
53 #include "input/input.h"
54 #include "input/mouse.h"
56 #include "vo_quartz.h"
58 static const vo_info_t info
=
62 "Nicolas Plourde <nicolasplourde@hotmail.com>, Romain Dolbeau <romain@dolbeau.org>",
66 const LIBVO_EXTERN(quartz
)
68 static uint32_t image_depth
;
69 static uint32_t image_format
;
70 static uint32_t image_size
;
71 static uint32_t image_buffer_size
;
72 static char *image_data
;
74 static ImageSequence seqId
;
75 static CodecType image_qtcodec
;
76 static PlanarPixmapInfoYUV420
*P
= NULL
;
79 ImageDescriptionHandle desc
;
80 Handle extension_colr
;
81 Handle extension_fiel
;
82 Handle extension_clap
;
83 Handle extension_pasp
;
85 static MatrixRecord matrix
;
86 static int EnterMoviesDone
= 0;
87 static int get_image_done
= 0;
89 static int vo_quartz_fs
; // we are in fullscreen
90 extern float monitor_aspect
;
91 extern float movie_aspect
;
92 static float old_movie_aspect
;
94 static int winLevel
= 1;
97 kCGDesktopWindowLevelKey
,
98 kCGNormalWindowLevelKey
,
99 kCGScreenSaverWindowLevelKey
102 static int int_pause
= 0;
103 static float winAlpha
= 1;
104 static int mouseHide
= FALSE
;
106 static int device_id
= 0;
108 static short fs_res_x
= 0;
109 static short fs_res_y
= 0;
111 static WindowRef theWindow
= NULL
;
112 static WindowGroupRef winGroup
= NULL
;
113 static CGRect bounds
;
114 static CGDirectDisplayID displayId
= 0;
115 static CFDictionaryRef originalMode
= NULL
;
117 static CGDataProviderRef dataProviderRef
= NULL
;
118 static CGImageRef image
= NULL
;
120 static Rect imgRect
; // size of the original image (unscaled)
121 static Rect dstRect
; // size of the displayed image (after scaling)
122 static Rect winRect
; // size of the window containg the displayed image (include padding)
123 static Rect oldWinRect
; // size of the window containg the displayed image (include padding) when NOT in FS mode
124 static CGRect displayRect
; // size of the display device
125 static Rect oldWinBounds
;
127 static MenuRef windMenu
;
128 static MenuRef movMenu
;
129 static MenuRef aspectMenu
;
131 static int lastScreensaverUpdate
= 0;
132 static int lastMouseHide
= 0;
138 kNormalScreenCmd
= 3,
139 kDoubleScreenCmd
= 4,
148 #include "osdep/keycodes.h"
150 //PROTOTYPE/////////////////////////////////////////////////////////////////
151 static OSStatus
KeyEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
);
152 static OSStatus
MouseEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
);
153 static OSStatus
WindowEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
);
154 void window_resized();
156 void window_fullscreen();
157 void window_panscan();
159 static inline int convert_key(UInt32 key
, UInt32 charcode
)
164 case QZ_RETURN
: return KEY_ENTER
;
165 case QZ_ESCAPE
: return KEY_ESC
;
166 case QZ_BACKSPACE
: return KEY_BACKSPACE
;
167 case QZ_LALT
: return KEY_BACKSPACE
;
168 case QZ_LCTRL
: return KEY_BACKSPACE
;
169 case QZ_LSHIFT
: return KEY_BACKSPACE
;
170 case QZ_F1
: return KEY_F
+ 1;
171 case QZ_F2
: return KEY_F
+ 2;
172 case QZ_F3
: return KEY_F
+ 3;
173 case QZ_F4
: return KEY_F
+ 4;
174 case QZ_F5
: return KEY_F
+ 5;
175 case QZ_F6
: return KEY_F
+ 6;
176 case QZ_F7
: return KEY_F
+ 7;
177 case QZ_F8
: return KEY_F
+ 8;
178 case QZ_F9
: return KEY_F
+ 9;
179 case QZ_F10
: return KEY_F
+ 10;
180 case QZ_F11
: return KEY_F
+ 11;
181 case QZ_F12
: return KEY_F
+ 12;
182 case QZ_INSERT
: return KEY_INSERT
;
183 case QZ_DELETE
: return KEY_DELETE
;
184 case QZ_HOME
: return KEY_HOME
;
185 case QZ_END
: return KEY_END
;
186 case QZ_KP_PLUS
: return '+';
187 case QZ_KP_MINUS
: return '-';
188 case QZ_TAB
: return KEY_TAB
;
189 case QZ_PAGEUP
: return KEY_PAGE_UP
;
190 case QZ_PAGEDOWN
: return KEY_PAGE_DOWN
;
191 case QZ_UP
: return KEY_UP
;
192 case QZ_DOWN
: return KEY_DOWN
;
193 case QZ_LEFT
: return KEY_LEFT
;
194 case QZ_RIGHT
: return KEY_RIGHT
;
195 case QZ_KP_MULTIPLY
: return '*';
196 case QZ_KP_DIVIDE
: return '/';
197 case QZ_KP_ENTER
: return KEY_KPENTER
;
198 case QZ_KP_PERIOD
: return KEY_KPDEC
;
199 case QZ_KP0
: return KEY_KP0
;
200 case QZ_KP1
: return KEY_KP1
;
201 case QZ_KP2
: return KEY_KP2
;
202 case QZ_KP3
: return KEY_KP3
;
203 case QZ_KP4
: return KEY_KP4
;
204 case QZ_KP5
: return KEY_KP5
;
205 case QZ_KP6
: return KEY_KP6
;
206 case QZ_KP7
: return KEY_KP7
;
207 case QZ_KP8
: return KEY_KP8
;
208 case QZ_KP9
: return KEY_KP9
;
209 default: return charcode
;
213 static void draw_alpha(int x0
, int y0
, int w
, int h
, unsigned char *src
, unsigned char *srca
, int stride
)
215 switch (image_format
)
218 vo_draw_alpha_rgb32(w
, h
, src
, srca
, stride
, image_data
+ 4 * (y0
* imgRect
.right
+ x0
), 4 * imgRect
.right
);
223 vo_draw_alpha_yv12(w
, h
, src
, srca
, stride
, ((char *)P
) + be2me_32(P
->componentInfoY
.offset
) + x0
+ y0
* imgRect
.right
, imgRect
.right
);
226 vo_draw_alpha_uyvy(w
, h
, src
, srca
, stride
, ((char *)P
) + (x0
+ y0
* imgRect
.right
) * 2, imgRect
.right
* 2);
229 vo_draw_alpha_yuy2(w
, h
, src
, srca
, stride
, ((char *)P
) + (x0
+ y0
* imgRect
.right
) * 2, imgRect
.right
* 2);
234 //default keyboard event handler
235 static OSStatus
KeyEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
)
237 OSStatus result
= noErr
;
238 UInt32
class = GetEventClass(event
);
239 UInt32 kind
= GetEventKind(event
);
241 result
= CallNextEventHandler(nextHandler
, event
);
243 if (class == kEventClassKeyboard
)
247 UInt32 macKeyModifiers
;
249 GetEventParameter(event
, kEventParamKeyMacCharCodes
, typeChar
, NULL
, sizeof(macCharCodes
), NULL
, &macCharCodes
);
250 GetEventParameter(event
, kEventParamKeyCode
, typeUInt32
, NULL
, sizeof(macKeyCode
), NULL
, &macKeyCode
);
251 GetEventParameter(event
, kEventParamKeyModifiers
, typeUInt32
, NULL
, sizeof(macKeyModifiers
), NULL
, &macKeyModifiers
);
253 if (macKeyModifiers
!= 256)
255 if (kind
== kEventRawKeyRepeat
|| kind
== kEventRawKeyDown
)
257 int key
= convert_key(macKeyCode
, macCharCodes
);
260 mplayer_put_key(key
);
263 else if (macKeyModifiers
== 256)
265 switch (macCharCodes
)
267 case '[': SetWindowAlpha(theWindow
, winAlpha
-= 0.05); break;
268 case ']': SetWindowAlpha(theWindow
, winAlpha
+= 0.05); break;
272 result
= eventNotHandledErr
;
278 //default mouse event handler
279 static OSStatus
MouseEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
)
281 OSStatus result
= noErr
;
282 UInt32
class = GetEventClass(event
);
283 UInt32 kind
= GetEventKind(event
);
285 result
= CallNextEventHandler(nextHandler
, event
);
287 if (class == kEventClassMouse
)
293 GetEventParameter(event
, kEventParamMouseLocation
, typeQDPoint
, 0, sizeof(Point
), 0, &mousePos
);
294 GetEventParameter(event
, kEventParamWindowMouseLocation
, typeQDPoint
, 0, sizeof(Point
), 0, &winMousePos
);
298 case kEventMouseMoved
:
302 CGDisplayShowCursor(displayId
);
308 case kEventMouseWheelMoved
:
313 GetEventParameter(event
, kEventParamMouseWheelDelta
, typeSInt32
, 0, sizeof(int), 0, &wheel
);
315 part
= FindWindow(mousePos
, &tmpWin
);
317 if (part
== inContent
)
320 mplayer_put_key(MOUSE_BTN3
);
322 mplayer_put_key(MOUSE_BTN4
);
327 case kEventMouseDown
:
330 EventMouseButton button
;
334 GetWindowPortBounds(theWindow
, &bounds
);
335 GetEventParameter(event
, kEventParamMouseButton
, typeMouseButton
, 0, sizeof(EventMouseButton
), 0, &button
);
337 part
= FindWindow(mousePos
, &tmpWin
);
338 if (kind
== kEventMouseUp
)
340 if (part
!= inContent
)
344 case kEventMouseButtonPrimary
:
345 mplayer_put_key(MOUSE_BTN0
);
347 case kEventMouseButtonSecondary
:
348 mplayer_put_key(MOUSE_BTN2
);
350 case kEventMouseButtonTertiary
:
351 mplayer_put_key(MOUSE_BTN1
);
355 result
= eventNotHandledErr
;
360 if ((winMousePos
.h
> (bounds
.right
- 15)) && (winMousePos
.v
> (bounds
.bottom
)))
366 ResizeWindow(theWindow
, mousePos
, NULL
, &newSize
);
369 else if (part
== inMenuBar
)
371 MenuSelect(mousePos
);
374 else if (part
== inContent
)
378 case kEventMouseButtonPrimary
:
379 mplayer_put_key(MOUSE_BTN0
| MP_KEY_DOWN
);
381 case kEventMouseButtonSecondary
:
382 mplayer_put_key(MOUSE_BTN2
| MP_KEY_DOWN
);
384 case kEventMouseButtonTertiary
:
385 mplayer_put_key(MOUSE_BTN1
| MP_KEY_DOWN
);
389 result
= eventNotHandledErr
;
396 case kEventMouseDragged
:
400 result
= eventNotHandledErr
;
408 //default window event handler
409 static OSStatus
WindowEventHandler(EventHandlerCallRef nextHandler
, EventRef event
, void *userData
)
411 OSStatus result
= noErr
;
414 UInt32
class = GetEventClass(event
);
415 UInt32 kind
= GetEventKind(event
);
417 result
= CallNextEventHandler(nextHandler
, event
);
419 aspect(&d_width
, &d_height
, A_NOZOOM
);
421 if (class == kEventClassCommand
)
423 HICommand theHICommand
;
425 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
, sizeof(HICommand
), NULL
, &theHICommand
);
427 switch (theHICommand
.commandID
)
430 mplayer_put_key(KEY_CLOSE_WIN
);
440 SizeWindow(theWindow
, (d_width
/ 2), ((d_width
/ movie_aspect
) / 2), 1);
444 case kNormalScreenCmd
:
451 SizeWindow(theWindow
, d_width
, (d_width
/ movie_aspect
), 1);
455 case kDoubleScreenCmd
:
462 SizeWindow(theWindow
, (d_width
* 2), ((d_width
/ movie_aspect
) * 2), 1);
472 vo_keepaspect
= (!(vo_keepaspect
));
473 CheckMenuItem(aspectMenu
, 1, vo_keepaspect
);
478 movie_aspect
= old_movie_aspect
;
481 SizeWindow(theWindow
, dstRect
.right
, (dstRect
.right
/ movie_aspect
), 1);
487 movie_aspect
= 4.0f
/ 3.0f
;
490 SizeWindow(theWindow
, dstRect
.right
, (dstRect
.right
/ movie_aspect
), 1);
496 movie_aspect
= 16.0f
/ 9.0f
;
499 SizeWindow(theWindow
, dstRect
.right
, (dstRect
.right
/ movie_aspect
), 1);
505 vo_panscan
= (!(vo_panscan
));
506 CheckMenuItem(aspectMenu
, 2, vo_panscan
);
512 result
= eventNotHandledErr
;
516 else if (class == kEventClassWindow
)
519 Rect rectWindow
= { 0, 0, 0, 0 };
521 GetEventParameter(event
, kEventParamDirectObject
, typeWindowRef
, NULL
, sizeof(WindowRef
), NULL
, &window
);
525 GetWindowBounds(window
, kWindowGlobalPortRgn
, &rectWindow
);
530 case kEventWindowClosed
:
532 mplayer_put_key(KEY_CLOSE_WIN
);
536 case kEventWindowZoomed
:
537 case kEventWindowBoundsChanged
:
544 result
= eventNotHandledErr
;
552 static void quartz_CreateWindow(uint32_t d_width
, uint32_t d_height
, WindowAttributes windowAttrs
)
554 CFStringRef titleKey
;
555 CFStringRef windowTitle
;
559 CFStringRef movMenuTitle
;
560 CFStringRef aspMenuTitle
;
562 const EventTypeSpec win_events
[] = {
563 {kEventClassWindow
, kEventWindowClosed
},
564 {kEventClassWindow
, kEventWindowBoundsChanged
},
565 {kEventClassCommand
, kEventCommandProcess
}
568 const EventTypeSpec key_events
[] = {
569 {kEventClassKeyboard
, kEventRawKeyDown
},
570 {kEventClassKeyboard
, kEventRawKeyRepeat
}
573 const EventTypeSpec mouse_events
[] = {
574 {kEventClassMouse
, kEventMouseMoved
},
575 {kEventClassMouse
, kEventMouseWheelMoved
},
576 {kEventClassMouse
, kEventMouseDown
},
577 {kEventClassMouse
, kEventMouseUp
},
578 {kEventClassMouse
, kEventMouseDragged
}
581 SetRect(&winRect
, 0, 0, d_width
, d_height
);
582 SetRect(&oldWinRect
, 0, 0, d_width
, d_height
);
583 SetRect(&dstRect
, 0, 0, d_width
, d_height
);
588 // Create Window Menu
589 CreateStandardWindowMenu(0, &windMenu
);
590 InsertMenu(windMenu
, 0);
593 CreateNewMenu(1004, 0, &movMenu
);
594 movMenuTitle
= CFSTR("Movie");
595 SetMenuTitleWithCFString(movMenu
, movMenuTitle
);
597 AppendMenuItemTextWithCFString(movMenu
, CFSTR("Half Size"), 0, kHalfScreenCmd
, &index
);
598 SetMenuItemCommandKey(movMenu
, index
, 0, '0');
600 AppendMenuItemTextWithCFString(movMenu
, CFSTR("Normal Size"), 0, kNormalScreenCmd
, &index
);
601 SetMenuItemCommandKey(movMenu
, index
, 0, '1');
603 AppendMenuItemTextWithCFString(movMenu
, CFSTR("Double Size"), 0, kDoubleScreenCmd
, &index
);
604 SetMenuItemCommandKey(movMenu
, index
, 0, '2');
606 AppendMenuItemTextWithCFString(movMenu
, CFSTR("Full Size"), 0, kFullScreenCmd
, &index
);
607 SetMenuItemCommandKey(movMenu
, index
, 0, 'F');
609 AppendMenuItemTextWithCFString(movMenu
, NULL
, kMenuItemAttrSeparator
, 0, &index
);
611 AppendMenuItemTextWithCFString(movMenu
, CFSTR("Aspect Ratio"), 0, 0, &index
);
613 //// Create Aspect Ratio Sub Menu
614 CreateNewMenu(0, 0, &aspectMenu
);
615 aspMenuTitle
= CFSTR("Aspect Ratio");
616 SetMenuTitleWithCFString(aspectMenu
, aspMenuTitle
);
617 SetMenuItemHierarchicalMenu(movMenu
, 6, aspectMenu
);
619 AppendMenuItemTextWithCFString(aspectMenu
, CFSTR("Keep"), 0, kKeepAspectCmd
, &index
);
620 CheckMenuItem(aspectMenu
, 1, vo_keepaspect
);
621 AppendMenuItemTextWithCFString(aspectMenu
, CFSTR("Pan-Scan"), 0, kPanScanCmd
, &index
);
622 CheckMenuItem(aspectMenu
, 2, vo_panscan
);
623 AppendMenuItemTextWithCFString(aspectMenu
, NULL
, kMenuItemAttrSeparator
, 0, &index
);
624 AppendMenuItemTextWithCFString(aspectMenu
, CFSTR("Original"), 0, kAspectOrgCmd
, &index
);
625 AppendMenuItemTextWithCFString(aspectMenu
, CFSTR("4:3"), 0, kAspectFullCmd
, &index
);
626 AppendMenuItemTextWithCFString(aspectMenu
, CFSTR("16:9"), 0, kAspectWideCmd
, &index
);
628 InsertMenu(movMenu
, GetMenuID(windMenu
)); //insert before Window menu
633 CreateNewWindow(kDocumentWindowClass
, windowAttrs
, &winRect
, &theWindow
);
635 CreateWindowGroup(0, &winGroup
);
636 SetWindowGroup(theWindow
, winGroup
);
639 titleKey
= CFSTR("MPlayer - The Movie Player");
640 windowTitle
= CFCopyLocalizedString(titleKey
, NULL
);
641 result
= SetWindowTitleWithCFString(theWindow
, windowTitle
);
643 CFRelease(windowTitle
);
645 // Install event handler
646 InstallApplicationEventHandler(NewEventHandlerUPP(KeyEventHandler
), GetEventTypeCount(key_events
), key_events
, NULL
, NULL
);
647 InstallApplicationEventHandler(NewEventHandlerUPP(MouseEventHandler
), GetEventTypeCount(mouse_events
), mouse_events
, NULL
, NULL
);
648 InstallWindowEventHandler(theWindow
, NewEventHandlerUPP(WindowEventHandler
), GetEventTypeCount(win_events
), win_events
, theWindow
, NULL
);
651 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
653 WindowAttributes windowAttrs
;
656 CGDisplayCount displayCount
;
657 CGDirectDisplayID
*displays
;
659 // Get Main device info///////////////////////////////////////////////////
661 // Display IDs might not be consecutive, get the list of all devices up to # device_id
662 displayCount
= device_id
+ 1;
663 displays
= malloc(sizeof(CGDirectDisplayID
) * displayCount
);
664 if (kCGErrorSuccess
!= CGGetActiveDisplayList(displayCount
, displays
, &displayCount
) || displayCount
< device_id
+ 1) {
665 mp_msg(MSGT_VO
, MSGL_FATAL
, "Quartz error: Device ID %d do not exist, falling back to main device.\n", device_id
);
666 displayId
= kCGDirectMainDisplay
;
671 displayId
= displays
[device_id
];
675 displayRect
= CGDisplayBounds(displayId
);
677 monitor_aspect
= (float)displayRect
.size
.width
/ (float)displayRect
.size
.height
;
679 // misc mplayer setup/////////////////////////////////////////////////////
680 SetRect(&imgRect
, 0, 0, width
, height
);
681 switch (image_format
)
694 image_size
= ((imgRect
.right
* imgRect
.bottom
* image_depth
) + 7) / 8;
696 vo_fs
= flags
& VOFLAG_FULLSCREEN
;
700 aspect_save_orig(width
, height
);
701 aspect_save_prescale(d_width
, d_height
);
702 aspect_save_screenres(displayRect
.size
.width
, displayRect
.size
.height
);
704 aspect(&d_width
, &d_height
, A_NOZOOM
);
706 movie_aspect
= (float)d_width
/ (float)d_height
;
707 old_movie_aspect
= movie_aspect
;
712 image_data
= malloc(image_size
);
714 // Create player window//////////////////////////////////////////////////
715 windowAttrs
= kWindowStandardDocumentAttributes
716 | kWindowStandardHandlerAttribute
717 | kWindowLiveResizeAttribute
;
719 windowAttrs
&= (~kWindowResizableAttribute
);
721 if (theWindow
== NULL
)
723 CGContextRef context
;
725 quartz_CreateWindow(d_width
, d_height
, windowAttrs
);
727 if (theWindow
== NULL
)
729 mp_msg(MSGT_VO
, MSGL_FATAL
, "Quartz error: Couldn't create window !!!!!\n");
732 tmpBounds
= CGRectMake(0, 0, winRect
.right
, winRect
.bottom
);
733 QDBeginCGContext(GetWindowPort(theWindow
), &context
);
734 CGContextFillRect(context
, tmpBounds
);
735 QDEndCGContext(GetWindowPort(theWindow
), &context
);
739 HideWindow(theWindow
);
740 ChangeWindowAttributes(theWindow
, ~windowAttrs
, windowAttrs
);
741 SetRect(&winRect
, 0, 0, d_width
, d_height
);
742 SetRect(&oldWinRect
, 0, 0, d_width
, d_height
);
743 SizeWindow(theWindow
, d_width
, d_height
, 1);
746 switch (image_format
)
750 CGContextRef context
;
752 QDBeginCGContext(GetWindowPort(theWindow
), &context
);
754 dataProviderRef
= CGDataProviderCreateWithData(0, image_data
, imgRect
.right
* imgRect
.bottom
* 4, 0);
756 image
= CGImageCreate(imgRect
.right
,
760 ((imgRect
.right
* 32) + 7) / 8,
761 CGColorSpaceCreateDeviceRGB(),
762 kCGImageAlphaNoneSkipFirst
,
763 dataProviderRef
, 0, 1, kCGRenderingIntentDefault
);
765 QDEndCGContext(GetWindowPort(theWindow
), &context
);
777 if (!EnterMoviesDone
)
779 qterr
= EnterMovies();
787 mp_msg(MSGT_VO
, MSGL_FATAL
, "Quartz error: EnterMovies (%d)\n", qterr
);
792 SetIdentityMatrix(&matrix
);
794 if ((d_width
!= width
) || (d_height
!= height
))
796 ScaleMatrix(&matrix
, FixDiv(Long2Fix(d_width
), Long2Fix(width
)), FixDiv(Long2Fix(d_height
), Long2Fix(height
)), 0, 0);
799 yuv_qt_stuff
.desc
= (ImageDescriptionHandle
) NewHandleClear(sizeof(ImageDescription
));
801 yuv_qt_stuff
.extension_colr
= NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension
));
802 ((NCLCColorInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_colr
))->colorParamType
= kVideoColorInfoImageDescriptionExtensionType
;
803 ((NCLCColorInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_colr
))->primaries
= 2;
804 ((NCLCColorInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_colr
))->transferFunction
= 2;
805 ((NCLCColorInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_colr
))->matrix
= 2;
807 yuv_qt_stuff
.extension_fiel
= NewHandleClear(sizeof(FieldInfoImageDescriptionExtension
));
808 ((FieldInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_fiel
))->fieldCount
= 1;
809 ((FieldInfoImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_fiel
))->fieldOrderings
= 0;
811 yuv_qt_stuff
.extension_clap
= NewHandleClear(sizeof(CleanApertureImageDescriptionExtension
));
812 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->cleanApertureWidthN
= imgRect
.right
;
813 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->cleanApertureWidthD
= 1;
814 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->cleanApertureHeightN
= imgRect
.bottom
;
815 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->cleanApertureHeightD
= 1;
816 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->horizOffN
= 0;
817 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->horizOffD
= 1;
818 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->vertOffN
= 0;
819 ((CleanApertureImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_clap
))->vertOffD
= 1;
821 yuv_qt_stuff
.extension_pasp
= NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension
));
822 ((PixelAspectRatioImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_pasp
))->hSpacing
= 1;
823 ((PixelAspectRatioImageDescriptionExtension
*) (*yuv_qt_stuff
.extension_pasp
))->vSpacing
= 1;
825 (*yuv_qt_stuff
.desc
)->idSize
= sizeof(ImageDescription
);
826 (*yuv_qt_stuff
.desc
)->cType
= image_qtcodec
;
827 (*yuv_qt_stuff
.desc
)->version
= 2;
828 (*yuv_qt_stuff
.desc
)->revisionLevel
= 0;
829 (*yuv_qt_stuff
.desc
)->vendor
= 'mpla';
830 (*yuv_qt_stuff
.desc
)->width
= imgRect
.right
;
831 (*yuv_qt_stuff
.desc
)->height
= imgRect
.bottom
;
832 (*yuv_qt_stuff
.desc
)->hRes
= Long2Fix(72);
833 (*yuv_qt_stuff
.desc
)->vRes
= Long2Fix(72);
834 (*yuv_qt_stuff
.desc
)->temporalQuality
= 0;
835 (*yuv_qt_stuff
.desc
)->spatialQuality
= codecLosslessQuality
;
836 (*yuv_qt_stuff
.desc
)->frameCount
= 1;
837 (*yuv_qt_stuff
.desc
)->dataSize
= 0;
838 (*yuv_qt_stuff
.desc
)->depth
= 24;
839 (*yuv_qt_stuff
.desc
)->clutID
= -1;
841 qterr
= AddImageDescriptionExtension(yuv_qt_stuff
.desc
, yuv_qt_stuff
.extension_colr
, kColorInfoImageDescriptionExtension
);
844 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr
);
847 qterr
= AddImageDescriptionExtension(yuv_qt_stuff
.desc
, yuv_qt_stuff
.extension_fiel
, kFieldInfoImageDescriptionExtension
);
850 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr
);
853 qterr
= AddImageDescriptionExtension(yuv_qt_stuff
.desc
, yuv_qt_stuff
.extension_clap
, kCleanApertureImageDescriptionExtension
);
856 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr
);
859 qterr
= AddImageDescriptionExtension(yuv_qt_stuff
.desc
, yuv_qt_stuff
.extension_pasp
, kCleanApertureImageDescriptionExtension
);
862 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr
);
864 if (P
!= NULL
) { // second or subsequent movie
867 P
= calloc(sizeof(PlanarPixmapInfoYUV420
) + image_size
, 1);
868 switch (image_format
)
873 P
->componentInfoY
.offset
= be2me_32(sizeof(PlanarPixmapInfoYUV420
));
874 P
->componentInfoCb
.offset
= be2me_32(be2me_32(P
->componentInfoY
.offset
) + image_size
/ 2);
875 P
->componentInfoCr
.offset
= be2me_32(be2me_32(P
->componentInfoCb
.offset
) + image_size
/ 4);
876 P
->componentInfoY
.rowBytes
= be2me_32(imgRect
.right
);
877 P
->componentInfoCb
.rowBytes
= be2me_32(imgRect
.right
/ 2);
878 P
->componentInfoCr
.rowBytes
= be2me_32(imgRect
.right
/ 2);
879 image_buffer_size
= image_size
+ sizeof(PlanarPixmapInfoYUV420
);
883 image_buffer_size
= image_size
;
887 qterr
= DecompressSequenceBeginS(&seqId
,
891 GetWindowPort(theWindow
),
894 ((d_width
!= width
) || (d_height
!= height
)) ?
899 codecLosslessQuality
,
904 mp_msg(MSGT_VO
, MSGL_FATAL
, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr
);
912 RepositionWindow(theWindow
, NULL
, kWindowCenterOnMainScreen
);
913 ShowWindow(theWindow
);
925 SetWindowGroupLevel(winGroup
, CGWindowLevelForKey(levelList
[winLevel
]));
934 static void check_events(void)
937 EventTargetRef theTarget
;
941 theTarget
= GetEventDispatcherTarget();
942 theErr
= ReceiveNextEvent(0, 0, kEventDurationNoWait
, true, &theEvent
);
943 if (theErr
== noErr
&& theEvent
!= NULL
)
945 SendEventToEventTarget(theEvent
, theTarget
);
946 ReleaseEvent(theEvent
);
950 static void draw_osd(void)
952 vo_draw_text(imgRect
.right
, imgRect
.bottom
, draw_alpha
);
955 static void flip_page(void)
959 if (theWindow
== NULL
)
962 switch (image_format
)
966 CGContextRef context
;
968 QDBeginCGContext(GetWindowPort(theWindow
), &context
);
969 CGContextDrawImage(context
, bounds
, image
);
970 QDEndCGContext(GetWindowPort(theWindow
), &context
);
982 CodecFlags flags
= 0;
984 qterr
= DecompressSequenceFrameWhen(seqId
,
987 0, //codecFlagUseImageBuffer,
993 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr
, flags
);
1001 CGContextRef context
;
1003 QDBeginCGContext(GetWindowPort(theWindow
), &context
);
1004 // render resize box
1005 CGContextBeginPath(context
);
1006 CGContextSetAllowsAntialiasing(context
, false);
1007 //CGContextSaveGState(context);
1010 CGContextSetRGBStrokeColor(context
, 0.2, 0.2, 0.2, 0.5);
1011 CGContextMoveToPoint(context
, winRect
.right
- 1, 1); CGContextAddLineToPoint(context
, winRect
.right
- 1, 1);
1012 CGContextMoveToPoint(context
, winRect
.right
- 1, 5); CGContextAddLineToPoint(context
, winRect
.right
- 5, 1);
1013 CGContextMoveToPoint(context
, winRect
.right
- 1, 9); CGContextAddLineToPoint(context
, winRect
.right
- 9, 1);
1014 CGContextStrokePath(context
);
1017 CGContextSetRGBStrokeColor(context
, 0.4, 0.4, 0.4, 0.5);
1018 CGContextMoveToPoint(context
, winRect
.right
- 1, 2); CGContextAddLineToPoint(context
, winRect
.right
- 2, 1);
1019 CGContextMoveToPoint(context
, winRect
.right
- 1, 6); CGContextAddLineToPoint(context
, winRect
.right
- 6, 1);
1020 CGContextMoveToPoint(context
, winRect
.right
- 1, 10); CGContextAddLineToPoint(context
, winRect
.right
- 10, 1);
1021 CGContextStrokePath(context
);
1024 CGContextSetRGBStrokeColor(context
, 0.6, 0.6, 0.6, 0.5);
1025 CGContextMoveToPoint(context
, winRect
.right
- 1, 3); CGContextAddLineToPoint(context
, winRect
.right
- 3, 1);
1026 CGContextMoveToPoint(context
, winRect
.right
- 1, 7); CGContextAddLineToPoint(context
, winRect
.right
- 7, 1);
1027 CGContextMoveToPoint(context
, winRect
.right
- 1, 11); CGContextAddLineToPoint(context
, winRect
.right
- 11, 1);
1028 CGContextStrokePath(context
);
1030 // CGContextRestoreGState( context );
1031 CGContextFlush(context
);
1032 QDEndCGContext(GetWindowPort(theWindow
), &context
);
1035 curTime
= TickCount() / 60;
1037 // auto hide mouse cursor (and future on-screen control?)
1038 if (vo_quartz_fs
&& !mouseHide
)
1040 if (((curTime
- lastMouseHide
) >= 5) || (lastMouseHide
== 0))
1042 CGDisplayHideCursor(displayId
);
1044 lastMouseHide
= curTime
;
1047 // update activity every 30 seconds to prevent
1048 // screensaver from starting up.
1049 if (((curTime
- lastScreensaverUpdate
) >= 30) || (lastScreensaverUpdate
== 0))
1051 UpdateSystemActivity(UsrActivity
);
1052 lastScreensaverUpdate
= curTime
;
1056 static int draw_slice(uint8_t * src
[], int stride
[], int w
, int h
, int x
, int y
)
1058 switch (image_format
)
1062 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoY
.offset
) + x
+ imgRect
.right
* y
, src
[0], w
, h
, imgRect
.right
, stride
[0]);
1063 x
=x
/2;y
=y
/2;w
=w
/2;h
=h
/2;
1065 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoCb
.offset
) + x
+ imgRect
.right
/ 2 * y
, src
[1], w
, h
, imgRect
.right
/ 2, stride
[1]);
1066 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoCr
.offset
) + x
+ imgRect
.right
/ 2 * y
, src
[2], w
, h
, imgRect
.right
/ 2, stride
[2]);
1070 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoY
.offset
) + x
+ imgRect
.right
* y
, src
[0], w
, h
, imgRect
.right
, stride
[0]);
1071 x
=x
/2;y
=y
/2;w
=w
/2;h
=h
/2;
1073 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoCr
.offset
) + x
+ imgRect
.right
/ 2 * y
, src
[1], w
, h
, imgRect
.right
/ 2, stride
[1]);
1074 memcpy_pic(((char *)P
) + be2me_32(P
->componentInfoCb
.offset
) + x
+ imgRect
.right
/ 2 * y
, src
[2], w
, h
, imgRect
.right
/ 2, stride
[2]);
1080 static int draw_frame(uint8_t * src
[])
1082 switch (image_format
)
1085 fast_memcpy(image_data
, src
[0], image_size
);
1090 memcpy_pic(((char *)P
), src
[0], imgRect
.right
* 2, imgRect
.bottom
, imgRect
.right
* 2, imgRect
.right
* 2);
1096 static int query_format(uint32_t format
)
1098 image_format
= format
;
1101 if (format
== IMGFMT_RGB32
)
1103 return VFCAP_CSP_SUPPORTED
| VFCAP_OSD
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
;
1106 if ((format
== IMGFMT_YV12
) || (format
== IMGFMT_IYUV
) || (format
== IMGFMT_I420
))
1108 image_qtcodec
= kMpegYUV420CodecType
; //kYUV420CodecType ?;
1109 return VFCAP_CSP_SUPPORTED
| VFCAP_OSD
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
| VFCAP_ACCEPT_STRIDE
;
1112 if (format
== IMGFMT_YUY2
)
1114 image_qtcodec
= kComponentVideoUnsigned
;
1115 return VFCAP_CSP_SUPPORTED
| VFCAP_OSD
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
;
1118 if (format
== IMGFMT_UYVY
)
1120 image_qtcodec
= k422YpCbCr8CodecType
;
1121 return VFCAP_CSP_SUPPORTED
| VFCAP_OSD
| VFCAP_HWSCALE_UP
| VFCAP_HWSCALE_DOWN
;
1127 static void uninit(void)
1131 switch (image_format
)
1139 if (EnterMoviesDone
)
1141 qterr
= CDSequenceEnd(seqId
);
1144 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: CDSequenceEnd (%d)\n", qterr
);
1156 static int preinit(const char *arg
)
1162 char *parse_pos
= (char *)&arg
[0];
1164 while (parse_pos
[0] && !parse_err
)
1166 if (strncmp(parse_pos
, "device_id=", 10) == 0)
1168 parse_pos
= &parse_pos
[10];
1169 device_id
= strtol(parse_pos
, &parse_pos
, 0);
1171 if (strncmp(parse_pos
, "fs_res=", 7) == 0)
1173 parse_pos
= &parse_pos
[7];
1174 fs_res_x
= strtol(parse_pos
, &parse_pos
, 0);
1175 parse_pos
= &parse_pos
[1];
1176 fs_res_y
= strtol(parse_pos
, &parse_pos
, 0);
1178 if (parse_pos
[0] == ':')
1179 parse_pos
= &parse_pos
[1];
1180 else if (parse_pos
[0])
1185 #if !defined (CONFIG_MACOSX_FINDER) || !defined (CONFIG_SDL)
1186 // this chunk of code is heavily based off SDL_macosx.m from SDL
1187 // the CPSEnableForegroundOperation that was here before is private and shouldn't be used
1188 // replaced by a call to the 10.3+ TransformProcessType
1190 ProcessSerialNumber myProc
, frProc
;
1193 if (GetFrontProcess(&frProc
) == noErr
)
1195 if (GetCurrentProcess(&myProc
) == noErr
)
1197 if (SameProcess(&frProc
, &myProc
, &sameProc
) == noErr
&& !sameProc
)
1199 TransformProcessType(&myProc
, kProcessTransformToForegroundApplication
);
1201 SetFrontProcess(&myProc
);
1210 static uint32_t draw_yuv_image(mp_image_t
* mpi
)
1212 // ATM we're only called for planar IMGFMT
1213 // drawing is done directly in P
1214 // and displaying is in flip_page.
1215 return get_image_done
? VO_TRUE
: VO_FALSE
;
1218 static uint32_t get_yuv_image(mp_image_t
* mpi
)
1220 if (mpi
->type
!= MP_IMGTYPE_EXPORT
) return VO_FALSE
;
1222 if (mpi
->imgfmt
!= image_format
) return VO_FALSE
;
1224 if (mpi
->flags
& MP_IMGFLAG_PLANAR
)
1226 if (mpi
->num_planes
!= 3)
1228 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi
->num_planes
);
1232 mpi
->planes
[0] = ((char *)P
) + be2me_32(P
->componentInfoY
.offset
);
1233 mpi
->stride
[0] = imgRect
.right
;
1234 mpi
->width
= imgRect
.right
;
1236 if (mpi
->flags
& MP_IMGFLAG_SWAPPED
)
1239 mpi
->planes
[1] = ((char *)P
) + be2me_32(P
->componentInfoCb
.offset
);
1240 mpi
->planes
[2] = ((char *)P
) + be2me_32(P
->componentInfoCr
.offset
);
1241 mpi
->stride
[1] = imgRect
.right
/ 2;
1242 mpi
->stride
[2] = imgRect
.right
/ 2;
1247 mpi
->planes
[1] = ((char *)P
) + be2me_32(P
->componentInfoCr
.offset
);
1248 mpi
->planes
[2] = ((char *)P
) + be2me_32(P
->componentInfoCb
.offset
);
1249 mpi
->stride
[1] = imgRect
.right
/ 2;
1250 mpi
->stride
[2] = imgRect
.right
/ 2;
1253 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1260 if (mpi
->num_planes
!= 1)
1262 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi
->num_planes
);
1266 mpi
->planes
[0] = (char *)P
;
1267 mpi
->stride
[0] = imgRect
.right
* 2;
1268 mpi
->width
= imgRect
.right
;
1269 mpi
->flags
|= MP_IMGFLAG_DIRECT
;
1276 static int control(uint32_t request
, void *data
, ...)
1280 case VOCTRL_PAUSE
: return int_pause
= 1;
1281 case VOCTRL_RESUME
: return int_pause
= 0;
1282 case VOCTRL_FULLSCREEN
: vo_fs
= (!(vo_fs
)); window_fullscreen(); return VO_TRUE
;
1283 case VOCTRL_ONTOP
: vo_ontop
= (!(vo_ontop
)); window_ontop(); return VO_TRUE
;
1284 case VOCTRL_QUERY_FORMAT
: return query_format(*((uint32_t *) data
));
1285 case VOCTRL_GET_PANSCAN
: return VO_TRUE
;
1286 case VOCTRL_SET_PANSCAN
: window_panscan(); return VO_TRUE
;
1288 case VOCTRL_GET_IMAGE
:
1289 switch (image_format
)
1296 return get_yuv_image(data
);
1301 case VOCTRL_DRAW_IMAGE
:
1302 switch (image_format
)
1309 return draw_yuv_image(data
);
1318 void window_resized()
1330 CGContextRef context
;
1332 GetWindowPortBounds(theWindow
, &winRect
);
1336 aspect(&d_width
, &d_height
, A_NOZOOM
);
1337 d_height
= ((float)d_width
/ movie_aspect
);
1339 aspectX
= (float)((float)winRect
.right
/ (float)d_width
);
1340 aspectY
= (float)((float)(winRect
.bottom
) / (float)d_height
);
1342 if ((d_height
* aspectX
) > (winRect
.bottom
))
1344 padding
= (winRect
.right
- d_width
* aspectY
) / 2;
1345 SetRect(&dstRect
, padding
, 0, d_width
* aspectY
+ padding
, d_height
* aspectY
);
1349 padding
= ((winRect
.bottom
) - d_height
* aspectX
) / 2;
1350 SetRect(&dstRect
, 0, padding
, (d_width
* aspectX
), d_height
* aspectX
+ padding
);
1355 SetRect(&dstRect
, 0, 0, winRect
.right
, winRect
.bottom
);
1358 switch (image_format
)
1362 bounds
= CGRectMake(dstRect
.left
, dstRect
.top
, dstRect
.right
- dstRect
.left
, dstRect
.bottom
- dstRect
.top
);
1371 long scale_X
= FixDiv(Long2Fix(dstRect
.right
- dstRect
.left
), Long2Fix(imgRect
.right
));
1372 long scale_Y
= FixDiv(Long2Fix(dstRect
.bottom
- dstRect
.top
), Long2Fix(imgRect
.bottom
));
1374 SetIdentityMatrix(&matrix
);
1375 if (((dstRect
.right
- dstRect
.left
) != imgRect
.right
) || ((dstRect
.bottom
- dstRect
.right
) != imgRect
.bottom
))
1377 ScaleMatrix(&matrix
, scale_X
, scale_Y
, 0, 0);
1381 TranslateMatrix(&matrix
, Long2Fix(dstRect
.left
), Long2Fix(dstRect
.top
));
1385 SetDSequenceMatrix(seqId
, &matrix
);
1393 tmpBounds
= CGRectMake(0, 0, winRect
.right
, winRect
.bottom
);
1394 QDBeginCGContext(GetWindowPort(theWindow
), &context
);
1395 CGContextFillRect(context
, tmpBounds
);
1396 QDEndCGContext(GetWindowPort(theWindow
), &context
);
1403 // Cycle between level
1408 SetWindowGroupLevel(winGroup
, CGWindowLevelForKey(levelList
[winLevel
]));
1411 void window_fullscreen()
1418 if (displayId
== kCGDirectMainDisplay
)
1420 SetSystemUIMode(kUIModeAllHidden
, kUIOptionAutoShowMenuBar
);
1421 CGDisplayHideCursor(displayId
);
1425 if (fs_res_x
!= 0 || fs_res_y
!= 0)
1427 CFDictionaryRef mode
;
1428 size_t desiredBitDepth
= 32;
1429 boolean_t exactMatch
;
1431 originalMode
= CGDisplayCurrentMode(displayId
);
1433 mode
= CGDisplayBestModeForParameters(displayId
, desiredBitDepth
, fs_res_x
, fs_res_y
, &exactMatch
);
1439 // Warn if the mode doesn't match exactly
1440 mp_msg(MSGT_VO
, MSGL_WARN
, "Quartz warning: did not get exact mode match (got %dx%d) \n", (int)CFDictionaryGetValue(mode
, kCGDisplayWidth
), (int)CFDictionaryGetValue(mode
, kCGDisplayHeight
));
1443 CGDisplayCapture(displayId
);
1444 CGDisplaySwitchToMode(displayId
, mode
);
1448 mp_msg(MSGT_VO
, MSGL_ERR
, "Quartz error: can't switch to fullscreen \n");
1451 // Get Main device info///////////////////////////////////////////////////
1452 displayRect
= CGDisplayBounds(displayId
);
1455 // save old window size
1458 GetWindowPortBounds(theWindow
, &oldWinRect
);
1459 GetWindowBounds(theWindow
, kWindowContentRgn
, &oldWinBounds
);
1463 ChangeWindowAttributes(theWindow
, kWindowNoShadowAttribute
, 0);
1464 MoveWindow(theWindow
, displayRect
.origin
.x
- (vo_panscan_x
>> 1), displayRect
.origin
.y
- (vo_panscan_y
>> 1), 1);
1465 SizeWindow(theWindow
, displayRect
.size
.width
+ vo_panscan_x
, displayRect
.size
.height
+ vo_panscan_y
, 1);
1469 else //go back to windowed mode
1472 if (originalMode
!= NULL
)
1474 CGDisplaySwitchToMode(displayId
, originalMode
);
1475 CGDisplayRelease(displayId
);
1477 // Get Main device info///////////////////////////////////////////////////
1478 displayRect
= CGDisplayBounds(displayId
);
1480 originalMode
= NULL
;
1482 SetSystemUIMode(kUIModeNormal
, 0);
1484 // show mouse cursor
1485 CGDisplayShowCursor(displayId
);
1488 // revert window to previous setting
1489 ChangeWindowAttributes(theWindow
, 0, kWindowNoShadowAttribute
);
1490 SizeWindow(theWindow
, oldWinRect
.right
, oldWinRect
.bottom
, 1);
1491 MoveWindow(theWindow
, oldWinBounds
.left
, oldWinBounds
.top
, 1);
1496 void window_panscan()
1501 CheckMenuItem(aspectMenu
, 2, 1);
1503 CheckMenuItem(aspectMenu
, 2, 0);
1507 MoveWindow(theWindow
, displayRect
.origin
.x
- (vo_panscan_x
>> 1), displayRect
.origin
.y
- (vo_panscan_y
>> 1), 1);
1508 SizeWindow(theWindow
, displayRect
.size
.width
+ vo_panscan_x
, displayRect
.size
.height
+ vo_panscan_y
, 1);