12296
|
1 /*
|
|
2 vo_quartz.c
|
|
3
|
|
4 by Nicolas Plourde <nicolasplourde@hotmail.com>
|
|
5
|
|
6 Copyright (c) Nicolas Plourde - April 2004
|
12414
|
7
|
|
8 YUV support Copyright (C) 2004 Romain Dolbeau <romain@dolbeau.org>
|
12296
|
9
|
|
10 MPlayer Mac OSX Quartz video out module.
|
|
11
|
12414
|
12 todo: -Redo event handling.
|
12296
|
13 -Choose fullscreen display device.
|
|
14 -Fullscreen antialiasing.
|
|
15 -resize black bar without CGContext
|
|
16 -rootwin
|
|
17 -non-blocking event
|
|
18 -(add sugestion here)
|
12414
|
19
|
|
20 Direct YUV support is functional, and is now enabled
|
|
21 by default. To constrain what format should be used,
|
|
22 use the format=XXX video filter (i.e. -vf format=uyvy).
|
12120
|
23 */
|
|
24
|
|
25 //SYS
|
|
26 #include <stdio.h>
|
|
27
|
|
28 //OSX
|
|
29 #include <Carbon/Carbon.h>
|
12414
|
30 #include <QuickTime/QuickTime.h>
|
12120
|
31
|
|
32 //MPLAYER
|
|
33 #include "config.h"
|
12414
|
34 #include "fastmemcpy.h"
|
12120
|
35 #include "video_out.h"
|
|
36 #include "video_out_internal.h"
|
|
37 #include "aspect.h"
|
12414
|
38 #include "mp_msg.h"
|
|
39 #include "m_option.h"
|
12120
|
40
|
|
41 #include "../input/input.h"
|
|
42 #include "../input/mouse.h"
|
|
43
|
|
44 #include "vo_quartz.h"
|
|
45
|
12414
|
46 #define QUARTZ_ENABLE_YUV
|
|
47
|
12296
|
48 static vo_info_t info =
|
|
49 {
|
|
50 "Mac OSX (Quartz)",
|
|
51 "quartz",
|
12414
|
52 "Nicolas Plourde <nicolasplourde@hotmail.com>, Romain Dolbeau <romain@dolbeau.org>",
|
12296
|
53 ""
|
12120
|
54 };
|
|
55
|
12296
|
56 LIBVO_EXTERN(quartz)
|
12120
|
57
|
12414
|
58 static uint32_t image_width;
|
|
59 static uint32_t image_height;
|
|
60 static uint32_t image_depth;
|
|
61 static uint32_t image_format;
|
|
62 static uint32_t image_size;
|
|
63 static uint32_t image_buffer_size;
|
|
64
|
|
65 #ifdef QUARTZ_ENABLE_YUV
|
|
66 static CodecType image_qtcodec;
|
|
67 static PlanarPixmapInfoYUV420 *P;
|
|
68 static struct {
|
|
69 ImageSequence seqId;
|
|
70 ImageDescriptionHandle desc;
|
|
71 Handle extension_colr;
|
|
72 Handle extension_fiel;
|
|
73 Handle extension_clap;
|
|
74 Handle extension_pasp;
|
|
75 MatrixRecord matrix;
|
|
76 } yuv_qt_stuff;
|
|
77 static DecompressorComponent mycodec;
|
|
78 static ComponentInstance myopenedcodec;
|
|
79 static int EnterMoviesDone = 0;
|
|
80 #endif
|
12296
|
81 char *image_data;
|
12120
|
82
|
12296
|
83 extern int vo_ontop;
|
|
84 extern int vo_fs;
|
12120
|
85
|
12296
|
86 int int_pause = 0;
|
|
87 float winAlpha = 1;
|
|
88
|
|
89 int device_width, device_height;
|
12120
|
90
|
|
91 WindowRef theWindow;
|
12296
|
92
|
|
93 GWorldPtr imgGWorld;
|
|
94
|
|
95 Rect imgRect;
|
|
96 Rect dstRect;
|
|
97 Rect winRect;
|
|
98
|
12120
|
99 CGContextRef context;
|
|
100
|
|
101 #include "../osdep/keycodes.h"
|
12296
|
102 extern void mplayer_put_key(int code);
|
|
103
|
|
104 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));
|
12120
|
105
|
|
106 //PROTOTYPE/////////////////////////////////////////////////////////////////
|
12296
|
107 void window_resized();
|
|
108 void window_ontop();
|
|
109 void window_fullscreen();
|
12120
|
110
|
12296
|
111 static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
|
|
112 static OSStatus MainKeyboardEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
|
|
113 static OSStatus MainMouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
|
|
114
|
|
115 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
|
|
116 {
|
12414
|
117 switch (image_format) {
|
|
118 case IMGFMT_RGB32:
|
|
119 vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right);
|
|
120 break;
|
|
121 #ifdef QUARTZ_ENABLE_YUV
|
|
122 case IMGFMT_YV12:
|
|
123 case IMGFMT_IYUV:
|
|
124 case IMGFMT_I420:
|
|
125 vo_draw_alpha_yv12(w,h,src,srca,stride,
|
|
126 ((char*)P) + P->componentInfoY.offset + x0 + y0 * image_width,
|
|
127 image_width);
|
|
128 break;
|
|
129 case IMGFMT_UYVY:
|
|
130 //vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * image_width) * 2,image_width*2);
|
|
131 break;
|
|
132 case IMGFMT_YUY2:
|
|
133 vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * image_width) * 2,image_width*2);
|
|
134 break;
|
|
135 #endif
|
|
136 }
|
12296
|
137 }
|
12120
|
138
|
|
139 //default window event handler
|
12296
|
140 static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
|
12120
|
141 {
|
12296
|
142 OSStatus err = noErr;
|
|
143 WindowRef window;
|
|
144 Rect rectPort = {0,0,0,0};
|
|
145 OSStatus result = eventNotHandledErr;
|
|
146 UInt32 class = GetEventClass (event);
|
|
147 UInt32 kind = GetEventKind (event);
|
12120
|
148
|
12296
|
149 GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
|
|
150 if(window)
|
|
151 {
|
|
152 GetWindowPortBounds (window, &rectPort);
|
|
153 }
|
|
154
|
|
155 switch (kind)
|
|
156 {
|
|
157 //close window
|
|
158 case kEventWindowClosed:
|
|
159 HideWindow(window);
|
|
160 mplayer_put_key(KEY_ESC);
|
|
161 break;
|
|
162
|
|
163 //resize window
|
|
164 case kEventWindowBoundsChanged:
|
|
165 window_resized();
|
|
166 flip_page();
|
|
167 break;
|
|
168
|
|
169 default:
|
|
170 err = eventNotHandledErr;
|
|
171 break;
|
12120
|
172 }
|
12296
|
173
|
|
174 return err;
|
12120
|
175 }
|
|
176
|
|
177 //keyboard event handler
|
12296
|
178 static OSStatus MainKeyboardEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
|
12120
|
179 {
|
12296
|
180 OSStatus err = noErr;
|
|
181 UInt32 macKeyCode;
|
|
182
|
|
183 GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(macKeyCode), NULL, &macKeyCode);
|
|
184
|
|
185 switch (GetEventKind (event))
|
|
186 {
|
|
187 case kEventRawKeyDown:
|
|
188 {
|
|
189 switch(macKeyCode)
|
|
190 {
|
|
191 case QZ_RETURN: mplayer_put_key(KEY_ENTER);break;
|
|
192 case QZ_ESCAPE: mplayer_put_key(KEY_ESC);break;
|
|
193 case QZ_q: mplayer_put_key('q');break;
|
|
194 case QZ_F1: mplayer_put_key(KEY_F+1);break;
|
|
195 case QZ_F2: mplayer_put_key(KEY_F+2);break;
|
|
196 case QZ_F3: mplayer_put_key(KEY_F+3);break;
|
|
197 case QZ_F4: mplayer_put_key(KEY_F+4);break;
|
|
198 case QZ_F5: mplayer_put_key(KEY_F+5);break;
|
|
199 case QZ_F6: mplayer_put_key(KEY_F+6);break;
|
|
200 case QZ_F7: mplayer_put_key(KEY_F+7);break;
|
|
201 case QZ_F8: mplayer_put_key(KEY_F+8);break;
|
|
202 case QZ_F9: mplayer_put_key(KEY_F+9);break;
|
|
203 case QZ_F10: mplayer_put_key(KEY_F+10);break;
|
|
204 case QZ_F11: mplayer_put_key(KEY_F+11);break;
|
|
205 case QZ_F12: mplayer_put_key(KEY_F+12);break;
|
|
206 case QZ_o: mplayer_put_key('o');break;
|
|
207 case QZ_SPACE: mplayer_put_key(' ');break;
|
|
208 case QZ_p: mplayer_put_key('p');break;
|
|
209 //case QZ_7: mplayer_put_key(shift_key?'/':'7');
|
|
210 //case QZ_PLUS: mplayer_put_key(shift_key?'*':'+');
|
|
211 case QZ_KP_PLUS: mplayer_put_key('+');break;
|
|
212 case QZ_MINUS:
|
|
213 case QZ_KP_MINUS: mplayer_put_key('-');break;
|
|
214 case QZ_TAB: mplayer_put_key('\t');break;
|
|
215 case QZ_PAGEUP: mplayer_put_key(KEY_PAGE_UP);break;
|
|
216 case QZ_PAGEDOWN: mplayer_put_key(KEY_PAGE_DOWN);break;
|
|
217 case QZ_UP: mplayer_put_key(KEY_UP);break;
|
|
218 case QZ_DOWN: mplayer_put_key(KEY_DOWN);break;
|
|
219 case QZ_LEFT: mplayer_put_key(KEY_LEFT);break;
|
|
220 case QZ_RIGHT: mplayer_put_key(KEY_RIGHT);break;
|
|
221 //case QZ_LESS: mplayer_put_key(shift_key?'>':'<'); break;
|
|
222 //case QZ_GREATER: mplayer_put_key('>'); break;
|
|
223 //case QZ_ASTERISK:
|
|
224 case QZ_KP_MULTIPLY: mplayer_put_key('*'); break;
|
|
225 case QZ_SLASH:
|
|
226 case QZ_KP_DIVIDE: mplayer_put_key('/'); break;
|
|
227 case QZ_KP0: mplayer_put_key(KEY_KP0); break;
|
|
228 case QZ_KP1: mplayer_put_key(KEY_KP1); break;
|
|
229 case QZ_KP2: mplayer_put_key(KEY_KP2); break;
|
|
230 case QZ_KP3: mplayer_put_key(KEY_KP3); break;
|
|
231 case QZ_KP4: mplayer_put_key(KEY_KP4); break;
|
|
232 case QZ_KP5: mplayer_put_key(KEY_KP5); break;
|
|
233 case QZ_KP6: mplayer_put_key(KEY_KP6); break;
|
|
234 case QZ_KP7: mplayer_put_key(KEY_KP7); break;
|
|
235 case QZ_KP8: mplayer_put_key(KEY_KP8); break;
|
|
236 case QZ_KP9: mplayer_put_key(KEY_KP9); break;
|
|
237 case QZ_KP_PERIOD: mplayer_put_key(KEY_KPDEC); break;
|
|
238 case QZ_KP_ENTER: mplayer_put_key(KEY_KPENTER); break;
|
|
239 case QZ_LEFTBRACKET: SetWindowAlpha(theWindow, winAlpha-=0.05);break;
|
|
240 case QZ_RIGHTBRACKET: SetWindowAlpha(theWindow, winAlpha+=0.05);break;
|
|
241 case QZ_f: mplayer_put_key('f'); break;
|
|
242 case QZ_t: mplayer_put_key('T'); break;
|
|
243 default:
|
|
244 break;
|
|
245 }
|
|
246 }
|
|
247 break;
|
|
248 default:
|
|
249 err = eventNotHandledErr;
|
|
250 break;
|
|
251 }
|
|
252
|
|
253 return err;
|
|
254 }
|
12120
|
255
|
12296
|
256 //Mouse event handler
|
|
257 static OSStatus MainMouseEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
|
|
258 {
|
|
259 OSStatus err = noErr;
|
|
260 WindowPtr tmpWin;
|
|
261 Point mousePos;
|
|
262
|
|
263 GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(Point), 0, &mousePos);
|
12120
|
264
|
12296
|
265 switch (GetEventKind (event))
|
12120
|
266 {
|
12296
|
267 case kEventMouseDown:
|
|
268 {
|
|
269 short part = FindWindow(mousePos,&tmpWin);
|
|
270
|
|
271 if(part == inMenuBar)
|
|
272 {
|
|
273 MenuSelect(mousePos);
|
|
274 }
|
|
275 }
|
|
276 break;
|
|
277 default:
|
|
278 err = eventNotHandledErr;
|
|
279 break;
|
12120
|
280 }
|
12296
|
281
|
|
282 HiliteMenu(0);
|
|
283 return err;
|
|
284 }
|
12120
|
285
|
12296
|
286 static uint32_t config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format)
|
|
287 {
|
|
288 WindowAttributes windowAttrs;
|
|
289 CFStringRef titleKey;
|
|
290 CFStringRef windowTitle;
|
|
291 OSStatus result;
|
|
292 GDHandle deviceHdl;
|
|
293 Rect deviceRect;
|
12414
|
294 OSErr qterr;
|
12296
|
295
|
|
296 //Get Main device info///////////////////////////////////////////////////
|
|
297 deviceHdl = GetMainDevice();
|
|
298 deviceRect = (*deviceHdl)->gdRect;
|
|
299
|
|
300 device_width = deviceRect.right;
|
|
301 device_height = deviceRect.bottom;
|
|
302
|
|
303 //misc mplayer setup/////////////////////////////////////////////////////
|
|
304 image_width = width;
|
|
305 image_height = height;
|
12414
|
306 switch (image_format)
|
|
307 {
|
|
308 case IMGFMT_RGB32:
|
|
309 image_depth = IMGFMT_RGB_DEPTH(format);
|
|
310 break;
|
|
311 #ifdef QUARTZ_ENABLE_YUV
|
|
312 case IMGFMT_YV12:
|
|
313 case IMGFMT_IYUV:
|
|
314 case IMGFMT_I420:
|
|
315 case IMGFMT_UYVY:
|
|
316 case IMGFMT_YUY2:
|
|
317 image_depth = 16;
|
|
318 break;
|
|
319 #endif
|
|
320 }
|
|
321 image_size = ((image_width*image_height*image_depth)+7)/8;
|
12296
|
322
|
|
323 vo_fs = flags & VOFLAG_FULLSCREEN;
|
|
324
|
|
325 //get movie aspect
|
|
326 aspect_save_orig(width,height);
|
|
327 aspect_save_prescale(d_width,d_height);
|
|
328 aspect_save_screenres(device_width, device_height);
|
|
329
|
|
330 aspect(&d_width,&d_height,A_NOZOOM);
|
|
331
|
|
332 //Create player window//////////////////////////////////////////////////
|
|
333 windowAttrs = kWindowStandardDocumentAttributes
|
|
334 | kWindowStandardHandlerAttribute
|
|
335 | kWindowLiveResizeAttribute;
|
|
336
|
|
337 SetRect(&winRect, 0, 0, d_width, d_height);
|
|
338 SetRect(&dstRect, 0, 0, d_width, d_height);
|
|
339 SetRect(&imgRect, 0, 0, image_width, image_height);
|
|
340
|
|
341 CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
|
|
342
|
|
343 //Set window title
|
|
344 titleKey = CFSTR("MPlayer");
|
|
345 windowTitle = CFCopyLocalizedString(titleKey, NULL);
|
|
346 result = SetWindowTitleWithCFString(theWindow, windowTitle);
|
|
347 CFRelease(titleKey);
|
|
348 CFRelease(windowTitle);
|
|
349
|
|
350 //Install event handler
|
|
351 const EventTypeSpec winEvents[] = { { kEventClassWindow, kEventWindowClosed }, { kEventClassWindow, kEventWindowBoundsChanged } };
|
|
352 const EventTypeSpec keyEvents[] = { { kEventClassKeyboard, kEventRawKeyDown } };
|
|
353 const EventTypeSpec mouseEvents[] = { { kEventClassMouse, kEventMouseDown } };
|
|
354
|
|
355 InstallWindowEventHandler (theWindow, NewEventHandlerUPP (MainWindowEventHandler), GetEventTypeCount(winEvents), winEvents, theWindow, NULL);
|
|
356 InstallWindowEventHandler (theWindow, NewEventHandlerUPP (MainKeyboardEventHandler), GetEventTypeCount(keyEvents), keyEvents, theWindow, NULL);
|
|
357 InstallApplicationEventHandler (NewEventHandlerUPP (MainMouseEventHandler), GetEventTypeCount(mouseEvents), mouseEvents, 0, NULL);
|
|
358
|
|
359 //Show window
|
|
360 RepositionWindow(theWindow, NULL, kWindowCascadeOnMainScreen);
|
12414
|
361 #ifdef QUARTZ_ENABLE_YUV
|
|
362 if (!(IMGFMT_IS_RGB(image_format))) {
|
|
363 if (!EnterMoviesDone) {
|
|
364 qterr = EnterMovies();
|
|
365 EnterMoviesDone = 1;
|
|
366 }
|
|
367 else
|
|
368 qterr = 0;
|
|
369 mp_msg(MSGT_VO, MSGL_INFO, "\nQuartz: EnterMovies\n");
|
|
370 if (qterr) {
|
|
371 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: EnterMovies (%d)\n", qterr);
|
|
372 }
|
|
373
|
|
374 {
|
|
375 ComponentDescription cd2;
|
|
376 Handle h1 = NewHandleClear(4);
|
|
377 Handle h2 = NewHandleClear(4);
|
|
378 char ch1[256], ch2[256];
|
|
379
|
|
380 qterr = FindCodec(image_qtcodec, bestSpeedCodec, NULL, &mycodec);
|
|
381 if (qterr) {
|
|
382 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: FindCodec (%d)\n", qterr);
|
|
383 }
|
|
384 qterr = GetComponentInfo(mycodec, &cd2, h1, h2, NULL);
|
|
385 if (qterr) {
|
|
386 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetComponentInfo (%d)\n", qterr);
|
|
387 }
|
|
388 memcpy(ch1, &((unsigned char*)(*h1))[1], ((unsigned char*)(*h1))[0]);
|
|
389 ch1[((unsigned char*)(*h1))[0]] = '\0';
|
|
390 memcpy(ch2, &((unsigned char*)(*h2))[1], ((unsigned char*)(*h2))[0]);
|
|
391 ch2[((unsigned char*)(*h2))[0]] = '\0';
|
|
392 DisposeHandle(h1);
|
|
393 DisposeHandle(h2);
|
|
394 mp_msg(MSGT_VO, MSGL_INFO, "Quartz: QuickTime FindCodec reports component %.4s %.4s %.4s, %s, %s, [flags: 0x%08x, mask: 0x%08x]\n",
|
|
395 &cd2.componentType,
|
|
396 &cd2.componentSubType,
|
|
397 &cd2.componentManufacturer,
|
|
398 ch1,
|
|
399 ch2,
|
|
400 cd2.componentFlags,
|
|
401 cd2.componentFlagsMask);
|
|
402
|
|
403 {
|
|
404 CodecInfo ci;
|
|
405 qterr = GetCodecInfo(&ci, 'imdc', mycodec);
|
|
406 if (qterr) {
|
|
407 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetCodecInfo (%d)\n", qterr);
|
|
408 }
|
|
409 mp_msg(MSGT_VO, MSGL_INFO, "Quartz: CodecInfo:\n\tname: %s\n\tvendor: %.4s\n\tversion/revision: %d/%d\n\tdecompressFlags: 0x%08x\n\tcompressFlags: 0x%08x\n\tformatFlags: 0x%08x\n", ch1, &ci.vendor, ci.version, ci.revisionLevel, ci.decompressFlags, ci.compressFlags, ci.formatFlags);
|
|
410 }
|
|
411 }
|
|
412 yuv_qt_stuff.desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) );
|
|
413 yuv_qt_stuff.extension_colr = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension));
|
|
414 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->colorParamType = kVideoColorInfoImageDescriptionExtensionType;
|
|
415 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->primaries = 2;
|
|
416 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->transferFunction = 2;
|
|
417 ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->matrix = 2;
|
|
418 yuv_qt_stuff.extension_fiel = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension));
|
|
419 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldCount = 1;
|
|
420 ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldOrderings = 0;
|
|
421 yuv_qt_stuff.extension_clap = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension));
|
|
422 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthN = image_width;
|
|
423 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthD = 1;
|
|
424 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightN = image_height;
|
|
425 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightD = 1;
|
|
426 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffN = 0;
|
|
427 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffD = 1;
|
|
428 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffN = 0;
|
|
429 ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffD = 1;
|
|
430 yuv_qt_stuff.extension_pasp = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension));
|
|
431 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->hSpacing = 1;
|
|
432 ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->vSpacing = 1;
|
|
433
|
|
434 (*yuv_qt_stuff.desc)->idSize = sizeof(ImageDescription);
|
|
435 (*yuv_qt_stuff.desc)->cType = image_qtcodec;
|
|
436 (*yuv_qt_stuff.desc)->version = 2;
|
|
437 (*yuv_qt_stuff.desc)->revisionLevel = 0;
|
|
438 (*yuv_qt_stuff.desc)->vendor = 'mpla';
|
|
439 (*yuv_qt_stuff.desc)->width = image_width;
|
|
440 (*yuv_qt_stuff.desc)->height = image_height;
|
|
441 (*yuv_qt_stuff.desc)->hRes = Long2Fix(72);
|
|
442 (*yuv_qt_stuff.desc)->vRes = Long2Fix(72);
|
|
443 (*yuv_qt_stuff.desc)->temporalQuality = 0;
|
|
444 (*yuv_qt_stuff.desc)->spatialQuality = codecLosslessQuality;
|
|
445 (*yuv_qt_stuff.desc)->frameCount = 1;
|
|
446 (*yuv_qt_stuff.desc)->dataSize = 0;
|
|
447 (*yuv_qt_stuff.desc)->depth = 24;
|
|
448 (*yuv_qt_stuff.desc)->clutID = -1;
|
|
449
|
|
450 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_colr, kColorInfoImageDescriptionExtension);
|
|
451 if (qterr) {
|
|
452 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr);
|
|
453 }
|
|
454 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_fiel, kFieldInfoImageDescriptionExtension);
|
|
455 if (qterr) {
|
|
456 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr);
|
|
457 }
|
|
458 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_clap, kCleanApertureImageDescriptionExtension);
|
|
459 if (qterr) {
|
|
460 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr);
|
|
461 }
|
|
462 qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_pasp, kCleanApertureImageDescriptionExtension);
|
|
463 if (qterr) {
|
|
464 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr);
|
|
465 }
|
|
466
|
|
467 SetPort(GetWindowPort(theWindow));
|
|
468 SetIdentityMatrix(&yuv_qt_stuff.matrix);
|
|
469 if ((d_width != width) || (d_height != height)) {
|
|
470 ScaleMatrix(&yuv_qt_stuff.matrix,
|
|
471 FixDiv(Long2Fix(d_width),Long2Fix(width)),
|
|
472 FixDiv(Long2Fix(d_height),Long2Fix(height)),
|
|
473 0,
|
|
474 0);
|
|
475 }
|
|
476 P = calloc(sizeof(PlanarPixmapInfoYUV420) + image_size, 1);
|
|
477 switch (image_format) {
|
|
478 case IMGFMT_YV12:
|
|
479 case IMGFMT_IYUV:
|
|
480 case IMGFMT_I420:
|
|
481 P->componentInfoY.offset = sizeof(PlanarPixmapInfoYUV420);
|
|
482 P->componentInfoCb.offset = P->componentInfoY.offset + image_size / 2;
|
|
483 P->componentInfoCr.offset = P->componentInfoCb.offset + image_size / 4;
|
|
484 P->componentInfoY.rowBytes = image_width;
|
|
485 P->componentInfoCb.rowBytes = image_width / 2;
|
|
486 P->componentInfoCr.rowBytes = image_width / 2;
|
|
487 image_buffer_size = image_size + sizeof(PlanarPixmapInfoYUV420);
|
|
488 break;
|
|
489 case IMGFMT_UYVY:
|
|
490 case IMGFMT_YUY2:
|
|
491 image_buffer_size = image_size;
|
|
492 break;
|
|
493 }
|
|
494 mp_msg(MSGT_VO, MSGL_INFO, "Quartz: DecompressSequenceBeginS\n");
|
|
495 mp_msg(MSGT_VO, MSGL_INFO, "Quartz: width=%d, height=%d, d_width=%d, d_height=%d\n",
|
|
496 width, height, d_width, d_height);
|
|
497 myopenedcodec = OpenComponent(mycodec);
|
|
498
|
|
499 qterr = DecompressSequenceBeginS(&yuv_qt_stuff.seqId,
|
|
500 yuv_qt_stuff.desc,
|
|
501 P,
|
|
502 image_buffer_size,
|
|
503 GetWindowPort(theWindow),
|
|
504 NULL, // GDHandle
|
|
505 NULL, // srcRect
|
|
506 ((d_width != width) || (d_height != height)) ?
|
|
507 &yuv_qt_stuff.matrix : NULL,
|
|
508 srcCopy,
|
|
509 NULL, // mask,
|
|
510 0, //codecFlagUseImageBuffer,
|
|
511 codecLosslessQuality,
|
|
512 bestSpeedCodec);
|
|
513 //mycodec); // some codec reported by FindCodec() won't work (?)
|
|
514 //myopenedcodec); // doesn't seem to help, either
|
|
515 if (qterr) {
|
|
516 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr);
|
|
517 }
|
|
518 mp_msg(MSGT_VO, MSGL_INFO, "Quartz: DecompressSequenceBeginS done\n");
|
|
519 }
|
|
520 #endif /* QUARTZ_ENABLE_YUV */
|
|
521
|
12296
|
522 ShowWindow (theWindow);
|
|
523
|
|
524 if(vo_fs)
|
|
525 window_fullscreen();
|
|
526
|
|
527 if(vo_ontop)
|
|
528 window_ontop();
|
|
529
|
|
530 return 0;
|
12120
|
531 }
|
|
532
|
12296
|
533 static void check_events(void)
|
12120
|
534 {
|
12296
|
535 EventRef theEvent;
|
|
536 EventTargetRef theTarget;
|
|
537 OSStatus theErr;
|
|
538
|
|
539 //Get event
|
|
540 theTarget = GetEventDispatcherTarget();
|
|
541 theErr = ReceiveNextEvent(0, 0, kEventDurationNoWait,true, &theEvent);
|
|
542 if(theErr == noErr && theEvent != NULL)
|
|
543 {
|
|
544 SendEventToEventTarget (theEvent, theTarget);
|
|
545 ReleaseEvent(theEvent);
|
|
546 }
|
12120
|
547
|
12296
|
548 //update activity every 30 seconds to prevent
|
|
549 //screensaver from starting up.
|
|
550 DateTimeRec d;
|
|
551 unsigned long curTime;
|
|
552 static unsigned long lastTime = 0;
|
|
553
|
|
554 GetTime(&d);
|
|
555 DateToSeconds( &d, &curTime);
|
|
556
|
|
557 if( ( (curTime - lastTime) >= 30) || (lastTime == 0))
|
|
558 {
|
|
559 UpdateSystemActivity(UsrActivity);
|
|
560 lastTime = curTime;
|
|
561 }
|
|
562 }
|
12120
|
563
|
12296
|
564 static void draw_osd(void)
|
|
565 {
|
|
566 vo_draw_text(image_width,image_height,draw_alpha);
|
|
567 }
|
12120
|
568
|
12296
|
569 static void flip_page(void)
|
|
570 {
|
12414
|
571 switch (image_format) {
|
|
572 case IMGFMT_RGB32:
|
|
573 {
|
12296
|
574 OSStatus error;
|
|
575 CGrafPtr oldPort,deskPort;
|
|
576 GDHandle oldGDevice;
|
|
577 OSStatus lockPixelsError;
|
|
578 Boolean canLockPixels;
|
12414
|
579
|
12296
|
580 GetGWorld (&oldPort, &oldGDevice);
|
|
581 SetGWorld(GetWindowPort(theWindow), GetMainDevice());
|
|
582
|
|
583 CGrafPtr windowPort = GetWindowPort(theWindow);
|
|
584
|
|
585 lockPixelsError = LockPortBits(windowPort);
|
|
586
|
|
587 if (lockPixelsError == noErr)
|
|
588 canLockPixels = true;
|
|
589 else
|
|
590 canLockPixels = false;
|
|
591
|
|
592 if (canLockPixels)
|
|
593 {
|
|
594 CopyBits( GetPortBitMapForCopyBits (imgGWorld), GetPortBitMapForCopyBits (windowPort), &imgRect, &dstRect, srcCopy, 0 );
|
|
595 lockPixelsError = UnlockPortBits(windowPort);
|
|
596 }
|
|
597
|
|
598 RgnHandle theVisibleRegion;
|
|
599
|
|
600 if (QDIsPortBuffered(windowPort))
|
|
601 {
|
|
602 theVisibleRegion = NewRgn();
|
|
603 GetPortVisibleRegion(windowPort, theVisibleRegion);
|
|
604 QDFlushPortBuffer(windowPort, theVisibleRegion);
|
|
605 DisposeRgn(theVisibleRegion);
|
|
606 }
|
12120
|
607
|
12296
|
608 SetGWorld(oldPort, oldGDevice);
|
12414
|
609 }
|
|
610 break;
|
|
611 #ifdef QUARTZ_ENABLE_YUV
|
|
612 case IMGFMT_YV12:
|
|
613 case IMGFMT_IYUV:
|
|
614 case IMGFMT_I420:
|
|
615 case IMGFMT_UYVY:
|
|
616 case IMGFMT_YUY2:
|
|
617 if (EnterMoviesDone) {
|
|
618 OSErr qterr;
|
|
619 CodecFlags flags = 0;
|
|
620 qterr = DecompressSequenceFrameWhen(yuv_qt_stuff.seqId,
|
|
621 P,
|
|
622 image_buffer_size,
|
|
623 0, //codecFlagUseImageBuffer,
|
|
624 &flags,
|
|
625 NULL,
|
|
626 NULL);
|
|
627 if (qterr) {
|
|
628 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr, flags);
|
|
629 }
|
|
630 }
|
|
631 break;
|
|
632 #endif
|
|
633 }
|
12296
|
634 }
|
|
635
|
|
636 static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
|
|
637 {
|
12414
|
638 #ifdef QUARTZ_ENABLE_YUV
|
|
639 switch (image_format) {
|
|
640 case IMGFMT_YV12:
|
|
641 case IMGFMT_I420:
|
|
642 memcpy_pic(((char*)P) + P->componentInfoY.offset + x + image_width * y, src[0],
|
|
643 w, h, image_width, stride[0]);
|
|
644 x=x/2;y=y/2;w=w/2;h=h/2;
|
|
645 memcpy_pic(((char*)P) + P->componentInfoCb.offset + x + image_width / 2 * y, src[1],
|
|
646 w, h, image_width / 2, stride[1]);
|
|
647 memcpy_pic(((char*)P) + P->componentInfoCr.offset + x + image_width / 2 * y, src[2],
|
|
648 w, h, image_width / 2, stride[2]);
|
|
649 return 0;
|
|
650
|
|
651 case IMGFMT_IYUV:
|
|
652 memcpy_pic(((char*)P) + P->componentInfoY.offset + x + image_width * y, src[0],
|
|
653 w, h, image_width, stride[0]);
|
|
654 x=x/2;y=y/2;w=w/2;h=h/2;
|
|
655 memcpy_pic(((char*)P) + P->componentInfoCr.offset + x + image_width / 2 * y, src[1],
|
|
656 w, h, image_width / 2, stride[1]);
|
|
657 memcpy_pic(((char*)P) + P->componentInfoCb.offset + x + image_width / 2 * y, src[2],
|
|
658 w, h, image_width / 2, stride[2]);
|
|
659 return 0;
|
|
660 }
|
|
661 #endif
|
12296
|
662 return -1;
|
|
663 }
|
|
664
|
|
665 static uint32_t draw_frame(uint8_t *src[])
|
|
666 {
|
12414
|
667 switch (image_format) {
|
|
668 case IMGFMT_RGB32:
|
12296
|
669 image_data = src[0];
|
|
670 DisposeGWorld(imgGWorld);
|
|
671 NewGWorldFromPtr (&imgGWorld, k32ARGBPixelFormat, &imgRect, 0, 0, 0, image_data, image_width * 4);
|
12414
|
672 return 0;
|
|
673 #ifdef QUARTZ_ENABLE_YUV
|
|
674 case IMGFMT_UYVY:
|
|
675 case IMGFMT_YUY2:
|
|
676 memcpy_pic(((char*)P), src[0], image_width * 2, image_height, image_width * 2, image_width * 2);
|
|
677 return 0;
|
|
678 #endif
|
|
679 }
|
|
680 return -1;
|
12296
|
681 }
|
12120
|
682
|
12296
|
683 static uint32_t query_format(uint32_t format)
|
|
684 {
|
|
685 image_format = format;
|
|
686
|
12414
|
687 if (format == IMGFMT_RGB32)
|
|
688 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE | VFCAP_CSP_SUPPORTED_BY_HW;
|
|
689
|
|
690 #ifdef QUARTZ_ENABLE_YUV
|
|
691 image_qtcodec = 0;
|
|
692
|
|
693 if ((format == IMGFMT_YV12) || (format == IMGFMT_IYUV) || (format == IMGFMT_I420)) {
|
|
694 image_qtcodec = kMpegYUV420CodecType; //kYUV420CodecType ?;
|
|
695 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE | VFCAP_ACCEPT_STRIDE;
|
|
696 }
|
|
697
|
|
698 if (format == IMGFMT_YUY2) {
|
|
699 image_qtcodec = kComponentVideoUnsigned;
|
|
700 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE;
|
|
701 }
|
|
702
|
|
703 if (format == IMGFMT_UYVY) {
|
|
704 image_qtcodec = k422YpCbCr8CodecType;
|
|
705 return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE;
|
|
706 }
|
|
707 #endif
|
|
708
|
12296
|
709 return 0;
|
|
710 }
|
12120
|
711
|
12296
|
712 static void uninit(void)
|
|
713 {
|
12414
|
714 switch (image_format) {
|
|
715 case IMGFMT_YV12:
|
|
716 case IMGFMT_IYUV:
|
|
717 case IMGFMT_I420:
|
|
718 case IMGFMT_UYVY:
|
|
719 case IMGFMT_YUY2:
|
|
720 {
|
|
721 OSErr qterr;
|
|
722 if (EnterMoviesDone) {
|
|
723 qterr = CDSequenceEnd(yuv_qt_stuff.seqId);
|
|
724 if (qterr) {
|
|
725 mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: CDSequenceEnd (%d)\n", qterr);
|
|
726 }
|
|
727 }
|
|
728 }
|
|
729 break;
|
|
730 default:
|
|
731 break;
|
|
732 }
|
12296
|
733 ShowMenuBar();
|
|
734 }
|
12120
|
735
|
12296
|
736 static uint32_t preinit(const char *arg)
|
|
737 {
|
|
738 return 0;
|
12120
|
739 }
|
|
740
|
12414
|
741 #ifdef QUARTZ_ENABLE_YUV
|
|
742 static uint32_t draw_yuv_image(mp_image_t *mpi) {
|
|
743 // ATM we're only called for planar IMGFMT
|
|
744 // drawing is done directly in P
|
|
745 // and displaying is in flip_page.
|
|
746 return VO_TRUE;
|
|
747 }
|
|
748
|
|
749 static uint32_t get_yuv_image(mp_image_t *mpi) {
|
|
750 if(mpi->type!=MP_IMGTYPE_EXPORT) return VO_FALSE;
|
|
751
|
|
752 if(mpi->imgfmt!=image_format) return VO_FALSE;
|
|
753
|
|
754 if(mpi->flags&MP_IMGFLAG_PLANAR){
|
|
755 if (mpi->num_planes != 3) {
|
|
756 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi->num_planes);
|
|
757 return VO_FALSE;
|
|
758 }
|
|
759
|
|
760 mpi->planes[0]=((char*)P) + P->componentInfoY.offset;
|
|
761 mpi->stride[0]=image_width;
|
|
762 mpi->width=image_width;
|
|
763
|
|
764 if(mpi->flags&MP_IMGFLAG_SWAPPED){
|
|
765 // I420
|
|
766 mpi->planes[1]=((char*)P) + P->componentInfoCb.offset;
|
|
767 mpi->planes[2]=((char*)P) + P->componentInfoCr.offset;
|
|
768 mpi->stride[1]=image_width/2;
|
|
769 mpi->stride[2]=image_width/2;
|
|
770 } else {
|
|
771 // YV12
|
|
772 mpi->planes[1]=((char*)P) + P->componentInfoCr.offset;
|
|
773 mpi->planes[2]=((char*)P) + P->componentInfoCb.offset;
|
|
774 mpi->stride[1]=image_width/2;
|
|
775 mpi->stride[2]=image_width/2;
|
|
776 }
|
|
777 mpi->flags|=MP_IMGFLAG_DIRECT;
|
|
778 return VO_TRUE;
|
|
779 } else { // doesn't work yet
|
|
780 if (mpi->num_planes != 1) {
|
|
781 mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi->num_planes);
|
|
782 return VO_FALSE;
|
|
783 }
|
|
784
|
|
785 mpi->planes[0] = (char*)P;
|
|
786 mpi->stride[0] = image_width * 2;
|
|
787 mpi->width=image_width;
|
|
788 mpi->flags|=MP_IMGFLAG_DIRECT;
|
|
789 return VO_TRUE;
|
|
790 }
|
|
791 return VO_FALSE;
|
|
792 }
|
|
793 #endif /* QUARTZ_ENABLE_YUV */
|
|
794
|
12296
|
795 static uint32_t control(uint32_t request, void *data, ...)
|
12120
|
796 {
|
12296
|
797 switch (request)
|
|
798 {
|
|
799 case VOCTRL_PAUSE: return (int_pause=1);
|
|
800 case VOCTRL_RESUME: return (int_pause=0);
|
|
801 case VOCTRL_FULLSCREEN: window_fullscreen(); return VO_TRUE;
|
|
802 case VOCTRL_ONTOP: window_ontop(); return VO_TRUE;
|
|
803 case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data));
|
12414
|
804 #ifdef QUARTZ_ENABLE_YUV
|
|
805 case VOCTRL_GET_IMAGE:
|
|
806 switch (image_format) {
|
|
807 case IMGFMT_YV12:
|
|
808 case IMGFMT_IYUV:
|
|
809 case IMGFMT_I420:
|
|
810 //case IMGFMT_UYVY:
|
|
811 //case IMGFMT_YUY2:
|
|
812 return get_yuv_image(data);
|
|
813 break;
|
|
814 }
|
|
815 case VOCTRL_DRAW_IMAGE:
|
|
816 switch (image_format) {
|
|
817 case IMGFMT_YV12:
|
|
818 case IMGFMT_IYUV:
|
|
819 case IMGFMT_I420:
|
|
820 //case IMGFMT_UYVY:
|
|
821 //case IMGFMT_YUY2:
|
|
822 return draw_yuv_image(data);
|
|
823 break;
|
|
824 }
|
|
825 #endif
|
12296
|
826 }
|
|
827 return VO_NOTIMPL;
|
12120
|
828 }
|
|
829
|
12296
|
830 void window_resized()
|
12120
|
831 {
|
12296
|
832 float aspectX;
|
|
833 float aspectY;
|
|
834
|
|
835 int padding;
|
|
836
|
|
837 uint32_t d_width;
|
|
838 uint32_t d_height;
|
|
839
|
|
840 GetWindowPortBounds(theWindow, &winRect);
|
12120
|
841
|
12296
|
842 aspect( &d_width, &d_height, A_NOZOOM);
|
|
843
|
|
844 aspectX = (float)((float)winRect.right/(float)d_width);
|
|
845 aspectY = (float)((float)winRect.bottom/(float)d_height);
|
|
846
|
|
847 if((d_height*aspectX)>winRect.bottom)
|
|
848 {
|
|
849 padding = (winRect.right - d_width*aspectY)/2;
|
|
850 SetRect(&dstRect, padding, 0, d_width*aspectY+padding, d_height*aspectY);
|
|
851 }
|
|
852 else
|
|
853 {
|
|
854 padding = (winRect.bottom - d_height*aspectX)/2;
|
|
855 SetRect(&dstRect, 0, padding, (d_width*aspectX), d_height*aspectX+padding);
|
|
856 }
|
12120
|
857
|
12296
|
858 //create a graphic context for the window
|
|
859 SetPortBounds(GetWindowPort(theWindow), &winRect);
|
|
860 CreateCGContextForPort(GetWindowPort(theWindow),&context);
|
|
861
|
|
862 //fill background with black
|
|
863 CGRect winBounds = CGRectMake( winRect.top, winRect.left, winRect.right, winRect.bottom);
|
|
864 CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
|
|
865 CGContextFillRect(context, winBounds);
|
|
866 CGContextFlush(context);
|
12414
|
867
|
|
868
|
|
869 switch (image_format) {
|
|
870 #ifdef QUARTZ_ENABLE_YUV
|
|
871 case IMGFMT_YV12:
|
|
872 case IMGFMT_IYUV:
|
|
873 case IMGFMT_I420:
|
|
874 case IMGFMT_UYVY:
|
|
875 case IMGFMT_YUY2:
|
|
876 {
|
|
877 long scale_X = FixDiv(Long2Fix(dstRect.right - dstRect.left),Long2Fix(image_width));
|
|
878 long scale_Y = FixDiv(Long2Fix(dstRect.bottom - dstRect.top),Long2Fix(image_height));
|
|
879
|
|
880 SetIdentityMatrix(&yuv_qt_stuff.matrix);
|
|
881 if (((dstRect.right - dstRect.left) != image_width) ||
|
|
882 ((dstRect.bottom - dstRect.right) != image_height)) {
|
|
883 ScaleMatrix(&yuv_qt_stuff.matrix,
|
|
884 scale_X,
|
|
885 scale_Y,
|
|
886 0,
|
|
887 0);
|
|
888
|
|
889 if (padding > 0) {
|
|
890 TranslateMatrix(&yuv_qt_stuff.matrix,
|
|
891 Long2Fix(dstRect.left),
|
|
892 Long2Fix(dstRect.top));
|
|
893 }
|
|
894 }
|
|
895 SetDSequenceMatrix(yuv_qt_stuff.seqId, &yuv_qt_stuff.matrix);
|
|
896 break;
|
|
897 }
|
|
898 #endif
|
|
899 default:
|
|
900 break;
|
|
901 }
|
12120
|
902 }
|
|
903
|
12296
|
904 void window_ontop()
|
|
905 {
|
|
906 if(!vo_ontop)
|
|
907 SetWindowClass( theWindow, kUtilityWindowClass);
|
|
908 else
|
|
909 SetWindowClass( theWindow, kDocumentWindowClass);
|
|
910
|
|
911 vo_ontop = (!(vo_ontop));
|
12120
|
912 }
|
|
913
|
12296
|
914 void window_fullscreen()
|
12120
|
915 {
|
12296
|
916 static Rect oldRect;
|
|
917 static Ptr *restoreState = nil;
|
|
918 short width=640;
|
|
919 short height=480;
|
|
920 RGBColor black={0,0,0};
|
|
921 GDHandle deviceHdl;
|
|
922 Rect deviceRect;
|
12120
|
923
|
12296
|
924 //go fullscreen
|
|
925 if(!vo_fs)
|
|
926 {
|
|
927 //BeginFullScreen( &restoreState,nil,&width,&height,nil,&black,nil);
|
|
928 HideMenuBar();
|
12120
|
929
|
12296
|
930 //Get Main device info///////////////////////////////////////////////////
|
|
931 deviceHdl = GetMainDevice();
|
|
932 deviceRect = (*deviceHdl)->gdRect;
|
|
933
|
|
934 device_width = deviceRect.right;
|
|
935 device_height = deviceRect.bottom;
|
12120
|
936
|
12296
|
937 //save old window size
|
|
938 GetWindowPortBounds(theWindow, &oldRect);
|
|
939
|
|
940 //hide mouse cursor
|
|
941 HideCursor();
|
|
942
|
|
943 //go fullscreen
|
|
944 ChangeWindowAttributes(theWindow, 0, kWindowResizableAttribute);
|
|
945 MoveWindow (theWindow, 0, 0, 1);
|
|
946 SizeWindow(theWindow, device_width, device_height,1);
|
12120
|
947
|
12296
|
948 vo_fs = 1;
|
|
949 }
|
|
950 else //go back to windowed mode
|
|
951 {
|
|
952 //EndFullScreen( restoreState,0);
|
|
953 ShowMenuBar();
|
|
954
|
|
955 //Get Main device info///////////////////////////////////////////////////
|
|
956 deviceHdl = GetMainDevice();
|
|
957 deviceRect = (*deviceHdl)->gdRect;
|
|
958
|
|
959 device_width = deviceRect.right;
|
|
960 device_height = deviceRect.bottom;
|
12120
|
961
|
12296
|
962 //show mouse cursor
|
|
963 ShowCursor();
|
|
964
|
|
965 //revert window to previous setting
|
|
966 ChangeWindowAttributes(theWindow, kWindowResizableAttribute, 0);
|
|
967 SizeWindow(theWindow, oldRect.right, oldRect.bottom,1);
|
|
968 RepositionWindow(theWindow, NULL, kWindowCascadeOnMainScreen);
|
|
969
|
|
970 vo_fs = 0;
|
|
971 }
|
|
972
|
|
973 window_resized();
|
12120
|
974 }
|
|
975
|