From 0fed23785642f8ba2ca867b6e70c151772a055c3 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sat, 20 Nov 2021 01:40:16 +0700 Subject: [PATCH] Minor tweaks --- Sources/ApertureCLI/notifications.swift | 218 ++++++++++++------------ Sources/ApertureCLI/record.swift | 156 ++++++++--------- index.js | 2 +- test.js | 2 +- 4 files changed, 189 insertions(+), 189 deletions(-) diff --git a/Sources/ApertureCLI/notifications.swift b/Sources/ApertureCLI/notifications.swift index 925e76c..4637e22 100644 --- a/Sources/ApertureCLI/notifications.swift +++ b/Sources/ApertureCLI/notifications.swift @@ -1,125 +1,125 @@ import Foundation final class ApertureNotification { - static func notificationName(forEvent event: String, processId: String) -> String { - "aperture.\(processId).\(event)" - } + static func notificationName(forEvent event: String, processId: String) -> String { + "aperture.\(processId).\(event)" + } - private var notification: Notification - var isAnswered = false + private var notification: Notification + var isAnswered = false - init(_ notification: Notification) { - self.notification = notification - } + init(_ notification: Notification) { + self.notification = notification + } - func getField(_ name: String) -> T? { - notification.userInfo?[name] as? T - } + func getField(_ name: String) -> T? { + notification.userInfo?[name] as? T + } - var data: String? { getField("data") } + var data: String? { getField("data") } - func answer(_ data: Any? = nil) { - isAnswered = true + func answer(_ data: Any? = nil) { + isAnswered = true - guard - let responseIdentifier: String = getField("responseIdentifier") + guard + let responseIdentifier: String = getField("responseIdentifier") else { - return - } - - var payload = [AnyHashable: Any]() - - if let payloadData = data { - payload["data"] = "\(payloadData)" - } - - DistributedNotificationCenter.default().postNotificationName( - .init(responseIdentifier), - object: nil, - userInfo: payload, - deliverImmediately: true - ) - } + return + } + + var payload = [AnyHashable: Any]() + + if let payloadData = data { + payload["data"] = "\(payloadData)" + } + + DistributedNotificationCenter.default().postNotificationName( + .init(responseIdentifier), + object: nil, + userInfo: payload, + deliverImmediately: true + ) + } } enum ApertureEvents { - static func answerEvent( - processId: String, - event: String, - using handler: @escaping (ApertureNotification) -> Void - ) -> NSObjectProtocol { + static func answerEvent( + processId: String, + event: String, + using handler: @escaping (ApertureNotification) -> Void + ) -> NSObjectProtocol { DistributedNotificationCenter.default().addObserver( - forName: .init(ApertureNotification.notificationName(forEvent: event, processId: processId)), - object: nil, - queue: nil - ) { notification in - let apertureNotification = ApertureNotification(notification) - handler(apertureNotification) - - if !apertureNotification.isAnswered { - apertureNotification.answer() - } + forName: .init(ApertureNotification.notificationName(forEvent: event, processId: processId)), + object: nil, + queue: nil + ) { notification in + let apertureNotification = ApertureNotification(notification) + handler(apertureNotification) + + if !apertureNotification.isAnswered { + apertureNotification.answer() + } + } + } + + static func sendEvent( + processId: String, + event: String, + data: Any?, + using callback: @escaping (ApertureNotification) -> Void + ) { + let notificationName = ApertureNotification.notificationName(forEvent: event, processId: processId) + let responseIdentifier = "\(notificationName).response.\(UUID().uuidString)" + + var payload: [AnyHashable: Any] = ["responseIdentifier": responseIdentifier] + + if let payloadData = data { + payload["data"] = "\(payloadData)" + } + + var observer: AnyObject? + + observer = DistributedNotificationCenter.default().addObserver( + forName: .init(responseIdentifier), + object: nil, + queue: nil + ) { notification in + DistributedNotificationCenter.default().removeObserver(observer!) + callback(ApertureNotification(notification)) + } + + DistributedNotificationCenter.default().postNotificationName( + .init( + ApertureNotification.notificationName(forEvent: event, processId: processId) + ), + object: nil, + userInfo: payload, + deliverImmediately: true + ) + } + + static func sendEvent( + processId: String, + event: String, + using callback: @escaping (ApertureNotification) -> Void + ) { + sendEvent( + processId: processId, + event: event, + data: nil, + using: callback + ) + } + + static func sendEvent( + processId: String, + event: String, + data: Any? = nil + ) { + sendEvent( + processId: processId, + event: event, + data: data + ) { _ in } } - } - - static func sendEvent( - processId: String, - event: String, - data: Any?, - using callback: @escaping (ApertureNotification) -> Void - ) { - let notificationName = ApertureNotification.notificationName(forEvent: event, processId: processId) - let responseIdentifier = "\(notificationName).response.\(UUID().uuidString)" - - var payload: [AnyHashable: Any] = ["responseIdentifier": responseIdentifier] - - if let payloadData = data { - payload["data"] = "\(payloadData)" - } - - var observer: AnyObject? - - observer = DistributedNotificationCenter.default().addObserver( - forName: .init(responseIdentifier), - object: nil, - queue: nil - ) { notification in - DistributedNotificationCenter.default().removeObserver(observer!) - callback(ApertureNotification(notification)) - } - - DistributedNotificationCenter.default().postNotificationName( - .init( - ApertureNotification.notificationName(forEvent: event, processId: processId) - ), - object: nil, - userInfo: payload, - deliverImmediately: true - ) - } - - static func sendEvent( - processId: String, - event: String, - using callback: @escaping (ApertureNotification) -> Void - ) { - sendEvent( - processId: processId, - event: event, - data: nil, - using: callback - ) - } - - static func sendEvent( - processId: String, - event: String, - data: Any? = nil - ) { - sendEvent( - processId: processId, - event: event, - data: data - ) { _ in } - } } diff --git a/Sources/ApertureCLI/record.swift b/Sources/ApertureCLI/record.swift index 0c8df69..528d73e 100644 --- a/Sources/ApertureCLI/record.swift +++ b/Sources/ApertureCLI/record.swift @@ -2,85 +2,85 @@ import AVFoundation import Aperture struct Options: Decodable { - let destination: URL - let framesPerSecond: Int - let cropRect: CGRect? - let showCursor: Bool - let highlightClicks: Bool - let screenId: CGDirectDisplayID - let audioDeviceId: String? - let videoCodec: String? + let destination: URL + let framesPerSecond: Int + let cropRect: CGRect? + let showCursor: Bool + let highlightClicks: Bool + let screenId: CGDirectDisplayID + let audioDeviceId: String? + let videoCodec: String? } func record(_ optionsString: String, processId: String) throws { - setbuf(__stdoutp, nil) - let options: Options = try optionsString.jsonDecoded() - var observers = [Any]() - - let recorder = try Aperture( - destination: options.destination, - framesPerSecond: options.framesPerSecond, - cropRect: options.cropRect, - showCursor: options.showCursor, - highlightClicks: options.highlightClicks, - screenId: options.screenId == 0 ? .main : options.screenId, - audioDevice: options.audioDeviceId != nil ? AVCaptureDevice(uniqueID: options.audioDeviceId!) : nil, - videoCodec: options.videoCodec != nil ? AVVideoCodecType(rawValue: options.videoCodec!) : nil - ) - - recorder.onStart = { - ApertureEvents.sendEvent(processId: processId, event: OutEvent.onFileReady.rawValue) - } - - recorder.onPause = { - ApertureEvents.sendEvent(processId: processId, event: OutEvent.onPause.rawValue) - } - - recorder.onResume = { - ApertureEvents.sendEvent(processId: processId, event: OutEvent.onResume.rawValue) - } - - recorder.onFinish = { error in - if let error = error { - print(error, to: .standardError) - exit(1) - } - - ApertureEvents.sendEvent(processId: processId, event: OutEvent.onFinish.rawValue) - - for observer in observers { - DistributedNotificationCenter.default().removeObserver(observer) - } - - exit(0) - } - - CLI.onExit = { - recorder.stop() - // Do not call `exit()` here as the video is not always done - // saving at this point and will be corrupted randomly - } - - observers.append( - ApertureEvents.answerEvent(processId: processId, event: InEvent.pause.rawValue) { _ in - recorder.pause() - } - ) - - observers.append( - ApertureEvents.answerEvent(processId: processId, event: InEvent.resume.rawValue) { _ in - recorder.resume() - } - ) - - observers.append( - ApertureEvents.answerEvent(processId: processId, event: InEvent.isPaused.rawValue) { notification in - notification.answer(recorder.isPaused) - } - ) - - recorder.start() - ApertureEvents.sendEvent(processId: processId, event: OutEvent.onStart.rawValue) - - RunLoop.main.run() + setbuf(__stdoutp, nil) + let options: Options = try optionsString.jsonDecoded() + var observers = [Any]() + + let recorder = try Aperture( + destination: options.destination, + framesPerSecond: options.framesPerSecond, + cropRect: options.cropRect, + showCursor: options.showCursor, + highlightClicks: options.highlightClicks, + screenId: options.screenId == 0 ? .main : options.screenId, + audioDevice: options.audioDeviceId != nil ? AVCaptureDevice(uniqueID: options.audioDeviceId!) : nil, + videoCodec: options.videoCodec != nil ? AVVideoCodecType(rawValue: options.videoCodec!) : nil + ) + + recorder.onStart = { + ApertureEvents.sendEvent(processId: processId, event: OutEvent.onFileReady.rawValue) + } + + recorder.onPause = { + ApertureEvents.sendEvent(processId: processId, event: OutEvent.onPause.rawValue) + } + + recorder.onResume = { + ApertureEvents.sendEvent(processId: processId, event: OutEvent.onResume.rawValue) + } + + recorder.onFinish = { error in + if let error = error { + print(error, to: .standardError) + exit(1) + } + + ApertureEvents.sendEvent(processId: processId, event: OutEvent.onFinish.rawValue) + + for observer in observers { + DistributedNotificationCenter.default().removeObserver(observer) + } + + exit(0) + } + + CLI.onExit = { + recorder.stop() + // Do not call `exit()` here as the video is not always done + // saving at this point and will be corrupted randomly + } + + observers.append( + ApertureEvents.answerEvent(processId: processId, event: InEvent.pause.rawValue) { _ in + recorder.pause() + } + ) + + observers.append( + ApertureEvents.answerEvent(processId: processId, event: InEvent.resume.rawValue) { _ in + recorder.resume() + } + ) + + observers.append( + ApertureEvents.answerEvent(processId: processId, event: InEvent.isPaused.rawValue) { notification in + notification.answer(recorder.isPaused) + } + ) + + recorder.start() + ApertureEvents.sendEvent(processId: processId, event: OutEvent.onStart.rawValue) + + RunLoop.main.run() } diff --git a/index.js b/index.js index 9e7a881..1cb8832 100644 --- a/index.js +++ b/index.js @@ -46,7 +46,7 @@ class Aperture { highlightClicks = false, screenId = 0, audioDeviceId = undefined, - videoCodec = undefined + videoCodec = 'h264' } = {}) { this.processId = getRandomId(); diff --git a/test.js b/test.js index acfd02d..b80d3d8 100644 --- a/test.js +++ b/test.js @@ -25,7 +25,7 @@ test('returns available video codecs', t => { test('records screen', async t => { const recorder = aperture(); - await recorder.startRecording({videoCodec: 'h264'}); + await recorder.startRecording(); t.true(fs.existsSync(await recorder.isFileReady)); await delay(1000); const videoPath = await recorder.stopRecording();