]> git.sesse.net Git - vlc/blobdiff - modules/video_output/macosx.m
video_output/mmal: Add mmal based video output plugin
[vlc] / modules / video_output / macosx.m
index 660a62b9a509281cf4f6a138a5eafee7f3a338e1..01392045e8e911af0a1fae7f02c531ff7173d35f 100644 (file)
@@ -1,18 +1,19 @@
 /*****************************************************************************
  * macosx.m: MacOS X OpenGL provider
  *****************************************************************************
- * Copyright (C) 2001-2012 VLC authors and VideoLAN
+ * Copyright (C) 2001-2013 VLC authors and VideoLAN
  * $Id$
  *
- * Authors: Colin Delacroix <colin@zoy.org>
- *          Florian G. Pflug <fgp@phlo.org>
- *          Derk-Jan Hartman <hartman at videolan dot org>
+ * Authors: Derk-Jan Hartman <hartman at videolan dot org>
  *          Eric Petit <titer@m0k.org>
  *          Benjamin Pracht <bigben at videolan dot org>
  *          Damien Fouilleul <damienf at videolan dot org>
  *          Pierre d'Herbemont <pdherbemont at videolan dot org>
  *          Felix Paul Kühne <fkuehne at videolan dot org>
  *          David Fuhrmann <david dot fuhrmann at googlemail dot com>
+ *          Rémi Denis-Courmont
+ *          Juho Vähä-Herttua <juhovh at iki dot fi>
+ *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -82,7 +83,7 @@ static void OpenglSwap (vlc_gl_t *gl);
 vlc_module_begin ()
     /* Will be loaded even without interface module. see voutgl.m */
     set_shortname ("Mac OS X")
-    set_description (N_("Mac OS X OpenGL video output (requires drawable-nsobject)"))
+    set_description (N_("Mac OS X OpenGL video output"))
     set_category (CAT_VIDEO)
     set_subcategory (SUBCAT_VIDEO_VOUT)
     set_capability ("vout display", 300)
@@ -142,11 +143,8 @@ static int Open (vlc_object_t *this)
     if (!sys)
         return VLC_ENOMEM;
 
-    if (!CGDisplayUsesOpenGLAcceleration (kCGDirectMainDisplay)) {
+    if (!CGDisplayUsesOpenGLAcceleration (kCGDirectMainDisplay))
         msg_Err (this, "no OpenGL hardware acceleration found. this can lead to slow output and unexpected results");
-        dialog_Fatal (this, _("OpenGL acceleration is not supported on your Mac"), _("Your Mac lacks Quartz Extreme acceleration, which is required for video output. It will still work, but much slower and with possibly unexpected results."));
-    } else
-        msg_Dbg (this, "Quartz Extreme acceleration is active");
 
     vd->sys = sys;
     sys->pool = NULL;
@@ -172,7 +170,7 @@ static int Open (vlc_object_t *this)
             container = sys->embed->handle.nsobject;
 
         if (!container) {
-            msg_Dbg(vd, "No drawable-nsobject nor vout_window_t found, passing over.");
+            msg_Err(vd, "No drawable-nsobject nor vout_window_t found, passing over.");
             goto error;
         }
     }
@@ -185,8 +183,10 @@ static int Open (vlc_object_t *this)
     nsPool = [[NSAutoreleasePool alloc] init];
 
     [VLCOpenGLVideoView performSelectorOnMainThread:@selector(getNewView:) withObject:[NSValue valueWithPointer:&sys->glView] waitUntilDone:YES];
-    if (!sys->glView)
+    if (!sys->glView) {
+        msg_Err(vd, "Initialization of open gl view failed");
         goto error;
+    }
 
     [sys->glView setVoutDisplay:vd];
 
@@ -215,10 +215,10 @@ static int Open (vlc_object_t *this)
     sys->gl.getProcAddress = OurGetProcAddress;
     sys->gl.sys = sys;
     const vlc_fourcc_t *subpicture_chromas;
