feat: report authoritative playback progress from shared backend
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import AppKit
|
||||
import Darwin
|
||||
import MediaPlayer
|
||||
|
||||
@_cdecl("terebi_app_main")
|
||||
@@ -92,6 +93,11 @@ private enum CLIInstanceCheck {
|
||||
static func run(_ configuration: URL) {
|
||||
let settings = try! JSONSerialization.jsonObject(with: Data(contentsOf: configuration)) as! [String: String]
|
||||
let directory = URL(fileURLWithPath: settings["directory"]!, isDirectory: true)
|
||||
let stderrURL = directory.appendingPathComponent("stderr-\(ProcessInfo.processInfo.processIdentifier).log")
|
||||
precondition(FileManager.default.createFile(atPath: stderrURL.path, contents: nil))
|
||||
let errorLog = try! FileHandle(forWritingTo: stderrURL)
|
||||
precondition(dup2(errorLog.fileDescriptor, STDERR_FILENO) >= 0)
|
||||
try! errorLog.close()
|
||||
setenv("PATH", settings["path"]!, 1)
|
||||
_ = NSApplication.shared
|
||||
_ = NotificationCenter.default.addObserver(forName: NSApplication.willFinishLaunchingNotification,
|
||||
@@ -115,17 +121,44 @@ private enum CLIInstanceCheck {
|
||||
let windows = NSApp.windows.filter { $0.canBecomeMain && !($0 is NSPanel) && $0.contentView != nil }
|
||||
for window in windows { window.alphaValue = 0 }
|
||||
let request = directory.appendingPathComponent("keys-\(pid).json")
|
||||
var pendingRequestID = ""
|
||||
if let data = try? Data(contentsOf: request),
|
||||
let command = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||
let id = command["id"] as? String, id != requestID, let window = windows.first {
|
||||
pendingRequestID = id
|
||||
if !NSApp.isActive || !window.isKeyWindow || !window.isMainWindow {
|
||||
NSApp.activate()
|
||||
// Synthetic native key requests need foreground focus; cooperative activation
|
||||
// can be refused by the unrelated app currently active on the workstation.
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
window.makeMain()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
requestID = id
|
||||
if let media = command["media"] as? String { model.open(URL(fileURLWithPath: media)) }
|
||||
if let action = command["action"] as? String {
|
||||
switch action {
|
||||
case "youtube":
|
||||
model.openYouTube(command["url"] as! String)
|
||||
case "seek":
|
||||
let position = command["position"] as! Double
|
||||
precondition(model.seekRelative(position - model.state.position), "Native seek must be accepted")
|
||||
case "pause":
|
||||
precondition(model.perform(.pause), "Native pause must be accepted")
|
||||
case "play":
|
||||
precondition(model.perform(.play), "Native play must be accepted")
|
||||
case "quality":
|
||||
precondition(model.canChangeYouTubeQuality, "Native quality change must be available")
|
||||
model.setYouTubeQuality((command["height"] as! Int))
|
||||
case "close":
|
||||
model.closeFile()
|
||||
case "quit":
|
||||
timer?.invalidate()
|
||||
precondition(model.perform(.quit), "Native quit must be accepted")
|
||||
return
|
||||
default:
|
||||
fatalError("Unknown native check action \(action)")
|
||||
}
|
||||
}
|
||||
if let events = command["events"] as? [[String: Any]] {
|
||||
window.makeKey()
|
||||
for input in events {
|
||||
@@ -159,6 +192,7 @@ private enum CLIInstanceCheck {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let applications = NSWorkspace.shared.runningApplications.filter {
|
||||
!$0.isTerminated && $0.bundleURL == Bundle.main.bundleURL
|
||||
@@ -169,6 +203,13 @@ private enum CLIInstanceCheck {
|
||||
"media": model.fileName ?? "",
|
||||
"status": model.state.status.rawValue,
|
||||
"position": model.state.position,
|
||||
"duration": model.state.duration,
|
||||
"seekPending": model.state.seek_pending,
|
||||
"canSeek": model.canSeek,
|
||||
"busy": model.isBusy,
|
||||
"youtubeHeight": model.youtubeHeight ?? 0,
|
||||
"canChangeQuality": model.canChangeYouTubeQuality,
|
||||
"qualityHeights": model.youtubeHeights,
|
||||
"windows": windows.count,
|
||||
"hasAudio": model.state.has_audio,
|
||||
"hasVideo": model.state.has_video,
|
||||
@@ -177,6 +218,10 @@ private enum CLIInstanceCheck {
|
||||
"automaticQuality": model.automaticYouTubeQuality,
|
||||
"snapToEdges": model.compactWindow.snappingEnabled,
|
||||
"requestID": requestID,
|
||||
"pendingRequestID": pendingRequestID,
|
||||
"active": NSApp.isActive,
|
||||
"keyWindow": windows.first?.isKeyWindow ?? false,
|
||||
"mainWindow": windows.first?.isMainWindow ?? false,
|
||||
"editorText": editorText,
|
||||
"compact": model.isCompact,
|
||||
"onTop": model.isOnTop,
|
||||
|
||||
Reference in New Issue
Block a user