From 5865086aa84cae5e5505698ccf115a53a1b6b4fa Mon Sep 17 00:00:00 2001 From: Akemi Date: Wed, 6 Jun 2018 17:04:40 +0200 Subject: cocoa-cb: remove pre-allocation of window, view and layer the pre-allocation was needed because the layer allocated a opengl context async itself and we couldn't influence that. so we had to start the core after the context was actually allocated. furthermore a window, view and layer hierarchy had to be created so the layer would create a context. now, instead of relying on the layer to create a context we do this manually and re-use that context later when the layer wants to create one async itself. --- video/out/cocoa-cb/events_view.swift | 5 +- video/out/cocoa-cb/video_layer.swift | 30 ++++------ video/out/cocoa-cb/window.swift | 74 ++++++++++++++++--------- video/out/cocoa_cb_common.swift | 104 +++++++++++++++++------------------ 4 files changed, 114 insertions(+), 99 deletions(-) (limited to 'video/out') diff --git a/video/out/cocoa-cb/events_view.swift b/video/out/cocoa-cb/events_view.swift index 7cc6a4022d..7cc295f362 100644 --- a/video/out/cocoa-cb/events_view.swift +++ b/video/out/cocoa-cb/events_view.swift @@ -31,9 +31,9 @@ class EventsView: NSView { override var acceptsFirstResponder: Bool { return true } - init(frame frameRect: NSRect, cocoaCB ccb: CocoaCB) { + init(cocoaCB ccb: CocoaCB) { cocoaCB = ccb - super.init(frame: frameRect) + super.init(frame: NSMakeRect(0, 0, 960, 480)) autoresizingMask = [.viewWidthSizable, .viewHeightSizable] wantsBestResolutionOpenGLSurface = true register(forDraggedTypes: [NSFilenamesPboardType, NSURLPboardType]) @@ -249,6 +249,7 @@ class EventsView: NSView { } func canHideCursor() -> Bool { + if cocoaCB.window == nil { return false } return !hasMouseDown && containsMouseLocation() && window!.isKeyWindow } diff --git a/video/out/cocoa-cb/video_layer.swift b/video/out/cocoa-cb/video_layer.swift index 2e347ba22e..c600b06b6c 100644 --- a/video/out/cocoa-cb/video_layer.swift +++ b/video/out/cocoa-cb/video_layer.swift @@ -61,7 +61,15 @@ class VideoLayer: CAOpenGLLayer { super.init() autoresizingMask = [.layerWidthSizable, .layerHeightSizable] backgroundColor = NSColor.black.cgColor - contentsScale = cocoaCB.window.backingScaleFactor + + CGLCreateContext(copyCGLPixelFormat(forDisplayMask: 0), nil, &cglContext) + var i: GLint = 1 + CGLSetParameter(cglContext!, kCGLCPSwapInterval, &i) + CGLSetCurrentContext(cglContext!) + + mpv.initRender() + mpv.setRenderUpdateCallback(updateCallback, context: self) + mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB) } override init(layer: Any) { @@ -74,12 +82,6 @@ class VideoLayer: CAOpenGLLayer { fatalError("init(coder:) has not been implemented") } - func setUpRender() { - mpv.initRender() - mpv.setRenderUpdateCallback(updateCallback, context: self) - mpv.setRenderControlCallback(cocoaCB.controlCallback, context: cocoaCB) - } - override func canDraw(inCGLContext ctx: CGLContextObj, pixelFormat pf: CGLPixelFormatObj, forLayerTime t: CFTimeInterval, @@ -177,23 +179,15 @@ class VideoLayer: CAOpenGLLayer { if err != kCGLNoError || pix == nil { let errS = String(cString: CGLErrorString(err)) - print("Couldn't create CGL pixel format: \(errS) (\(err.rawValue))") + mpv.sendError("Couldn't create CGL pixel format: \(errS) (\(err.rawValue))") exit(1) } return pix! } override func copyCGLContext(forPixelFormat pf: CGLPixelFormatObj) -> CGLContextObj { - let ctx = super.copyCGLContext(forPixelFormat: pf) - var i: GLint = 1 - CGLSetParameter(ctx, kCGLCPSwapInterval, &i) - CGLSetCurrentContext(ctx) - cglContext = ctx - - if let app = NSApp as? Application { - app.initMPVCore() - } - return ctx + contentsScale = cocoaCB.window.backingScaleFactor + return cglContext! } let updateCallback: mpv_render_update_fn = { (ctx) in diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift index b3db7aeb8f..907476fc09 100644 --- a/video/out/cocoa-cb/window.swift +++ b/video/out/cocoa-cb/window.swift @@ -78,28 +78,23 @@ class Window: NSWindow, NSWindowDelegate { } } - convenience init(cocoaCB ccb: CocoaCB) { - self.init(contentRect: NSMakeRect(0, 0, 960, 480), - styleMask: [.titled, .closable, .miniaturizable, .resizable], - backing: .buffered, defer: false, screen: NSScreen.main()) - cocoaCB = ccb - title = "mpv" - } - - convenience init(contentRect: NSRect, styleMask style: NSWindowStyleMask, - screen: NSScreen?, cocoaCB ccb: CocoaCB) - { - self.init(contentRect: contentRect, styleMask: style, + convenience init(contentRect: NSRect, screen: NSScreen?, view: NSView, cocoaCB ccb: CocoaCB) { + self.init(contentRect: contentRect, + styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: false, screen: screen) cocoaCB = ccb + title = cocoaCB.title minSize = NSMakeSize(160, 90) collectionBehavior = .fullScreenPrimary delegate = self + contentView!.addSubview(view) + view.frame = contentView!.frame unfsContentFrame = convertToScreen(contentView!.frame) targetScreen = screen! currentScreen = screen! unfScreen = screen! + initTitleBar() if let app = NSApp as? Application { app.menuBar.register(#selector(setHalfWindowSize), for: MPM_H_SIZE) @@ -123,14 +118,31 @@ class Window: NSWindow, NSWindowDelegate { titleBarEffect!.blendingMode = .withinWindow titleBarEffect!.autoresizingMask = [.viewWidthSizable, .viewMinYMargin] - setTitleBarStyle(mpv.getStringProperty("macos-title-bar-style") ?? "dark") + setTitleBarStyle(Int(mpv.macOpts!.macos_title_bar_style)) contentView!.addSubview(titleBarEffect!, positioned: .above, relativeTo: nil) - - border = mpv.getBoolProperty("border") } - func setTitleBarStyle(_ style: String) { - var effect = style + func setTitleBarStyle(_ style: Any) { + var effect: String + + if style is Int { + switch style as! Int { + case 4: + effect = "auto" + case 3: + effect = "mediumlight" + case 2: + effect = "light" + case 1: + effect = "ultradark" + case 0: fallthrough + default: + effect = "dark" + } + } else { + effect = style as! String + } + if effect == "auto" { let systemStyle = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") effect = systemStyle == nil ? "mediumlight" : "ultradark" @@ -339,16 +351,26 @@ class Window: NSWindow, NSWindowDelegate { } } - func setOnTop(_ state: Bool) { + func setOnTop(_ state: Bool, _ ontopLevel: Any) { if state { - let ontopLevel = mpv.getStringProperty("ontop-level") ?? "window" - switch ontopLevel { - case "window": - level = Int(CGWindowLevelForKey(.floatingWindow)) - case "system": - level = Int(CGWindowLevelForKey(.statusWindow))+1 - default: - level = Int(ontopLevel)! + if ontopLevel is Int { + switch ontopLevel as! Int { + case -1: + level = Int(CGWindowLevelForKey(.floatingWindow)) + case -2: + level = Int(CGWindowLevelForKey(.statusWindow))+1 + default: + level = ontopLevel as! Int + } + } else { + switch ontopLevel as! String { + case "window": + level = Int(CGWindowLevelForKey(.floatingWindow)) + case "system": + level = Int(CGWindowLevelForKey(.statusWindow))+1 + default: + level = Int(ontopLevel as! String)! + } } collectionBehavior.remove(.transient) collectionBehavior.insert(.managed) diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 32e1d42b28..e6705902c4 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -30,6 +30,10 @@ class CocoaCB: NSObject { var cursorVisibilityWanted: Bool = true var isShuttingDown: Bool = false + var title: String = "mpv" { + didSet { if window != nil { window.title = title } } + } + enum State { case uninit case needsInit @@ -47,31 +51,29 @@ class CocoaCB: NSObject { let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue") - override init() { - super.init() - window = Window(cocoaCB: self) - - view = EventsView(frame: window.contentView!.bounds, cocoaCB: self) - window.contentView!.addSubview(view) - + convenience init(_ mpvHandle: OpaquePointer) { + self.init() + mpv = MPVHelper(mpvHandle) layer = VideoLayer(cocoaCB: self) - view.layer = layer - view.wantsLayer = true - view.layerContentsPlacement = .scaleProportionallyToFit - } - - func setMpvHandle(_ ctx: OpaquePointer) { - mpv = MPVHelper(ctx) - layer.setUpRender() } - func preinit() { + func preinit(_ vo: UnsafeMutablePointer) { if backendState == .uninit { backendState = .needsInit - DispatchQueue.main.async { - self.updateICCProfile() + + if let app = NSApp as? Application { + let ptr = mp_get_config_group(mpv.mpctx!, vo.pointee.global, + app.getMacOSConf()) + mpv.macOpts = UnsafeMutablePointer(OpaquePointer(ptr))!.pointee } - startDisplayLink() + + view = EventsView(cocoaCB: self) + view.layer = layer + view.wantsLayer = true + view.layerContentsPlacement = .scaleProportionallyToFit + startDisplayLink(vo) + initLightSensor() + addDisplayReconfigureObserver() } } @@ -82,39 +84,37 @@ class CocoaCB: NSObject { func reconfig(_ vo: UnsafeMutablePointer) { if backendState == .needsInit { - initBackend(vo) + DispatchQueue.main.sync { self.initBackend(vo) } } else { - layer.setVideo(true) - updateWindowSize(vo) - layer.update() + DispatchQueue.main.async { + self.layer.setVideo(true) + self.updateWindowSize(vo) + self.layer.update() + } } } func initBackend(_ vo: UnsafeMutablePointer) { let opts: mp_vo_opts = vo.pointee.opts.pointee NSApp.setActivationPolicy(.regular) + setAppIcon() - let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main() + let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main() let wr = getWindowGeometry(forScreen: targetScreen!, videoOut: vo) - let win = Window(contentRect: wr, styleMask: window.styleMask, - screen: targetScreen, cocoaCB: self) - win.title = window.title - win.setOnTop(mpv.getBoolProperty("ontop")) - win.keepAspect = mpv.getBoolProperty("keepaspect-window") - window.close() - window = win - window.contentView!.addSubview(view) - view.frame = window.contentView!.frame - window.initTitleBar() + window = Window(contentRect: wr, screen: targetScreen, view: view, cocoaCB: self) + updateICCProfile() + window.setOnTop(Bool(opts.ontop), Int(opts.ontop_level)) + window.keepAspect = Bool(opts.keepaspect_window) + window.title = title + window.border = Bool(opts.border) - setAppIcon() window.isRestorable = false window.makeMain() window.makeKeyAndOrderFront(nil) NSApp.activate(ignoringOtherApps: true) layer.setVideo(true) - if mpv.getBoolProperty("fullscreen") { + if Bool(opts.fullscreen) { DispatchQueue.main.async { self.window.toggleFullScreen(nil) } @@ -122,13 +122,12 @@ class CocoaCB: NSObject { window.isMovableByWindowBackground = true } - initLightSensor() - addDisplayReconfigureObserver() backendState = .init } func updateWindowSize(_ vo: UnsafeMutablePointer) { - let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main() + let opts: mp_vo_opts = vo.pointee.opts.pointee + let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main() let wr = getWindowGeometry(forScreen: targetScreen!, videoOut: vo) if !window.isVisible { window.makeKeyAndOrderFront(nil) @@ -155,8 +154,11 @@ class CocoaCB: NSObject { return kCVReturnSuccess } - func startDisplayLink() { - let displayId = UInt32(window.screen!.deviceDescription["NSScreenNumber"] as! Int) + func startDisplayLink(_ vo: UnsafeMutablePointer) { + let opts: mp_vo_opts = vo.pointee.opts.pointee + let screen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main() + let displayId = screen!.deviceDescription["NSScreenNumber"] as! UInt32 + CVDisplayLinkCreateWithActiveCGDisplays(&link) CVDisplayLinkSetCurrentCGDisplay(link!, displayId) if #available(macOS 10.12, *) { @@ -324,8 +326,8 @@ class CocoaCB: NSObject { } func getTargetScreen(forFullscreen fs: Bool) -> NSScreen? { - let screenID = fs ? mpv.getStringProperty("fs-screen") ?? "current": - mpv.getStringProperty("screen") ?? "current" + let screenType = fs ? "fs-screen" : "screen" + let screenID = mpv.getStringProperty(screenType) ?? "current" switch screenID { case "current", "default", "all": @@ -432,21 +434,17 @@ class CocoaCB: NSObject { let titleData = data!.assumingMemoryBound(to: Int8.self) let title = String(cString: titleData) DispatchQueue.main.async { - ccb.window.title = String(cString: titleData) + ccb.title = String(cString: titleData) } return VO_TRUE case VOCTRL_PREINIT: - ccb.preinit() + DispatchQueue.main.sync { ccb.preinit(vo!) } return VO_TRUE case VOCTRL_UNINIT: - DispatchQueue.main.async { - ccb.uninit() - } + DispatchQueue.main.async { ccb.uninit() } return VO_TRUE case VOCTRL_RECONFIG: - DispatchQueue.main.async { - ccb.reconfig(vo!) - } + ccb.reconfig(vo!) return VO_TRUE default: return VO_NOTIMPL @@ -472,7 +470,7 @@ class CocoaCB: NSObject { func processEvent(_ event: UnsafePointer) { switch event.pointee.event_id { case MPV_EVENT_SHUTDOWN: - if window.isAnimating { + if window != nil && window.isAnimating { isShuttingDown = true return } @@ -499,7 +497,7 @@ class CocoaCB: NSObject { } case "ontop": if let data = MPVHelper.mpvFlagToBool(property.data) { - window.setOnTop(data) + window.setOnTop(data, mpv.getStringProperty("ontop-level") ?? "window") } case "keepaspect-window": if let data = MPVHelper.mpvFlagToBool(property.data) { -- cgit v1.2.3