-    video_format_t fmt = vd->fmt;
 
     sys->vgl = vout_display_opengl_New (&vd->fmt, &subpicture_chromas, &sys->gl);
     if (!sys->vgl) {
+        msg_Err(vd, "Error while initializing opengl display.");
         sys->gl.sys = NULL;
         goto error;
     }
@@ -239,7 +239,7 @@ static int Open (vlc_object_t *this)
     vd->control = Control;
 
     /* */
-    vout_display_SendEventDisplaySize (vd, vd->source.i_visible_width, vd->source.i_visible_height, false);
+    vout_display_SendEventDisplaySize (vd, vd->fmt.i_visible_width, vd->fmt.i_visible_height, false);
 
     return VLC_SUCCESS;
 
@@ -265,11 +265,11 @@ void Close (vlc_object_t *this)
     [(id)sys->container performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
     [sys->glView performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:NO];
 
-    [sys->glView release];
-
     if (sys->gl.sys != NULL)
         vout_display_opengl_Delete (sys->vgl);
 
+    [sys->glView release];
+
     if (sys->embed)
         vout_display_DeleteWindow (vd, sys->embed);
     free (sys);
@@ -314,6 +314,12 @@ static int Control (vout_display_t *vd, int query, va_list ap)
 {
     vout_display_sys_t *sys = vd->sys;
 
+    if (!vd->sys)
+        return VLC_EGENERIC;
+
+    if (!sys->embed)
+        return VLC_EGENERIC;
+
     switch (query)
     {
         case VOUT_DISPLAY_CHANGE_FULLSCREEN:
@@ -327,7 +333,7 @@ static int Control (vout_display_t *vd, int query, va_list ap)
         case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
         {
             unsigned state = va_arg (ap, unsigned);
-            return vout_window_SetState (sys->embed, state);            
+            return vout_window_SetState (sys->embed, state);
         }
         case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
         case VOUT_DISPLAY_CHANGE_ZOOM:
@@ -335,14 +341,13 @@ static int Control (vout_display_t *vd, int query, va_list ap)
         case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
         case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
         {
-            if (!vd->sys)
-                return VLC_EGENERIC;
-
             NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
 
             id o_window = [sys->glView window];
-            if (!o_window)
+            if (!o_window) {
+                [o_pool release];
                 return VLC_SUCCESS; // this is okay, since the event will occur again when we have a window
+            }
 
             NSSize windowMinSize = [o_window minSize];
 
@@ -361,12 +366,12 @@ static int Control (vout_display_t *vd, int query, va_list ap)
             }
 
             if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE && is_forced
-                && (cfg->display.width != vd->cfg->display.width
-                    || cfg->display.height != vd->cfg->display.height)
-                && vout_window_SetSize (sys->embed, cfg->display.width, cfg->display.height))
+                && vout_window_SetSize (sys->embed, cfg->display.width, cfg->display.height)) {
+                [o_pool release];
                 return VLC_EGENERIC;
-            /* we always use our current frame here, because we have some size constraints 
+            }
+
+            /* we always use our current frame here, because we have some size constraints
                in the ui vout provider */
             vout_display_cfg_t cfg_tmp = *cfg;
             NSRect bounds;
@@ -478,6 +483,7 @@ static void OpenglSwap (vlc_gl_t *gl)
         NSOpenGLPFAAlphaSize, 8,
         NSOpenGLPFADepthSize, 24,
         NSOpenGLPFAWindow,
+        NSOpenGLPFAAllowOfflineRenderers,
         0
     };
 
@@ -502,10 +508,25 @@ static void OpenglSwap (vlc_gl_t *gl)
     GLint params[] = { 1 };
     CGLSetParameter ([[self openGLContext] CGLContextObj], kCGLCPSwapInterval, params);
 
+    [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidChangeScreenParametersNotification
+                                                      object:[NSApplication sharedApplication]
+                                                       queue:nil
+                                                  usingBlock:^(NSNotification *notification) {
+                                                      [self performSelectorOnMainThread:@selector(reshape)
+                                                                             withObject:nil
+                                                                          waitUntilDone:NO];
+                                                  }];
+
     [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
     return self;
 }
 
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    [super dealloc];
+}
+
 /**
  * Gets called by the Open() method.
  */
