libvo: Move aspect.c static variables to vo struct
[mplayer/glamo.git] / libvo / vo_quartz.c
blobbefe158e14b33462760dca7ccff394f299f65cf9
1 /*
2 vo_quartz.c
4 by Nicolas Plourde <nicolasplourde@gmail.com>
6 Copyright (c) Nicolas Plourde - April 2004
8 YUV support Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
10 MPlayer Mac OSX Quartz video out module.
12 todo: -screen overlay output
13 -fit osd in black bar when available
14 -fix RGB32
15 -(add sugestion here)
18 //SYS
19 #include <stdio.h>
21 //OSX
22 #include <Carbon/Carbon.h>
23 #include <QuickTime/QuickTime.h>
25 //MPLAYER
26 #include "config.h"
27 #include "fastmemcpy.h"
28 #include "video_out.h"
29 #include "video_out_internal.h"
30 #include "aspect.h"
31 #include "mp_msg.h"
32 #include "m_option.h"
33 #include "mp_fifo.h"
34 #include "mpbswap.h"
36 #include "input/input.h"
37 #include "input/mouse.h"
39 #include "vo_quartz.h"
41 static const vo_info_t info =
43 "Mac OSX (Quartz)",
44 "quartz",
45 "Nicolas Plourde <nicolasplourde@hotmail.com>, Romain Dolbeau <romain@dolbeau.org>",
49 const LIBVO_EXTERN(quartz)
51 static uint32_t image_depth;
52 static uint32_t image_format;
53 static uint32_t image_size;
54 static uint32_t image_buffer_size;
55 static char *image_data;
57 static ImageSequence seqId;
58 static CodecType image_qtcodec;
59 static PlanarPixmapInfoYUV420 *P = NULL;
60 static struct
62 ImageDescriptionHandle desc;
63 Handle extension_colr;
64 Handle extension_fiel;
65 Handle extension_clap;
66 Handle extension_pasp;
67 } yuv_qt_stuff;
68 static MatrixRecord matrix;
69 static int EnterMoviesDone = 0;
70 static int get_image_done = 0;
72 static int vo_quartz_fs; // we are in fullscreen
73 static float old_movie_aspect;
75 static int winLevel = 1;
76 int levelList[] =
78 kCGDesktopWindowLevelKey,
79 kCGNormalWindowLevelKey,
80 kCGScreenSaverWindowLevelKey
83 static int int_pause = 0;
84 static float winAlpha = 1;
85 static int mouseHide = FALSE;
87 static int device_width;
88 static int device_height;
89 static int device_id;
91 static short fs_res_x=0;
92 static short fs_res_y=0;
94 static WindowRef theWindow = NULL;
95 static WindowGroupRef winGroup = NULL;
96 static CGContextRef context;
97 static CGRect bounds;
98 static GDHandle deviceHdl;
100 static CGDataProviderRef dataProviderRef;
101 static CGImageRef image;
103 static Rect imgRect; // size of the original image (unscaled)
104 static Rect dstRect; // size of the displayed image (after scaling)
105 static Rect winRect; // size of the window containg the displayed image (include padding)
106 static Rect oldWinRect; // size of the window containg the displayed image (include padding) when NOT in FS mode
107 static Rect deviceRect; // size of the display device
108 static Rect oldWinBounds;
110 static MenuRef windMenu;
111 static MenuRef movMenu;
112 static MenuRef aspectMenu;
114 enum
116 kQuitCmd = 1,
117 kHalfScreenCmd = 2,
118 kNormalScreenCmd = 3,
119 kDoubleScreenCmd = 4,
120 kFullScreenCmd = 5,
121 kKeepAspectCmd = 6,
122 kAspectOrgCmd = 7,
123 kAspectFullCmd = 8,
124 kAspectWideCmd = 9,
125 kPanScanCmd = 10
128 #include "osdep/keycodes.h"
130 //PROTOTYPE/////////////////////////////////////////////////////////////////
131 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
132 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
133 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
134 void window_resized();
135 void window_ontop();
136 void window_fullscreen();
137 void window_panscan();
139 static inline int convert_key(UInt32 key, UInt32 charcode)
141 switch(key)
143 case QZ_IBOOK_ENTER:
144 case QZ_RETURN: return KEY_ENTER;
145 case QZ_ESCAPE: return KEY_ESC;
146 case QZ_BACKSPACE: return KEY_BACKSPACE;
147 case QZ_LALT: return KEY_BACKSPACE;
148 case QZ_LCTRL: return KEY_BACKSPACE;
149 case QZ_LSHIFT: return KEY_BACKSPACE;
150 case QZ_F1: return KEY_F+1;
151 case QZ_F2: return KEY_F+2;
152 case QZ_F3: return KEY_F+3;
153 case QZ_F4: return KEY_F+4;
154 case QZ_F5: return KEY_F+5;
155 case QZ_F6: return KEY_F+6;
156 case QZ_F7: return KEY_F+7;
157 case QZ_F8: return KEY_F+8;
158 case QZ_F9: return KEY_F+9;
159 case QZ_F10: return KEY_F+10;
160 case QZ_F11: return KEY_F+11;
161 case QZ_F12: return KEY_F+12;
162 case QZ_INSERT: return KEY_INSERT;
163 case QZ_DELETE: return KEY_DELETE;
164 case QZ_HOME: return KEY_HOME;
165 case QZ_END: return KEY_END;
166 case QZ_KP_PLUS: return '+';
167 case QZ_KP_MINUS: return '-';
168 case QZ_TAB: return KEY_TAB;
169 case QZ_PAGEUP: return KEY_PAGE_UP;
170 case QZ_PAGEDOWN: return KEY_PAGE_DOWN;
171 case QZ_UP: return KEY_UP;
172 case QZ_DOWN: return KEY_DOWN;
173 case QZ_LEFT: return KEY_LEFT;
174 case QZ_RIGHT: return KEY_RIGHT;
175 case QZ_KP_MULTIPLY: return '*';
176 case QZ_KP_DIVIDE: return '/';
177 case QZ_KP_ENTER: return KEY_KPENTER;
178 case QZ_KP_PERIOD: return KEY_KPDEC;
179 case QZ_KP0: return KEY_KP0;
180 case QZ_KP1: return KEY_KP1;
181 case QZ_KP2: return KEY_KP2;
182 case QZ_KP3: return KEY_KP3;
183 case QZ_KP4: return KEY_KP4;
184 case QZ_KP5: return KEY_KP5;
185 case QZ_KP6: return KEY_KP6;
186 case QZ_KP7: return KEY_KP7;
187 case QZ_KP8: return KEY_KP8;
188 case QZ_KP9: return KEY_KP9;
189 default: return charcode;
193 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
195 switch (image_format)
197 case IMGFMT_RGB32:
198 vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
199 break;
200 case IMGFMT_YV12:
201 case IMGFMT_IYUV:
202 case IMGFMT_I420:
203 vo_draw_alpha_yv12(w,h,src,srca,stride, ((char*)P) + be2me_32(P->componentInfoY.offset) + x0 + y0 * imgRect.right, imgRect.right);
204 break;
205 case IMGFMT_UYVY:
206 vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
207 break;
208 case IMGFMT_YUY2:
209 vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
210 break;
214 //default keyboard event handler
215 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
217 OSStatus result = noErr;
218 UInt32 class = GetEventClass (event);
219 UInt32 kind = GetEventKind (event);
221 result = CallNextEventHandler(nextHandler, event);
223 if(class == kEventClassKeyboard)
225 char macCharCodes;
226 UInt32 macKeyCode;
227 UInt32 macKeyModifiers;
229 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(macCharCodes), NULL, &macCharCodes);
230 GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode);
231 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(macKeyModifiers), NULL, &macKeyModifiers);
233 if(macKeyModifiers != 256)
235 if (kind == kEventRawKeyRepeat || kind == kEventRawKeyDown)
237 int key = convert_key(macKeyCode, macCharCodes);
238 if(key != -1)
239 mplayer_put_key(key);
242 else if(macKeyModifiers == 256)
244 switch(macCharCodes)
246 case '[': SetWindowAlpha(theWindow, winAlpha-=0.05); break;
247 case ']': SetWindowAlpha(theWindow, winAlpha+=0.05); break;
250 else
251 result = eventNotHandledErr;
254 return result;
257 //default mouse event handler
258 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
260 OSStatus result = noErr;
261 UInt32 class = GetEventClass (event);
262 UInt32 kind = GetEventKind (event);
264 result = CallNextEventHandler(nextHandler, event);
266 if(class == kEventClassMouse)
268 WindowPtr tmpWin;
269 Point mousePos;
270 Point winMousePos;
272 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &mousePos);
273 GetEventParameter(event, kEventParamWindowMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &winMousePos);
275 switch (kind)
277 case kEventMouseMoved:
279 if(vo_quartz_fs)
281 CGDisplayShowCursor(kCGDirectMainDisplay);
282 mouseHide = FALSE;
285 break;
287 case kEventMouseWheelMoved:
289 int wheel;
290 short part;
292 GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, sizeof(int), 0, &wheel);
294 part = FindWindow(mousePos,&tmpWin);
296 if(part == inContent)
298 if(wheel > 0)
299 mplayer_put_key(MOUSE_BTN3);
300 else
301 mplayer_put_key(MOUSE_BTN4);
304 break;
306 case kEventMouseDown:
307 case kEventMouseUp:
309 EventMouseButton button;
310 short part;
311 Rect bounds;
313 GetWindowPortBounds(theWindow, &bounds);
314 GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0, sizeof(EventMouseButton), 0, &button);
316 part = FindWindow(mousePos,&tmpWin);
317 if(kind == kEventMouseUp)
319 if (part != inContent)
320 break;
321 switch(button)
323 case kEventMouseButtonPrimary:
324 mplayer_put_key(MOUSE_BTN0);
325 break;
326 case kEventMouseButtonSecondary:
327 mplayer_put_key(MOUSE_BTN2);
328 break;
329 case kEventMouseButtonTertiary:
330 mplayer_put_key(MOUSE_BTN1);
331 break;
333 default:result = eventNotHandledErr;break;
335 break;
337 if( (winMousePos.h > (bounds.right - 15)) && (winMousePos.v > (bounds.bottom)) )
339 if(!vo_quartz_fs)
341 GrowWindow(theWindow, mousePos, NULL);
344 else if(part == inMenuBar)
346 MenuSelect(mousePos);
347 HiliteMenu(0);
349 else if(part == inContent)
351 switch(button)
353 case kEventMouseButtonPrimary:
354 mplayer_put_key(MOUSE_BTN0 | MP_KEY_DOWN);
355 break;
356 case kEventMouseButtonSecondary:
357 mplayer_put_key(MOUSE_BTN2 | MP_KEY_DOWN);
358 break;
359 case kEventMouseButtonTertiary:
360 mplayer_put_key(MOUSE_BTN1 | MP_KEY_DOWN);
361 break;
363 default:result = eventNotHandledErr;break;
367 break;
369 case kEventMouseDragged:
370 break;
372 default:result = eventNotHandledErr;break;
376 return result;
379 //default window event handler
380 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
382 OSStatus result = noErr;
383 uint32_t d_width;
384 uint32_t d_height;
385 UInt32 class = GetEventClass (event);
386 UInt32 kind = GetEventKind (event);
388 result = CallNextEventHandler(nextHandler, event);
390 aspect(&d_width,&d_height,A_NOZOOM);
392 if(class == kEventClassCommand)
394 HICommand theHICommand;
395 GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand );
397 switch ( theHICommand.commandID )
399 case kHICommandQuit:
400 mplayer_put_key(KEY_CLOSE_WIN);
401 break;
403 case kHalfScreenCmd:
404 if(vo_quartz_fs)
406 vo_fs = (!(vo_fs)); window_fullscreen();
409 SizeWindow(theWindow, (d_width/2), ((d_width/movie_aspect)/2), 1);
410 window_resized();
411 break;
413 case kNormalScreenCmd:
414 if(vo_quartz_fs)
416 vo_fs = (!(vo_fs)); window_fullscreen();
419 SizeWindow(theWindow, d_width, (d_width/movie_aspect), 1);
420 window_resized();
421 break;
423 case kDoubleScreenCmd:
424 if(vo_quartz_fs)
426 vo_fs = (!(vo_fs)); window_fullscreen();
429 SizeWindow(theWindow, (d_width*2), ((d_width/movie_aspect)*2), 1);
430 window_resized();
431 break;
433 case kFullScreenCmd:
434 vo_fs = (!(vo_fs)); window_fullscreen();
435 break;
437 case kKeepAspectCmd:
438 vo_keepaspect = (!(vo_keepaspect));
439 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
440 window_resized();
441 break;
443 case kAspectOrgCmd:
444 movie_aspect = old_movie_aspect;
445 if(!vo_quartz_fs)
447 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
449 window_resized();
450 break;
452 case kAspectFullCmd:
453 movie_aspect = 4.0f/3.0f;
454 if(!vo_quartz_fs)
456 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
458 window_resized();
459 break;
461 case kAspectWideCmd:
462 movie_aspect = 16.0f/9.0f;
463 if(!vo_quartz_fs)
465 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
467 window_resized();
468 break;
470 case kPanScanCmd:
471 vo_panscan = (!(vo_panscan));
472 CheckMenuItem (aspectMenu, 2, vo_panscan);
473 window_panscan();
474 window_resized();
475 break;
477 default:
478 result = eventNotHandledErr;
479 break;
482 else if(class == kEventClassWindow)
484 WindowRef window;
485 Rect rectPort = {0,0,0,0};
487 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
489 if(window)
491 GetPortBounds(GetWindowPort(window), &rectPort);
494 switch (kind)
496 case kEventWindowClosed:
497 theWindow = NULL;
498 mplayer_put_key(KEY_CLOSE_WIN);
499 break;
501 //resize window
502 case kEventWindowZoomed:
503 case kEventWindowBoundsChanged:
504 window_resized();
505 flip_page();
506 window_resized();
507 break;
509 default:
510 result = eventNotHandledErr;
511 break;
515 return result;
518 static void quartz_CreateWindow(uint32_t d_width, uint32_t d_height, WindowAttributes windowAttrs)
520 CFStringRef titleKey;
521 CFStringRef windowTitle;
522 OSStatus result;
524 MenuItemIndex index;
525 CFStringRef movMenuTitle;
526 CFStringRef aspMenuTitle;
528 const EventTypeSpec win_events[] = {
529 { kEventClassWindow, kEventWindowClosed },
530 { kEventClassWindow, kEventWindowBoundsChanged },
531 { kEventClassCommand, kEventCommandProcess }
534 const EventTypeSpec key_events[] = {
535 { kEventClassKeyboard, kEventRawKeyDown },
536 { kEventClassKeyboard, kEventRawKeyRepeat }
539 const EventTypeSpec mouse_events[] = {
540 { kEventClassMouse, kEventMouseMoved },
541 { kEventClassMouse, kEventMouseWheelMoved },
542 { kEventClassMouse, kEventMouseDown },
543 { kEventClassMouse, kEventMouseUp },
544 { kEventClassMouse, kEventMouseDragged }
547 SetRect(&winRect, 0, 0, d_width, d_height);
548 SetRect(&oldWinRect, 0, 0, d_width, d_height);
549 SetRect(&dstRect, 0, 0, d_width, d_height);
551 //Clear Menu Bar
552 ClearMenuBar();
554 //Create Window Menu
555 CreateStandardWindowMenu(0, &windMenu);
556 InsertMenu(windMenu, 0);
558 //Create Movie Menu
559 CreateNewMenu (1004, 0, &movMenu);
560 movMenuTitle = CFSTR("Movie");
561 SetMenuTitleWithCFString(movMenu, movMenuTitle);
563 AppendMenuItemTextWithCFString(movMenu, CFSTR("Half Size"), 0, kHalfScreenCmd, &index);
564 SetMenuItemCommandKey(movMenu, index, 0, '0');
566 AppendMenuItemTextWithCFString(movMenu, CFSTR("Normal Size"), 0, kNormalScreenCmd, &index);
567 SetMenuItemCommandKey(movMenu, index, 0, '1');
569 AppendMenuItemTextWithCFString(movMenu, CFSTR("Double Size"), 0, kDoubleScreenCmd, &index);
570 SetMenuItemCommandKey(movMenu, index, 0, '2');
572 AppendMenuItemTextWithCFString(movMenu, CFSTR("Full Size"), 0, kFullScreenCmd, &index);
573 SetMenuItemCommandKey(movMenu, index, 0, 'F');
575 AppendMenuItemTextWithCFString(movMenu, NULL, kMenuItemAttrSeparator, 0, &index);
577 AppendMenuItemTextWithCFString(movMenu, CFSTR("Aspect Ratio"), 0, 0, &index);
579 ////Create Aspect Ratio Sub Menu
580 CreateNewMenu (0, 0, &aspectMenu);
581 aspMenuTitle = CFSTR("Aspect Ratio");
582 SetMenuTitleWithCFString(aspectMenu, aspMenuTitle);
583 SetMenuItemHierarchicalMenu(movMenu, 6, aspectMenu);
585 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Keep"), 0, kKeepAspectCmd, &index);
586 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
587 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Pan-Scan"), 0, kPanScanCmd, &index);
588 CheckMenuItem (aspectMenu, 2, vo_panscan);
589 AppendMenuItemTextWithCFString(aspectMenu, NULL, kMenuItemAttrSeparator, 0, &index);
590 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Original"), 0, kAspectOrgCmd, &index);
591 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("4:3"), 0, kAspectFullCmd, &index);
592 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("16:9"), 0, kAspectWideCmd, &index);
594 InsertMenu(movMenu, GetMenuID(windMenu)); //insert before Window menu
596 DrawMenuBar();
598 //create window
599 CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
601 CreateWindowGroup(0, &winGroup);
602 SetWindowGroup(theWindow, winGroup);
604 //Set window title
605 titleKey = CFSTR("MPlayer - The Movie Player");
606 windowTitle = CFCopyLocalizedString(titleKey, NULL);
607 result = SetWindowTitleWithCFString(theWindow, windowTitle);
608 CFRelease(titleKey);
609 CFRelease(windowTitle);
611 //Install event handler
612 InstallApplicationEventHandler (NewEventHandlerUPP (KeyEventHandler), GetEventTypeCount(key_events), key_events, NULL, NULL);
613 InstallApplicationEventHandler (NewEventHandlerUPP (MouseEventHandler), GetEventTypeCount(mouse_events), mouse_events, NULL, NULL);
614 InstallWindowEventHandler (theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, theWindow, NULL);
617 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)
619 WindowAttributes windowAttrs;
620 OSErr qterr;
621 int i;
622 CGRect tmpBounds;
624 //Get Main device info///////////////////////////////////////////////////
627 deviceHdl = GetMainDevice();
629 for(i=0; i<device_id; i++)
631 deviceHdl = GetNextDevice(deviceHdl);
633 if(deviceHdl == NULL)
635 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Device ID %d do not exist, falling back to main device.\n", device_id);
636 deviceHdl = GetMainDevice();
637 device_id = 0;
638 break;
642 deviceRect = (*deviceHdl)->gdRect;
643 device_width = deviceRect.right-deviceRect.left;
644 device_height = deviceRect.bottom-deviceRect.top;
646 monitor_aspect = (float)device_width/(float)device_height;
648 //misc mplayer setup/////////////////////////////////////////////////////
649 SetRect(&imgRect, 0, 0, width, height);
650 switch (image_format)
652 case IMGFMT_RGB32:
653 image_depth = 32;
654 break;
655 case IMGFMT_YV12:
656 case IMGFMT_IYUV:
657 case IMGFMT_I420:
658 case IMGFMT_UYVY:
659 case IMGFMT_YUY2:
660 image_depth = 16;
661 break;
663 image_size = ((imgRect.right*imgRect.bottom*image_depth)+7)/8;
665 vo_fs = flags & VOFLAG_FULLSCREEN;
667 //get movie aspect
668 panscan_init();
669 aspect_save_orig(width,height);
670 aspect_save_prescale(d_width,d_height);
671 aspect_save_screenres(device_width, device_height);
673 aspect(&d_width,&d_height,A_NOZOOM);
675 movie_aspect = (float)d_width/(float)d_height;
676 old_movie_aspect = movie_aspect;
678 if(image_data)
679 free(image_data);
681 image_data = malloc(image_size);
683 //Create player window//////////////////////////////////////////////////
684 windowAttrs = kWindowStandardDocumentAttributes
685 | kWindowStandardHandlerAttribute
686 | kWindowLiveResizeAttribute;
688 windowAttrs &= (~kWindowResizableAttribute);
690 if (theWindow == NULL)
692 quartz_CreateWindow(d_width, d_height, windowAttrs);
694 if (theWindow == NULL)
696 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Couldn't create window !!!!!\n");
697 return -1;
699 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
700 CreateCGContextForPort(GetWindowPort(theWindow),&context);
701 CGContextFillRect(context, tmpBounds);
703 else
705 HideWindow(theWindow);
706 ChangeWindowAttributes(theWindow, ~windowAttrs, windowAttrs);
707 SetRect(&winRect, 0, 0, d_width, d_height);
708 SetRect(&oldWinRect, 0, 0, d_width, d_height);
709 SizeWindow (theWindow, d_width, d_height, 1);
712 switch (image_format)
714 case IMGFMT_RGB32:
716 CreateCGContextForPort (GetWindowPort (theWindow), &context);
718 dataProviderRef = CGDataProviderCreateWithData (0, image_data, imgRect.right * imgRect.bottom * 4, 0);
720 image = CGImageCreate (imgRect.right,
721 imgRect.bottom,
723 image_depth,
724 ((imgRect.right*32)+7)/8,
725 CGColorSpaceCreateDeviceRGB(),
726 kCGImageAlphaNoneSkipFirst,
727 dataProviderRef, 0, 1, kCGRenderingIntentDefault);
728 break;
731 case IMGFMT_YV12:
732 case IMGFMT_IYUV:
733 case IMGFMT_I420:
734 case IMGFMT_UYVY:
735 case IMGFMT_YUY2:
737 get_image_done = 0;
739 if (!EnterMoviesDone)
741 qterr = EnterMovies();
742 EnterMoviesDone = 1;
744 else
745 qterr = 0;
747 if (qterr)
749 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: EnterMovies (%d)\n", qterr);
750 return -1;
754 SetIdentityMatrix(&matrix);
756 if ((d_width != width) || (d_height != height))
758 ScaleMatrix(&matrix, FixDiv(Long2Fix(d_width),Long2Fix(width)), FixDiv(Long2Fix(d_height),Long2Fix(height)), 0, 0);
761 yuv_qt_stuff.desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
763 yuv_qt_stuff.extension_colr = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension));
764 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->colorParamType = kVideoColorInfoImageDescriptionExtensionType;
765 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->primaries = 2;
766 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->transferFunction = 2;
767 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->matrix = 2;
769 yuv_qt_stuff.extension_fiel = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension));
770 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldCount = 1;
771 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldOrderings = 0;
773 yuv_qt_stuff.extension_clap = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension));
774 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthN = imgRect.right;
775 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthD = 1;
776 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightN = imgRect.bottom;
777 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightD = 1;
778 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffN = 0;
779 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffD = 1;
780 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffN = 0;
781 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffD = 1;
783 yuv_qt_stuff.extension_pasp = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension));
784 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->hSpacing = 1;
785 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->vSpacing = 1;
787 (*yuv_qt_stuff.desc)->idSize = sizeof(ImageDescription);
788 (*yuv_qt_stuff.desc)->cType = image_qtcodec;
789 (*yuv_qt_stuff.desc)->version = 2;
790 (*yuv_qt_stuff.desc)->revisionLevel = 0;
791 (*yuv_qt_stuff.desc)->vendor = 'mpla';
792 (*yuv_qt_stuff.desc)->width = imgRect.right;
793 (*yuv_qt_stuff.desc)->height = imgRect.bottom;
794 (*yuv_qt_stuff.desc)->hRes = Long2Fix(72);
795 (*yuv_qt_stuff.desc)->vRes = Long2Fix(72);
796 (*yuv_qt_stuff.desc)->temporalQuality = 0;
797 (*yuv_qt_stuff.desc)->spatialQuality = codecLosslessQuality;
798 (*yuv_qt_stuff.desc)->frameCount = 1;
799 (*yuv_qt_stuff.desc)->dataSize = 0;
800 (*yuv_qt_stuff.desc)->depth = 24;
801 (*yuv_qt_stuff.desc)->clutID = -1;
803 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_colr, kColorInfoImageDescriptionExtension);
804 if (qterr)
806 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr);
809 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_fiel, kFieldInfoImageDescriptionExtension);
810 if (qterr)
812 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr);
815 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_clap, kCleanApertureImageDescriptionExtension);
816 if (qterr)
818 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr);
821 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_pasp, kCleanApertureImageDescriptionExtension);
822 if (qterr)
824 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr);
826 if (P != NULL) { // second or subsequent movie
827 free(P);
829 P = calloc(sizeof(PlanarPixmapInfoYUV420) + image_size, 1);
830 switch (image_format)
832 case IMGFMT_YV12:
833 case IMGFMT_IYUV:
834 case IMGFMT_I420:
835 P->componentInfoY.offset = be2me_32(sizeof(PlanarPixmapInfoYUV420));
836 P->componentInfoCb.offset = be2me_32(be2me_32(P->componentInfoY.offset) + image_size / 2);
837 P->componentInfoCr.offset = be2me_32(be2me_32(P->componentInfoCb.offset) + image_size / 4);
838 P->componentInfoY.rowBytes = be2me_32(imgRect.right);
839 P->componentInfoCb.rowBytes = be2me_32(imgRect.right / 2);
840 P->componentInfoCr.rowBytes = be2me_32(imgRect.right / 2);
841 image_buffer_size = image_size + sizeof(PlanarPixmapInfoYUV420);
842 break;
843 case IMGFMT_UYVY:
844 case IMGFMT_YUY2:
845 image_buffer_size = image_size;
846 break;
849 qterr = DecompressSequenceBeginS(&seqId,
850 yuv_qt_stuff.desc,
851 (char *)P,
852 image_buffer_size,
853 GetWindowPort(theWindow),
854 NULL,
855 NULL,
856 ((d_width != width) || (d_height != height)) ?
857 &matrix : NULL,
858 srcCopy,
859 NULL,
861 codecLosslessQuality,
862 bestSpeedCodec);
864 if (qterr)
866 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr);
867 return -1;
870 break;
873 //Show window
874 RepositionWindow(theWindow, NULL, kWindowCenterOnMainScreen);
875 ShowWindow (theWindow);
877 if(vo_fs)
878 window_fullscreen();
880 if(vo_ontop)
881 window_ontop();
883 if(vo_rootwin)
885 vo_fs = TRUE;
886 winLevel = 0;
887 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
888 window_fullscreen();
891 window_resized();
893 return 0;
896 static void check_events(void)
898 EventRef theEvent;
899 EventTargetRef theTarget;
900 OSStatus theErr;
902 //Get event
903 theTarget = GetEventDispatcherTarget();
904 theErr = ReceiveNextEvent(0, 0, kEventDurationNoWait,true, &theEvent);
905 if(theErr == noErr && theEvent != NULL)
907 SendEventToEventTarget (theEvent, theTarget);
908 ReleaseEvent(theEvent);
912 static void draw_osd(void)
914 vo_draw_text(imgRect.right,imgRect.bottom,draw_alpha);
917 static void flip_page(void)
919 int curTime;
920 static int lastTime = 0;
922 if(theWindow == NULL)
923 return;
925 switch (image_format)
927 case IMGFMT_RGB32:
929 CGContextDrawImage (context, bounds, image);
931 break;
933 case IMGFMT_YV12:
934 case IMGFMT_IYUV:
935 case IMGFMT_I420:
936 case IMGFMT_UYVY:
937 case IMGFMT_YUY2:
938 if (EnterMoviesDone)
940 OSErr qterr;
941 CodecFlags flags = 0;
942 qterr = DecompressSequenceFrameWhen(seqId,
943 (char *)P,
944 image_buffer_size,
945 0, //codecFlagUseImageBuffer,
946 &flags,
947 NULL,
948 NULL);
949 if (qterr)
951 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr, flags);
954 break;
957 if(!vo_quartz_fs)
959 //render resize box
960 CGContextBeginPath(context);
961 CGContextSetAllowsAntialiasing(context, false);
962 //CGContextSaveGState(context);
964 //line white
965 CGContextSetRGBStrokeColor (context, 0.2, 0.2, 0.2, 0.5);
966 CGContextMoveToPoint( context, winRect.right-1, 1); CGContextAddLineToPoint( context, winRect.right-1, 1);
967 CGContextMoveToPoint( context, winRect.right-1, 5); CGContextAddLineToPoint( context, winRect.right-5, 1);
968 CGContextMoveToPoint( context, winRect.right-1, 9); CGContextAddLineToPoint( context, winRect.right-9, 1);
969 CGContextStrokePath( context );
971 //line gray
972 CGContextSetRGBStrokeColor (context, 0.4, 0.4, 0.4, 0.5);
973 CGContextMoveToPoint( context, winRect.right-1, 2); CGContextAddLineToPoint( context, winRect.right-2, 1);
974 CGContextMoveToPoint( context, winRect.right-1, 6); CGContextAddLineToPoint( context, winRect.right-6, 1);
975 CGContextMoveToPoint( context, winRect.right-1, 10); CGContextAddLineToPoint( context, winRect.right-10, 1);
976 CGContextStrokePath( context );
978 //line black
979 CGContextSetRGBStrokeColor (context, 0.6, 0.6, 0.6, 0.5);
980 CGContextMoveToPoint( context, winRect.right-1, 3); CGContextAddLineToPoint( context, winRect.right-3, 1);
981 CGContextMoveToPoint( context, winRect.right-1, 7); CGContextAddLineToPoint( context, winRect.right-7, 1);
982 CGContextMoveToPoint( context, winRect.right-1, 11); CGContextAddLineToPoint( context, winRect.right-11, 1);
983 CGContextStrokePath( context );
985 //CGContextRestoreGState( context );
986 CGContextFlush (context);
989 //auto hide mouse cursor and futur on-screen control?
990 if(vo_quartz_fs && !mouseHide)
992 int curTime = TickCount()/60;
993 static int lastTime = 0;
995 if( ((curTime - lastTime) >= 5) || (lastTime == 0) )
997 CGDisplayHideCursor(kCGDirectMainDisplay);
998 mouseHide = TRUE;
999 lastTime = curTime;
1003 //update activity every 30 seconds to prevent
1004 //screensaver from starting up.
1005 curTime = TickCount()/60;
1007 if( ((curTime - lastTime) >= 30) || (lastTime == 0) )
1009 UpdateSystemActivity(UsrActivity);
1010 lastTime = curTime;
1014 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
1016 switch (image_format)
1018 case IMGFMT_YV12:
1019 case IMGFMT_I420:
1020 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1021 x=x/2;y=y/2;w=w/2;h=h/2;
1023 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1024 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1025 return 0;
1027 case IMGFMT_IYUV:
1028 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1029 x=x/2;y=y/2;w=w/2;h=h/2;
1031 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1032 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1033 return 0;
1035 return -1;
1038 static int draw_frame(uint8_t *src[])
1040 switch (image_format)
1042 case IMGFMT_RGB32:
1043 fast_memcpy(image_data,src[0],image_size);
1044 return 0;
1046 case IMGFMT_UYVY:
1047 case IMGFMT_YUY2:
1048 memcpy_pic(((char*)P), src[0], imgRect.right * 2, imgRect.bottom, imgRect.right * 2, imgRect.right * 2);
1049 return 0;
1051 return -1;
1054 static int query_format(uint32_t format)
1056 image_format = format;
1057 image_qtcodec = 0;
1059 if (format == IMGFMT_RGB32)
1061 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1064 if ((format == IMGFMT_YV12) || (format == IMGFMT_IYUV) || (format == IMGFMT_I420))
1066 image_qtcodec = kMpegYUV420CodecType; //kYUV420CodecType ?;
1067 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
1070 if (format == IMGFMT_YUY2)
1072 image_qtcodec = kComponentVideoUnsigned;
1073 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1076 if (format == IMGFMT_UYVY)
1078 image_qtcodec = k422YpCbCr8CodecType;
1079 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1082 return 0;
1085 static void uninit(void)
1087 OSErr qterr;
1089 switch (image_format)
1091 case IMGFMT_YV12:
1092 case IMGFMT_IYUV:
1093 case IMGFMT_I420:
1094 case IMGFMT_UYVY:
1095 case IMGFMT_YUY2:
1097 if (EnterMoviesDone)
1099 qterr = CDSequenceEnd(seqId);
1100 if (qterr)
1102 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: CDSequenceEnd (%d)\n", qterr);
1105 break;
1107 default:
1108 break;
1111 ShowMenuBar();
1114 static int preinit(const char *arg)
1116 int parse_err = 0;
1118 if(arg)
1120 char *parse_pos = (char *)&arg[0];
1121 while (parse_pos[0] && !parse_err)
1123 if (strncmp (parse_pos, "device_id=", 10) == 0)
1125 parse_pos = &parse_pos[10];
1126 device_id = strtol(parse_pos, &parse_pos, 0);
1128 if (strncmp (parse_pos, "fs_res=", 7) == 0)
1130 parse_pos = &parse_pos[7];
1131 fs_res_x = strtol(parse_pos, &parse_pos, 0);
1132 parse_pos = &parse_pos[1];
1133 fs_res_y = strtol(parse_pos, &parse_pos, 0);
1135 if (parse_pos[0] == ':') parse_pos = &parse_pos[1];
1136 else if (parse_pos[0]) parse_err = 1;
1140 #if !defined (MACOSX_FINDER_SUPPORT) || !defined (HAVE_SDL)
1141 //this chunk of code is heavily based off SDL_macosx.m from SDL
1142 //it uses an Apple private function to request foreground operation
1144 void CPSEnableForegroundOperation(ProcessSerialNumber* psn);
1145 ProcessSerialNumber myProc, frProc;
1146 Boolean sameProc;
1148 if (GetFrontProcess(&frProc) == noErr)
1150 if (GetCurrentProcess(&myProc) == noErr)
1152 if (SameProcess(&frProc, &myProc, &sameProc) == noErr && !sameProc)
1154 CPSEnableForegroundOperation(&myProc);
1156 SetFrontProcess(&myProc);
1160 #endif
1162 return 0;
1165 static uint32_t draw_yuv_image(mp_image_t *mpi)
1167 // ATM we're only called for planar IMGFMT
1168 // drawing is done directly in P
1169 // and displaying is in flip_page.
1170 return get_image_done ? VO_TRUE : VO_FALSE;
1173 static uint32_t get_yuv_image(mp_image_t *mpi)
1175 if(mpi->type!=MP_IMGTYPE_EXPORT) return VO_FALSE;
1177 if(mpi->imgfmt!=image_format) return VO_FALSE;
1179 if(mpi->flags&MP_IMGFLAG_PLANAR)
1181 if (mpi->num_planes != 3)
1183 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi->num_planes);
1184 return VO_FALSE;
1187 mpi->planes[0]=((char*)P) + be2me_32(P->componentInfoY.offset);
1188 mpi->stride[0]=imgRect.right;
1189 mpi->width=imgRect.right;
1191 if(mpi->flags&MP_IMGFLAG_SWAPPED)
1193 // I420
1194 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1195 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1196 mpi->stride[1]=imgRect.right/2;
1197 mpi->stride[2]=imgRect.right/2;
1199 else
1201 // YV12
1202 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1203 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1204 mpi->stride[1]=imgRect.right/2;
1205 mpi->stride[2]=imgRect.right/2;
1208 mpi->flags|=MP_IMGFLAG_DIRECT;
1209 get_image_done = 1;
1210 return VO_TRUE;
1212 else
1214 // doesn't work yet
1215 if (mpi->num_planes != 1)
1217 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi->num_planes);
1218 return VO_FALSE;
1221 mpi->planes[0] = (char*)P;
1222 mpi->stride[0] = imgRect.right * 2;
1223 mpi->width=imgRect.right;
1224 mpi->flags|=MP_IMGFLAG_DIRECT;
1225 get_image_done = 1;
1226 return VO_TRUE;
1228 return VO_FALSE;
1231 static int control(uint32_t request, void *data)
1233 switch (request)
1235 case VOCTRL_PAUSE: return (int_pause=1);
1236 case VOCTRL_RESUME: return (int_pause=0);
1237 case VOCTRL_FULLSCREEN: vo_fs = (!(vo_fs)); window_fullscreen(); return VO_TRUE;
1238 case VOCTRL_ONTOP: vo_ontop = (!(vo_ontop)); window_ontop(); return VO_TRUE;
1239 case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data));
1240 case VOCTRL_GET_PANSCAN: return VO_TRUE;
1241 case VOCTRL_SET_PANSCAN: window_panscan(); return VO_TRUE;
1243 case VOCTRL_GET_IMAGE:
1244 switch (image_format)
1246 case IMGFMT_YV12:
1247 case IMGFMT_IYUV:
1248 case IMGFMT_I420:
1249 case IMGFMT_UYVY:
1250 case IMGFMT_YUY2:
1251 return get_yuv_image(data);
1252 break;
1253 default:
1254 break;
1256 case VOCTRL_DRAW_IMAGE:
1257 switch (image_format)
1259 case IMGFMT_YV12:
1260 case IMGFMT_IYUV:
1261 case IMGFMT_I420:
1262 case IMGFMT_UYVY:
1263 case IMGFMT_YUY2:
1264 return draw_yuv_image(data);
1265 break;
1266 default:
1267 break;
1270 return VO_NOTIMPL;
1273 void window_resized()
1275 float aspectX;
1276 float aspectY;
1278 int padding = 0;
1280 uint32_t d_width;
1281 uint32_t d_height;
1283 CGRect tmpBounds;
1285 GetPortBounds( GetWindowPort(theWindow), &winRect );
1287 if(vo_keepaspect)
1289 aspect( &d_width, &d_height, A_NOZOOM);
1290 d_height = ((float)d_width/movie_aspect);
1292 aspectX = (float)((float)winRect.right/(float)d_width);
1293 aspectY = (float)((float)(winRect.bottom)/(float)d_height);
1295 if((d_height*aspectX)>(winRect.bottom))
1297 padding = (winRect.right - d_width*aspectY)/2;
1298 SetRect(&dstRect, padding, 0, d_width*aspectY+padding, d_height*aspectY);
1300 else
1302 padding = ((winRect.bottom) - d_height*aspectX)/2;
1303 SetRect(&dstRect, 0, padding, (d_width*aspectX), d_height*aspectX+padding);
1306 else
1308 SetRect(&dstRect, 0, 0, winRect.right, winRect.bottom);
1311 switch (image_format)
1313 case IMGFMT_RGB32:
1315 bounds = CGRectMake(dstRect.left, dstRect.top, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top);
1316 CreateCGContextForPort (GetWindowPort (theWindow), &context);
1317 break;
1319 case IMGFMT_YV12:
1320 case IMGFMT_IYUV:
1321 case IMGFMT_I420:
1322 case IMGFMT_UYVY:
1323 case IMGFMT_YUY2:
1325 long scale_X = FixDiv(Long2Fix(dstRect.right - dstRect.left),Long2Fix(imgRect.right));
1326 long scale_Y = FixDiv(Long2Fix(dstRect.bottom - dstRect.top),Long2Fix(imgRect.bottom));
1328 SetIdentityMatrix(&matrix);
1329 if (((dstRect.right - dstRect.left) != imgRect.right) || ((dstRect.bottom - dstRect.right) != imgRect.bottom))
1331 ScaleMatrix(&matrix, scale_X, scale_Y, 0, 0);
1333 if (padding > 0)
1335 TranslateMatrix(&matrix, Long2Fix(dstRect.left), Long2Fix(dstRect.top));
1339 SetDSequenceMatrix(seqId, &matrix);
1340 break;
1342 default:
1343 break;
1346 //Clear Background
1347 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
1348 CreateCGContextForPort(GetWindowPort(theWindow),&context);
1349 CGContextFillRect(context, tmpBounds);
1352 void window_ontop()
1354 if(!vo_quartz_fs)
1356 //Cycle between level
1357 winLevel++;
1358 if(winLevel>2)
1359 winLevel = 1;
1361 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
1364 void window_fullscreen()
1366 static Ptr restoreState = NULL;
1368 //go fullscreen
1369 if(vo_fs)
1371 if(winLevel != 0)
1373 if(device_id == 0)
1375 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1376 CGDisplayHideCursor(kCGDirectMainDisplay);
1377 mouseHide = TRUE;
1380 if(fs_res_x != 0 || fs_res_y != 0)
1382 BeginFullScreen( &restoreState, deviceHdl, &fs_res_x, &fs_res_y, NULL, NULL, 0);
1384 //Get Main device info///////////////////////////////////////////////////
1385 deviceRect = (*deviceHdl)->gdRect;
1387 device_width = deviceRect.right;
1388 device_height = deviceRect.bottom;
1392 //save old window size
1393 if (!vo_quartz_fs)
1395 GetWindowPortBounds(theWindow, &oldWinRect);
1396 GetWindowBounds(theWindow, kWindowContentRgn, &oldWinBounds);
1399 //go fullscreen
1400 panscan_calc();
1401 ChangeWindowAttributes(theWindow, kWindowNoShadowAttribute, 0);
1402 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1403 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);
1405 vo_quartz_fs = 1;
1407 else //go back to windowed mode
1409 vo_quartz_fs = 0;
1410 if(restoreState != NULL)
1412 EndFullScreen(restoreState, 0);
1414 //Get Main device info///////////////////////////////////////////////////
1415 deviceRect = (*deviceHdl)->gdRect;
1417 device_width = deviceRect.right;
1418 device_height = deviceRect.bottom;
1419 restoreState = NULL;
1421 SetSystemUIMode( kUIModeNormal, 0);
1423 //show mouse cursor
1424 CGDisplayShowCursor(kCGDirectMainDisplay);
1425 mouseHide = FALSE;
1427 //revert window to previous setting
1428 ChangeWindowAttributes(theWindow, 0, kWindowNoShadowAttribute);
1429 SizeWindow(theWindow, oldWinRect.right, oldWinRect.bottom,1);
1430 MoveWindow(theWindow, oldWinBounds.left, oldWinBounds.top, 1);
1432 window_resized();
1435 void window_panscan()
1437 panscan_calc();
1439 if(vo_panscan > 0)
1440 CheckMenuItem (aspectMenu, 2, 1);
1441 else
1442 CheckMenuItem (aspectMenu, 2, 0);
1444 if(vo_quartz_fs)
1446 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1447 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);