summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkemi <der.richter@gmx.de>2018-06-06 17:04:40 +0200
committerJan Ekström <jeebjp@gmail.com>2018-06-12 01:51:01 +0300
commit5865086aa84cae5e5505698ccf115a53a1b6b4fa (patch)
tree416b5ce30ae4c4d35af4130aa1956757fb6252ff
parent20dffe0621b3e26674850ef0b46ba3e689931d87 (diff)
downloadmpv-5865086aa84cae5e5505698ccf115a53a1b6b4fa.tar.bz2
mpv-5865086aa84cae5e5505698ccf115a53a1b6b4fa.tar.xz
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.
-rw-r--r--osdep/macOS_mpv_helper.swift7
-rw-r--r--osdep/macOS_swift_bridge.h1
-rw-r--r--osdep/macosx_application.h5
-rw-r--r--osdep/macosx_application.m70
-rw-r--r--osdep/macosx_application_objc.h2
-rw-r--r--video/out/cocoa-cb/events_view.swift5
-rw-r--r--video/out/cocoa-cb/video_layer.swift30
-rw-r--r--video/out/cocoa-cb/window.swift74
-rw-r--r--video/out/cocoa_cb_common.swift104
9 files changed, 158 insertions, 140 deletions
diff --git a/osdep/macOS_mpv_helper.swift b/osdep/macOS_mpv_helper.swift
index b023c4f098..e1fb3cf6cb 100644
--- a/osdep/macOS_mpv_helper.swift
+++ b/osdep/macOS_mpv_helper.swift
@@ -21,6 +21,12 @@ import OpenGL.GL3
let glDummy: @convention(c) () -> Void = {}
+extension Bool {
+ init(_ num: Int32) {
+ self.init(num > 0)
+ }
+}
+
class MPVHelper: NSObject {
var mpvHandle: OpaquePointer?
@@ -28,6 +34,7 @@ class MPVHelper: NSObject {
var mpvLog: OpaquePointer?
var inputContext: OpaquePointer?
var mpctx: UnsafeMutablePointer<MPContext>?
+ var macOpts: macos_opts?
var fbo: GLint = 1
init(_ mpv: OpaquePointer) {
diff --git a/osdep/macOS_swift_bridge.h b/osdep/macOS_swift_bridge.h
index b0121d2a0f..4204b514d1 100644
--- a/osdep/macOS_swift_bridge.h
+++ b/osdep/macOS_swift_bridge.h
@@ -23,6 +23,7 @@
#include "video/out/libmpv.h"
#include "libmpv/render_gl.h"
+#include "options/m_config.h"
#include "player/core.h"
#include "input/input.h"
#include "video/out/win_state.h"
diff --git a/osdep/macosx_application.h b/osdep/macosx_application.h
index 96a861fa35..c04f479c5b 100644
--- a/osdep/macosx_application.h
+++ b/osdep/macosx_application.h
@@ -20,6 +20,11 @@
#include "osdep/macosx_menubar.h"
+struct macos_opts {
+ int macos_title_bar_style;
+ int macos_fs_animation_duration;
+};
+
// multithreaded wrapper for mpv_main
int cocoa_main(int argc, char *argv[]);
void cocoa_register_menu_item_action(MPMenuKey key, void* action);
diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m
index 4bc8eec0eb..66daa45909 100644
--- a/osdep/macosx_application.m
+++ b/osdep/macosx_application.m
@@ -40,11 +40,6 @@
#define MPV_PROTOCOL @"mpv://"
-struct macos_opts {
- int macos_title_bar_style;
- int macos_fs_animation_duration;
-};
-
#define OPT_BASE_STRUCT struct macos_opts
const struct m_sub_options macos_conf = {
.opts = (const struct m_option[]) {
@@ -66,13 +61,7 @@ const struct m_sub_options macos_conf = {
// running in libmpv mode, and cocoa_main() was never called.
static bool application_instantiated;
-struct playback_thread_ctx {
- int *argc;
- char ***argv;
-};
-
static pthread_t playback_thread_id;
-static struct playback_thread_ctx thread_ctx = {0};
@interface Application ()
{
@@ -92,18 +81,6 @@ static void terminate_cocoa_application(void)
[NSApp terminate:NSApp];
}
-static void *playback_thread(void *ctx_obj)
-{
- mpthread_set_name("playback core (OSX)");
- @autoreleasepool {
- struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj;
- int r = mpv_main(*ctx->argc, *ctx->argv);
- terminate_cocoa_application();
- // normally never reached - unless the cocoa mainloop hasn't started yet
- exit(r);
- }
-}
-
@implementation Application
@synthesize menuBar = _menu_bar;
@synthesize openCount = _open_count;
@@ -141,12 +118,6 @@ static void *playback_thread(void *ctx_obj)
[super dealloc];
}
-- (void)initMPVCore
-{
- pthread_create(&playback_thread_id, NULL, playback_thread, &thread_ctx);
- [[EventsResponder sharedInstance] waitForInputContext];
-}
-
static const char macosx_icon[] =
#include "osdep/macosx_icon.inc"
;
@@ -187,9 +158,14 @@ static const char macosx_icon[] =
- (void)setMpvHandle:(struct mpv_handle *)ctx
{
- if (_cocoa_cb) {
- [_cocoa_cb setMpvHandle:ctx];
- }
+#if HAVE_MACOS_COCOA_CB
+ [NSApp setCocoaCB:[[CocoaCB alloc] init:ctx]];
+#endif
+}
+
+- (const struct m_sub_options *)getMacOSConf
+{
+ return &macos_conf;
}
- (void)queueCommand:(char *)cmd
@@ -255,6 +231,11 @@ static const char macosx_icon[] =
}
@end
+struct playback_thread_ctx {
+ int *argc;
+ char ***argv;
+};
+
static void cocoa_run_runloop(void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -262,6 +243,18 @@ static void cocoa_run_runloop(void)
[pool drain];
}
+static void *playback_thread(void *ctx_obj)
+{
+ mpthread_set_name("playback core (OSX)");
+ @autoreleasepool {
+ struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj;
+ int r = mpv_main(*ctx->argc, *ctx->argv);
+ terminate_cocoa_application();
+ // normally never reached - unless the cocoa mainloop hasn't started yet
+ exit(r);
+ }
+}
+
void cocoa_register_menu_item_action(MPMenuKey key, void* action)
{
if (application_instantiated)
@@ -274,10 +267,6 @@ static void init_cocoa_application(bool regular)
[NSApp setDelegate:NSApp];
[NSApp setMenuBar:[[MenuBar alloc] init]];
-#if HAVE_MACOS_COCOA_CB
- [NSApp setCocoaCB:[[CocoaCB alloc] init]];
-#endif
-
// Will be set to Regular from cocoa_common during UI creation so that we
// don't create an icon when playing audio only files.
[NSApp setActivationPolicy: regular ?
@@ -339,8 +328,9 @@ int cocoa_main(int argc, char *argv[])
application_instantiated = true;
[[EventsResponder sharedInstance] setIsApplication:YES];
- thread_ctx.argc = &argc;
- thread_ctx.argv = &argv;
+ struct playback_thread_ctx ctx = {0};
+ ctx.argc = &argc;
+ ctx.argv = &argv;
if (bundle_started_from_finder(argv)) {
setup_bundle(&argc, argv);
@@ -353,8 +343,8 @@ int cocoa_main(int argc, char *argv[])
init_cocoa_application(false);
}
- if (![NSApp cocoaCB])
- [NSApp initMPVCore];
+ pthread_create(&playback_thread_id, NULL, playback_thread, &ctx);
+ [[EventsResponder sharedInstance] waitForInputContext];
cocoa_run_runloop();
// This should never be reached: cocoa_run_runloop blocks until the
diff --git a/osdep/macosx_application_objc.h b/osdep/macosx_application_objc.h
index 22e6f7e525..1685c99ba8 100644
--- a/osdep/macosx_application_objc.h
+++ b/osdep/macosx_application_objc.h
@@ -31,7 +31,7 @@ struct mpv_handle;
- (void)stopMPV:(char *)cmd;
- (void)openFiles:(NSArray *)filenames;
- (void)setMpvHandle:(struct mpv_handle *)ctx;
-- (void)initMPVCore;
+- (const struct m_sub_options *)getMacOSConf;
@property(nonatomic, retain) MenuBar *menuBar;
@property(nonatomic, assign) size_t openCount;
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<vo>) {
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<macos_opts>(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<vo>) {
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<vo>) {
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<vo>) {
- 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<vo>) {
+ 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<mpv_event>) {
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) {