@@ -614,7 +635,7 @@ static void OpenglSwap (vlc_gl_t *gl)
     else
         bounds = [self bounds];
     vout_display_place_t place;
-    
+
     @synchronized(self) {
         if (vd) {
             vout_display_cfg_t cfg_tmp = *(vd->cfg);
@@ -701,9 +722,13 @@ static void OpenglSwap (vlc_gl_t *gl)
 
 - (void)mouseDown:(NSEvent *)o_event
 {
-    if ([o_event type] == NSLeftMouseDown && !([o_event modifierFlags] &  NSControlKeyMask)) {
-        if ([o_event clickCount] <= 1)
-            vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_LEFT);
+    @synchronized (self) {
+        if (vd) {
+            if ([o_event type] == NSLeftMouseDown && !([o_event modifierFlags] &  NSControlKeyMask)) {
+                if ([o_event clickCount] <= 1)
+                    vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_LEFT);
+            }
+        }
     }
 
     [super mouseDown:o_event];
@@ -711,53 +736,54 @@ static void OpenglSwap (vlc_gl_t *gl)
 
 - (void)otherMouseDown:(NSEvent *)o_event
 {
-    vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_CENTER);
+    @synchronized (self) {
+        if (vd)
+            vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_CENTER);
+    }
 
     [super otherMouseDown: o_event];
 }
 
 - (void)mouseUp:(NSEvent *)o_event
 {
-    if ([o_event type] == NSLeftMouseUp)
-        vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_LEFT);
+    @synchronized (self) {
+        if (vd) {
+            if ([o_event type] == NSLeftMouseUp)
+                vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_LEFT);
+        }
+    }
 
     [super mouseUp: o_event];
 }
 
 - (void)otherMouseUp:(NSEvent *)o_event
 {
-    vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_CENTER);
+    @synchronized (self) {
+        if (vd)
+            vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_CENTER);
+    }
 
     [super otherMouseUp: o_event];
 }
 
 - (void)mouseMoved:(NSEvent *)o_event
 {
-    NSPoint ml;
-    NSRect s_rect;
-    BOOL b_inside;
-
     /* on HiDPI displays, the point bounds don't equal the actual pixel based bounds */
-    if (OSX_LION)
-        s_rect = [self convertRectToBacking:[self bounds]];
-    else
-        s_rect = [self bounds];
-    ml = [self convertPoint: [o_event locationInWindow] fromView: nil];
-    b_inside = [self mouse: ml inRect: s_rect];
-    
+    NSPoint ml = [self convertPoint: [o_event locationInWindow] fromView: nil];
+    NSRect videoRect = [self bounds];
+    BOOL b_inside = [self mouse: ml inRect: videoRect];
+
+    if (OSX_LION) {
+        ml = [self convertPointToBacking: ml];
+        videoRect = [self convertRectToBacking: videoRect];
+    }
+
     if (b_inside) {
         @synchronized (self) {
             if (vd) {
-                vout_display_place_t place = vd->sys->place;
-
-                if (place.width > 0 && place.height > 0) {
-                    const int x = vd->source.i_x_offset +
-                    (int64_t)(ml.x - place.x) * vd->source.i_visible_width / place.width;
-                    const int y = vd->source.i_y_offset +
-                    (int64_t)((int)s_rect.size.height - (int)ml.y - place.y) * vd->source.i_visible_height / place.height;
-
-                    vout_display_SendEventMouseMoved (vd, x, y);
-                }
+                vout_display_SendMouseMovedDisplayCoordinates(vd, ORIENT_NORMAL,
+                                                              (int)ml.x, videoRect.size.height - (int)ml.y,
+                                                              &vd->sys->place);
             }
         }
     }