vo_xv.c: Make reconfig logic more robust
[mplayer.git] / libvo / vo_quartz.c
blobddaedd8b996f1770476526f5e522ecd4a0eb0490
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 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 //PROTOTYPE/////////////////////////////////////////////////////////////////
133 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
134 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
135 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
136 void window_resized();
137 void window_ontop();
138 void window_fullscreen();
139 void window_panscan();
141 static inline int convert_key(UInt32 key, UInt32 charcode)
143 switch(key)
145 case QZ_IBOOK_ENTER:
146 case QZ_RETURN: return KEY_ENTER;
147 case QZ_ESCAPE: return KEY_ESC;
148 case QZ_BACKSPACE: return KEY_BACKSPACE;
149 case QZ_LALT: return KEY_BACKSPACE;
150 case QZ_LCTRL: return KEY_BACKSPACE;
151 case QZ_LSHIFT: return KEY_BACKSPACE;
152 case QZ_F1: return KEY_F+1;
153 case QZ_F2: return KEY_F+2;
154 case QZ_F3: return KEY_F+3;
155 case QZ_F4: return KEY_F+4;
156 case QZ_F5: return KEY_F+5;
157 case QZ_F6: return KEY_F+6;
158 case QZ_F7: return KEY_F+7;
159 case QZ_F8: return KEY_F+8;
160 case QZ_F9: return KEY_F+9;
161 case QZ_F10: return KEY_F+10;
162 case QZ_F11: return KEY_F+11;
163 case QZ_F12: return KEY_F+12;
164 case QZ_INSERT: return KEY_INSERT;
165 case QZ_DELETE: return KEY_DELETE;
166 case QZ_HOME: return KEY_HOME;
167 case QZ_END: return KEY_END;
168 case QZ_KP_PLUS: return '+';
169 case QZ_KP_MINUS: return '-';
170 case QZ_TAB: return KEY_TAB;
171 case QZ_PAGEUP: return KEY_PAGE_UP;
172 case QZ_PAGEDOWN: return KEY_PAGE_DOWN;
173 case QZ_UP: return KEY_UP;
174 case QZ_DOWN: return KEY_DOWN;
175 case QZ_LEFT: return KEY_LEFT;
176 case QZ_RIGHT: return KEY_RIGHT;
177 case QZ_KP_MULTIPLY: return '*';
178 case QZ_KP_DIVIDE: return '/';
179 case QZ_KP_ENTER: return KEY_KPENTER;
180 case QZ_KP_PERIOD: return KEY_KPDEC;
181 case QZ_KP0: return KEY_KP0;
182 case QZ_KP1: return KEY_KP1;
183 case QZ_KP2: return KEY_KP2;
184 case QZ_KP3: return KEY_KP3;
185 case QZ_KP4: return KEY_KP4;
186 case QZ_KP5: return KEY_KP5;
187 case QZ_KP6: return KEY_KP6;
188 case QZ_KP7: return KEY_KP7;
189 case QZ_KP8: return KEY_KP8;
190 case QZ_KP9: return KEY_KP9;
191 default: return charcode;
195 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
197 switch (image_format)
199 case IMGFMT_RGB32:
200 vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
201 break;
202 case IMGFMT_YV12:
203 case IMGFMT_IYUV:
204 case IMGFMT_I420:
205 vo_draw_alpha_yv12(w,h,src,srca,stride, ((char*)P) + be2me_32(P->componentInfoY.offset) + x0 + y0 * imgRect.right, imgRect.right);
206 break;
207 case IMGFMT_UYVY:
208 vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
209 break;
210 case IMGFMT_YUY2:
211 vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2);
212 break;
216 //default keyboard event handler
217 static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
219 OSStatus result = noErr;
220 UInt32 class = GetEventClass (event);
221 UInt32 kind = GetEventKind (event);
223 result = CallNextEventHandler(nextHandler, event);
225 if(class == kEventClassKeyboard)
227 char macCharCodes;
228 UInt32 macKeyCode;
229 UInt32 macKeyModifiers;
231 GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(macCharCodes), NULL, &macCharCodes);
232 GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode);
233 GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(macKeyModifiers), NULL, &macKeyModifiers);
235 if(macKeyModifiers != 256)
237 if (kind == kEventRawKeyRepeat || kind == kEventRawKeyDown)
239 int key = convert_key(macKeyCode, macCharCodes);
240 if(key != -1)
241 mplayer_put_key(key);
244 else if(macKeyModifiers == 256)
246 switch(macCharCodes)
248 case '[': SetWindowAlpha(theWindow, winAlpha-=0.05); break;
249 case ']': SetWindowAlpha(theWindow, winAlpha+=0.05); break;
252 else
253 result = eventNotHandledErr;
256 return result;
259 //default mouse event handler
260 static OSStatus MouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
262 OSStatus result = noErr;
263 UInt32 class = GetEventClass (event);
264 UInt32 kind = GetEventKind (event);
266 result = CallNextEventHandler(nextHandler, event);
268 if(class == kEventClassMouse)
270 WindowPtr tmpWin;
271 Point mousePos;
272 Point winMousePos;
274 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &mousePos);
275 GetEventParameter(event, kEventParamWindowMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &winMousePos);
277 switch (kind)
279 case kEventMouseMoved:
281 if(vo_quartz_fs)
283 CGDisplayShowCursor(kCGDirectMainDisplay);
284 mouseHide = FALSE;
287 break;
289 case kEventMouseWheelMoved:
291 int wheel;
292 short part;
294 GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, sizeof(int), 0, &wheel);
296 part = FindWindow(mousePos,&tmpWin);
298 if(part == inContent)
300 if(wheel > 0)
301 mplayer_put_key(MOUSE_BTN3);
302 else
303 mplayer_put_key(MOUSE_BTN4);
306 break;
308 case kEventMouseDown:
309 case kEventMouseUp:
311 EventMouseButton button;
312 short part;
313 Rect bounds;
315 GetWindowPortBounds(theWindow, &bounds);
316 GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0, sizeof(EventMouseButton), 0, &button);
318 part = FindWindow(mousePos,&tmpWin);
319 if(kind == kEventMouseUp)
321 if (part != inContent)
322 break;
323 switch(button)
325 case kEventMouseButtonPrimary:
326 mplayer_put_key(MOUSE_BTN0);
327 break;
328 case kEventMouseButtonSecondary:
329 mplayer_put_key(MOUSE_BTN2);
330 break;
331 case kEventMouseButtonTertiary:
332 mplayer_put_key(MOUSE_BTN1);
333 break;
335 default:result = eventNotHandledErr;break;
337 break;
339 if( (winMousePos.h > (bounds.right - 15)) && (winMousePos.v > (bounds.bottom)) )
341 if(!vo_quartz_fs)
343 GrowWindow(theWindow, mousePos, NULL);
346 else if(part == inMenuBar)
348 MenuSelect(mousePos);
349 HiliteMenu(0);
351 else if(part == inContent)
353 switch(button)
355 case kEventMouseButtonPrimary:
356 mplayer_put_key(MOUSE_BTN0 | MP_KEY_DOWN);
357 break;
358 case kEventMouseButtonSecondary:
359 mplayer_put_key(MOUSE_BTN2 | MP_KEY_DOWN);
360 break;
361 case kEventMouseButtonTertiary:
362 mplayer_put_key(MOUSE_BTN1 | MP_KEY_DOWN);
363 break;
365 default:result = eventNotHandledErr;break;
369 break;
371 case kEventMouseDragged:
372 break;
374 default:result = eventNotHandledErr;break;
378 return result;
381 //default window event handler
382 static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
384 OSStatus result = noErr;
385 uint32_t d_width;
386 uint32_t d_height;
387 UInt32 class = GetEventClass (event);
388 UInt32 kind = GetEventKind (event);
390 result = CallNextEventHandler(nextHandler, event);
392 aspect(&d_width,&d_height,A_NOZOOM);
394 if(class == kEventClassCommand)
396 HICommand theHICommand;
397 GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand );
399 switch ( theHICommand.commandID )
401 case kHICommandQuit:
402 mplayer_put_key(KEY_CLOSE_WIN);
403 break;
405 case kHalfScreenCmd:
406 if(vo_quartz_fs)
408 vo_fs = (!(vo_fs)); window_fullscreen();
411 SizeWindow(theWindow, (d_width/2), ((d_width/movie_aspect)/2), 1);
412 window_resized();
413 break;
415 case kNormalScreenCmd:
416 if(vo_quartz_fs)
418 vo_fs = (!(vo_fs)); window_fullscreen();
421 SizeWindow(theWindow, d_width, (d_width/movie_aspect), 1);
422 window_resized();
423 break;
425 case kDoubleScreenCmd:
426 if(vo_quartz_fs)
428 vo_fs = (!(vo_fs)); window_fullscreen();
431 SizeWindow(theWindow, (d_width*2), ((d_width/movie_aspect)*2), 1);
432 window_resized();
433 break;
435 case kFullScreenCmd:
436 vo_fs = (!(vo_fs)); window_fullscreen();
437 break;
439 case kKeepAspectCmd:
440 vo_keepaspect = (!(vo_keepaspect));
441 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
442 window_resized();
443 break;
445 case kAspectOrgCmd:
446 movie_aspect = old_movie_aspect;
447 if(!vo_quartz_fs)
449 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
451 window_resized();
452 break;
454 case kAspectFullCmd:
455 movie_aspect = 4.0f/3.0f;
456 if(!vo_quartz_fs)
458 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
460 window_resized();
461 break;
463 case kAspectWideCmd:
464 movie_aspect = 16.0f/9.0f;
465 if(!vo_quartz_fs)
467 SizeWindow(theWindow, dstRect.right, (dstRect.right/movie_aspect),1);
469 window_resized();
470 break;
472 case kPanScanCmd:
473 vo_panscan = (!(vo_panscan));
474 CheckMenuItem (aspectMenu, 2, vo_panscan);
475 window_panscan();
476 window_resized();
477 break;
479 default:
480 result = eventNotHandledErr;
481 break;
484 else if(class == kEventClassWindow)
486 WindowRef window;
487 Rect rectPort = {0,0,0,0};
489 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
491 if(window)
493 GetPortBounds(GetWindowPort(window), &rectPort);
496 switch (kind)
498 case kEventWindowClosed:
499 theWindow = NULL;
500 mplayer_put_key(KEY_CLOSE_WIN);
501 break;
503 //resize window
504 case kEventWindowZoomed:
505 case kEventWindowBoundsChanged:
506 window_resized();
507 flip_page();
508 window_resized();
509 break;
511 default:
512 result = eventNotHandledErr;
513 break;
517 return result;
520 static void quartz_CreateWindow(uint32_t d_width, uint32_t d_height, WindowAttributes windowAttrs)
522 CFStringRef titleKey;
523 CFStringRef windowTitle;
524 OSStatus result;
526 MenuItemIndex index;
527 CFStringRef movMenuTitle;
528 CFStringRef aspMenuTitle;
530 const EventTypeSpec win_events[] = {
531 { kEventClassWindow, kEventWindowClosed },
532 { kEventClassWindow, kEventWindowBoundsChanged },
533 { kEventClassCommand, kEventCommandProcess }
536 const EventTypeSpec key_events[] = {
537 { kEventClassKeyboard, kEventRawKeyDown },
538 { kEventClassKeyboard, kEventRawKeyRepeat }
541 const EventTypeSpec mouse_events[] = {
542 { kEventClassMouse, kEventMouseMoved },
543 { kEventClassMouse, kEventMouseWheelMoved },
544 { kEventClassMouse, kEventMouseDown },
545 { kEventClassMouse, kEventMouseUp },
546 { kEventClassMouse, kEventMouseDragged }
549 SetRect(&winRect, 0, 0, d_width, d_height);
550 SetRect(&oldWinRect, 0, 0, d_width, d_height);
551 SetRect(&dstRect, 0, 0, d_width, d_height);
553 //Clear Menu Bar
554 ClearMenuBar();
556 //Create Window Menu
557 CreateStandardWindowMenu(0, &windMenu);
558 InsertMenu(windMenu, 0);
560 //Create Movie Menu
561 CreateNewMenu (1004, 0, &movMenu);
562 movMenuTitle = CFSTR("Movie");
563 SetMenuTitleWithCFString(movMenu, movMenuTitle);
565 AppendMenuItemTextWithCFString(movMenu, CFSTR("Half Size"), 0, kHalfScreenCmd, &index);
566 SetMenuItemCommandKey(movMenu, index, 0, '0');
568 AppendMenuItemTextWithCFString(movMenu, CFSTR("Normal Size"), 0, kNormalScreenCmd, &index);
569 SetMenuItemCommandKey(movMenu, index, 0, '1');
571 AppendMenuItemTextWithCFString(movMenu, CFSTR("Double Size"), 0, kDoubleScreenCmd, &index);
572 SetMenuItemCommandKey(movMenu, index, 0, '2');
574 AppendMenuItemTextWithCFString(movMenu, CFSTR("Full Size"), 0, kFullScreenCmd, &index);
575 SetMenuItemCommandKey(movMenu, index, 0, 'F');
577 AppendMenuItemTextWithCFString(movMenu, NULL, kMenuItemAttrSeparator, 0, &index);
579 AppendMenuItemTextWithCFString(movMenu, CFSTR("Aspect Ratio"), 0, 0, &index);
581 ////Create Aspect Ratio Sub Menu
582 CreateNewMenu (0, 0, &aspectMenu);
583 aspMenuTitle = CFSTR("Aspect Ratio");
584 SetMenuTitleWithCFString(aspectMenu, aspMenuTitle);
585 SetMenuItemHierarchicalMenu(movMenu, 6, aspectMenu);
587 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Keep"), 0, kKeepAspectCmd, &index);
588 CheckMenuItem (aspectMenu, 1, vo_keepaspect);
589 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Pan-Scan"), 0, kPanScanCmd, &index);
590 CheckMenuItem (aspectMenu, 2, vo_panscan);
591 AppendMenuItemTextWithCFString(aspectMenu, NULL, kMenuItemAttrSeparator, 0, &index);
592 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("Original"), 0, kAspectOrgCmd, &index);
593 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("4:3"), 0, kAspectFullCmd, &index);
594 AppendMenuItemTextWithCFString(aspectMenu, CFSTR("16:9"), 0, kAspectWideCmd, &index);
596 InsertMenu(movMenu, GetMenuID(windMenu)); //insert before Window menu
598 DrawMenuBar();
600 //create window
601 CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
603 CreateWindowGroup(0, &winGroup);
604 SetWindowGroup(theWindow, winGroup);
606 //Set window title
607 titleKey = CFSTR("MPlayer - The Movie Player");
608 windowTitle = CFCopyLocalizedString(titleKey, NULL);
609 result = SetWindowTitleWithCFString(theWindow, windowTitle);
610 CFRelease(titleKey);
611 CFRelease(windowTitle);
613 //Install event handler
614 InstallApplicationEventHandler (NewEventHandlerUPP (KeyEventHandler), GetEventTypeCount(key_events), key_events, NULL, NULL);
615 InstallApplicationEventHandler (NewEventHandlerUPP (MouseEventHandler), GetEventTypeCount(mouse_events), mouse_events, NULL, NULL);
616 InstallWindowEventHandler (theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, theWindow, NULL);
619 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)
621 WindowAttributes windowAttrs;
622 OSErr qterr;
623 int i;
624 CGRect tmpBounds;
626 //Get Main device info///////////////////////////////////////////////////
629 deviceHdl = GetMainDevice();
631 for(i=0; i<device_id; i++)
633 deviceHdl = GetNextDevice(deviceHdl);
635 if(deviceHdl == NULL)
637 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Device ID %d do not exist, falling back to main device.\n", device_id);
638 deviceHdl = GetMainDevice();
639 device_id = 0;
640 break;
644 deviceRect = (*deviceHdl)->gdRect;
645 device_width = deviceRect.right-deviceRect.left;
646 device_height = deviceRect.bottom-deviceRect.top;
648 monitor_aspect = (float)device_width/(float)device_height;
650 //misc mplayer setup/////////////////////////////////////////////////////
651 SetRect(&imgRect, 0, 0, width, height);
652 switch (image_format)
654 case IMGFMT_RGB32:
655 image_depth = 32;
656 break;
657 case IMGFMT_YV12:
658 case IMGFMT_IYUV:
659 case IMGFMT_I420:
660 case IMGFMT_UYVY:
661 case IMGFMT_YUY2:
662 image_depth = 16;
663 break;
665 image_size = ((imgRect.right*imgRect.bottom*image_depth)+7)/8;
667 vo_fs = flags & VOFLAG_FULLSCREEN;
669 //get movie aspect
670 panscan_init();
671 aspect_save_orig(width,height);
672 aspect_save_prescale(d_width,d_height);
673 aspect_save_screenres(device_width, device_height);
675 aspect(&d_width,&d_height,A_NOZOOM);
677 movie_aspect = (float)d_width/(float)d_height;
678 old_movie_aspect = movie_aspect;
680 if(image_data)
681 free(image_data);
683 image_data = malloc(image_size);
685 //Create player window//////////////////////////////////////////////////
686 windowAttrs = kWindowStandardDocumentAttributes
687 | kWindowStandardHandlerAttribute
688 | kWindowLiveResizeAttribute;
690 windowAttrs &= (~kWindowResizableAttribute);
692 if (theWindow == NULL)
694 quartz_CreateWindow(d_width, d_height, windowAttrs);
696 if (theWindow == NULL)
698 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: Couldn't create window !!!!!\n");
699 return -1;
701 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
702 CreateCGContextForPort(GetWindowPort(theWindow),&context);
703 CGContextFillRect(context, tmpBounds);
705 else
707 HideWindow(theWindow);
708 ChangeWindowAttributes(theWindow, ~windowAttrs, windowAttrs);
709 SetRect(&winRect, 0, 0, d_width, d_height);
710 SetRect(&oldWinRect, 0, 0, d_width, d_height);
711 SizeWindow (theWindow, d_width, d_height, 1);
714 switch (image_format)
716 case IMGFMT_RGB32:
718 CreateCGContextForPort (GetWindowPort (theWindow), &context);
720 dataProviderRef = CGDataProviderCreateWithData (0, image_data, imgRect.right * imgRect.bottom * 4, 0);
722 image = CGImageCreate (imgRect.right,
723 imgRect.bottom,
725 image_depth,
726 ((imgRect.right*32)+7)/8,
727 CGColorSpaceCreateDeviceRGB(),
728 kCGImageAlphaNoneSkipFirst,
729 dataProviderRef, 0, 1, kCGRenderingIntentDefault);
730 break;
733 case IMGFMT_YV12:
734 case IMGFMT_IYUV:
735 case IMGFMT_I420:
736 case IMGFMT_UYVY:
737 case IMGFMT_YUY2:
739 get_image_done = 0;
741 if (!EnterMoviesDone)
743 qterr = EnterMovies();
744 EnterMoviesDone = 1;
746 else
747 qterr = 0;
749 if (qterr)
751 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: EnterMovies (%d)\n", qterr);
752 return -1;
756 SetIdentityMatrix(&matrix);
758 if ((d_width != width) || (d_height != height))
760 ScaleMatrix(&matrix, FixDiv(Long2Fix(d_width),Long2Fix(width)), FixDiv(Long2Fix(d_height),Long2Fix(height)), 0, 0);
763 yuv_qt_stuff.desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
765 yuv_qt_stuff.extension_colr = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension));
766 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->colorParamType = kVideoColorInfoImageDescriptionExtensionType;
767 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->primaries = 2;
768 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->transferFunction = 2;
769 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->matrix = 2;
771 yuv_qt_stuff.extension_fiel = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension));
772 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldCount = 1;
773 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldOrderings = 0;
775 yuv_qt_stuff.extension_clap = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension));
776 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthN = imgRect.right;
777 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthD = 1;
778 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightN = imgRect.bottom;
779 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightD = 1;
780 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffN = 0;
781 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffD = 1;
782 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffN = 0;
783 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffD = 1;
785 yuv_qt_stuff.extension_pasp = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension));
786 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->hSpacing = 1;
787 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->vSpacing = 1;
789 (*yuv_qt_stuff.desc)->idSize = sizeof(ImageDescription);
790 (*yuv_qt_stuff.desc)->cType = image_qtcodec;
791 (*yuv_qt_stuff.desc)->version = 2;
792 (*yuv_qt_stuff.desc)->revisionLevel = 0;
793 (*yuv_qt_stuff.desc)->vendor = 'mpla';
794 (*yuv_qt_stuff.desc)->width = imgRect.right;
795 (*yuv_qt_stuff.desc)->height = imgRect.bottom;
796 (*yuv_qt_stuff.desc)->hRes = Long2Fix(72);
797 (*yuv_qt_stuff.desc)->vRes = Long2Fix(72);
798 (*yuv_qt_stuff.desc)->temporalQuality = 0;
799 (*yuv_qt_stuff.desc)->spatialQuality = codecLosslessQuality;
800 (*yuv_qt_stuff.desc)->frameCount = 1;
801 (*yuv_qt_stuff.desc)->dataSize = 0;
802 (*yuv_qt_stuff.desc)->depth = 24;
803 (*yuv_qt_stuff.desc)->clutID = -1;
805 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_colr, kColorInfoImageDescriptionExtension);
806 if (qterr)
808 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr);
811 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_fiel, kFieldInfoImageDescriptionExtension);
812 if (qterr)
814 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr);
817 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_clap, kCleanApertureImageDescriptionExtension);
818 if (qterr)
820 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr);
823 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_pasp, kCleanApertureImageDescriptionExtension);
824 if (qterr)
826 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr);
828 if (P != NULL) { // second or subsequent movie
829 free(P);
831 P = calloc(sizeof(PlanarPixmapInfoYUV420) + image_size, 1);
832 switch (image_format)
834 case IMGFMT_YV12:
835 case IMGFMT_IYUV:
836 case IMGFMT_I420:
837 P->componentInfoY.offset = be2me_32(sizeof(PlanarPixmapInfoYUV420));
838 P->componentInfoCb.offset = be2me_32(be2me_32(P->componentInfoY.offset) + image_size / 2);
839 P->componentInfoCr.offset = be2me_32(be2me_32(P->componentInfoCb.offset) + image_size / 4);
840 P->componentInfoY.rowBytes = be2me_32(imgRect.right);
841 P->componentInfoCb.rowBytes = be2me_32(imgRect.right / 2);
842 P->componentInfoCr.rowBytes = be2me_32(imgRect.right / 2);
843 image_buffer_size = image_size + sizeof(PlanarPixmapInfoYUV420);
844 break;
845 case IMGFMT_UYVY:
846 case IMGFMT_YUY2:
847 image_buffer_size = image_size;
848 break;
851 qterr = DecompressSequenceBeginS(&seqId,
852 yuv_qt_stuff.desc,
853 (char *)P,
854 image_buffer_size,
855 GetWindowPort(theWindow),
856 NULL,
857 NULL,
858 ((d_width != width) || (d_height != height)) ?
859 &matrix : NULL,
860 srcCopy,
861 NULL,
863 codecLosslessQuality,
864 bestSpeedCodec);
866 if (qterr)
868 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr);
869 return -1;
872 break;
875 //Show window
876 RepositionWindow(theWindow, NULL, kWindowCenterOnMainScreen);
877 ShowWindow (theWindow);
879 if(vo_fs)
880 window_fullscreen();
882 if(vo_ontop)
883 window_ontop();
885 if(vo_rootwin)
887 vo_fs = TRUE;
888 winLevel = 0;
889 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
890 window_fullscreen();
893 window_resized();
895 return 0;
898 static void check_events(void)
900 EventRef theEvent;
901 EventTargetRef theTarget;
902 OSStatus theErr;
904 //Get event
905 theTarget = GetEventDispatcherTarget();
906 theErr = ReceiveNextEvent(0, 0, kEventDurationNoWait,true, &theEvent);
907 if(theErr == noErr && theEvent != NULL)
909 SendEventToEventTarget (theEvent, theTarget);
910 ReleaseEvent(theEvent);
914 static void draw_osd(void)
916 vo_draw_text(imgRect.right,imgRect.bottom,draw_alpha);
919 static void flip_page(void)
921 int curTime;
922 static int lastTime = 0;
924 if(theWindow == NULL)
925 return;
927 switch (image_format)
929 case IMGFMT_RGB32:
931 CGContextDrawImage (context, bounds, image);
933 break;
935 case IMGFMT_YV12:
936 case IMGFMT_IYUV:
937 case IMGFMT_I420:
938 case IMGFMT_UYVY:
939 case IMGFMT_YUY2:
940 if (EnterMoviesDone)
942 OSErr qterr;
943 CodecFlags flags = 0;
944 qterr = DecompressSequenceFrameWhen(seqId,
945 (char *)P,
946 image_buffer_size,
947 0, //codecFlagUseImageBuffer,
948 &flags,
949 NULL,
950 NULL);
951 if (qterr)
953 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr, flags);
956 break;
959 if(!vo_quartz_fs)
961 //render resize box
962 CGContextBeginPath(context);
963 CGContextSetAllowsAntialiasing(context, false);
964 //CGContextSaveGState(context);
966 //line white
967 CGContextSetRGBStrokeColor (context, 0.2, 0.2, 0.2, 0.5);
968 CGContextMoveToPoint( context, winRect.right-1, 1); CGContextAddLineToPoint( context, winRect.right-1, 1);
969 CGContextMoveToPoint( context, winRect.right-1, 5); CGContextAddLineToPoint( context, winRect.right-5, 1);
970 CGContextMoveToPoint( context, winRect.right-1, 9); CGContextAddLineToPoint( context, winRect.right-9, 1);
971 CGContextStrokePath( context );
973 //line gray
974 CGContextSetRGBStrokeColor (context, 0.4, 0.4, 0.4, 0.5);
975 CGContextMoveToPoint( context, winRect.right-1, 2); CGContextAddLineToPoint( context, winRect.right-2, 1);
976 CGContextMoveToPoint( context, winRect.right-1, 6); CGContextAddLineToPoint( context, winRect.right-6, 1);
977 CGContextMoveToPoint( context, winRect.right-1, 10); CGContextAddLineToPoint( context, winRect.right-10, 1);
978 CGContextStrokePath( context );
980 //line black
981 CGContextSetRGBStrokeColor (context, 0.6, 0.6, 0.6, 0.5);
982 CGContextMoveToPoint( context, winRect.right-1, 3); CGContextAddLineToPoint( context, winRect.right-3, 1);
983 CGContextMoveToPoint( context, winRect.right-1, 7); CGContextAddLineToPoint( context, winRect.right-7, 1);
984 CGContextMoveToPoint( context, winRect.right-1, 11); CGContextAddLineToPoint( context, winRect.right-11, 1);
985 CGContextStrokePath( context );
987 //CGContextRestoreGState( context );
988 CGContextFlush (context);
991 //auto hide mouse cursor and futur on-screen control?
992 if(vo_quartz_fs && !mouseHide)
994 int curTime = TickCount()/60;
995 static int lastTime = 0;
997 if( ((curTime - lastTime) >= 5) || (lastTime == 0) )
999 CGDisplayHideCursor(kCGDirectMainDisplay);
1000 mouseHide = TRUE;
1001 lastTime = curTime;
1005 //update activity every 30 seconds to prevent
1006 //screensaver from starting up.
1007 curTime = TickCount()/60;
1009 if( ((curTime - lastTime) >= 30) || (lastTime == 0) )
1011 UpdateSystemActivity(UsrActivity);
1012 lastTime = curTime;
1016 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
1018 switch (image_format)
1020 case IMGFMT_YV12:
1021 case IMGFMT_I420:
1022 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1023 x=x/2;y=y/2;w=w/2;h=h/2;
1025 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1026 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1027 return 0;
1029 case IMGFMT_IYUV:
1030 memcpy_pic(((char*)P) + be2me_32(P->componentInfoY.offset) + x + imgRect.right * y, src[0], w, h, imgRect.right, stride[0]);
1031 x=x/2;y=y/2;w=w/2;h=h/2;
1033 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCr.offset) + x + imgRect.right / 2 * y, src[1], w, h, imgRect.right / 2, stride[1]);
1034 memcpy_pic(((char*)P) + be2me_32(P->componentInfoCb.offset) + x + imgRect.right / 2 * y, src[2], w, h, imgRect.right / 2, stride[2]);
1035 return 0;
1037 return -1;
1040 static int draw_frame(uint8_t *src[])
1042 switch (image_format)
1044 case IMGFMT_RGB32:
1045 fast_memcpy(image_data,src[0],image_size);
1046 return 0;
1048 case IMGFMT_UYVY:
1049 case IMGFMT_YUY2:
1050 memcpy_pic(((char*)P), src[0], imgRect.right * 2, imgRect.bottom, imgRect.right * 2, imgRect.right * 2);
1051 return 0;
1053 return -1;
1056 static int query_format(uint32_t format)
1058 image_format = format;
1059 image_qtcodec = 0;
1061 if (format == IMGFMT_RGB32)
1063 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1066 if ((format == IMGFMT_YV12) || (format == IMGFMT_IYUV) || (format == IMGFMT_I420))
1068 image_qtcodec = kMpegYUV420CodecType; //kYUV420CodecType ?;
1069 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
1072 if (format == IMGFMT_YUY2)
1074 image_qtcodec = kComponentVideoUnsigned;
1075 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1078 if (format == IMGFMT_UYVY)
1080 image_qtcodec = k422YpCbCr8CodecType;
1081 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN;
1084 return 0;
1087 static void uninit(void)
1089 OSErr qterr;
1091 switch (image_format)
1093 case IMGFMT_YV12:
1094 case IMGFMT_IYUV:
1095 case IMGFMT_I420:
1096 case IMGFMT_UYVY:
1097 case IMGFMT_YUY2:
1099 if (EnterMoviesDone)
1101 qterr = CDSequenceEnd(seqId);
1102 if (qterr)
1104 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: CDSequenceEnd (%d)\n", qterr);
1107 break;
1109 default:
1110 break;
1113 ShowMenuBar();
1116 static int preinit(const char *arg)
1118 int parse_err = 0;
1120 if(arg)
1122 char *parse_pos = (char *)&arg[0];
1123 while (parse_pos[0] && !parse_err)
1125 if (strncmp (parse_pos, "device_id=", 10) == 0)
1127 parse_pos = &parse_pos[10];
1128 device_id = strtol(parse_pos, &parse_pos, 0);
1130 if (strncmp (parse_pos, "fs_res=", 7) == 0)
1132 parse_pos = &parse_pos[7];
1133 fs_res_x = strtol(parse_pos, &parse_pos, 0);
1134 parse_pos = &parse_pos[1];
1135 fs_res_y = strtol(parse_pos, &parse_pos, 0);
1137 if (parse_pos[0] == ':') parse_pos = &parse_pos[1];
1138 else if (parse_pos[0]) parse_err = 1;
1142 #if !defined (MACOSX_FINDER_SUPPORT) || !defined (HAVE_SDL)
1143 //this chunk of code is heavily based off SDL_macosx.m from SDL
1144 //it uses an Apple private function to request foreground operation
1146 void CPSEnableForegroundOperation(ProcessSerialNumber* psn);
1147 ProcessSerialNumber myProc, frProc;
1148 Boolean sameProc;
1150 if (GetFrontProcess(&frProc) == noErr)
1152 if (GetCurrentProcess(&myProc) == noErr)
1154 if (SameProcess(&frProc, &myProc, &sameProc) == noErr && !sameProc)
1156 CPSEnableForegroundOperation(&myProc);
1158 SetFrontProcess(&myProc);
1162 #endif
1164 return 0;
1167 static uint32_t draw_yuv_image(mp_image_t *mpi)
1169 // ATM we're only called for planar IMGFMT
1170 // drawing is done directly in P
1171 // and displaying is in flip_page.
1172 return get_image_done ? VO_TRUE : VO_FALSE;
1175 static uint32_t get_yuv_image(mp_image_t *mpi)
1177 if(mpi->type!=MP_IMGTYPE_EXPORT) return VO_FALSE;
1179 if(mpi->imgfmt!=image_format) return VO_FALSE;
1181 if(mpi->flags&MP_IMGFLAG_PLANAR)
1183 if (mpi->num_planes != 3)
1185 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi->num_planes);
1186 return VO_FALSE;
1189 mpi->planes[0]=((char*)P) + be2me_32(P->componentInfoY.offset);
1190 mpi->stride[0]=imgRect.right;
1191 mpi->width=imgRect.right;
1193 if(mpi->flags&MP_IMGFLAG_SWAPPED)
1195 // I420
1196 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1197 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1198 mpi->stride[1]=imgRect.right/2;
1199 mpi->stride[2]=imgRect.right/2;
1201 else
1203 // YV12
1204 mpi->planes[1]=((char*)P) + be2me_32(P->componentInfoCr.offset);
1205 mpi->planes[2]=((char*)P) + be2me_32(P->componentInfoCb.offset);
1206 mpi->stride[1]=imgRect.right/2;
1207 mpi->stride[2]=imgRect.right/2;
1210 mpi->flags|=MP_IMGFLAG_DIRECT;
1211 get_image_done = 1;
1212 return VO_TRUE;
1214 else
1216 // doesn't work yet
1217 if (mpi->num_planes != 1)
1219 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi->num_planes);
1220 return VO_FALSE;
1223 mpi->planes[0] = (char*)P;
1224 mpi->stride[0] = imgRect.right * 2;
1225 mpi->width=imgRect.right;
1226 mpi->flags|=MP_IMGFLAG_DIRECT;
1227 get_image_done = 1;
1228 return VO_TRUE;
1230 return VO_FALSE;
1233 static int control(uint32_t request, void *data)
1235 switch (request)
1237 case VOCTRL_PAUSE: return (int_pause=1);
1238 case VOCTRL_RESUME: return (int_pause=0);
1239 case VOCTRL_FULLSCREEN: vo_fs = (!(vo_fs)); window_fullscreen(); return VO_TRUE;
1240 case VOCTRL_ONTOP: vo_ontop = (!(vo_ontop)); window_ontop(); return VO_TRUE;
1241 case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data));
1242 case VOCTRL_GET_PANSCAN: return VO_TRUE;
1243 case VOCTRL_SET_PANSCAN: window_panscan(); return VO_TRUE;
1245 case VOCTRL_GET_IMAGE:
1246 switch (image_format)
1248 case IMGFMT_YV12:
1249 case IMGFMT_IYUV:
1250 case IMGFMT_I420:
1251 case IMGFMT_UYVY:
1252 case IMGFMT_YUY2:
1253 return get_yuv_image(data);
1254 break;
1255 default:
1256 break;
1258 case VOCTRL_DRAW_IMAGE:
1259 switch (image_format)
1261 case IMGFMT_YV12:
1262 case IMGFMT_IYUV:
1263 case IMGFMT_I420:
1264 case IMGFMT_UYVY:
1265 case IMGFMT_YUY2:
1266 return draw_yuv_image(data);
1267 break;
1268 default:
1269 break;
1272 return VO_NOTIMPL;
1275 void window_resized()
1277 float aspectX;
1278 float aspectY;
1280 int padding = 0;
1282 uint32_t d_width;
1283 uint32_t d_height;
1285 CGRect tmpBounds;
1287 GetPortBounds( GetWindowPort(theWindow), &winRect );
1289 if(vo_keepaspect)
1291 aspect( &d_width, &d_height, A_NOZOOM);
1292 d_height = ((float)d_width/movie_aspect);
1294 aspectX = (float)((float)winRect.right/(float)d_width);
1295 aspectY = (float)((float)(winRect.bottom)/(float)d_height);
1297 if((d_height*aspectX)>(winRect.bottom))
1299 padding = (winRect.right - d_width*aspectY)/2;
1300 SetRect(&dstRect, padding, 0, d_width*aspectY+padding, d_height*aspectY);
1302 else
1304 padding = ((winRect.bottom) - d_height*aspectX)/2;
1305 SetRect(&dstRect, 0, padding, (d_width*aspectX), d_height*aspectX+padding);
1308 else
1310 SetRect(&dstRect, 0, 0, winRect.right, winRect.bottom);
1313 switch (image_format)
1315 case IMGFMT_RGB32:
1317 bounds = CGRectMake(dstRect.left, dstRect.top, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top);
1318 CreateCGContextForPort (GetWindowPort (theWindow), &context);
1319 break;
1321 case IMGFMT_YV12:
1322 case IMGFMT_IYUV:
1323 case IMGFMT_I420:
1324 case IMGFMT_UYVY:
1325 case IMGFMT_YUY2:
1327 long scale_X = FixDiv(Long2Fix(dstRect.right - dstRect.left),Long2Fix(imgRect.right));
1328 long scale_Y = FixDiv(Long2Fix(dstRect.bottom - dstRect.top),Long2Fix(imgRect.bottom));
1330 SetIdentityMatrix(&matrix);
1331 if (((dstRect.right - dstRect.left) != imgRect.right) || ((dstRect.bottom - dstRect.right) != imgRect.bottom))
1333 ScaleMatrix(&matrix, scale_X, scale_Y, 0, 0);
1335 if (padding > 0)
1337 TranslateMatrix(&matrix, Long2Fix(dstRect.left), Long2Fix(dstRect.top));
1341 SetDSequenceMatrix(seqId, &matrix);
1342 break;
1344 default:
1345 break;
1348 //Clear Background
1349 tmpBounds = CGRectMake( 0, 0, winRect.right, winRect.bottom);
1350 CreateCGContextForPort(GetWindowPort(theWindow),&context);
1351 CGContextFillRect(context, tmpBounds);
1354 void window_ontop()
1356 if(!vo_quartz_fs)
1358 //Cycle between level
1359 winLevel++;
1360 if(winLevel>2)
1361 winLevel = 1;
1363 SetWindowGroupLevel(winGroup, CGWindowLevelForKey(levelList[winLevel]));
1366 void window_fullscreen()
1368 static Ptr restoreState = NULL;
1370 //go fullscreen
1371 if(vo_fs)
1373 if(winLevel != 0)
1375 if(device_id == 0)
1377 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
1378 CGDisplayHideCursor(kCGDirectMainDisplay);
1379 mouseHide = TRUE;
1382 if(fs_res_x != 0 || fs_res_y != 0)
1384 BeginFullScreen( &restoreState, deviceHdl, &fs_res_x, &fs_res_y, NULL, NULL, 0);
1386 //Get Main device info///////////////////////////////////////////////////
1387 deviceRect = (*deviceHdl)->gdRect;
1389 device_width = deviceRect.right;
1390 device_height = deviceRect.bottom;
1394 //save old window size
1395 if (!vo_quartz_fs)
1397 GetWindowPortBounds(theWindow, &oldWinRect);
1398 GetWindowBounds(theWindow, kWindowContentRgn, &oldWinBounds);
1401 //go fullscreen
1402 panscan_calc();
1403 ChangeWindowAttributes(theWindow, kWindowNoShadowAttribute, 0);
1404 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1405 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);
1407 vo_quartz_fs = 1;
1409 else //go back to windowed mode
1411 vo_quartz_fs = 0;
1412 if(restoreState != NULL)
1414 EndFullScreen(restoreState, 0);
1416 //Get Main device info///////////////////////////////////////////////////
1417 deviceRect = (*deviceHdl)->gdRect;
1419 device_width = deviceRect.right;
1420 device_height = deviceRect.bottom;
1421 restoreState = NULL;
1423 SetSystemUIMode( kUIModeNormal, 0);
1425 //show mouse cursor
1426 CGDisplayShowCursor(kCGDirectMainDisplay);
1427 mouseHide = FALSE;
1429 //revert window to previous setting
1430 ChangeWindowAttributes(theWindow, 0, kWindowNoShadowAttribute);
1431 SizeWindow(theWindow, oldWinRect.right, oldWinRect.bottom,1);
1432 MoveWindow(theWindow, oldWinBounds.left, oldWinBounds.top, 1);
1434 window_resized();
1437 void window_panscan()
1439 panscan_calc();
1441 if(vo_panscan > 0)
1442 CheckMenuItem (aspectMenu, 2, 1);
1443 else
1444 CheckMenuItem (aspectMenu, 2, 0);
1446 if(vo_quartz_fs)
1448 MoveWindow(theWindow, deviceRect.left-(vo_panscan_x >> 1), deviceRect.top-(vo_panscan_y >> 1), 1);
1449 SizeWindow(theWindow, device_width+vo_panscan_x, device_height+vo_panscan_y,1);