From c8cc203735d73f62def2692d1027f45ac10c03db Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 30 Nov 2019 23:47:52 +0100 Subject: cocoa-cb: use m_config_cache and new VOCTRL for option handling this removes the direct access of the mp_vo_opts stuct via the vo struct and replaces it with the m_config_cache usage. this updates the fullscreen and window-minimized property via m_config_cache_write_opt instead of the old mechanism via VOCTRL and event flagging. also use the new VOCTRL_VO_OPTS_CHANGED event for fullscreen and border changes. --- osdep/macos/mpv_helper.swift | 41 ++++++++++++++++++++--- osdep/macos/swift_extensions.swift | 7 ++++ osdep/macosx_application.m | 5 +++ osdep/macosx_application_objc.h | 1 + video/out/cocoa-cb/window.swift | 8 ++--- video/out/cocoa_cb_common.swift | 67 +++++++++++++++++++------------------- 6 files changed, 87 insertions(+), 42 deletions(-) diff --git a/osdep/macos/mpv_helper.swift b/osdep/macos/mpv_helper.swift index ce1fb5ffec..5e97470a09 100644 --- a/osdep/macos/mpv_helper.swift +++ b/osdep/macos/mpv_helper.swift @@ -20,24 +20,41 @@ import Cocoa class MPVHelper: LogHelper { var vo: UnsafeMutablePointer + var optsCachePtr: UnsafeMutablePointer + var optsPtr: UnsafeMutablePointer + + // these computed properties return a local copy of the struct accessed: + // - don't use if you rely on the pointers + // - only for reading var vout: vo { get { return vo.pointee } } - var opts: mp_vo_opts { get { return vout.opts.pointee } } + var optsCache: m_config_cache { get { return optsCachePtr.pointee } } + var opts: mp_vo_opts { get { return optsPtr.pointee } } + var input: OpaquePointer { get { return vout.input_ctx } } var macOpts: macos_opts = macos_opts() init(_ vo: UnsafeMutablePointer, _ name: String) { self.vo = vo + + guard let app = NSApp as? Application, + let cache = m_config_cache_alloc(vo, vo.pointee.global, app.getVoSubConf()) else + { + print("NSApp couldn't be retrieved") + exit(1) + } + let newlog = mp_log_new(vo, vo.pointee.log, name) + optsCachePtr = cache + optsPtr = UnsafeMutablePointer(OpaquePointer(cache.pointee.opts)) super.init(newlog) - guard let app = NSApp as? Application, - let ptr = mp_get_config_group(vo, + guard let ptr = mp_get_config_group(vo, vo.pointee.global, app.getMacOSConf()) else { - sendError("macOS config group couldn't be retrieved'") - exit(1) + // will never be hit, mp_get_config_group asserts for invalid groups + return } macOpts = UnsafeMutablePointer(OpaquePointer(ptr)).pointee } @@ -59,6 +76,20 @@ class MPVHelper: LogHelper { mp_input_put_wheel(input, mpkey, delta) } + func nextChangedConfig(property: inout UnsafeMutableRawPointer?) -> Bool { + return m_config_cache_get_next_changed(optsCachePtr, &property) + } + + func setConfigProperty(fullscreen: Bool) { + optsPtr.pointee.fullscreen = Int32(fullscreen) + m_config_cache_write_opt(optsCachePtr, UnsafeMutableRawPointer(&optsPtr.pointee.fullscreen)) + } + + func setConfigProperty(minimized: Bool) { + optsPtr.pointee.window_minimized = Int32(minimized) + m_config_cache_write_opt(optsCachePtr, UnsafeMutableRawPointer(&optsPtr.pointee.window_minimized)) + } + func command(_ cmd: String) { let cCmd = UnsafePointer(strdup(cmd)) let mpvCmd = mp_input_parse_cmd(input, bstr0(cCmd), "") diff --git a/osdep/macos/swift_extensions.swift b/osdep/macos/swift_extensions.swift index c48ad6e798..a1aeb0abf7 100644 --- a/osdep/macos/swift_extensions.swift +++ b/osdep/macos/swift_extensions.swift @@ -80,3 +80,10 @@ extension Bool { self.init(int32 != 0) } } + +extension Int32 { + + init(_ bool: Bool) { + self.init(bool ? 1 : 0) + } +} diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m index a07f4f5db9..8b3fac95a4 100644 --- a/osdep/macosx_application.m +++ b/osdep/macosx_application.m @@ -189,6 +189,11 @@ static const char macosx_icon[] = return &macos_conf; } +- (const struct m_sub_options *)getVoSubConf +{ + return &vo_sub_opts; +} + - (void)queueCommand:(char *)cmd { [_eventsResponder queueCommand:cmd]; diff --git a/osdep/macosx_application_objc.h b/osdep/macosx_application_objc.h index 1685c99ba8..11959a83ea 100644 --- a/osdep/macosx_application_objc.h +++ b/osdep/macosx_application_objc.h @@ -32,6 +32,7 @@ struct mpv_handle; - (void)openFiles:(NSArray *)filenames; - (void)setMpvHandle:(struct mpv_handle *)ctx; - (const struct m_sub_options *)getMacOSConf; +- (const struct m_sub_options *)getVoSubConf; @property(nonatomic, retain) MenuBar *menuBar; @property(nonatomic, assign) size_t openCount; diff --git a/video/out/cocoa-cb/window.swift b/video/out/cocoa-cb/window.swift index 1ac0e2bc78..48f3210a22 100644 --- a/video/out/cocoa-cb/window.swift +++ b/video/out/cocoa-cb/window.swift @@ -182,7 +182,7 @@ class Window: NSWindow, NSWindowDelegate { func windowDidEnterFullScreen(_ notification: Notification) { isInFullscreen = true - cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) + cocoaCB.mpv?.setConfigProperty(fullscreen: isInFullscreen) cocoaCB.updateCusorVisibility() endAnimation(frame) cocoaCB.titleBar?.show() @@ -191,7 +191,7 @@ class Window: NSWindow, NSWindowDelegate { func windowDidExitFullScreen(_ notification: Notification) { guard let tScreen = targetScreen else { return } isInFullscreen = false - cocoaCB.flagEvents(VO_EVENT_FULLSCREEN_STATE) + cocoaCB.mpv?.setConfigProperty(fullscreen: isInFullscreen) endAnimation(calculateWindowPosition(for: tScreen, withoutBounds: targetScreen == screen)) cocoaCB.view?.layerContentsPlacement = .scaleProportionallyToFit } @@ -474,11 +474,11 @@ class Window: NSWindow, NSWindowDelegate { } func windowDidMiniaturize(_ notification: Notification) { - cocoaCB.flagEvents(VO_EVENT_WIN_STATE) + cocoaCB.mpv?.setConfigProperty(minimized: true) } func windowDidDeminiaturize(_ notification: Notification) { - cocoaCB.flagEvents(VO_EVENT_WIN_STATE) + cocoaCB.mpv?.setConfigProperty(minimized: false) } func windowDidResignKey(_ notification: Notification) { diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 504f0dfad6..aa1315fbbf 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -59,7 +59,6 @@ class CocoaCB: NSObject { layer = VideoLayer(cocoaCB: self) libmpv.observeFlag("ontop") - libmpv.observeFlag("border") libmpv.observeFlag("keepaspect-window") libmpv.observeString("macos-title-bar-style") libmpv.observeString("macos-title-bar-appearance") @@ -68,10 +67,10 @@ class CocoaCB: NSObject { } func preinit(_ vo: UnsafeMutablePointer) { + mpv = MPVHelper(vo, "cocoacb") + if backendState == .uninitialized { backendState = .needsInit - - mpv = MPVHelper(vo, "cocoacb") view = EventsView(cocoaCB: self) view?.layer = layer view?.wantsLayer = true @@ -84,6 +83,7 @@ class CocoaCB: NSObject { func uninit() { window?.orderOut(nil) + mpv = nil } func reconfig(_ vo: UnsafeMutablePointer) { @@ -99,10 +99,13 @@ class CocoaCB: NSObject { } func initBackend(_ vo: UnsafeMutablePointer) { - let opts: mp_vo_opts = vo.pointee.opts.pointee NSApp.setActivationPolicy(.regular) setAppIcon() + guard let opts: mp_vo_opts = mpv?.opts else { + libmpv.sendError("Something went wrong, no MPVHelper was initialized") + exit(1) + } guard let view = self.view else { libmpv.sendError("Something went wrong, no View was initialized") exit(1) @@ -144,8 +147,9 @@ class CocoaCB: NSObject { } func updateWindowSize(_ vo: UnsafeMutablePointer) { - let opts: mp_vo_opts = vo.pointee.opts.pointee - guard let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main else { + guard let opts: mp_vo_opts = mpv?.opts, + let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main else + { libmpv.sendWarning("Couldn't update Window size, no Screen available") return } @@ -177,13 +181,13 @@ class CocoaCB: NSObject { } func startDisplayLink(_ vo: UnsafeMutablePointer) { - let opts: mp_vo_opts = vo.pointee.opts.pointee CVDisplayLinkCreateWithActiveCGDisplays(&link) - guard let screen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main, + guard let opts: mp_vo_opts = mpv?.opts, + let screen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main, let link = self.link else { - libmpv.sendWarning("Couldn't start DisplayLink, no Screen or DisplayLink available") + libmpv.sendWarning("Couldn't start DisplayLink, no MPVHelper, Screen or DisplayLink available") return } @@ -426,8 +430,8 @@ class CocoaCB: NSObject { var controlCallback: mp_render_cb_control_fn = { ( vo, ctx, events, request, data ) -> Int32 in let ccb = unsafeBitCast(ctx, to: CocoaCB.self) - guard let vout = vo, let opts: mp_vo_opts = vout.pointee.opts?.pointee else { - ccb.libmpv.sendWarning("Nil vo or opts in Control Callback") + guard let vout = vo else { + ccb.libmpv.sendWarning("Nil vo in Control Callback") return VO_FALSE } @@ -438,17 +442,25 @@ class CocoaCB: NSObject { return VO_TRUE } return VO_FALSE - case VOCTRL_FULLSCREEN: - DispatchQueue.main.async { - ccb.window?.toggleFullScreen(nil) + case VOCTRL_VO_OPTS_CHANGED: + guard let mpv: MPVHelper = ccb.mpv else { + return VO_FALSE } - return VO_TRUE - case VOCTRL_GET_FULLSCREEN: - if let fsData = data?.assumingMemoryBound(to: Int32.self) { - fsData.pointee = (ccb.window?.isInFullscreen ?? false) ? 1 : 0 - return VO_TRUE + + var opt: UnsafeMutableRawPointer? + while mpv.nextChangedConfig(property: &opt) { + if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.border) { + DispatchQueue.main.async { + ccb.window?.border = Bool(mpv.opts.border) + } + } + if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.fullscreen) { + DispatchQueue.main.async { + ccb.window?.toggleFullScreen(nil) + } + } } - return VO_FALSE + return VO_TRUE case VOCTRL_GET_DISPLAY_FPS: if let fps = data?.assumingMemoryBound(to: CDouble.self) { fps.pointee = ccb.currentFps() @@ -475,7 +487,7 @@ class CocoaCB: NSObject { let size = UnsafeBufferPointer(start: sizeData, count: 2) var rect = NSMakeRect(0, 0, CGFloat(size[0]), CGFloat(size[1])) DispatchQueue.main.async { - if let screen = ccb.window?.currentScreen, !Bool(opts.hidpi_window_scale) { + if let screen = ccb.window?.currentScreen, !Bool(ccb.mpv?.opts.hidpi_window_scale ?? 1) { rect = screen.convertRectFromBacking(rect) } ccb.window?.updateSize(rect.size) @@ -483,19 +495,12 @@ class CocoaCB: NSObject { return VO_TRUE } return VO_FALSE - case VOCTRL_GET_WIN_STATE: - if let minimized = data?.assumingMemoryBound(to: Int32.self) { - minimized.pointee = ccb.window?.isMiniaturized ?? false ? - VO_WIN_STATE_MINIMIZED : Int32(0) - return VO_TRUE - } - return VO_FALSE case VOCTRL_GET_DISPLAY_NAMES: if let dnames = data?.assumingMemoryBound(to: UnsafeMutablePointer?>?.self) { var array: UnsafeMutablePointer?>? = nil var count: Int32 = 0 let screen = ccb.window != nil ? ccb.window?.screen : - ccb.getScreenBy(id: Int(opts.screen_id)) ?? + ccb.getScreenBy(id: Int(ccb.mpv?.opts.screen_id ?? 0)) ?? NSScreen.main let displayName = screen?.displayName ?? "Unknown" @@ -569,10 +574,6 @@ class CocoaCB: NSObject { } switch String(cString: property.name) { - case "border": - if let data = LibmpvHelper.mpvFlagToBool(property.data) { - window?.border = data - } case "ontop": if let data = LibmpvHelper.mpvFlagToBool(property.data) { window?.setOnTop(data, Int(mpv?.opts.ontop_level ?? -1)) -- cgit v1.2.3