Fix mouse right button and middle button incorrect identifications.
[mplayer/greg.git] / libvo / vo_quartz.c
blob94d82522c4618e4ad1459fcc86cdfc5aa2e696d2
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 vo_info_t info =
43 "Mac OSX (Quartz)",
44 "quartz",
45 "Nicolas Plourde <nicolasplourde@hotmail.com>, Romain Dolbeau <romain@dolbeau.org>",
49 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 extern float monitor_aspect;
74 extern float movie_aspect;
75 static float old_movie_aspect;
77 static int winLevel = 1;
78 int levelList[] =
80 kCGDesktopWindowLevelKey,
81 kCGNormalWindowLevelKey,
82 kCGScreenSaverWindowLevelKey
85 static int int_pause = 0;
86 static float winAlpha = 1;
87 static int mouseHide = FALSE;
89 static int device_width;
90 static int device_height;
91 static int device_id;
93 static short fs_res_x=0;
94 static short fs_res_y=0;
96 static WindowRef theWindow = NULL;
97 static WindowGroupRef winGroup = NULL;
98 static CGContextRef context;
99 static CGRect bounds;
100 static GDHandle deviceHdl;
102 static CGDataProviderRef dataProviderRef;
103 static CGImageRef image;
105 static Rect imgRect; // size of the original image (unscaled)
106 static Rect dstRect; // size of the displayed image (after scaling)
107 static Rect winRect; // size of the window containg the displayed image (include padding)
108 static Rect oldWinRect; // size of the window containg the displayed image (include padding) when NOT in FS mode
109 static Rect deviceRect; // size of the display device
110 static Rect oldWinBounds;
112 static MenuRef windMenu;
113 static MenuRef movMenu;
114 static MenuRef aspectMenu;
116 enum
118 kQuitCmd = 1,
119 kHalfScreenCmd = 2,
120 kNormalScreenCmd = 3,
121 kDoubleScreenCmd = 4,
122 kFullScreenCmd = 5,
123 kKeepAspectCmd = 6,
124 kAspectOrgCmd = 7,
125 kAspectFullCmd = 8,
126 kAspectWideCmd = 9,
127 kPanScanCmd = 10
130 #include "osdep/keycodes.h"
132 extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride));
134 //PROTOTYPE/////////////////////////////////////////////////////////////////
135 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
136 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
137 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
138 void window_resized();
139 void window_ontop();
140 void window_fullscreen();
141 void window_panscan();
143 static inline int convert_key(UInt32 key, UInt32 charcode)
145 switch(key)
147 case QZ_IBOOK_ENTER:
148 case QZ_RETURN: return KEY_ENTER;
149 case QZ_ESCAPE: return KEY_ESC;
150 case QZ_BACKSPACE: return KEY_BACKSPACE;
151 case QZ_LALT: return KEY_BACKSPACE;
152 case QZ_LCTRL: return KEY_BACKSPACE;
153 case QZ_LSHIFT: return KEY_BACKSPACE;
154 case QZ_F1: return KEY_F+1;
155 case QZ_F2: return KEY_F+2;
156 case QZ_F3: return KEY_F+3;
157 case QZ_F4: return KEY_F+4;
158 case QZ_F5: return KEY_F+5;
159 case QZ_F6: return KEY_F+6;
160 case QZ_F7: return KEY_F+7;
161 case QZ_F8: return KEY_F+8;
162 case QZ_F9: return KEY_F+9;
163 case QZ_F10: return KEY_F+10;
164 case QZ_F11: return KEY_F+11;
165 case QZ_F12: return KEY_F+12;
166 case QZ_INSERT: return KEY_INSERT;
167 case QZ_DELETE: return KEY_DELETE;
168 case QZ_HOME: return KEY_HOME;
169 case QZ_END: return KEY_END;
170 case QZ_KP_PLUS: return '+';
171 case QZ_KP_MINUS: return '-';
172 case QZ_TAB: return KEY_TAB;
173 case QZ_PAGEUP: return KEY_PAGE_UP;
174 case QZ_PAGEDOWN: return KEY_PAGE_DOWN;
175 case QZ_UP: return KEY_UP;
176 case QZ_DOWN: return KEY_DOWN;
177 case QZ_LEFT: return KEY_LEFT;
178 case QZ_RIGHT: return KEY_RIGHT;
179 case QZ_KP_MULTIPLY: return '*';
180 case QZ_KP_DIVIDE: return '/';
181 case QZ_KP_ENTER: return KEY_KPENTER;
182 case QZ_KP_PERIOD: return KEY_KPDEC;
183 case QZ_KP0: return KEY_KP0;
184 case QZ_KP1: return KEY_KP1;
185 case QZ_KP2: return KEY_KP2;
186 case QZ_KP3: return KEY_KP3;
187 case QZ_KP4: return KEY_KP4;
188 case QZ_KP5: return KEY_KP5;
189 case QZ_KP6: return KEY_KP6;
190 case QZ_KP7: return KEY_KP7;
191 case QZ_KP8: return KEY_KP8;
192 case QZ_KP9: return KEY_KP9;
193 default: return charcode;
197 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
199 switch (image_format)
201 case IMGFMT_RGB32:
202 vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
203 break;
204 case IMGFMT_YV12:
205 case IMGFMT_IYUV:
206 case IMGFMT_I420:
207 vo_draw_alpha_yv12(w,h,src,srca,stride, ((char*)P) + be2me_32(P->componentInfoY.offset) + x0 + y0 * imgRect.right, imgRect.right);
208 break;
209 case IMGFMT_UYVY:
210 vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
211 break;
212 case IMGFMT_YUY2:
213 vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
214 break;
218 //default keyboard event handler
219 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
221 OSStatus result = noErr;
222 UInt32 class = GetEventClass (event);
223 UInt32 kind = GetEventKind (event);
225 result = CallNextEventHandler(nextHandler, event);
227 if(class == kEventClassKeyboard)
229 char macCharCodes;
230 UInt32 macKeyCode;
231 UInt32 macKeyModifiers;
233 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(macCharCodes), NULL, &macCharCodes);
234 GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode);
235 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(macKeyModifiers), NULL, &macKeyModifiers);
237 if(macKeyModifiers != 256)
239 if (kind == kEventRawKeyRepeat || kind == kEventRawKeyDown)
241 int key = convert_key(macKeyCode, macCharCodes);
242 if(key != -1)
243 mplayer_put_key(key);
246 else if(macKeyModifiers == 256)
248 switch(macCharCodes)
250 case '[': SetWindowAlpha(theWindow, winAlpha-=0.05); break;
251 case ']': SetWindowAlpha(theWindow, winAlpha+=0.05); break;
254 else
255 result = eventNotHandledErr;
258 return result;
261 //default mouse event handler
262 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
264 OSStatus result = noErr;
265 UInt32 class = GetEventClass (event);
266 UInt32 kind = GetEventKind (event);
268 result = CallNextEventHandler(nextHandler, event);
270 if(class == kEventClassMouse)
272 WindowPtr tmpWin;
273 Point mousePos;
274 Point winMousePos;
276 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &mousePos);
277 GetEventParameter(event, kEventParamWindowMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &winMousePos);
279 switch (kind)
281 case kEventMouseMoved:
283 if(vo_quartz_fs)
285 CGDisplayShowCursor(kCGDirectMainDisplay);
286 mouseHide = FALSE;
289 break;
291 case kEventMouseWheelMoved:
293 int wheel;
294 short part;
296 GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, sizeof(int), 0, &wheel);
298 part = FindWindow(mousePos,&tmpWin);
300 if(part == inContent)
302 if(wheel > 0)
303 mplayer_put_key(MOUSE_BTN3);
304 else
305 mplayer_put_key(MOUSE_BTN4);
308 break;
310 case kEventMouseDown:
312 EventMouseButton button;
313 short part;
314 Rect bounds;
316 GetWindowPortBounds(theWindow, &bounds);
317 GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0, sizeof(EventMouseButton), 0, &button);
319 part = FindWindow(mousePos,&tmpWin);
321 if( (winMousePos.h > (bounds.right - 15)) && (winMousePos.v > (bounds.bottom)) )
323 if(!vo_quartz_fs)
325 GrowWindow(theWindow, mousePos, NULL);
328 else if(part == inMenuBar)
330 MenuSelect(mousePos);
331 HiliteMenu(0);
333 else if(part == inContent)
335 switch(button)
337 case kEventMouseButtonPrimary:
338 mplayer_put_key(MOUSE_BTN0);
339 break;
340 case kEventMouseButtonSecondary:
341 mplayer_put_key(MOUSE_BTN1);
342 break;
343 case kEventMouseButtonTertiary:
344 mplayer_put_key(MOUSE_BTN2);
345 break;
347 default:result = eventNotHandledErr;break;
351 break;
353 case kEventMouseUp:
354 break;
356 case kEventMouseDragged:
357 break;
359 default:result = eventNotHandledErr;break;
363 return result;
366 //default window event handler
367 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
369 OSStatus result = noErr;
370 uint32_t d_width;
371 uint32_t d_height;
372 UInt32 class = GetEventClass (event);
373 UInt32 kind = GetEventKind (event);
375 result = CallNextEventHandler(nextHandler, event);
377 aspect(&d_width,&d_height,A_NOZOOM);
379 if(class == kEventClassCommand)
381 HICommand theHICommand;
382 GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand );
384 switch ( theHICommand.commandID )
386 case kHICommandQuit:
387 mplayer_put_key(KEY_CLOSE_WIN);
388 break;
390 case kHalfScreenCmd:
391 if(vo_quartz_fs)
393 vo_fs = (!(vo_fs)); window_fullscreen();
396 SizeWindow(theWindow, (d_width/2), ((d_width/movie_aspect)/2), 1);
397 window_resized();
398 break;
400 case kNormalScreenCmd:
401 if(vo_quartz_fs)
403 vo_fs = (!(vo_fs)); window_fullscreen();
406 SizeWindow(theWindow, d_width, (d_width/movie_aspect), 1);
407 window_resized();
408 break;
410 case kDoubleScreenCmd:
411 if(vo_quartz_fs)
413 vo_fs = (!(vo_fs)); window_fullscreen();
416 SizeWindow(theWindow, (d_width*2), ((d_width/movie_aspect)*2), 1);
417 window_resized();
418 break;
420 case kFullScreenCmd:
421 vo_fs = (!(vo_fs)); window_fullscreen();
422 break;
424 case kKeepAspectCmd:
425 vo_keepaspect = (!(vo_keepaspect));
426 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
427 window_resized();
428 break;
430 case kAspectOrgCmd:
431 movie_aspect = old_movie_aspect;
432 if(!vo_quartz_fs)
434 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
436 window_resized();
437 break;
439 case kAspectFullCmd:
440 movie_aspect = 4.0f/3.0f;
441 if(!vo_quartz_fs)
443 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
445 window_resized();
446 break;
448 case kAspectWideCmd:
449 movie_aspect = 16.0f/9.0f;
450 if(!vo_quartz_fs)
452 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
454 window_resized();
455 break;
457 case kPanScanCmd:
458 vo_panscan = (!(vo_panscan));
459 CheckMenuItem (aspectMenu, 2, vo_panscan);
460 window_panscan();
461 window_resized();
462 break;
464 default:
465 result = eventNotHandledErr;
466 break;
469 else if(class == kEventClassWindow)
471 WindowRef window;
472 Rect rectPort = {0,0,0,0};
474 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
476 if(window)
478 GetPortBounds(GetWindowPort(window), &rectPort);
481 switch (kind)
483 case kEventWindowClosed:
484 theWindow = NULL;
485 mplayer_put_key(KEY_CLOSE_WIN);
486 break;
488 //resize window
489 case kEventWindowZoomed:
490 case kEventWindowBoundsChanged:
491 window_resized();
492 flip_page();
493 window_resized();
494 break;
496 default:
497 result = eventNotHandledErr;
498 break;
502 return result;
505 static void quartz_CreateWindow(uint32_t d_width, uint32_t d_height, WindowAttributes windowAttrs)
507 CFStringRef titleKey;
508 CFStringRef windowTitle;
509 OSStatus result;
511 MenuItemIndex index;
512 CFStringRef movMenuTitle;
513 CFStringRef aspMenuTitle;
515 const EventTypeSpec win_events[] = {
516 { kEventClassWindow, kEventWindowClosed },
517 { kEventClassWindow, kEventWindowBoundsChanged },
518 { kEventClassCommand, kEventCommandProcess }
521 const EventTypeSpec key_events[] = {
522 { kEventClassKeyboard, kEventRawKeyDown },
523 { kEventClassKeyboard, kEventRawKeyRepeat }
526 const EventTypeSpec mouse_events[] = {
527 { kEventClassMouse, kEventMouseMoved },
528 { kEventClassMouse, kEventMouseWheelMoved },
529 { kEventClassMouse, kEventMouseDown },
530 { kEventClassMouse, kEventMouseUp },
531 { kEventClassMouse, kEventMouseDragged }
534 SetRect(&winRect, 0, 0, d_width, d_height);
535 SetRect(&oldWinRect, 0, 0, d_width, d_height);
536 SetRect(&dstRect, 0, 0, d_width, d_height);
538 //Clear Menu Bar
539 ClearMenuBar();
541 //Create Window Menu
542 CreateStandardWindowMenu(0, &windMenu);
543 InsertMenu(windMenu, 0);
545 //Create Movie Menu
546 CreateNewMenu (1004, 0, &movMenu);
547 movMenuTitle = CFSTR("Movie");
548 SetMenuTitleWithCFString(movMenu, movMenuTitle);
550 AppendMenuItemTextWithCFString(movMenu, CFSTR("Half Size"), 0, kHalfScreenCmd, &index);
551 SetMenuItemCommandKey(movMenu, index, 0, '0');
553 AppendMenuItemTextWithCFString(movMenu, CFSTR("Normal Size"), 0, kNormalScreenCmd, &index);
554 SetMenuItemCommandKey(movMenu, index, 0, '1');
556 AppendMenuItemTextWithCFString(movMenu, CFSTR("Double Size"), 0, kDoubleScreenCmd, &index);
557 SetMenuItemCommandKey(movMenu, index, 0, '2');
559 AppendMenuItemTextWithCFString(movMenu, CFSTR("Full Size"), 0, kFullScreenCmd, &index);
560 SetMenuItemCommandKey(movMenu, index, 0, 'F');
562 AppendMenuItemTextWithCFString(movMenu, NULL, kMenuItemAttrSeparator, 0, &index);
564 AppendMenuItemTextWithCFString(movMenu, CFSTR("Aspect Ratio"), 0, 0, &index);
566 ////Create Aspect Ratio Sub Menu
567 CreateNewMenu (0, 0, &aspectMenu);
568 aspMenuTitle = CFSTR("Aspect Ratio");
569 SetMenuTitleWithCFString(aspectMenu, aspMenuTitle);
570 SetMenuItemHierarchicalMenu(movMenu, 6, aspectMenu);
572 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Keep"), 0, kKeepAspectCmd, &index);
573 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
574 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Pan-Scan"), 0, kPanScanCmd, &index);
575 CheckMenuItem (aspectMenu, 2, vo_panscan);
576 AppendMenuItemTextWithCFString(aspectMenu, NULL, kMenuItemAttrSeparator, 0, &index);
577 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Original"), 0, kAspectOrgCmd, &index);
578 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("4:3"), 0, kAspectFullCmd, &index);
579 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("16:9"), 0, kAspectWideCmd, &index);
581 InsertMenu(movMenu, GetMenuID(windMenu)); //insert before Window menu
583 DrawMenuBar();
585 //create window
586 CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
588 CreateWindowGroup(0, &winGroup);
589 SetWindowGroup(theWindow, winGroup);
591 //Set window title
592 titleKey = CFSTR("MPlayer - The Movie Player");
593 windowTitle = CFCopyLocalizedString(titleKey, NULL);
594 result = SetWindowTitleWithCFString(theWindow, windowTitle);
595 CFRelease(titleKey);
596 CFRelease(windowTitle);
598 //Install event handler
599 InstallApplicationEventHandler (NewEventHandlerUPP (KeyEventHandler), GetEventTypeCount(key_events), key_events, NULL, NULL);
600 InstallApplicationEventHandler (NewEventHandlerUPP (MouseEventHandler), GetEventTypeCount(mouse_events), mouse_events, NULL, NULL);
601 InstallWindowEventHandler (theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, theWindow, NULL);
604 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)
606 WindowAttributes windowAttrs;
607 OSErr qterr;
608 int i;
609 CGRect tmpBounds;
611 //Get Main device info///////////////////////////////////////////////////
614 deviceHdl = GetMainDevice();
616 for(i=0; i<device_id; i++)
618 deviceHdl = GetNextDevice(deviceHdl);
620 if(deviceHdl == NULL)
622 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Device ID %d do not exist, falling back to main device.\n", device_id);
623 deviceHdl = GetMainDevice();
624 device_id = 0;
625 break;
629 deviceRect = (*deviceHdl)->gdRect;
630 device_width = deviceRect.right-deviceRect.left;
631 device_height = deviceRect.bottom-deviceRect.top;
633 monitor_aspect = (float)device_width/(float)device_height;
635 //misc mplayer setup/////////////////////////////////////////////////////
636 SetRect(&imgRect, 0, 0, width, height);
637 switch (image_format)
639 case IMGFMT_RGB32:
640 image_depth = 32;
641 break;
642 case IMGFMT_YV12:
643 case IMGFMT_IYUV:
644 case IMGFMT_I420:
645 case IMGFMT_UYVY:
646 case IMGFMT_YUY2:
647 image_depth = 16;
648 break;
650 image_size = ((imgRect.right*imgRect.bottom*image_depth)+7)/8;
652 vo_fs = flags & VOFLAG_FULLSCREEN;
654 //get movie aspect
655 panscan_init();
656 aspect_save_orig(width,height);
657 aspect_save_prescale(d_width,d_height);
658 aspect_save_screenres(device_width, device_height);
660 aspect(&d_width,&d_height,A_NOZOOM);
662 movie_aspect = (float)d_width/(float)d_height;
663 old_movie_aspect = movie_aspect;
665 if(image_data)
666 free(image_data);
668 image_data = malloc(image_size);
670 //Create player window//////////////////////////////////////////////////
671 windowAttrs = kWindowStandardDocumentAttributes
672 | kWindowStandardHandlerAttribute
673 | kWindowLiveResizeAttribute;
675 windowAttrs &= (~kWindowResizableAttribute);
677 if (theWindow == NULL)
679 quartz_CreateWindow(d_width, d_height, windowAttrs);
681 if (theWindow == NULL)
683 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Couldn't create window !!!!!\n");
684 return -1;
686 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
687 CreateCGContextForPort(GetWindowPort(theWindow),&context);
688 CGContextFillRect(context, tmpBounds);
690 else
692 HideWindow(theWindow);
693 ChangeWindowAttributes(theWindow, ~windowAttrs, windowAttrs);
694 SetRect(&winRect, 0, 0, d_width, d_height);
695 SetRect(&oldWinRect, 0, 0, d_width, d_height);
696 SizeWindow (theWindow, d_width, d_height, 1);
699 switch (image_format)
701 case IMGFMT_RGB32:
703 CreateCGContextForPort (GetWindowPort (theWindow), &context);
705 dataProviderRef = CGDataProviderCreateWithData (0, image_data, imgRect.right * imgRect.bottom * 4, 0);
707 image = CGImageCreate (imgRect.right,
708 imgRect.bottom,
710 image_depth,
711 ((imgRect.right*32)+7)/8,
712 CGColorSpaceCreateDeviceRGB(),
713 kCGImageAlphaNoneSkipFirst,
714 dataProviderRef, 0, 1, kCGRenderingIntentDefault);
715 break;
718 case IMGFMT_YV12:
719 case IMGFMT_IYUV:
720 case IMGFMT_I420:
721 case IMGFMT_UYVY:
722 case IMGFMT_YUY2:
724 get_image_done = 0;
726 if (!EnterMoviesDone)
728 qterr = EnterMovies();
729 EnterMoviesDone = 1;
731 else
732 qterr = 0;
734 if (qterr)
736 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: EnterMovies (%d)\n", qterr);
737 return -1;
741 SetIdentityMatrix(&matrix);
743 if ((d_width != width) || (d_height != height))
745 ScaleMatrix(&matrix, FixDiv(Long2Fix(d_width),Long2Fix(width)), FixDiv(Long2Fix(d_height),Long2Fix(height)), 0, 0);
748 yuv_qt_stuff.desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
750 yuv_qt_stuff.extension_colr = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension));
751 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->colorParamType = kVideoColorInfoImageDescriptionExtensionType;
752 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->primaries = 2;
753 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->transferFunction = 2;
754 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->matrix = 2;
756 yuv_qt_stuff.extension_fiel = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension));
757 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldCount = 1;
758 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldOrderings = 0;
760 yuv_qt_stuff.extension_clap = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension));
761 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthN = imgRect.right;
762 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthD = 1;
763 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightN = imgRect.bottom;
764 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightD = 1;
765 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffN = 0;
766 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffD = 1;
767 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffN = 0;
768 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffD = 1;
770 yuv_qt_stuff.extension_pasp = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension));
771 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->hSpacing = 1;
772 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->vSpacing = 1;
774 (*yuv_qt_stuff.desc)->idSize = sizeof(ImageDescription);
775 (*yuv_qt_stuff.desc)->cType = image_qtcodec;
776 (*yuv_qt_stuff.desc)->version = 2;
777 (*yuv_qt_stuff.desc)->revisionLevel = 0;
778 (*yuv_qt_stuff.desc)->vendor = 'mpla';
779 (*yuv_qt_stuff.desc)->width = imgRect.right;
780 (*yuv_qt_stuff.desc)->height = imgRect.bottom;
781 (*yuv_qt_stuff.desc)->hRes = Long2Fix(72);
782 (*yuv_qt_stuff.desc)->vRes = Long2Fix(72);
783 (*yuv_qt_stuff.desc)->temporalQuality = 0;
784 (*yuv_qt_stuff.desc)->spatialQuality = codecLosslessQuality;
785 (*yuv_qt_stuff.desc)->frameCount = 1;
786 (*yuv_qt_stuff.desc)->dataSize = 0;
787 (*yuv_qt_stuff.desc)->depth = 24;
788 (*yuv_qt_stuff.desc)->clutID = -1;
790 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_colr, kColorInfoImageDescriptionExtension);
791 if (qterr)
793 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr);
796 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_fiel, kFieldInfoImageDescriptionExtension);
797 if (qterr)
799 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr);
802 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_clap, kCleanApertureImageDescriptionExtension);
803 if (qterr)
805 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr);
808 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_pasp, kCleanApertureImageDescriptionExtension);
809 if (qterr)
811 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr);
813 if (P != NULL) { // second or subsequent movie
814 free(P);
816 P = calloc(sizeof(PlanarPixmapInfoYUV420) + image_size, 1);
817 switch (image_format)
819 case IMGFMT_YV12:
820 case IMGFMT_IYUV:
821 case IMGFMT_I420:
822 P->componentInfoY.offset = be2me_32(sizeof(PlanarPixmapInfoYUV420));
823 P->componentInfoCb.offset = be2me_32(be2me_32(P->componentInfoY.offset) + image_size / 2);
824 P->componentInfoCr.offset = be2me_32(be2me_32(P->componentInfoCb.offset) + image_size / 4);
825 P->componentInfoY.rowBytes = be2me_32(imgRect.right);
826 P->componentInfoCb.rowBytes = be2me_32(imgRect.right / 2);
827 P->componentInfoCr.rowBytes = be2me_32(imgRect.right / 2);
828 image_buffer_size = image_size + sizeof(PlanarPixmapInfoYUV420);
829 break;
830 case IMGFMT_UYVY:
831 case IMGFMT_YUY2:
832 image_buffer_size = image_size;
833 break;
836 qterr = DecompressSequenceBeginS(&seqId,
837 yuv_qt_stuff.desc,
838 (char *)P,
839 image_buffer_size,
840 GetWindowPort(theWindow),
841 NULL,
842 NULL,
843 ((d_width != width) || (d_height != height)) ?
844 &matrix : NULL,
845 srcCopy,
846 NULL,
848 codecLosslessQuality,
849 bestSpeedCodec);
851 if (qterr)
853 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr);
854 return -1;
857 break;
860 //Show window
861 RepositionWindow(theWindow, NULL, kWindowCenterOnMainScreen);
862 ShowWindow (theWindow);
864 if(vo_fs)
865 window_fullscreen();
867 if(vo_ontop)
868 window_ontop();
870 if(vo_rootwin)
872 vo_fs = TRUE;
873 winLevel = 0;
874 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
875 window_fullscreen();
878 window_resized();
880 return 0;
883 static void check_events(void)
885 EventRef theEvent;
886 EventTargetRef theTarget;
887 OSStatus theErr;
889 //Get event
890 theTarget = GetEventDispatcherTarget();
891 theErr = ReceiveNextEvent(0, 0, kEventDurationNoWait,true, &theEvent);
892 if(theErr == noErr && theEvent != NULL)
894 SendEventToEventTarget (theEvent, theTarget);
895 ReleaseEvent(theEvent);
899 static void draw_osd(void)
901 vo_draw_text(imgRect.right,imgRect.bottom,draw_alpha);
904 static void flip_page(void)
906 int curTime;
907 static int lastTime = 0;
909 if(theWindow == NULL)
910 return;
912 switch (image_format)
914 case IMGFMT_RGB32:
916 CGContextDrawImage (context, bounds, image);
918 break;
920 case IMGFMT_YV12:
921 case IMGFMT_IYUV:
922 case IMGFMT_I420:
923 case IMGFMT_UYVY:
924 case IMGFMT_YUY2:
925 if (EnterMoviesDone)
927 OSErr qterr;
928 CodecFlags flags = 0;
929 qterr = DecompressSequenceFrameWhen(seqId,
930 (char *)P,
931 image_buffer_size,
932 0, //codecFlagUseImageBuffer,
933 &flags,
934 NULL,
935 NULL);
936 if (qterr)
938 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr, flags);
941 break;
944 if(!vo_quartz_fs)
946 //render resize box
947 CGContextBeginPath(context);
948 CGContextSetAllowsAntialiasing(context, false);
949 //CGContextSaveGState(context);
951 //line white
952 CGContextSetRGBStrokeColor (context, 0.2, 0.2, 0.2, 0.5);
953 CGContextMoveToPoint( context, winRect.right-1, 1); CGContextAddLineToPoint( context, winRect.right-1, 1);
954 CGContextMoveToPoint( context, winRect.right-1, 5); CGContextAddLineToPoint( context, winRect.right-5, 1);
955 CGContextMoveToPoint( context, winRect.right-1, 9); CGContextAddLineToPoint( context, winRect.right-9, 1);
956 CGContextStrokePath( context );
958 //line gray
959 CGContextSetRGBStrokeColor (context, 0.4, 0.4, 0.4, 0.5);
960 CGContextMoveToPoint( context, winRect.right-1, 2); CGContextAddLineToPoint( context, winRect.right-2, 1);
961 CGContextMoveToPoint( context, winRect.right-1, 6); CGContextAddLineToPoint( context, winRect.right-6, 1);
962 CGContextMoveToPoint( context, winRect.right-1, 10); CGContextAddLineToPoint( context, winRect.right-10, 1);
963 CGContextStrokePath( context );
965 //line black
966 CGContextSetRGBStrokeColor (context, 0.6, 0.6, 0.6, 0.5);
967 CGContextMoveToPoint( context, winRect.right-1, 3); CGContextAddLineToPoint( context, winRect.right-3, 1);
968 CGContextMoveToPoint( context, winRect.right-1, 7); CGContextAddLineToPoint( context, winRect.right-7, 1);
969 CGContextMoveToPoint( context, winRect.right-1, 11); CGContextAddLineToPoint( context, winRect.right-11, 1);
970 CGContextStrokePath( context );
972 //CGContextRestoreGState( context );
973 CGContextFlush (context);
976 //auto hide mouse cursor and futur on-screen control?
977 if(vo_quartz_fs && !mouseHide)
979 int curTime = TickCount()/60;
980 static int lastTime = 0;
982 if( ((curTime - lastTime) >= 5) || (lastTime == 0) )
984 CGDisplayHideCursor(kCGDirectMainDisplay);
985 mouseHide = TRUE;
986 lastTime = curTime;
990 //update activity every 30 seconds to prevent
991 //screensaver from starting up.
992 curTime = TickCount()/60;
994 if( ((curTime - lastTime) >= 30) || (lastTime == 0) )
996 UpdateSystemActivity(UsrActivity);
997 lastTime = curTime;
1001 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
1003 switch (image_format)
1005 case IMGFMT_YV12:
1006 case IMGFMT_I420:
1007 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1008 x=x/2;y=y/2;w=w/2;h=h/2;
1010 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1011 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1012 return 0;
1014 case IMGFMT_IYUV:
1015 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1016 x=x/2;y=y/2;w=w/2;h=h/2;
1018 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1019 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1020 return 0;
1022 return -1;
1025 static int draw_frame(uint8_t *src[])
1027 switch (image_format)
1029 case IMGFMT_RGB32:
1030 fast_memcpy(image_data,src[0],image_size);
1031 return 0;
1033 case IMGFMT_UYVY:
1034 case IMGFMT_YUY2:
1035 memcpy_pic(((char*)P), src[0], imgRect.right * 2, imgRect.bottom, imgRect.right * 2, imgRect.right * 2);
1036 return 0;
1038 return -1;
1041 static int query_format(uint32_t format)
1043 image_format = format;
1044 image_qtcodec = 0;
1046 if (format == IMGFMT_RGB32)
1048 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1051 if ((format == IMGFMT_YV12) || (format == IMGFMT_IYUV) || (format == IMGFMT_I420))
1053 image_qtcodec = kMpegYUV420CodecType; //kYUV420CodecType ?;
1054 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
1057 if (format == IMGFMT_YUY2)
1059 image_qtcodec = kComponentVideoUnsigned;
1060 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1063 if (format == IMGFMT_UYVY)
1065 image_qtcodec = k422YpCbCr8CodecType;
1066 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1069 return 0;
1072 static void uninit(void)
1074 OSErr qterr;
1076 switch (image_format)
1078 case IMGFMT_YV12:
1079 case IMGFMT_IYUV:
1080 case IMGFMT_I420:
1081 case IMGFMT_UYVY:
1082 case IMGFMT_YUY2:
1084 if (EnterMoviesDone)
1086 qterr = CDSequenceEnd(seqId);
1087 if (qterr)
1089 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: CDSequenceEnd (%d)\n", qterr);
1092 break;
1094 default:
1095 break;
1098 ShowMenuBar();
1101 static int preinit(const char *arg)
1103 int parse_err = 0;
1105 if(arg)
1107 char *parse_pos = (char *)&arg[0];
1108 while (parse_pos[0] && !parse_err)
1110 if (strncmp (parse_pos, "device_id=", 10) == 0)
1112 parse_pos = &parse_pos[10];
1113 device_id = strtol(parse_pos, &parse_pos, 0);
1115 if (strncmp (parse_pos, "fs_res=", 7) == 0)
1117 parse_pos = &parse_pos[7];
1118 fs_res_x = strtol(parse_pos, &parse_pos, 0);
1119 parse_pos = &parse_pos[1];
1120 fs_res_y = strtol(parse_pos, &parse_pos, 0);
1122 if (parse_pos[0] == ':') parse_pos = &parse_pos[1];
1123 else if (parse_pos[0]) parse_err = 1;
1127 #if !defined (MACOSX_FINDER_SUPPORT) || !defined (HAVE_SDL)
1128 //this chunk of code is heavily based off SDL_macosx.m from SDL
1129 //it uses an Apple private function to request foreground operation
1131 void CPSEnableForegroundOperation(ProcessSerialNumber* psn);
1132 ProcessSerialNumber myProc, frProc;
1133 Boolean sameProc;
1135 if (GetFrontProcess(&frProc) == noErr)
1137 if (GetCurrentProcess(&myProc) == noErr)
1139 if (SameProcess(&frProc, &myProc, &sameProc) == noErr && !sameProc)
1141 CPSEnableForegroundOperation(&myProc);
1143 SetFrontProcess(&myProc);
1147 #endif
1149 return 0;
1152 static uint32_t draw_yuv_image(mp_image_t *mpi)
1154 // ATM we're only called for planar IMGFMT
1155 // drawing is done directly in P
1156 // and displaying is in flip_page.
1157 return get_image_done ? VO_TRUE : VO_FALSE;
1160 static uint32_t get_yuv_image(mp_image_t *mpi)
1162 if(mpi->type!=MP_IMGTYPE_EXPORT) return VO_FALSE;
1164 if(mpi->imgfmt!=image_format) return VO_FALSE;
1166 if(mpi->flags&MP_IMGFLAG_PLANAR)
1168 if (mpi->num_planes != 3)
1170 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi->num_planes);
1171 return VO_FALSE;
1174 mpi->planes[0]=((char*)P) + be2me_32(P->componentInfoY.offset);
1175 mpi->stride[0]=imgRect.right;
1176 mpi->width=imgRect.right;
1178 if(mpi->flags&MP_IMGFLAG_SWAPPED)
1180 // I420
1181 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1182 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1183 mpi->stride[1]=imgRect.right/2;
1184 mpi->stride[2]=imgRect.right/2;
1186 else
1188 // YV12
1189 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1190 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1191 mpi->stride[1]=imgRect.right/2;
1192 mpi->stride[2]=imgRect.right/2;
1195 mpi->flags|=MP_IMGFLAG_DIRECT;
1196 get_image_done = 1;
1197 return VO_TRUE;
1199 else
1201 // doesn't work yet
1202 if (mpi->num_planes != 1)
1204 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi->num_planes);
1205 return VO_FALSE;
1208 mpi->planes[0] = (char*)P;
1209 mpi->stride[0] = imgRect.right * 2;
1210 mpi->width=imgRect.right;
1211 mpi->flags|=MP_IMGFLAG_DIRECT;
1212 get_image_done = 1;
1213 return VO_TRUE;
1215 return VO_FALSE;
1218 static int control(uint32_t request, void *data, ...)
1220 switch (request)
1222 case VOCTRL_PAUSE: return (int_pause=1);
1223 case VOCTRL_RESUME: return (int_pause=0);
1224 case VOCTRL_FULLSCREEN: vo_fs = (!(vo_fs)); window_fullscreen(); return VO_TRUE;
1225 case VOCTRL_ONTOP: vo_ontop = (!(vo_ontop)); window_ontop(); return VO_TRUE;
1226 case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data));
1227 case VOCTRL_GET_PANSCAN: return VO_TRUE;
1228 case VOCTRL_SET_PANSCAN: window_panscan(); return VO_TRUE;
1230 case VOCTRL_GET_IMAGE:
1231 switch (image_format)
1233 case IMGFMT_YV12:
1234 case IMGFMT_IYUV:
1235 case IMGFMT_I420:
1236 case IMGFMT_UYVY:
1237 case IMGFMT_YUY2:
1238 return get_yuv_image(data);
1239 break;
1240 default:
1241 break;
1243 case VOCTRL_DRAW_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 draw_yuv_image(data);
1252 break;
1253 default:
1254 break;
1257 return VO_NOTIMPL;
1260 void window_resized()
1262 float aspectX;
1263 float aspectY;
1265 int padding = 0;
1267 uint32_t d_width;
1268 uint32_t d_height;
1270 CGRect tmpBounds;
1272 GetPortBounds( GetWindowPort(theWindow), &winRect );
1274 if(vo_keepaspect)
1276 aspect( &d_width, &d_height, A_NOZOOM);
1277 d_height = ((float)d_width/movie_aspect);
1279 aspectX = (float)((float)winRect.right/(float)d_width);
1280 aspectY = (float)((float)(winRect.bottom)/(float)d_height);
1282 if((d_height*aspectX)>(winRect.bottom))
1284 padding = (winRect.right - d_width*aspectY)/2;
1285 SetRect(&dstRect, padding, 0, d_width*aspectY+padding, d_height*aspectY);
1287 else
1289 padding = ((winRect.bottom) - d_height*aspectX)/2;
1290 SetRect(&dstRect, 0, padding, (d_width*aspectX), d_height*aspectX+padding);
1293 else
1295 SetRect(&dstRect, 0, 0, winRect.right, winRect.bottom);
1298 switch (image_format)
1300 case IMGFMT_RGB32:
1302 bounds = CGRectMake(dstRect.left, dstRect.top, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top);
1303 CreateCGContextForPort (GetWindowPort (theWindow), &context);
1304 break;
1306 case IMGFMT_YV12:
1307 case IMGFMT_IYUV:
1308 case IMGFMT_I420:
1309 case IMGFMT_UYVY:
1310 case IMGFMT_YUY2:
1312 long scale_X = FixDiv(Long2Fix(dstRect.right - dstRect.left),Long2Fix(imgRect.right));
1313 long scale_Y = FixDiv(Long2Fix(dstRect.bottom - dstRect.top),Long2Fix(imgRect.bottom));
1315 SetIdentityMatrix(&matrix);
1316 if (((dstRect.right - dstRect.left) != imgRect.right) || ((dstRect.bottom - dstRect.right) != imgRect.bottom))
1318 ScaleMatrix(&matrix, scale_X, scale_Y, 0, 0);
1320 if (padding > 0)
1322 TranslateMatrix(&matrix, Long2Fix(dstRect.left), Long2Fix(dstRect.top));
1326 SetDSequenceMatrix(seqId, &matrix);
1327 break;
1329 default:
1330 break;
1333 //Clear Background
1334 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
1335 CreateCGContextForPort(GetWindowPort(theWindow),&context);
1336 CGContextFillRect(context, tmpBounds);
1339 void window_ontop()
1341 if(!vo_quartz_fs)
1343 //Cycle between level
1344 winLevel++;
1345 if(winLevel>2)
1346 winLevel = 1;
1348 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
1351 void window_fullscreen()
1353 static Ptr restoreState = NULL;
1355 //go fullscreen
1356 if(vo_fs)
1358 if(winLevel != 0)
1360 if(device_id == 0)
1362 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1363 CGDisplayHideCursor(kCGDirectMainDisplay);
1364 mouseHide = TRUE;
1367 if(fs_res_x != 0 || fs_res_y != 0)
1369 BeginFullScreen( &restoreState, deviceHdl, &fs_res_x, &fs_res_y, NULL, NULL, 0);
1371 //Get Main device info///////////////////////////////////////////////////
1372 deviceRect = (*deviceHdl)->gdRect;
1374 device_width = deviceRect.right;
1375 device_height = deviceRect.bottom;
1379 //save old window size
1380 if (!vo_quartz_fs)
1382 GetWindowPortBounds(theWindow, &oldWinRect);
1383 GetWindowBounds(theWindow, kWindowContentRgn, &oldWinBounds);
1386 //go fullscreen
1387 panscan_calc();
1388 ChangeWindowAttributes(theWindow, kWindowNoShadowAttribute, 0);
1389 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1390 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);
1392 vo_quartz_fs = 1;
1394 else //go back to windowed mode
1396 vo_quartz_fs = 0;
1397 if(restoreState != NULL)
1399 EndFullScreen(restoreState, 0);
1401 //Get Main device info///////////////////////////////////////////////////
1402 deviceRect = (*deviceHdl)->gdRect;
1404 device_width = deviceRect.right;
1405 device_height = deviceRect.bottom;
1406 restoreState = NULL;
1408 SetSystemUIMode( kUIModeNormal, 0);
1410 //show mouse cursor
1411 CGDisplayShowCursor(kCGDirectMainDisplay);
1412 mouseHide = FALSE;
1414 //revert window to previous setting
1415 ChangeWindowAttributes(theWindow, 0, kWindowNoShadowAttribute);
1416 SizeWindow(theWindow, oldWinRect.right, oldWinRect.bottom,1);
1417 MoveWindow(theWindow, oldWinBounds.left, oldWinBounds.top, 1);
1419 window_resized();
1422 void window_panscan()
1424 panscan_calc();
1426 if(vo_panscan > 0)
1427 CheckMenuItem (aspectMenu, 2, 1);
1428 else
1429 CheckMenuItem (aspectMenu, 2, 0);
1431 if(vo_quartz_fs)
1433 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1434 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);