MacOSX/Framework/VLCVideoView.m: Supports the opengllayer video_output.
authorPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 28 Dec 2007 18:28:29 +0000 (18:28 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Fri, 28 Dec 2007 18:28:29 +0000 (18:28 +0000)
extras/MacOSX/Framework/Headers/Public/VLCVideoView.h
extras/MacOSX/Framework/Sources/VLCVideoView.m

index d51c091..65720d2 100644 (file)
@@ -23,6 +23,8 @@
  *****************************************************************************/
 
 #import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
+@class CALayer;
 
 /* Notifications */
 extern NSString * VLCVideoViewEnteredFullScreen;
@@ -34,40 +36,26 @@ extern NSString * VLCVideoViewLeftFullScreen;
 - (void)videoLeftFullscreen:(NSNotification *)aNotification;
 @end
 
-@protocol VLCOpenGLVoutEmbedding
-- (void)addVoutSubview:(NSView *)view;
-- (void)removeVoutSubview:(NSView *)view;
-
-- (void)enterFullscreen;
-- (void)leaveFullscreen;
-
-- (BOOL)stretchesVideo;
-
-//- (void)setOnTop: (BOOL)ontop; /* Do we really want that in protocol? */
-@end
-
-@interface VLCVideoView : NSView <VLCOpenGLVoutEmbedding>
+@interface VLCVideoView : NSView
 {
     id delegate;
     NSColor * backColor;
     BOOL stretchesVideo;
-    
+    BOOL fullscreen;
+    id layoutManager;
     // TODO: Allow for view to report transparency to do some cool effects
     // with the video?
 }
 
+@property (readonly, assign) BOOL fullscreen;
+@property BOOL fillScreen;
+
 - (void)setDelegate:(id)value;
 - (id)delegate;
 
 - (void)setBackColor:(NSColor *)value;
 - (NSColor *)backColor;
 
-- (void)setStretchesVideo:(BOOL)value;
-- (BOOL)stretchesVideo;
-
-- (void)addVoutSubview:(NSView *)aView;
-- (void)removeVoutSubview:(NSView *)aView;
-
 - (void)enterFullscreen;
 - (void)leaveFullscreen;
 
index 20e6c4d..317e6c8 100644 (file)
 #include <vlc/vlc.h>
 #include <vlc/libvlc.h>
 
+#import <QuartzCore/QuartzCore.h>
+
 /* Notifications */
 NSString *VLCVideoViewEnteredFullScreen = @"VLCVideoViewEnteredFullScreen";
 NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
 
+/******************************************************************************
+ * Soon deprecated stuff 
+ */
+
 /* This is a forward reference to VLCOpenGLVoutView specified in minimal_macosx
    library.  We could get rid of this, but it prevents warnings from the 
-   compiler. */
+   compiler. (Scheduled to deletion) */
 @interface VLCOpenGLVoutView : NSView
 - (void)detachFromVout;
 @end
 
+/* Depreacted methods */
+@interface VLCVideoView (Deprecated)
+- (void)setStretchesVideo:(BOOL)value;
+- (BOOL)stretchesVideo;
+
+- (void)addVoutSubview:(NSView *)aView;  /* (Scheduled to deletion) */
+- (void)removeVoutSubview:(NSView *)aView;  /* (Scheduled to deletion) */
+@end
+
+/******************************************************************************
+ * VLCVideoView (Private) 
+ */
+@interface VLCVideoView ()
+/* Property */
+@property (readwrite, assign) BOOL fullscreen;
+@end
+
+@interface VLCVideoView (Private)
+/* Method */
+- (void)addVoutLayer:(CALayer *)aLayer;
+@end
+
+
+
+/******************************************************************************
+ * Interface & Implementation VLCConstraintLayoutManager
+ *
+ * Manage the size of the video layer 
+ */
+@interface VLCConstraintLayoutManager : CAConstraintLayoutManager
+{
+    CGSize originalVideoSize;
+    BOOL  fillScreenEntirely;
+}
+@property BOOL  fillScreenEntirely;
+@property CGSize originalVideoSize;
+@end
+
+@implementation VLCConstraintLayoutManager 
+@synthesize  fillScreenEntirely;
+@synthesize  originalVideoSize;
+- (id)init
+{
+    if( self = [super init] )
+    {
+        self.originalVideoSize = CGSizeMake(0., 0.);
+        self.fillScreenEntirely = NO;
+    }
+    return self;
+
+}
++ (id)layoutManager
+{
+    return [[[VLCConstraintLayoutManager alloc] init] autorelease];
+}
+- (void)layoutSublayersOfLayer:(CALayer *)layer
+{
+    /* Called by CA, when our rootLayer needs layout */
+    [super layoutSublayersOfLayer:layer];
+
+    /* After having done everything normally resize the vlcopengllayer */
+    if( [[layer sublayers] count] > 0 && [[[[layer sublayers] objectAtIndex:0] name] isEqualToString:@"vlcopengllayer"])
+    {
+        CALayer * videolayer = [[layer sublayers] objectAtIndex:0];
+        CGRect bounds = layer.bounds;
+        float new_height = (bounds.size.width * originalVideoSize.height) / originalVideoSize.width;
+
+        if( fillScreenEntirely )
+        {
+            if( bounds.size.height > new_height )
+                bounds.size.height = new_height;
+            else
+                bounds.size.width = (bounds.size.height * originalVideoSize.width) / originalVideoSize.height;
+        }
+        else
+        {
+            if( bounds.size.height > new_height )
+                bounds.size.width = (bounds.size.height * originalVideoSize.width) / originalVideoSize.height;
+            else
+                bounds.size.height = new_height;
+        }
+
+        bounds.origin = CGPointMake( 0.0, 0.0 );
+        videolayer.bounds = bounds;
+        videolayer.position = CGPointMake((layer.bounds.size.width - layer.bounds.origin.x)/2, (layer.bounds.size.height - layer.bounds.origin.y)/2);
+    }
+}
+@end
+
+/******************************************************************************
+ * Implementation VLCVideoView 
+ */
+
 @implementation VLCVideoView
+@synthesize fullscreen;
+
+- (BOOL)fillScreen
+{
+    return [layoutManager fillScreenEntirely];
+}
+- (void)setFillScreen:(BOOL)fillScreen
+{
+    [layoutManager setFillScreenEntirely:fillScreen];
+    [[self layer] setNeedsLayout];
+}
+
+
 - (id)initWithFrame:(NSRect)rect
 {
     if (self = [super initWithFrame:rect]) 
@@ -50,12 +162,15 @@ NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
         [self setBackColor:[NSColor blackColor]];
         [self setStretchesVideo:NO];
         [self setAutoresizesSubviews:YES];
+        [self setFillScreen: NO];
+        layoutManager = [VLCConstraintLayoutManager layoutManager];
     }
     return self;
 }
 
 - (void)dealloc
 {
+    [layoutManager release];
     delegate = nil;
     [backColor release];
     [super dealloc];
@@ -85,45 +200,6 @@ NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
     return backColor;
 }
 
