HaishinKit.swift/Platforms/macOS/DisplayLink-macOS.swift

77 lines
2.1 KiB
Swift

#if os(macOS)
import CoreVideo
import Foundation
final class DisplayLink: NSObject {
var isPaused = false {
didSet {
guard let displayLink = displayLink, oldValue != isPaused else {
return
}
if isPaused {
status = CVDisplayLinkStop(displayLink)
} else {
status = CVDisplayLinkStart(displayLink)
}
}
}
var frameInterval = 0
var preferredFramesPerSecond = 1
private(set) var duration = 0.0
private(set) var timestamp: CFTimeInterval = 0
private var status: CVReturn = 0
private var displayLink: CVDisplayLink?
private var selector: Selector?
private weak var delegate: NSObject?
deinit {
selector = nil
}
init(target: NSObject, selector sel: Selector) {
super.init()
status = CVDisplayLinkCreateWithActiveCGDisplays(&displayLink)
guard let displayLink = displayLink else {
return
}
self.delegate = target
self.selector = sel
CVDisplayLinkSetOutputHandler(displayLink) { [unowned self] _, inNow, _, _, _ -> CVReturn in
self.timestamp = inNow.pointee.timestamp
self.duration = inNow.pointee.duration
_ = self.delegate?.perform(self.selector, with: self)
return kCVReturnSuccess
}
}
func add(to runloop: RunLoop, forMode mode: RunLoop.Mode) {
guard let displayLink = displayLink, !isPaused else {
return
}
status = CVDisplayLinkStart(displayLink)
}
func invalidate() {
guard let displayLink = displayLink, isPaused else {
return
}
status = CVDisplayLinkStop(displayLink)
}
}
extension CVTimeStamp {
// swiftlint:disable attributes
@inlinable @inline(__always)
var timestamp: Double {
Double(self.videoTime) / Double(self.videoTimeScale)
}
// swiftlint:disable attributes
@inlinable @inline(__always) var duration: Double {
Double(self.videoRefreshPeriod) / Double(self.videoTimeScale)
}
}
#endif