Skip to content

Commit

Permalink
mojave native edition
Browse files Browse the repository at this point in the history
  • Loading branch information
kotan-kn committed Nov 27, 2018
1 parent a5c3651 commit a397c92
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 161 deletions.
60 changes: 21 additions & 39 deletions Core/YASMP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,7 @@ class YASMP: NSObject {
interval: Double,
average: Int,
service: String = "YASMP") throws {
let assets: Array<AVAsset> = urls.map {
let asset: AVURLAsset = AVURLAsset(url: $0, options: Dictionary<String, Any>(dictionaryLiteral: (AVURLAssetPreferPreciseDurationAndTimingKey, true)))
let key: String = "tracks"
let semaphore: DispatchSemaphore = DispatchSemaphore(value: 0)
asset.loadValuesAsynchronously(forKeys: Array<String>(repeating: key, count: 1)) {
var error: NSError?
switch asset.statusOfValue(forKey: key, error: &error) {
case .loaded:
semaphore.signal()
case .loading:
os_log("%@", log: facility, type: .debug, error?.localizedDescription ?? #function)
case .cancelled, .unknown, .failed:
os_log("%@", log: facility, type: .fault, error?.localizedDescription ?? #function)
fatalError()
}
}
semaphore.wait()
return asset
}
let assets: Array<AVAsset> = urls.map(AVURLAsset.init)
let maxfps: Double = Double(assets.reduce([], { $0 + $1.tracks }).reduce(1, { max($0, $1.nominalFrameRate )}))
let index: Array<Int> = {
switch $0 {
Expand All @@ -65,11 +47,11 @@ class YASMP: NSObject {
}
} ( mode )
let composition: AVComposition = try index.reduce(AVMutableComposition()) {
try $0.insertTimeRange(CMTimeRange(start: kCMTimeZero, duration: assets[$1].duration), of: assets[$1], at: $0.duration)
try $0.insertTimeRange(CMTimeRange(start: .zero, duration: assets[$1].duration), of: assets[$1], at: $0.duration)
return $0
}
full = composition.duration
half = CMTimeMultiplyByRatio(full, 1, 2)
half = CMTimeMultiplyByRatio(full, multiplier: 1, divisor: 2)
player = AVQueuePlayer()
looper = AVPlayerLooper(player: player, templateItem: AVPlayerItem(asset: composition))
master = CMClockGetHostTimeClock()
Expand All @@ -81,15 +63,15 @@ class YASMP: NSObject {
source = DispatchSource.makeTimerSource(flags: .strict, queue: .global(qos: .userInteractive))
threshold = 1 / maxfps
divisor = Int32(average)
delay = kCMTimeZero
selfAnchor = kCMTimeZero
peerAnchor = kCMTimeZero
delay = .zero
selfAnchor = .zero
peerAnchor = .zero
super.init()
//player.actionAtItemEnd = .none
player.masterClock = master
player.automaticallyWaitsToMinimizeStalling = false
source.setEventHandler(handler: check)
source.scheduleRepeating(deadline: .now(), interval: interval)
source.schedule(wallDeadline: .now(), repeating: interval)
advertiser.delegate = self
browser.delegate = self
session.delegate = self
Expand Down Expand Up @@ -125,8 +107,8 @@ extension YASMP {
let mutating: UnsafeMutablePointer<CMTime> = UnsafeMutablePointer<CMTime>(mutating: ref)
mutating[0] = playedTime
mutating[1] = masterTime
mutating[4] = kCMTimeZero
mutating[5] = UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(kCMTimeZero, CMTimeAdd)
mutating[4] = .zero
mutating[5] = UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(.zero, CMTimeAdd)
}
do {
try session.send(data, toPeers: Array<MCPeerID>(repeating: dwarf, count: 1), with: .unreliable)
Expand Down Expand Up @@ -186,25 +168,25 @@ extension YASMP: MCSessionDelegate {
let playedTime: CMTime = player.currentTime()
let masterTime: CMTime = CMClockGetTime(master)
data.withUnsafeBytes { (ref: UnsafePointer<CMTime>) in
guard ref[5] == UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(kCMTimeZero, CMTimeAdd) else {
guard ref[5] == UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(.zero, CMTimeAdd) else {
os_log("incorrect data", log: facility, type: .error)
return
}
switch ref[4] {
case kCMTimeZero:
case .zero:
let mutating: UnsafeMutablePointer<CMTime> = UnsafeMutablePointer<CMTime>(mutating: ref)
mutating[2] = playedTime
mutating[3] = masterTime
mutating[4] = kCMTimeInvalid
mutating[5] = UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(kCMTimeZero, CMTimeAdd)
mutating[4] = .invalid
mutating[5] = UnsafeBufferPointer<CMTime>(start: ref, count: 4).reduce(.zero, CMTimeAdd)
do {
try session.send(data, toPeers: Array<MCPeerID>(repeating: peerID, count: 1), with: .unreliable)
} catch {
os_log("%s", log: facility, type: .error, error.localizedDescription)
}
case kCMTimeInvalid:
let selfPlayedTime: CMTime = CMTimeMultiplyByRatio(CMTimeAdd(playedTime, ref[0]), 1, 2)
let selfMasterTime: CMTime = CMTimeMultiplyByRatio(CMTimeAdd(masterTime, ref[1]), 1, 2)
case .invalid:
let selfPlayedTime: CMTime = CMTimeMultiplyByRatio(CMTimeAdd(playedTime, ref[0]), multiplier: 1, divisor: 2)
let selfMasterTime: CMTime = CMTimeMultiplyByRatio(CMTimeAdd(masterTime, ref[1]), multiplier: 1, divisor: 2)
let peerPlayedTime: CMTime = ref[2]
let peerMasterTime: CMTime = ref[3]
let delta: CMTime = CMTimeSubtract(CMTimeModApprox(CMTimeAdd(CMTimeSubtract(peerPlayedTime, selfPlayedTime), half), full), half)
Expand All @@ -217,15 +199,15 @@ extension YASMP: MCSessionDelegate {
delay = delta
return
}
delay = CMTimeAdd(CMTimeMultiplyByRatio(delta, 1, divisor), CMTimeMultiplyByRatio(delay, divisor - 1, divisor))
delay = CMTimeAdd(CMTimeMultiplyByRatio(delta, multiplier: 1, divisor: divisor), CMTimeMultiplyByRatio(delay, multiplier: divisor - 1, divisor: divisor))
guard threshold < CMTimeGetSeconds(CMTimeAbsoluteValue(delay)) else { return }
let selfElapsed: CMTime = CMTimeSubtract(selfMasterTime, selfAnchor)
let peerElapsed: CMTime = CMTimeSubtract(peerMasterTime, peerAnchor)
let rate: Double = CMTimeGetSeconds(peerElapsed) / CMTimeGetSeconds(selfElapsed)
player.setRate(Float(rate), time: peerPlayedTime, atHostTime: selfMasterTime)
os_log("Adjust rate %lf for delay %lf sec", log: facility, type: .info, rate, CMTimeGetSeconds(delta))
print("\(Date()): Adjust rate \(rate) for delay \(CMTimeGetSeconds(delta)) sec")
delay = kCMTimeZero
delay = .zero
default:
break
}
Expand All @@ -237,14 +219,14 @@ extension YASMP: MCSessionDelegate {
func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {
//nop
}
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL, withError error: Error?) {
func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {
//nop
}
}
private func gcd<T: Integer>(_ m: T, _ n: T) -> T {
private func gcd<T: BinaryInteger>(_ m: T, _ n: T) -> T {
return n == 0 ? m : gcd(n, m % n)
}
private func mod<T: Integer>(_ m: T, _ n: T) -> T {
private func mod<T: BinaryInteger>(_ m: T, _ n: T) -> T {
return ( ( m % n ) + n ) % n
}
private func CMTimeMod(_ x: CMTime, _ y: CMTime) -> CMTime {
Expand Down
120 changes: 4 additions & 116 deletions YASMP.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@
PRODUCT_BUNDLE_IDENTIFIER = com.organi2e.kn.kotan.macYASMP;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
Expand Down Expand Up @@ -402,7 +401,6 @@
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.organi2e.kn.kotan.macYASMP;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand Down Expand Up @@ -457,7 +455,6 @@
SDKROOT = appletvos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 10.0;
};
Expand Down Expand Up @@ -506,7 +503,6 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 3.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 10.0;
VALIDATE_PRODUCT = YES;
Expand All @@ -516,138 +512,30 @@
879F2C2A1D910D5E006DFB8B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
879F2C2B1D910D5E006DFB8B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
87D6F7381D87BDA2003339BD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
CLANG_ENABLE_OBJC_ARC = YES;
SWIFT_VERSION = 4.2;
};
name = Debug;
};
87D6F7391D87BDA2003339BD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
CLANG_ENABLE_OBJC_ARC = YES;
SWIFT_VERSION = 4.2;
};
name = Release;
};
Expand Down
12 changes: 6 additions & 6 deletions YASMP/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Cocoa
import os.log
extension NSScreen {
func apply(profile: URL) -> Bool {
guard let num: UInt32 = deviceDescription["NSScreenNumber"] as? UInt32 else { return false }
guard let num: UInt32 = deviceDescription[.init(rawValue: "NSScreenNumber")] as? UInt32 else { return false }
return ColorSyncDeviceSetCustomProfiles(kColorSyncDisplayDeviceClass.takeUnretainedValue(),
CGDisplayCreateUUIDFromDisplayID(num).takeUnretainedValue(),
[(kColorSyncDeviceDefaultProfileID.takeUnretainedValue() as String): (profile as URL),
Expand All @@ -33,11 +33,11 @@ guard let interval: Double = arguments["--interval"]?.first as? Double else { ab
//guard let playlist: Array<Int> = (arguments["--playlist"]?.first? as? String)?.components(separatedBy: ",").flatMap { Int($0) } ?? [Int]()
guard let loop: Int = arguments["--loop"]?.first as? Int else { abort() }
let lock: Bool = arguments["--lock"]?.isEmpty == false
let profile: URL? = arguments["--profile"]?.flatMap{$0 as?String}.filter{FileManager.default.fileExists(atPath: $0)}.map{URL(fileURLWithPath: $0)}.first
let profile: URL? = arguments["--profile"]?.compactMap{$0 as?String}.filter{FileManager.default.fileExists(atPath: $0)}.map{URL(fileURLWithPath: $0)}.first
let urls: Array<URL> = rest.filter { FileManager.default.fileExists(atPath: $0) }.map { URL(fileURLWithPath: $0) }
do {
let app: NSApplication = NSApplication.shared()
guard let screen: NSScreen = NSScreen.main() else {
let app: NSApplication = .shared
guard let screen: NSScreen = .main else {
throw NSError(domain: #function, code: #line, userInfo: nil)
}
if let profile: URL = profile {
Expand All @@ -54,8 +54,8 @@ do {
yasmp.resume()

if !lock {
NSEvent.addLocalMonitorForEvents(matching: NSEventMask.keyDown) {
if $0.modifierFlags.contains(NSEventModifierFlags.command), $0.charactersIgnoringModifiers == "q" {
NSEvent.addLocalMonitorForEvents(matching: .keyDown) {
if $0.modifierFlags.contains(.command), $0.charactersIgnoringModifiers == "q" {
app.terminate(app)
}
return $0
Expand Down

0 comments on commit a397c92

Please sign in to comment.