-- (void)setStretchesVideo:(BOOL)value
-{
-    stretchesVideo = value;
-}
-
-- (BOOL)stretchesVideo
-{
-    return stretchesVideo;
-}
-
-/* This is called by the libvlc module 'minimal_macosx' as soon as there is one 
- * vout available 
- */
-- (void)addVoutSubview:(NSView *)aView
-{
-    if( [[self subviews] count] )
-    {
-        /* XXX: This is a hack until core gets fixed */
-        int i;
-        for( i = 0; i < [[self subviews] count]; i++ )
-        {
-            [[[self subviews] objectAtIndex:i] detachFromVout];
-            [[[self subviews] objectAtIndex:i] retain];
-            [[[self subviews] objectAtIndex:i] removeFromSuperview];
-        }
-    }
-    [self addSubview:aView];
-    [aView setFrame:[self bounds]];
-    
-    // TODO: Should we let the media player specify these values?
-    [aView setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
-}
-
-- (void)removeVoutSubview:(NSView *)view
-{
-    // Should we do something?  I don't know, however the protocol requires
-    // this to be implemented
-}
-
 /* This is a LibVLC notification that we're about to enter into full screen,
    there is no other place where I can see where we can trap this event */
 - (void)enterFullscreen
@@ -133,7 +209,8 @@ NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
                                                    withDelegateMethod:nil 
                                                  withNotificationName:VLCVideoViewEnteredFullScreen];
     
