[vlc-commits] [Git][videolan/vlc][master] 3 commits: macosx: update Xcode project to recommended settings

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Wed Dec 8 14:58:51 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
18cd6b6a by Marvin Scholz at 2021-12-08T14:43:31+00:00
macosx: update Xcode project to recommended settings

Makes new versions of Xcode happy.

- - - - -
d7cf9a8d by Marvin Scholz at 2021-12-08T14:43:31+00:00
vout: macosx: add standalone window provider

Initial version of a standalone vout window provider for macOS,
it still lacks mouse handling and only works if the macosx inteface
module was loaded (or NSApp was initialized by other means).

- - - - -
c8797d1a by Marvin Scholz at 2021-12-08T14:43:31+00:00
macosx: add standalone vout window to Xcode project

- - - - -


3 changed files:

- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- modules/video_output/Makefile.am
- + modules/video_output/window_macosx.m


Changes:

=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -80,6 +80,7 @@
 		6B0292E61F43256300A50082 /* VLCBottomBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0292E51F43256300A50082 /* VLCBottomBarView.m */; };
 		6B0AB0F01F1AC8B3003A1B4E /* VLCSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0ED1F1AC8B3003A1B4E /* VLCSlider.m */; };
 		6B0AB0F11F1AC8B3003A1B4E /* VLCSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B0AB0EF1F1AC8B3003A1B4E /* VLCSliderCell.m */; };
+		6B196852265E974400870512 /* window_macosx.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B19684F265E928A00870512 /* window_macosx.m */; };
 		6B2EFC601F2819F700F3C0EA /* VLCVolumeSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B2EFC5F1F2819F700F3C0EA /* VLCVolumeSlider.m */; };
 		6B2EFC631F281A0900F3C0EA /* VLCVolumeSliderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B2EFC621F281A0900F3C0EA /* VLCVolumeSliderCell.m */; };
 		6B397C4F216C8EB200403ED0 /* NSString+Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B397C4E216C8EB200403ED0 /* NSString+Helpers.m */; };
