summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--osdep/macos/libmpv_helper.swift20
-rw-r--r--osdep/macos/log_helper.swift1
-rw-r--r--osdep/macos/mpv_helper.swift12
-rw-r--r--osdep/macos/remote_command_center.swift1
-rw-r--r--video/out/cocoa_cb_common.swift521
-rw-r--r--video/out/mac/common.swift544
-rw-r--r--video/out/mac/gl_layer.swift (renamed from video/out/cocoa-cb/video_layer.swift)41
-rw-r--r--video/out/mac/title_bar.swift (renamed from video/out/cocoa-cb/title_bar.swift)27
-rw-r--r--video/out/mac/view.swift (renamed from video/out/cocoa-cb/events_view.swift)37
-rw-r--r--video/out/mac/window.swift (renamed from video/out/cocoa-cb/window.swift)90
-rw-r--r--wscript_build.py13
11 files changed, 741 insertions, 566 deletions
diff --git a/osdep/macos/libmpv_helper.swift b/osdep/macos/libmpv_helper.swift
index 5f465370dd..61c8483022 100644
--- a/osdep/macos/libmpv_helper.swift
+++ b/osdep/macos/libmpv_helper.swift
@@ -21,8 +21,8 @@ import OpenGL.GL3
let glDummy: @convention(c) () -> Void = {}
-class LibmpvHelper: LogHelper {
-
+class LibmpvHelper {
+ var log: LogHelper
var mpvHandle: OpaquePointer?
var mpvRenderContext: OpaquePointer?
var macOptsPtr: UnsafeMutableRawPointer?
@@ -30,17 +30,16 @@ class LibmpvHelper: LogHelper {
var fbo: GLint = 1
let deinitLock = NSLock()
- init(_ mpv: OpaquePointer, _ name: String) {
- let newlog = mp_log_new(UnsafeMutablePointer<MPContext>(mpv), mp_client_get_log(mpv), name)
- super.init(newlog)
+ init(_ mpv: OpaquePointer, _ mpLog: OpaquePointer?) {
mpvHandle = mpv
+ log = LogHelper(mpLog)
guard let app = NSApp as? Application,
let ptr = mp_get_config_group(nil,
mp_client_get_global(mpvHandle),
app.getMacOSConf()) else
{
- sendError("macOS config group couldn't be retrieved'")
+ log.sendError("macOS config group couldn't be retrieved'")
exit(1)
}
macOptsPtr = ptr
@@ -62,7 +61,7 @@ class LibmpvHelper: LogHelper {
if (mpv_render_context_create(&mpvRenderContext, mpvHandle, &params) < 0)
{
- sendError("Render context init has failed.")
+ log.sendError("Render context init has failed.")
exit(1)
}
}
@@ -86,7 +85,7 @@ class LibmpvHelper: LogHelper {
func setRenderUpdateCallback(_ callback: @escaping mpv_render_update_fn, context object: AnyObject) {
if mpvRenderContext == nil {
- sendWarning("Init mpv render context first.")
+ log.sendWarning("Init mpv render context first.")
} else {
mpv_render_context_set_update_callback(mpvRenderContext, callback, MPVHelper.bridge(obj: object))
}
@@ -94,7 +93,7 @@ class LibmpvHelper: LogHelper {
func setRenderControlCallback(_ callback: @escaping mp_render_cb_control_fn, context object: AnyObject) {
if mpvRenderContext == nil {
- sendWarning("Init mpv render context first.")
+ log.sendWarning("Init mpv render context first.")
} else {
mp_render_context_set_control_callback(mpvRenderContext, callback, MPVHelper.bridge(obj: object))
}
@@ -153,7 +152,7 @@ class LibmpvHelper: LogHelper {
func setRenderICCProfile(_ profile: NSColorSpace) {
if mpvRenderContext == nil { return }
guard var iccData = profile.iccProfileData else {
- sendWarning("Invalid ICC profile data.")
+ log.sendWarning("Invalid ICC profile data.")
return
}
iccData.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) in
@@ -235,7 +234,6 @@ class LibmpvHelper: LogHelper {
ta_free(macOptsPtr)
macOptsPtr = nil
mpvHandle = nil
- log = nil
}
// *(char **) MPV_FORMAT_STRING on mpv_event_property
diff --git a/osdep/macos/log_helper.swift b/osdep/macos/log_helper.swift
index 6d834c0631..94640756bd 100644
--- a/osdep/macos/log_helper.swift
+++ b/osdep/macos/log_helper.swift
@@ -18,7 +18,6 @@
import Cocoa
class LogHelper: NSObject {
-
var log: OpaquePointer?
init(_ log: OpaquePointer?) {
diff --git a/osdep/macos/mpv_helper.swift b/osdep/macos/mpv_helper.swift
index d01694d736..8a05f26cb1 100644
--- a/osdep/macos/mpv_helper.swift
+++ b/osdep/macos/mpv_helper.swift
@@ -17,8 +17,8 @@
import Cocoa
-class MPVHelper: LogHelper {
-
+class MPVHelper {
+ var log: LogHelper
var vo: UnsafeMutablePointer<vo>
var optsCachePtr: UnsafeMutablePointer<m_config_cache>
var optsPtr: UnsafeMutablePointer<mp_vo_opts>
@@ -33,22 +33,20 @@ class MPVHelper: LogHelper {
var input: OpaquePointer { get { return vout.input_ctx } }
var macOpts: macos_opts = macos_opts()
- init(_ vo: UnsafeMutablePointer<vo>, _ name: String) {
+ init(_ vo: UnsafeMutablePointer<vo>, _ log: LogHelper) {
self.vo = vo
+ self.log = log
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")
+ log.sendError("NSApp couldn't be retrieved")
exit(1)
}
- let newlog = mp_log_new(vo, vo.pointee.log, name)
optsCachePtr = cache
optsPtr = UnsafeMutablePointer<mp_vo_opts>(OpaquePointer(cache.pointee.opts))
- super.init(newlog)
-
guard let ptr = mp_get_config_group(vo,
vo.pointee.global,
app.getMacOSConf()) else
diff --git a/osdep/macos/remote_command_center.swift b/osdep/macos/remote_command_center.swift
index a5dd662737..d97cb3328c 100644
--- a/osdep/macos/remote_command_center.swift
+++ b/osdep/macos/remote_command_center.swift
@@ -19,7 +19,6 @@ import MediaPlayer
@available(macOS 10.12.2, *)
class RemoteCommandCenter: NSObject {
-
enum KeyType {
case normal
case repeatable
diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift
index c3f0ab2cc8..10e3c30cc1 100644
--- a/video/out/cocoa_cb_common.swift
+++ b/video/out/cocoa_cb_common.swift
@@ -16,25 +16,13 @@
*/
import Cocoa
-import IOKit.pwr_mgt
-class CocoaCB: NSObject {
-
- var mpv: MPVHelper?
+class CocoaCB: Common {
var libmpv: LibmpvHelper
- var window: Window?
- var titleBar: TitleBar?
- var view: EventsView?
- var layer: VideoLayer?
- var link: CVDisplayLink?
+ var layer: GLLayer?
- var cursorVisibilityWanted: Bool = true
@objc var isShuttingDown: Bool = false
- var title: String = "mpv" {
- didSet { if let window = window { window.title = title } }
- }
-
enum State {
case uninitialized
case needsInit
@@ -42,20 +30,12 @@ class CocoaCB: NSObject {
}
var backendState: State = .uninitialized
- let eventsLock = NSLock()
- var events: Int = 0
-
- var lightSensor: io_connect_t = 0
- var lastLmu: UInt64 = 0
- var lightSensorIOPort: IONotificationPortRef?
- var displaySleepAssertion: IOPMAssertionID = IOPMAssertionID(0)
-
- let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue")
@objc init(_ mpvHandle: OpaquePointer) {
- libmpv = LibmpvHelper(mpvHandle, "cocoacb")
- super.init()
- layer = VideoLayer(cocoaCB: self)
+ let newlog = mp_log_new(UnsafeMutablePointer<MPContext>(mpvHandle), mp_client_get_log(mpvHandle), "cocoacb")
+ libmpv = LibmpvHelper(mpvHandle, newlog)
+ super.init(newlog)
+ layer = GLLayer(cocoaCB: self)
libmpv.observeString("macos-title-bar-style")
libmpv.observeString("macos-title-bar-appearance")
@@ -64,17 +44,18 @@ class CocoaCB: NSObject {
}
func preinit(_ vo: UnsafeMutablePointer<vo>) {
- mpv = MPVHelper(vo, "cocoacb")
+ mpv = MPVHelper(vo, log)
if backendState == .uninitialized {
backendState = .needsInit
- view = EventsView(cocoaCB: self)
- view?.layer = layer
- view?.wantsLayer = true
- view?.layerContentsPlacement = .scaleProportionallyToFit
- startDisplayLink(vo)
- initLightSensor()
- addDisplayReconfigureObserver()
+
+ guard let layer = self.layer else {
+ log.sendError("Something went wrong, no GLLayer was initialized")
+ exit(1)
+ }
+
+ initView(vo, layer)
+ initMisc(vo)
}
}
@@ -97,58 +78,10 @@ class CocoaCB: NSObject {
}
func initBackend(_ vo: UnsafeMutablePointer<vo>) {
- 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)
- }
- guard let targetScreen = getScreenBy(id: Int(opts.screen_id)) ?? NSScreen.main else {
- libmpv.sendError("Something went wrong, no Screen was found")
- exit(1)
- }
-
- let wr = getWindowGeometry(forScreen: targetScreen, videoOut: vo)
- window = Window(contentRect: wr, screen: targetScreen, view: view, cocoaCB: self)
- guard let window = self.window else {
- libmpv.sendError("Something went wrong, no Window was initialized")
- exit(1)
- }
-
+ initApp()
+ initWindow(vo)
updateICCProfile()
- window.setOnTop(Bool(opts.ontop), Int(opts.ontop_level))
- window.keepAspect = Bool(opts.keepaspect_window)
- window.title = title
- window.border = Bool(opts.border)
-
- titleBar = TitleBar(frame: wr, window: window, cocoaCB: self)
-
- let minimized = Bool(opts.window_minimized)
- window.isRestorable = false
- window.isReleasedWhenClosed = false
- window.setMaximized(minimized ? false : Bool(opts.window_maximized))
- window.setMinimized(minimized)
- window.makeMain()
- window.makeKey()
-
- if !minimized {
- window.orderFront(nil)
- }
-
- NSApp.activate(ignoringOtherApps: true)
-
- if Bool(opts.fullscreen) {
- DispatchQueue.main.async {
- self.window?.toggleFullScreen(nil)
- }
- } else {
- window.isMovableByWindowBackground = true
- }
+ initWindowState()
backendState = .initialized
}
@@ -157,7 +90,7 @@ class CocoaCB: NSObject {
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")
+ log.sendWarning("Couldn't update Window size, no Screen available")
return
}
@@ -172,119 +105,23 @@ class CocoaCB: NSObject {
window?.updateSize(wr.size)
}
- func setAppIcon() {
- if let app = NSApp as? Application,
- ProcessInfo.processInfo.environment["MPVBUNDLE"] != "true"
- {
- NSApp.applicationIconImage = app.getMPVIcon()
- }
- }
-
- let linkCallback: CVDisplayLinkOutputCallback = {
- (displayLink: CVDisplayLink,
- inNow: UnsafePointer<CVTimeStamp>,
- inOutputTime: UnsafePointer<CVTimeStamp>,
- flagsIn: CVOptionFlags,
- flagsOut: UnsafeMutablePointer<CVOptionFlags>,
- displayLinkContext: UnsafeMutableRawPointer?) -> CVReturn in
- let ccb = unsafeBitCast(displayLinkContext, to: CocoaCB.self)
- ccb.libmpv.reportRenderFlip()
+ override func displayLinkCallback(_ displayLink: CVDisplayLink,
+ _ inNow: UnsafePointer<CVTimeStamp>,
+ _ inOutputTime: UnsafePointer<CVTimeStamp>,
+ _ flagsIn: CVOptionFlags,
+ _ flagsOut: UnsafeMutablePointer<CVOptionFlags>) -> CVReturn
+ {
+ libmpv.reportRenderFlip()
return kCVReturnSuccess
}
- func startDisplayLink(_ vo: UnsafeMutablePointer<vo>) {
- CVDisplayLinkCreateWithActiveCGDisplays(&link)
-
- 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 MPVHelper, Screen or DisplayLink available")
- return
- }
-
- CVDisplayLinkSetCurrentCGDisplay(link, screen.displayID)
- if #available(macOS 10.12, *) {
- CVDisplayLinkSetOutputHandler(link) { link, now, out, inFlags, outFlags -> CVReturn in
- self.libmpv.reportRenderFlip()
- return kCVReturnSuccess
- }
- } else {
- CVDisplayLinkSetOutputCallback(link, linkCallback, MPVHelper.bridge(obj: self))
- }
- CVDisplayLinkStart(link)
- }
-
- func stopDisplaylink() {
- if let link = self.link, CVDisplayLinkIsRunning(link) {
- CVDisplayLinkStop(link)
- }
- }
-
- func updateDisplaylink() {
- guard let screen = window?.screen, let link = self.link else {
- libmpv.sendWarning("Couldn't update DisplayLink, no Screen or DisplayLink available")
- return
- }
-
- CVDisplayLinkSetCurrentCGDisplay(link, screen.displayID)
- queue.asyncAfter(deadline: DispatchTime.now() + 0.1) {
- self.flagEvents(VO_EVENT_WIN_STATE)
- }
- }
-
- func currentFps() -> Double {
- if let link = self.link {
- var actualFps = CVDisplayLinkGetActualOutputVideoRefreshPeriod(link)
- let nominalData = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link)
-
- if (nominalData.flags & Int32(CVTimeFlags.isIndefinite.rawValue)) < 1 {
- let nominalFps = Double(nominalData.timeScale) / Double(nominalData.timeValue)
-
- if actualFps > 0 {
- actualFps = 1/actualFps
- }
-
- if fabs(actualFps - nominalFps) > 0.1 {
- libmpv.sendVerbose("Falling back to nominal display refresh rate: \(nominalFps)")
- return nominalFps
- } else {
- return actualFps
- }
- }
- } else {
- libmpv.sendWarning("No DisplayLink available")
- }
-
- libmpv.sendWarning("Falling back to standard display refresh rate: 60Hz")
- return 60.0
- }
-
- func enableDisplaySleep() {
- IOPMAssertionRelease(displaySleepAssertion)
- displaySleepAssertion = IOPMAssertionID(0)
+ override func lightSensorUpdate() {
+ libmpv.setRenderLux(lmuToLux(lastLmu))
}
- func disableDisplaySleep() {
- if displaySleepAssertion != IOPMAssertionID(0) { return }
- IOPMAssertionCreateWithName(
- kIOPMAssertionTypePreventUserIdleDisplaySleep as CFString,
- IOPMAssertionLevel(kIOPMAssertionLevelOn),
- "io.mpv.video_playing_back" as CFString,
- &displaySleepAssertion)
- }
-
- func updateCursorVisibility() {
- setCursorVisiblility(cursorVisibilityWanted)
- }
-
- func setCursorVisiblility(_ visible: Bool) {
- NSCursor.setHiddenUntilMouseMoves(!visible && (view?.canHideCursor() ?? false))
- }
-
- func updateICCProfile() {
+ override func updateICCProfile() {
guard let colorSpace = window?.screen?.colorSpace else {
- libmpv.sendWarning("Couldn't update ICC Profile, no color space available")
+ log.sendWarning("Couldn't update ICC Profile, no color space available")
return
}
@@ -294,288 +131,86 @@ class CocoaCB: NSObject {
}
}
- func lmuToLux(_ v: UInt64) -> Int {
- // the polinomial approximation for apple lmu value -> lux was empirically
- // derived by firefox developers (Apple provides no documentation).
- // https://bugzilla.mozilla.org/show_bug.cgi?id=793728
- let power_c4: Double = 1 / pow(10, 27)
- let power_c3: Double = 1 / pow(10, 19)
- let power_c2: Double = 1 / pow(10, 12)
- let power_c1: Double = 1 / pow(10, 5)
-
- let lum = Double(v)
- let term4: Double = -3.0 * power_c4 * pow(lum, 4.0)
- let term3: Double = 2.6 * power_c3 * pow(lum, 3.0)
- let term2: Double = -3.4 * power_c2 * pow(lum, 2.0)
- let term1: Double = 3.9 * power_c1 * lum
-
- let lux = Int(ceil(term4 + term3 + term2 + term1 - 0.19))
- return lux > 0 ? lux : 0
+ override func windowDidEndAnimation() {
+ layer?.update()
+ checkShutdown()
}
- var lightSensorCallback: IOServiceInterestCallback = { (ctx, service, messageType, messageArgument) -> Void in
- let ccb = unsafeBitCast(ctx, to: CocoaCB.self)
-
- var outputs: UInt32 = 2
- var values: [UInt64] = [0, 0]
-
- var kr = IOConnectCallMethod(ccb.lightSensor, 0, nil, 0, nil, 0, &values, &outputs, nil, nil)
- if kr == KERN_SUCCESS {
- var mean = (values[0] + values[1]) / 2
- if ccb.lastLmu != mean {
- ccb.lastLmu = mean
- ccb.libmpv.setRenderLux(ccb.lmuToLux(ccb.lastLmu))
- }
- }
+ override func windowSetToFullScreen() {
+ layer?.update()
}
- func initLightSensor() {
- let srv = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleLMUController"))
- if srv == IO_OBJECT_NULL {
- libmpv.sendVerbose("Can't find an ambient light sensor")
- return
- }
-
- lightSensorIOPort = IONotificationPortCreate(kIOMasterPortDefault)
- IONotificationPortSetDispatchQueue(lightSensorIOPort, queue)
- var n = io_object_t()
- IOServiceAddInterestNotification(lightSensorIOPort, srv, kIOGeneralInterest, lightSensorCallback, MPVHelper.bridge(obj: self), &n)
- let kr = IOServiceOpen(srv, mach_task_self_, 0, &lightSensor)
- IOObjectRelease(srv)
-
- if kr != KERN_SUCCESS {
- libmpv.sendVerbose("Can't start ambient light sensor connection")
- return
- }
- lightSensorCallback(MPVHelper.bridge(obj: self), 0, 0, nil)
+ override func windowSetToWindow() {
+ layer?.update()
}
- func uninitLightSensor() {
- if lightSensorIOPort != nil {
- IONotificationPortDestroy(lightSensorIOPort)
- IOObjectRelease(lightSensor)
- }
+ override func windowDidUpdateFrame() {
+ layer?.update(force: true)
}
- var reconfigureCallback: CGDisplayReconfigurationCallBack = { (display, flags, userInfo) in
- if flags.contains(.setModeFlag) {
- let ccb = unsafeBitCast(userInfo, to: CocoaCB.self)
- let displayID = ccb.window?.screen?.displayID ?? display
-
- if displayID == display {
- ccb.libmpv.sendVerbose("Detected display mode change, updating screen refresh rate")
- ccb.flagEvents(VO_EVENT_WIN_STATE)
- }
- }
+ override func windowDidChangeScreen() {
+ layer?.update(force: true)
}
- func addDisplayReconfigureObserver() {
- CGDisplayRegisterReconfigurationCallback(reconfigureCallback, MPVHelper.bridge(obj: self))
+ override func windowDidChangeScreenProfile() {
+ layer?.needsICCUpdate = true
}
- func removeDisplayReconfigureObserver() {
- CGDisplayRemoveReconfigurationCallback(reconfigureCallback, MPVHelper.bridge(obj: self))
+ override func windowDidChangeBackingProperties() {
+ layer?.contentsScale = window?.backingScaleFactor ?? 1
}
- func getTargetScreen(forFullscreen fs: Bool) -> NSScreen? {
- let screenID = fs ? (mpv?.opts.fsscreen_id ?? 0) : (mpv?.opts.screen_id ?? 0)
- return getScreenBy(id: Int(screenID))
+ override func windowWillStartLiveResize() {
+ layer?.inLiveResize = true
}
- func getScreenBy(id screenID: Int) -> NSScreen? {
- if screenID >= NSScreen.screens.count {
- libmpv.sendInfo("Screen ID \(screenID) does not exist, falling back to current device")
- return nil
- } else if screenID < 0 {
- return nil
- }
- return NSScreen.screens[screenID]
+ override func windowDidEndLiveResize() {
+ layer?.inLiveResize = false
}
- func getWindowGeometry(forScreen targetScreen: NSScreen,
- videoOut vo: UnsafeMutablePointer<vo>) -> NSRect {
- let r = targetScreen.convertRectToBacking(targetScreen.frame)
- var screenRC: mp_rect = mp_rect(x0: Int32(0),
- y0: Int32(0),
- x1: Int32(r.size.width),
- y1: Int32(r.size.height))
-
- var geo: vo_win_geometry = vo_win_geometry()
- vo_calc_window_geometry2(vo, &screenRC, Double(targetScreen.backingScaleFactor), &geo)
-
- // flip y coordinates
- geo.win.y1 = Int32(r.size.height) - geo.win.y1
- geo.win.y0 = Int32(r.size.height) - geo.win.y0
-
- let wr = NSMakeRect(CGFloat(geo.win.x0), CGFloat(geo.win.y1),
- CGFloat(geo.win.x1 - geo.win.x0),
- CGFloat(geo.win.y0 - geo.win.y1))
- return targetScreen.convertRectFromBacking(wr)
+ override func windowDidChangeOcclusionState() {
+ layer?.update(force: true)
}
- func flagEvents(_ ev: Int) {
- eventsLock.lock()
- events |= ev
- eventsLock.unlock()
+ var controlCallback: mp_render_cb_control_fn = { ( v, ctx, e, request, d ) -> Int32 in
+ let ccb = unsafeBitCast(ctx, to: CocoaCB.self)
- guard let vout = mpv?.vo else {
- libmpv.sendWarning("vo nil in flagEvents")
- return
+ // the data pointer can be a null pointer, the libmpv control callback
+ // provides nil instead of the 0 address like the usual control call of
+ // an internal vo, workaround to create a null pointer instead of nil
+ var data = UnsafeMutableRawPointer.init(bitPattern: 0).unsafelyUnwrapped
+ if let dunwrapped = d {
+ data = dunwrapped
}
- vo_wakeup(vout)
- }
- func checkEvents() -> Int {
- eventsLock.lock()
- let ev = events
- events = 0
- eventsLock.unlock()
- return ev
- }
-
- 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 else {
- ccb.libmpv.sendWarning("Nil vo in Control Callback")
+ guard let vo = v, let events = e else {
+ ccb.log.sendWarning("Unexpected nil value in Control Callback")
return VO_FALSE
}
- switch mp_voctrl(request) {
- case VOCTRL_CHECK_EVENTS:
- if let ev = events {
- ev.pointee = Int32(ccb.checkEvents())
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_VO_OPTS_CHANGED:
- guard let mpv: MPVHelper = ccb.mpv else {
- return VO_FALSE
- }
-
- 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)
- }
- }
- if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.ontop) {
- DispatchQueue.main.async {
- ccb.window?.setOnTop(Bool(mpv.opts.ontop), Int(mpv.opts.ontop_level))
- }
- }
- if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.keepaspect_window) {
- DispatchQueue.main.async {
- ccb.window?.keepAspect = Bool(mpv.opts.keepaspect_window)
- }
- }
- if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.window_minimized) {
- DispatchQueue.main.async {
- ccb.window?.setMinimized(Bool(mpv.opts.window_minimized))
- }
- }
- if opt! == UnsafeMutableRawPointer(&mpv.optsPtr.pointee.window_maximized) {
- DispatchQueue.main.async {
- ccb.window?.setMaximized(Bool(mpv.opts.window_maximized))
- }
- }
- }
- return VO_TRUE
- case VOCTRL_GET_DISPLAY_FPS:
- if let fps = data?.assumingMemoryBound(to: CDouble.self) {
- fps.pointee = ccb.currentFps()
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_GET_HIDPI_SCALE:
- if let scaleFactor = data?.assumingMemoryBound(to: CDouble.self) {
- let factor = ccb.window?.backingScaleFactor ??
- ccb.getTargetScreen(forFullscreen: false)?.backingScaleFactor ??
- NSScreen.main?.backingScaleFactor ?? 1.0
- scaleFactor.pointee = Double(factor)
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_RESTORE_SCREENSAVER:
- ccb.enableDisplaySleep()
- return VO_TRUE
- case VOCTRL_KILL_SCREENSAVER:
- ccb.disableDisplaySleep()
- return VO_TRUE
- case VOCTRL_SET_CURSOR_VISIBILITY:
- if let cursorVisibility = data?.assumingMemoryBound(to: CBool.self) {
- ccb.cursorVisibilityWanted = cursorVisibility.pointee
- DispatchQueue.main.async {
- ccb.setCursorVisiblility(ccb.cursorVisibilityWanted)
- }
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_GET_UNFS_WINDOW_SIZE:
- let sizeData = data?.assumingMemoryBound(to: Int32.self)
- let size = UnsafeMutableBufferPointer(start: sizeData, count: 2)
- var rect = ccb.window?.unfsContentFrame ?? NSRect(x: 0, y: 0, width: 1280, height: 720)
- if let screen = ccb.window?.currentScreen, !Bool(ccb.mpv?.opts.hidpi_window_scale ?? 0) {
- rect = screen.convertRectToBacking(rect)
- }
+ return ccb.control(vo, events: events, request: request, data: data)
+ }
- size[0] = Int32(rect.size.width)
- size[1] = Int32(rect.size.height)
- return VO_TRUE
- case VOCTRL_SET_UNFS_WINDOW_SIZE:
- if let sizeData = data?.assumingMemoryBound(to: Int32.self) {
- 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(ccb.mpv?.opts.hidpi_window_scale ?? 1) {
- rect = screen.convertRectFromBacking(rect)
- }
- ccb.window?.updateSize(rect.size)
- }
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_GET_DISPLAY_NAMES:
- if let dnames = data?.assumingMemoryBound(to: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?.self) {
- var array: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>? = nil
- var count: Int32 = 0
- let screen = ccb.window != nil ? ccb.window?.screen :
- ccb.getTargetScreen(forFullscreen: false) ??
- NSScreen.main
- let displayName = screen?.displayName ?? "Unknown"
-
- SWIFT_TARRAY_STRING_APPEND(nil, &array, &count, ta_xstrdup(nil, displayName))
- SWIFT_TARRAY_STRING_APPEND(nil, &array, &count, nil)
- dnames.pointee = array
- return VO_TRUE
- }
- return VO_FALSE
- case VOCTRL_UPDATE_WINDOW_TITLE:
- if let titleData = data?.assumingMemoryBound(to: Int8.self) {
- DispatchQueue.main.async {
- let title = NSString(utf8String: titleData) as String?
- ccb.title = title ?? "Unknown Title"
- }
- return VO_TRUE
- }
- return VO_FALSE
+ override func control(_ vo: UnsafeMutablePointer<vo>,
+ events: UnsafeMutablePointer<Int32>,
+ request: UInt32,
+ data: UnsafeMutableRawPointer) -> Int32
+ {
+ switch mp_voctrl(request) {
case VOCTRL_PREINIT:
- DispatchQueue.main.sync { ccb.preinit(vout) }
+ DispatchQueue.main.sync { self.preinit(vo) }
return VO_TRUE
case VOCTRL_UNINIT:
- DispatchQueue.main.async { ccb.uninit() }
+ DispatchQueue.main.async { self.uninit() }
return VO_TRUE
case VOCTRL_RECONFIG:
- ccb.reconfig(vout)
+ reconfig(vo)
return VO_TRUE
default:
- return VO_NOTIMPL
+ break
}
+
+ return super.control(vo, events: events, request: request, data: data)
}
func shutdown(_ destroy: Bool = false) {
@@ -587,10 +222,8 @@ class CocoaCB: NSObject {
if isShuttingDown { return }
uninit()
- setCursorVisiblility(true)
- stopDisplaylink()
- uninitLightSensor()
- removeDisplayReconfigureObserver()
+ uninitCommon()
+
libmpv.deinitRender()
libmpv.deinitMPV(destroy)
}
diff --git a/video/out/mac/common.swift b/video/out/mac/common.swift
new file mode 100644
index 0000000000..b4aa105b23
--- /dev/null
+++ b/video/out/mac/common.swift
@@ -0,0 +1,544 @@
+/*
+ * This file is part of mpv.
+ *
+ * mpv 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.
+ *
+ * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import Cocoa
+import IOKit.pwr_mgt
+
+class Common: NSObject {
+ var mpv: MPVHelper?
+ var log: LogHelper
+ let queue: DispatchQueue = DispatchQueue(label: "io.mpv.queue")
+
+ var window: Window?
+ var view: View?
+ var titleBar: TitleBar?
+
+ var link: CVDisplayLink?
+
+ let eventsLock = NSLock()
+ var events: Int = 0
+
+ var lightSensor: io_connect_t = 0
+ var lastLmu: UInt64 = 0
+ var lightSensorIOPort: IONotificationPortRef?
+
+ var displaySleepAssertion: IOPMAssertionID = IOPMAssertionID(0)
+
+ var cursorVisibilityWanted: Bool = true
+
+ var title: String = "mpv" {
+ didSet { if let window = window { window.title = title } }
+ }
+
+ init(_ mpLog: OpaquePointer?) {
+ log = LogHelper(mpLog)
+ }
+
+ func initMisc(_ vo: UnsafeMutablePointer<vo>) {
+ startDisplayLink(vo)
+ initLightSensor()
+ addDisplayReconfigureObserver()
+ }
+
+ func initApp() {
+ NSApp.setActivationPolicy(.regular)
+ setAppIcon()
+ }
+
+ func initWindow(_ vo: UnsafeMutablePointer<vo>) {
+ let (mpv, targetScreen, wr) = getInitProperties(vo)
+
+ guard let view = self.view else {
+ log.sendError("Something went wrong, no View was initialized")
+ exit(1)
+ }
+
+ window = Window(contentRect: wr, screen: targetScreen, view: view, common: self)
+ guard let window = self.window else {
+ log.sendError("Something went wrong, no Window was initialized")
+ exit(1)
+ }
+
+ window.setOnTop(Bool(mpv.opts.ontop), Int(mpv.opts.ontop_level))
+ window.keepAspect = Bool(mpv.opts.keepaspect_window)
+ window.title = title
+ window.border = Bool(mpv.opts.border)
+
+ titleBar = TitleBar(frame: wr, window: window, common: self)
+
+ let minimized = Bool(mpv.opts.window_minimized)
+ window.isRestorable = false
+ window.isReleasedWhenClosed = false
+ window.setMaximized(minimized ? false : Bool(mpv.opts.window_maximized))
+ window.setMinimized(minimized)
+ window.makeMain()
+ window.makeKey()
+
+ if !minimized {
+ window.orderFront(nil)
+ }
+
+ NSApp.activate(ignoringOtherApps: true)
+ }
+
+ func initView(_ vo: UnsafeMutablePointer<vo>, _ layer: CALayer) {
+ let (_, _, wr) = getInitProperties(vo)
+
+ view = View(frame: wr, common: self)
+ guard let view = self.view else {
+ log.sendError("Something went wrong, no View was initialized")
+ exit(1)
+ }
+
+ view.layer = layer
+ view.wantsLayer = true
+ view.layerContentsPlacement = .scaleProportionallyToFit
+ }
+
+ func initWindowState() {
+ if mpv?.opts.fullscreen ?? false {
+ DispatchQueue.main.async {
+ self.window?.toggleFullScreen(nil)
+ }
+ } else