summaryrefslogtreecommitdiffstats
path: root/libvo/vo_quartz.c
diff options
context:
space:
mode:
authoralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-04-05 21:20:19 +0000
committeralex <alex@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-04-05 21:20:19 +0000
commitfac2bcf4f9c9a399e323478ec4303b03bd1ce9d9 (patch)
tree9cdfaaa7ec6c1a3a1af2b9accab5b4c7080f14ad /libvo/vo_quartz.c
parentbfcc5b3160482db90fa24d02dbf11540e8d5384f (diff)
downloadmpv-fac2bcf4f9c9a399e323478ec4303b03bd1ce9d9.tar.bz2
mpv-fac2bcf4f9c9a399e323478ec4303b03bd1ce9d9.tar.xz
Quartz/MacOSX video output module by Nicolas Plourde
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@12121 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libvo/vo_quartz.c')
-rw-r--r--libvo/vo_quartz.c529
1 files changed, 529 insertions, 0 deletions
diff --git a/libvo/vo_quartz.c b/libvo/vo_quartz.c
new file mode 100644
index 0000000000..bf59ced483
--- /dev/null
+++ b/libvo/vo_quartz.c
@@ -0,0 +1,529 @@
+/*
+ * vo_quartz.c
+ *
+ * Copyright (c) Nicolas Plourde - January 2004
+ *
+ * MPlayer Mac OSX Quartz video out module.
+ *
+ * TODO: -Fullscreen
+ * -Better event handling
+ *
+ * Note on performance:
+ * Right now i can play fullsize dvd video with -framedrop on my
+ * iBook G4 800mhz. YUV to RGB converstion will speed up thing alot.
+ * Another thing is the slow fps when you maximize the window, I was
+ * not expecting that. I will fix this a.s.a.p. Im new to Mac
+ * programming so help is welcome.
+ */
+
+//SYS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+//OSX
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h>
+
+//MPLAYER
+#include "config.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "aspect.h"
+
+#include "../input/input.h"
+#include "../input/mouse.h"
+
+#include "vo_quartz.h"
+
+static vo_info_t info = {
+ "MacOS X (Quartz)",
+ "quartz",
+ "Nicolas Plourde <nicolasplourde@hotmail.com>",
+ ""
+};
+
+LIBVO_EXTERN (quartz)
+static unsigned char *ImageData = NULL;
+
+static uint32_t image_width;
+static uint32_t image_height;
+static uint32_t image_depth;
+static uint32_t image_bytes;
+static uint32_t image_format;
+
+static int int_pause = 0;
+
+int screen_width, screen_height;
+
+WindowRef theWindow;
+CGContextRef context;
+CGRect bounds;
+CGRect winBounds;
+Rect contentRect;
+CGImageRef image;
+CGDataProviderRef dataProviderRef;
+Ptr oldscreenstate;
+RGBColor black = { 0, 0, 0 };
+float winAlpha = 1;
+
+#include "../osdep/keycodes.h"
+extern void mplayer_put_key (int code);
+
+//PROTOTYPE/////////////////////////////////////////////////////////////////
+void resize_window (uint32_t width, uint32_t height);
+static OSStatus MainWindowEventHandler (EventHandlerCallRef nextHandler,
+ EventRef event, void *userData);
+static OSStatus MainKeyEventHandler (EventHandlerCallRef nextHandler,
+ EventRef event, void *userData);
+
+
+//default window event handler
+static OSStatus
+MainWindowEventHandler (EventHandlerCallRef nextHandler, EventRef event,
+ void *userData)
+{
+ OSStatus err = noErr;
+ WindowRef window;
+ Rect rectPort = { 0, 0, 0, 0 };
+ OSStatus result = eventNotHandledErr;
+ UInt32 class = GetEventClass (event);
+ UInt32 kind = GetEventKind (event);
+
+ GetEventParameter (event, kEventParamDirectObject, typeWindowRef, NULL,
+ sizeof (WindowRef), NULL, &window);
+ if (window)
+ {
+ GetWindowPortBounds (window, &rectPort);
+ }
+
+ switch (kind)
+ {
+ case kEventWindowActivated:
+
+ case kEventWindowDrawContent:
+ break;
+
+ case kEventWindowClosed:
+ HideWindow (window);
+ mplayer_put_key (KEY_ESC);
+ break;
+
+ case kEventWindowShown:
+ InvalWindowRect (window, &rectPort);
+ break;
+
+ case kEventWindowBoundsChanged:
+ resize_window (rectPort.right, rectPort.bottom);
+ break;
+
+ case kEventWindowZoomed:
+ resize_window (rectPort.right, rectPort.bottom);
+ break;
+
+ default:
+ err = eventNotHandledErr;
+ break;
+ }
+
+ return err;
+}
+
+//keyboard event handler
+static OSStatus
+MainKeyEventHandler (EventHandlerCallRef nextHandler, EventRef event,
+ void *userData)
+{
+ OSStatus err = noErr;
+ UInt32 macKeyCode;
+
+ GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL,
+ sizeof (macKeyCode), NULL, &macKeyCode);
+
+ switch (GetEventKind (event))
+ {
+ case kEventRawKeyDown:
+ {
+ switch (macKeyCode)
+ {
+ case QZ_RETURN:
+ mplayer_put_key (KEY_ENTER);
+ break;
+ case QZ_ESCAPE:
+ EndFullScreen (oldscreenstate, 0);
+ QuitApplicationEventLoop ();
+ mplayer_put_key (KEY_ESC);
+ break;
+ case QZ_q:
+ mplayer_put_key ('q');
+ break;
+ case QZ_F1:
+ mplayer_put_key (KEY_F + 1);
+ break;
+ case QZ_F2:
+ mplayer_put_key (KEY_F + 2);
+ break;
+ case QZ_F3:
+ mplayer_put_key (KEY_F + 3);
+ break;
+ case QZ_F4:
+ mplayer_put_key (KEY_F + 4);
+ break;
+ case QZ_F5:
+ mplayer_put_key (KEY_F + 5);
+ break;
+ case QZ_F6:
+ mplayer_put_key (KEY_F + 6);
+ break;
+ case QZ_F7:
+ mplayer_put_key (KEY_F + 7);
+ break;
+ case QZ_F8:
+ mplayer_put_key (KEY_F + 8);
+ break;
+ case QZ_F9:
+ mplayer_put_key (KEY_F + 9);
+ break;
+ case QZ_F10:
+ mplayer_put_key (KEY_F + 10);
+ break;
+ case QZ_F11:
+ mplayer_put_key (KEY_F + 11);
+ break;
+ case QZ_F12:
+ mplayer_put_key (KEY_F + 12);
+ break;
+ case QZ_o:
+ mplayer_put_key ('o');
+ break;
+ case QZ_SPACE:
+ mplayer_put_key (' ');
+ break;
+ case QZ_p:
+ mplayer_put_key ('p');
+ break;
+ //case QZ_7: mplayer_put_key(shift_key?'/':'7');
+ //case QZ_PLUS: mplayer_put_key(shift_key?'*':'+');
+ case QZ_KP_PLUS:
+ mplayer_put_key ('+');
+ break;
+ case QZ_MINUS:
+ case QZ_KP_MINUS:
+ mplayer_put_key ('-');
+ break;
+ case QZ_TAB:
+ mplayer_put_key ('\t');
+ break;
+ case QZ_PAGEUP:
+ mplayer_put_key (KEY_PAGE_UP);
+ break;
+ case QZ_PAGEDOWN:
+ mplayer_put_key (KEY_PAGE_DOWN);
+ break;
+ case QZ_UP:
+ mplayer_put_key (KEY_UP);
+ break;
+ case QZ_DOWN:
+ mplayer_put_key (KEY_DOWN);
+ break;
+ case QZ_LEFT:
+ mplayer_put_key (KEY_LEFT);
+ break;
+ case QZ_RIGHT:
+ mplayer_put_key (KEY_RIGHT);
+ break;
+ //case QZ_LESS: mplayer_put_key(shift_key?'>':'<'); break;
+ //case QZ_GREATER: mplayer_put_key('>'); break;
+ //case QZ_ASTERISK:
+ case QZ_KP_MULTIPLY:
+ mplayer_put_key ('*');
+ break;
+ case QZ_SLASH:
+ case QZ_KP_DIVIDE:
+ mplayer_put_key ('/');
+ break;
+ case QZ_KP0:
+ mplayer_put_key (KEY_KP0);
+ break;
+ case QZ_KP1:
+ mplayer_put_key (KEY_KP1);
+ break;
+ case QZ_KP2:
+ mplayer_put_key (KEY_KP2);
+ break;
+ case QZ_KP3:
+ mplayer_put_key (KEY_KP3);
+ break;
+ case QZ_KP4:
+ mplayer_put_key (KEY_KP4);
+ break;
+ case QZ_KP5:
+ mplayer_put_key (KEY_KP5);
+ break;
+ case QZ_KP6:
+ mplayer_put_key (KEY_KP6);
+ break;
+ case QZ_KP7:
+ mplayer_put_key (KEY_KP7);
+ break;
+ case QZ_KP8:
+ mplayer_put_key (KEY_KP8);
+ break;
+ case QZ_KP9:
+ mplayer_put_key (KEY_KP9);
+ break;
+ case QZ_KP_PERIOD:
+ mplayer_put_key (KEY_KPDEC);
+ break;
+ case QZ_KP_ENTER:
+ mplayer_put_key (KEY_KPENTER);
+ break;
+ case QZ_LEFTBRACKET:
+ SetWindowAlpha (theWindow, winAlpha -= 0.05);
+ break;
+ case QZ_RIGHTBRACKET:
+ SetWindowAlpha (theWindow, winAlpha += 0.05);
+ break;
+ case QZ_f:
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ err = eventNotHandledErr;
+ break;
+ }
+
+ return err;
+}
+
+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)
+{
+ WindowAttributes windowAttrs;
+ CFStringRef titleKey;
+ CFStringRef windowTitle;
+ OSStatus result;
+ GDHandle deviceHdl;
+ Rect deviceRect;
+
+ //Get Main device info///////////////////////////////////////////////////
+ deviceHdl = GetMainDevice ();
+ deviceRect = (*deviceHdl)->gdRect;
+
+ screen_width = deviceRect.right;
+ screen_height = deviceRect.bottom;
+
+ //misc mplayer setup/////////////////////////////////////////////////////
+ image_width = width;
+ image_height = height;
+ image_depth = IMGFMT_RGB_DEPTH (format);
+ image_bytes = (IMGFMT_RGB_DEPTH (format) + 7) / 8;
+
+ aspect_save_orig (width, height);
+ aspect_save_prescale (d_width, d_height);
+ aspect_save_screenres (screen_width, screen_height);
+
+ aspect (&d_width, &d_height, A_NOZOOM);
+
+ if (ImageData)
+ free (ImageData);
+ ImageData = malloc (image_width * image_height * image_bytes);
+
+ //Create player window//////////////////////////////////////////////////
+ windowAttrs = kWindowStandardDocumentAttributes
+ | kWindowMetalAttribute
+ | kWindowStandardHandlerAttribute
+ | kWindowInWindowMenuAttribute
+ | kWindowLiveResizeAttribute | kWindowCompositingAttribute;
+
+ SetRect (&contentRect, 0, 0, d_width, d_height);
+ CreateNewWindow (kDocumentWindowClass, windowAttrs, &contentRect,
+ &theWindow);
+
+ titleKey = CFSTR ("MPlayer");
+ windowTitle = CFCopyLocalizedString (titleKey, NULL);
+ result = SetWindowTitleWithCFString (theWindow, windowTitle);
+ CFRelease (titleKey);
+ CFRelease (windowTitle);
+
+ const EventTypeSpec winEvents[] = {
+ {kEventClassWindow, kEventWindowActivated},
+ {kEventClassWindow, kEventWindowDrawContent},
+ {kEventClassWindow, kEventWindowClosed},
+ {kEventClassWindow, kEventWindowShown},
+ {kEventClassWindow, kEventWindowBoundsChanged},
+ {kEventClassWindow, kEventWindowZoomed}
+ };
+
+ const EventTypeSpec keyEvents[] =
+ { {kEventClassKeyboard, kEventRawKeyDown} };
+ InstallWindowEventHandler (theWindow,
+ NewEventHandlerUPP (MainWindowEventHandler),
+ GetEventTypeCount (winEvents), winEvents,
+ theWindow, NULL);
+ InstallWindowEventHandler (theWindow,
+ NewEventHandlerUPP (MainKeyEventHandler),
+ GetEventTypeCount (keyEvents), keyEvents,
+ theWindow, NULL);
+
+ RepositionWindow (theWindow, NULL, kWindowCascadeOnMainScreen);
+ ShowWindow (theWindow);
+
+ //Setup Quartz context
+ CreateCGContextForPort (GetWindowPort (theWindow), &context);
+
+ //set size and aspect for current window
+ resize_window (d_width, d_height);
+
+ return 0;
+}
+
+//resize drawing context to fit window
+void
+resize_window (uint32_t width, uint32_t height)
+{
+ //this is a "wow it work". Need some improvement.
+ uint32_t d_width;
+ uint32_t d_height;
+ uint32_t size;
+ Rect tmpRect;
+
+ float aspectX;
+ float aspectY;
+
+ aspect (&d_width, &d_height, A_NOZOOM);
+
+ aspectX = (float) ((float) d_width * (width / (float) d_width));
+ aspectY = (float) ((float) d_height * (width / (float) d_width));
+
+ if (aspectY > height)
+ {
+ aspectX = (float) ((float) d_width * (height / (float) d_height));
+ aspectY = (float) ((float) d_height * (height / (float) d_height));
+
+ bounds = CGRectMake ((width - aspectX) / 2, 0, aspectX, aspectY);
+ }
+ else
+ {
+ bounds = CGRectMake (0, (height - aspectY) / 2, aspectX, aspectY);
+ }
+
+ //create a graphic context for the window
+ GetWindowPortBounds (theWindow, &tmpRect);
+ SetPortBounds (GetWindowPort (theWindow), &tmpRect);
+ CreateCGContextForPort (GetWindowPort (theWindow), &context);
+
+ //fill background with black
+ winBounds =
+ CGRectMake (tmpRect.top, tmpRect.left, tmpRect.right, tmpRect.bottom);
+ CGContextSetRGBFillColor (context, 0.0, 0.0, 0.0, 1.0);
+ CGContextFillRect (context, winBounds);
+}
+
+static void
+check_events (void)
+{
+ EventRef theEvent;
+ EventTargetRef theTarget;
+
+ theTarget = GetEventDispatcherTarget ();
+
+ ReceiveNextEvent (0, NULL, kEventDurationNoWait, true, &theEvent);
+ SendEventToEventTarget (theEvent, theTarget);
+ ReleaseEvent (theEvent);
+
+ //if(VO_EVENT_RESIZE) resize_window(vo_dwidth,vo_dheight);
+ if (VO_EVENT_EXPOSE && int_pause)
+ flip_page ();
+}
+
+static void
+draw_osd (void)
+{
+}
+
+static void
+flip_page (void)
+{
+ CGContextFlush (context);
+}
+
+static uint32_t
+draw_slice (uint8_t * src[], int stride[], int w, int h, int x, int y)
+{
+ return -1;
+}
+
+static uint32_t
+draw_frame (uint8_t * src[])
+{
+ //this is very slow. I have to find another way.
+ CGImageAlphaInfo alphaInfo;
+
+ dataProviderRef =
+ CGDataProviderCreateWithData (0, src[0],
+ image_width * image_height * image_bytes,
+ 0);
+
+ if (image_format == IMGFMT_RGB24)
+ alphaInfo = kCGImageAlphaNone;
+ else if (image_format == IMGFMT_RGB32)
+ alphaInfo = kCGImageAlphaNoneSkipFirst;
+
+ image = CGImageCreate (image_width,
+ image_height,
+ 8,
+ image_depth,
+ ((image_width * image_depth) + 7) / 8,
+ CGColorSpaceCreateDeviceRGB (),
+ alphaInfo,
+ dataProviderRef, 0, 0, kCGRenderingIntentDefault);
+
+ CGContextDrawImage (context, bounds, image);
+
+ return 0;
+}
+
+static uint32_t
+query_format (uint32_t format)
+{
+ image_format = format;
+
+ //Curently supporting only rgb format.
+ if ((format == IMGFMT_RGB24) || (format == IMGFMT_RGB32))
+ return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
+ return 0;
+}
+
+
+static void
+uninit (void)
+{
+}
+
+static uint32_t
+preinit (const char *arg)
+{
+ return 0;
+}
+
+static uint32_t
+control (uint32_t request, void *data, ...)
+{
+ switch (request)
+ {
+ case VOCTRL_PAUSE:
+ return (int_pause = 1);
+ case VOCTRL_RESUME:
+ return (int_pause = 0);
+ case VOCTRL_QUERY_FORMAT:
+ return query_format (*((uint32_t *) data));
+ }
+ return VO_NOTIMPL;
+}