@@ -231,6 +232,7 @@
 		6B0AB0EF1F1AC8B3003A1B4E /* VLCSliderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCSliderCell.m; sourceTree = "<group>"; };
 		6B13E2A61BC67678001AD24A /* VLCScrollingClipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCScrollingClipView.h; sourceTree = "<group>"; };
 		6B13E2A71BC67678001AD24A /* VLCScrollingClipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCScrollingClipView.m; sourceTree = "<group>"; };
+		6B19684F265E928A00870512 /* window_macosx.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = window_macosx.m; path = ../../../modules/video_output/window_macosx.m; sourceTree = "<group>"; };
 		6B2EFC5E1F2819F700F3C0EA /* VLCVolumeSlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCVolumeSlider.h; sourceTree = "<group>"; };
 		6B2EFC5F1F2819F700F3C0EA /* VLCVolumeSlider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCVolumeSlider.m; sourceTree = "<group>"; };
 		6B2EFC611F281A0900F3C0EA /* VLCVolumeSliderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCVolumeSliderCell.h; sourceTree = "<group>"; };
@@ -1534,6 +1536,7 @@
 		CCDDF1AE172FF4CE007729A1 /* vout */ = {
 			isa = PBXGroup;
 			children = (
+				6B19684F265E928A00870512 /* window_macosx.m */,
 				CCDBA3B313D32E200006127B /* macosx.m */,
 				7DBB06631CC2314D004C74D2 /* caopengllayer.m */,
 			);
@@ -1645,7 +1648,7 @@
 		089C1669FE841209C02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
-				LastUpgradeCheck = 1150;
+				LastUpgradeCheck = 1240;
 				TargetAttributes = {
 					1CCB5F2E1A62A6A5004C3E90 = {
 						CreatedOnToolsVersion = 6.1.1;
@@ -1835,6 +1838,7 @@
 			files = (
 				7D903EA92243921000917358 /* darwinvlc.m in Sources */,
 				7D903EB6224394BE00917358 /* specific.c in Sources */,
+				6B196852265E974400870512 /* window_macosx.m in Sources */,
 				7D903E0E22438F8F00917358 /* error.c in Sources */,
 				7D903E2222438F8F00917358 /* dirs.m in Sources */,
 				7D903E4D22438F8F00917358 /* netconf.m in Sources */,
@@ -2092,6 +2096,7 @@
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -2146,6 +2151,7 @@
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -2198,6 +2204,7 @@
 				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;


=====================================
modules/video_output/Makefile.am
=====================================
@@ -50,6 +50,12 @@ endif
 
 
 if HAVE_OSX
+libwindow_macosx_plugin_la_SOURCES = video_output/window_macosx.m
+libwindow_macosx_plugin_la_LDFLAGS = $(AM_LDFLAGS) \
+	-Wl,-framework,Cocoa
+libwindow_macosx_plugin_la_OBJCFLAGS = $(AM_OBJCFLAGS) \
+	-fobjc-arc -fobjc-exceptions
+
 libvout_macosx_plugin_la_SOURCES = video_output/macosx.m \
 	$(OPENGL_VOUT_COMMONSOURCES)
 libvout_macosx_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAVE_GL_CORE_SYMBOLS
@@ -64,7 +70,7 @@ libcaopengllayer_plugin_la_LIBADD = libvlc_opengl.la
 libcaopengllayer_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)' \
 	-Wl,-framework,OpenGL,-framework,Cocoa,-framework,QuartzCore
 
-vout_LTLIBRARIES += libvout_macosx_plugin.la libcaopengllayer_plugin.la
+vout_LTLIBRARIES += libvout_macosx_plugin.la libcaopengllayer_plugin.la libwindow_macosx_plugin.la
 endif
 
 libvout_ios_plugin_la_SOURCES = video_output/opengl/display.c $(OPENGL_VOUT_COMMONSOURCES)


=====================================
modules/video_output/window_macosx.m
=====================================
@@ -0,0 +1,590 @@
+/**
+ * @file window_macosx.m
+ * @brief macOS Window and View output provider
+ */
+
+/* Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * Authors: Marvin Scholz <epirat 07 at gmail dot com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#import <Cocoa/Cocoa.h>
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_window.h>
+
+#define VLC_ASSERT_MAINTHREAD NSAssert([[NSThread currentThread] isMainThread], \
+    @"Must be called from the main thread!")
+
+/**
+ * Style mask for a decorated window
+ */
+static const NSWindowStyleMask decoratedWindowStyleMask =
+    NSWindowStyleMaskTitled
+    | NSWindowStyleMaskClosable
+    | NSWindowStyleMaskMiniaturizable
+    | NSWindowStyleMaskResizable;
+
+/**
+ * Style mask for a non-decorated window
+ */
+static const NSWindowStyleMask undecoratedWindowStyleMask =
+    NSWindowStyleMaskBorderless
+    | NSWindowStyleMaskResizable;
+
+
+#pragma mark -
+#pragma mark Obj-C Interfaces
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Window delegate and Core interactions class
+ *
+ * Acts as delegate for the Window and handles communication
+ * of the window state from/to the core. This is not done directly
+ * in the window controller, as the module on VLCs side might be
+ * already gone when the window and its controller is still around
+ * so we need a separate object that we can invalidate as soon
+ * as the VLC module object is gone.
+ */
+ at interface VLCVideoWindowModuleDelegate : NSObject {
+    @private
+    // VLC window object, only use it on the eventQueue
+    vout_window_t*     vlc_vout_window;
+    dispatch_queue_t   eventQueue;
+
+    BOOL               _isViewSet;
+}
+
+- (instancetype)initWithVLCVoutWindow:(vout_window_t *)vout_window;
+
+/// Reports that the window is fullscreen now
+- (void)reportFullscreen;
+
+/// Reports that the previously fullscreen window is no longer fullscreen
+- (void)reportWindowed;
+
+/// Reports the new window size in pixels
+- (void)reportSizeChanged:(NSSize)newSize;
+
+/// Reports that the window was closed
+- (void)reportClose;
+
+ at end
+
+/**
+ * Video output window class
+ *
+ * Custom NSWindow subclass, mostly to overwrite that the window
+ * can become the key window even if its using the borderless
+ * (undecorated) style.
+ */
+ at interface VLCVideoWindow : NSWindow
+ at end
+
+
+/**
+ * Video view class
+ *
+ * Custom NSWindow subclass, used to track resizes so that
+ * the core can be notified about the new sizes in a timely manner.
+ */
+ at interface VLCVideoWindowContentView : NSView {
+    @private
+    __weak VLCVideoWindowModuleDelegate *_moduleDelegate;
+}
+
+- (instancetype)initWithModuleDelegate:(VLCVideoWindowModuleDelegate *)delegate;
+ at end
+
+/**
+ * Video output window controller class
+ *
+ * Controller for the VLC standalone video window (independent of the interface)
+ *
+ * Implements all interactions between the display module and the NSWindow
+ * class, except for resizes (which is handled by VLCVideoWindowContentView).
+ */
+ at interface VLCVideoStandaloneWindowController : NSWindowController <NSWindowDelegate> {
+ at private
+    __weak VLCVideoWindowModuleDelegate *_moduleDelegate;
+}
+
+- (instancetype)initWithModuleDelegate:(VLCVideoWindowModuleDelegate *)delegate;
+- (void)showWindowWithConfig:(const vout_window_cfg_t *restrict)config;
+
+/* Methods called by the callbacks to change properties of the Window */
+- (void)setWindowDecorated:(BOOL)decorated;
+- (void)setWindowFullscreen:(BOOL)fullscreen;
+
+ at end
+
+
+#pragma mark -
+#pragma mark Obj-C Implementations
+
+ at implementation VLCVideoWindowModuleDelegate : NSObject
+
+- (instancetype)initWithVLCVoutWindow:(vout_window_t *)vout_window
+{
+    NSAssert(vout_window != NULL,
+             @"VLCVideoWindowDelegate must be initialized with a valid vout_window");
+
+    self = [super init];
+    if (self) {
+        eventQueue = dispatch_queue_create("org.videolan.vlc.vout", DISPATCH_QUEUE_SERIAL);
+
+        vlc_vout_window = vout_window;
+    }
+
+    return self;
+}
+
+- (void)enqueueEventBlock:(void (^)(void))block
+{
+    dispatch_async(eventQueue, block);
+}
+
+- (void)setViewObject:(id)view
+{
+    NSAssert(_isViewSet == NO,
+             @"VLCVideoWindowDelegate's viewObject must only bet set once");
+    vlc_vout_window->type = VOUT_WINDOW_TYPE_NSOBJECT;
+    vlc_vout_window->handle.nsobject = (__bridge void*)view;
+}
+
+- (void)reportFullscreen
+{
+    [self enqueueEventBlock:^void (void) {
+        vout_window_ReportFullscreen(vlc_vout_window, NULL);
+    }];
+}
+
+- (void)reportWindowed
+{
+    [self enqueueEventBlock:^void (void) {
+        vout_window_ReportWindowed(vlc_vout_window);
+    }];
+}
+
+- (void)reportSizeChanged:(NSSize)newSize
+{
+    [self enqueueEventBlock:^void (void) {
+        vout_window_ReportSize(vlc_vout_window,
+                               (unsigned int)newSize.width,
+                               (unsigned int)newSize.height);
+    }];
+}
+
+- (void)reportClose
+{
+    [self enqueueEventBlock:^void (void) {
+        vout_window_ReportClose(vlc_vout_window);
+    }];
+}
+
+- (void)dealloc
+{
+    dispatch_sync(eventQueue, ^void (void) {
+        self->vlc_vout_window = NULL;
+    });
+}
+
+ at end
+
+
+ at implementation VLCVideoStandaloneWindowController
+
+/**
+ * Initializes the window controller with the given module delegate
+ */
+- (instancetype)initWithModuleDelegate:(VLCVideoWindowModuleDelegate *)delegate;
+{
+    VLC_ASSERT_MAINTHREAD;
+
+    NSWindow *window = [[NSWindow alloc] initWithContentRect:NSZeroRect
+                                                   styleMask:decoratedWindowStyleMask
+                                                     backing:NSBackingStoreBuffered
+                                                       defer:YES];
+
+    self = [super initWithWindow:window];
+    if (self) {
+        // Set the initial vout title
+        [window setTitle:[NSString stringWithUTF8String:VOUT_TITLE " (VLC Video Output)"]];
+
+        // The content always changes during live resize
+        [window setPreservesContentDuringLiveResize:NO];
+
+        // Do not release on close (we might want to re-open the window later)
+        [window setReleasedWhenClosed:NO];
+
+        // Hint that the window should become a primary fullscreen window
+        [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+
+        // Create and set custom content view for the window
+        VLCVideoWindowContentView *view =
+            [[VLCVideoWindowContentView alloc] initWithModuleDelegate:delegate];
+
+        if (view == nil)
+            return nil;
+
+        [window setContentView:view];
+
+        [window setDelegate:self];
+
+        // Position the window in the center
+        [window center];
+
+        [self setWindowFrameAutosaveName:@"VLCVideoStandaloneWindow"];
+
+        _moduleDelegate = delegate;
+
+        [_moduleDelegate setViewObject:view];
+    }
+
+    return self;
+}
+
+/**
+ * Applies the given config to the window and shows it.
+ */
+- (void)showWindowWithConfig:(const vout_window_cfg_t *restrict)config
+{
+    VLC_ASSERT_MAINTHREAD;
+
+    // Convert from backing to window coordinates
+    NSRect backingRect = NSMakeRect(0, 0, config->width, config->height);
+    NSRect windowRect = [self.window convertRectFromBacking:backingRect];
+    [self.window setContentSize:windowRect.size];
+
+    // Set decoration
+    [self setWindowDecorated:config->is_decorated];
+
+    // This should always be called last, to ensure we only show the
+    // window once its fully configured. Else there could be visible
+    // changes or animations when the config is applied.
+    [self showWindow:nil];
+    [self.window makeKeyAndOrderFront:nil];
+}
+
+- (BOOL)windowShouldClose:(NSWindow *)sender
+{
+    [_moduleDelegate reportClose];
+    return YES;
+}
+
+#pragma mark Helper methods
+
+- (BOOL)isWindowFullscreen
+{
+    return ((self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask);
+}
+
+#pragma mark Module interactions
+
+- (void)setWindowDecorated:(BOOL)decorated
+{
+    NSWindowStyleMask mask =
+        (decorated) ? decoratedWindowStyleMask : undecoratedWindowStyleMask;
+
+    [self.window setStyleMask:mask];
+}
+
+- (void)setWindowFullscreen:(BOOL)fullscreen
+{
+    if (!!fullscreen == !![self isWindowFullscreen]) {
+        // Nothing to do, just report the state to core
+        if (fullscreen) {
+            [_moduleDelegate reportFullscreen];
+        } else {
+            [_moduleDelegate reportWindowed];
+        }
+        return;
+    }
+
+    [self.window toggleFullScreen:nil];
+}
+
+#pragma mark Window delegate
+
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
+{
+    [_moduleDelegate reportFullscreen];
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+    [_moduleDelegate reportWindowed];
+}
+
+ at end
+
+
+
+ at implementation VLCVideoWindowContentView
+
+- (instancetype)initWithModuleDelegate:(VLCVideoWindowModuleDelegate *)delegate;
+{
+    self = [super init];
+    if (self) {
+        NSAssert(delegate != nil, @"Invalid VLCVideoWindowModuleDelegate passed.");
+        _moduleDelegate = delegate;
+    }
+    return self;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+    [[NSColor blackColor] setFill];
+    NSRectFill(dirtyRect);
+}
+
+/**
+ * Report the view size in the backing size dimensions to VLC core
+ */
+- (void)reportBackingSize
+{
+    NSRect bounds = [self convertRectToBacking:self.bounds];
+    [_moduleDelegate reportSizeChanged:bounds.size];
+}
+
+/**
+ * Handle view size changes
+ */
+- (void)resizeSubviewsWithOldSize:(NSSize)oldSize
+{
+    [self reportBackingSize];
+    [super resizeSubviewsWithOldSize:oldSize];
+}
+
+/**
+ * Handle view backing property changes
+ */
+- (void)viewDidChangeBackingProperties
+{
+    // When the view backing size changes, it means the view effectively
+    // resizes from VLC core perspective, as it operates on the real
+    // backing dimensions, not the view point size.
+    [self reportBackingSize];
+    [super viewDidChangeBackingProperties];
+}
+
+ at end
+
+ at implementation VLCVideoWindow
+
+- (BOOL)canBecomeKeyWindow
+{
+    // A window with NSWindowStyleMaskBorderless can usually not become key
+    // window, unless we return YES here.
+    return YES;
+}
+
+ at end
+
+NS_ASSUME_NONNULL_END
+
+
+#pragma mark -
+#pragma mark VLC module
+
+typedef struct
+{
+    VLCVideoStandaloneWindowController *windowController;
+    VLCVideoWindowModuleDelegate *delegate;
+} vout_window_sys_t;
+
+/* Enable Window
+ */
+static int WindowEnable(vout_window_t *wnd, const vout_window_cfg_t *restrict cfg)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_sync(dispatch_get_main_queue(), ^{
+            [weakWc showWindowWithConfig:cfg];
+        });
+    }
+
+    return VLC_SUCCESS;
+}
+
+/* Request to close the window */
+static void WindowDisable(vout_window_t *wnd)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [weakWc close];
+        });
+    }
+}
+
+/* Request to resize the window */
+static void WindowResize(vout_window_t *wnd, unsigned width, unsigned height)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            VLCVideoStandaloneWindowController *wc = weakWc;
+            // Convert from backing to window coordinates
+            NSRect backingRect = NSMakeRect(0, 0, width, height);
+            NSRect windowRect = [wc.window convertRectFromBacking:backingRect];
+            [wc.window setContentSize:windowRect.size];
+
+            // Size is reported by resizeSubviewsWithOldSize:, do not
+            // report it here, else it would get reported twice.
+        });
+    }
+}
+
+/* Request to enable/disable Window decorations */
+static void SetDecoration(vout_window_t *wnd, bool decorated)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [weakWc setWindowDecorated:decorated];
+        });
+    }
+}
+
+/* Request to enter fullscreen */
+static void WindowSetFullscreen(vout_window_t *wnd, const char *idstr)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [weakWc setWindowFullscreen:YES];
+        });
+    }
+}
+
+/* Request to exit fullscreen */
+static void WindowUnsetFullscreen(vout_window_t *wnd)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [weakWc setWindowFullscreen:NO];
+        });
+    }
+}
+
+static void WindowSetTitle(struct vout_window_t *wnd, const char *title)
+{
+    vout_window_sys_t *sys = wnd->sys;
+    @autoreleasepool {
+        __weak VLCVideoStandaloneWindowController *weakWc = sys->windowController;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [weakWc.window setTitle:[NSString stringWithUTF8String:title]];
+        });
+    }
+}
+
+/*
+ * Module destruction
+ */
+void Close(vout_window_t *wnd)
+{
+    vout_window_sys_t *sys = wnd->sys;
+
+    // ARC can not know when to release an object in a heap-allocated
+    // struct, so we need to explicitly set it to nil here.
+    sys->windowController = nil;
+    sys->delegate = nil;
+}
+
+/*
+ * Callbacks
+ */
+static const struct vout_window_operations ops = {
+    .enable = WindowEnable,
+    .disable = WindowDisable,
+    .resize = WindowResize,
+    .set_state = NULL,
+    .unset_fullscreen = WindowUnsetFullscreen,
+    .set_fullscreen = WindowSetFullscreen,
+    .set_title = WindowSetTitle,
+    .destroy = Close,
+};
+
+/*
+ * Module initialization
+ */
+int Open(vout_window_t *wnd)
+{
+    @autoreleasepool {
+        msg_Info(wnd, "using the macOS new video output window module");
+
+        // Check if there is an NSApplication, needed for the connection
+        // to the Window Server so we can use NSWindows, NSViews, etc.
+        if (NSApp == nil) {
+            msg_Err(wnd, "cannot create video output window without NSApplication");
+            return VLC_EGENERIC;
+        }
+
+        vout_window_sys_t *sys = vlc_obj_calloc(VLC_OBJECT(wnd), 1, sizeof(*sys));
+        if (unlikely(sys == NULL))
+            return VLC_ENOMEM;
+
+        VLCVideoWindowModuleDelegate *_moduleDelegate;
+        _moduleDelegate = [[VLCVideoWindowModuleDelegate alloc] initWithVLCVoutWindow:wnd];
+        if (unlikely(_moduleDelegate == nil))
+            return VLC_ENOMEM;
+        sys->delegate = _moduleDelegate;
+
+        __block VLCVideoStandaloneWindowController *_windowController;
+        dispatch_sync(dispatch_get_main_queue(), ^{
+            _windowController = [[VLCVideoStandaloneWindowController alloc] initWithModuleDelegate:_moduleDelegate];
+        });
+        if (unlikely(_windowController == nil))
+            return VLC_ENOMEM;
+        sys->windowController = _windowController;
+
+        wnd->ops = &ops;
+        wnd->sys = sys;
+
+        return VLC_SUCCESS;
+    }
+}
+
+/*
+ * Module declaration
+ */
+vlc_module_begin()
+    set_description("macOS Video Output Window")
+    set_capability("vout window", 1000)
+    set_callback(Open)
+vlc_module_end()



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/34d0186ecd6a1506e1f2cd65023c78f123ea4462...c8797d1a224baccae34db9b3c5185634ae5faa98

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/34d0186ecd6a1506e1f2cd65023c78f123ea4462...c8797d1a224baccae34db9b3c5185634ae5faa98
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list