-    // There is nothing else to do, as this object strictly displays the video feed
+    [super enterFullScreenMode:[[self window] screen] withOptions:nil];
+    self.fullscreen = YES;
 }
 
 /* This is a LibVLC notification that we're about to enter leaving full screen,
@@ -146,6 +223,8 @@ NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
                                                  withNotificationName:VLCVideoViewLeftFullScreen];
     
     // There is nothing else to do, as this object strictly displays the video feed
+    [super exitFullScreenModeWithOptions:nil];
+    self.fullscreen = NO;
 }
 
 - (void)drawRect:(NSRect)aRect
@@ -160,4 +239,93 @@ NSString *VLCVideoViewLeftFullScreen = @"VLCVideoViewLeftFullScreen";
 {
     return YES;
 }
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+    if([theEvent clickCount] != 2)
+        return;
+    if(self.fullscreen)
+        [self leaveFullscreen];
+    else
+        [self enterFullscreen];
+}
+@end
+
+/******************************************************************************
+ * Implementation VLCVideoView  (Private)
+ */
+
+@implementation VLCVideoView (Private)
+
+/* This is called by the libvlc module 'opengllayer' as soon as there is one 
+ * vout available
+ */
+- (void)addVoutLayer:(CALayer *)aLayer
+{
+    [CATransaction begin];
+    [self setWantsLayer: YES];
+       CALayer * rootLayer = [self layer];
+
+    aLayer.name = @"vlcopengllayer";
+
+    [layoutManager setOriginalVideoSize:aLayer.bounds.size];
+    [rootLayer setLayoutManager:layoutManager];
+    [rootLayer insertSublayer:aLayer atIndex:0];
+
+    [aLayer setNeedsLayout];
+    [aLayer setNeedsDisplay];
+    [rootLayer setNeedsDisplay];
+    [rootLayer layoutIfNeeded];
+    [CATransaction commit];
+}
+
+@end
+
+/******************************************************************************
+ * Implementation VLCVideoView  (Deprecated)
+ */
+
+@implementation VLCVideoView (Deprecated)
+
+- (void)setStretchesVideo:(BOOL)value
+{
+    stretchesVideo = value;
+}
+
+- (BOOL)stretchesVideo
+{
+    return stretchesVideo;
+}
+
+/* This is called by the libvlc module 'minimal_macosx' as soon as there is one 
+ * vout available
+ */
+- (void)addVoutSubview:(NSView *)aView /* (Scheduled to deletion) */
+{
+    /* This is where the real video comes from */
+    if( [[self subviews] count] )
+    {
+        /* XXX: This is a hack until core gets fixed */
+        int i;
+        for( i = 0; i < [[self subviews] count]; i++ )
+        {
+            [[[self subviews] objectAtIndex:i] detachFromVout];
+            [[[self subviews] objectAtIndex:i] retain];
+            [[[self subviews] objectAtIndex:i] removeFromSuperview];
+        }
+    }
+
+    [aView setFrame:[self bounds]];
+    
+    [self addSubview:aView];
+
+    // TODO: Should we let the media player specify these values?
+    [aView setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
+}
+
+- (void)removeVoutSubview:(NSView *)view /* (Scheduled to deletion) */
+{
+    // Should we do something?  I don't know, however the protocol requires
+    // this to be implemented
+}
 @end