From 471c635574b3ba477b529337b211e568e2e71fa6 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Fri, 15 Sep 2017 13:24:40 +0700 Subject: [PATCH] Use the new Decodable Swift protocol to handle options Fixes #8 --- README.md | 8 ++--- index.js | 20 ++++++------ swift/aperture/main.swift | 64 +++++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index ad34fb6..9634e58 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,8 @@ Number of frames per seconds. ##### cropArea -Type: `Object` `string`
-Default: `'none'` +Type: `Object`
+Default: `null` Record only an area of the screen. Accepts an object with `x`, `y`, `width`, `height` properties. @@ -116,8 +116,8 @@ Display to record. ##### audioSourceId -Type: `Object` `string`
-Default: `'none'` +Type: `string`
+Default: `null` Audio source to include in the screen recording. Should be one of the `id`'s from `aperture.getAudioSources()`. diff --git a/index.js b/index.js index 4cf7df9..ea4ecb0 100644 --- a/index.js +++ b/index.js @@ -15,11 +15,11 @@ class Aperture { startRecording({ fps = 30, - cropArea = 'none', + cropArea = undefined, showCursor = true, highlightClicks = false, displayId = 'main', - audioSourceId = 'none' + audioSourceId = undefined } = {}) { return new Promise((resolve, reject) => { if (this.recorder !== undefined) { @@ -27,12 +27,12 @@ class Aperture { return; } + this.tmpPath = tempy.file({extension: 'mp4'}); + if (highlightClicks === true) { showCursor = true; } - this.tmpPath = tempy.file({extension: 'mp4'}); - if (typeof cropArea === 'object') { if (typeof cropArea.x !== 'number' || typeof cropArea.y !== 'number' || @@ -41,21 +41,19 @@ class Aperture { reject(new Error('Invalid `cropArea` option object')); return; } - - cropArea = `${cropArea.x}:${cropArea.y}:${cropArea.width}:${cropArea.height}`; } - const recorderOpts = [ - this.tmpPath, + const recorderOpts = { + destination: this.tmpPath, fps, cropArea, showCursor, highlightClicks, displayId, - audioSourceId - ]; + audioDeviceId: audioSourceId + }; - this.recorder = execa(BIN, recorderOpts); + this.recorder = execa(BIN, [JSON.stringify(recorderOpts)]); const timeout = setTimeout(() => { // `.stopRecording()` was called already diff --git a/swift/aperture/main.swift b/swift/aperture/main.swift index 484ba69..05e9137 100644 --- a/swift/aperture/main.swift +++ b/swift/aperture/main.swift @@ -2,37 +2,51 @@ import Foundation import AVFoundation var recorder: Recorder! +let arguments = CommandLine.arguments.dropFirst() func quit(_: Int32) { recorder.stop() } -func record() throws { - // TODO: Use JSON and `Codable` here when Swift 4 is out +struct CropArea: Decodable { + let x: CGFloat + let y: CGFloat + let width: CGFloat + let height: CGFloat +} + +struct Options: Decodable { + let destination: String // TODO: Figure out a way to make this decodable into an `URL` + let fps: Int + let cropArea: CropArea? // TODO: Figure out a way to make this decodable into a `CGRect` + let showCursor: Bool + let highlightClicks: Bool + let displayId: String + let audioDeviceId: String? +} - let args = CommandLine.arguments - let destination = args[1] - let fps = args[2] - let cropArea = args[3] - let showCursor = args[4] - let highlightClicks = args[5] - let displayId = args[6] - let audioDeviceId = args[7] +func record() throws { + let json = arguments.first!.data(using: .utf8)! + let options = try JSONDecoder().decode(Options.self, from: json) var cropRect: CGRect? - if cropArea != "none" { - let points = cropArea.components(separatedBy: ":").map { Double($0)! } - cropRect = CGRect(x: points[0], y: points[1], width: points[2], height: points[3]) + if let cropArea = options.cropArea { + cropRect = CGRect( + x: cropArea.x, + y: cropArea.y, + width: cropArea.width, + height: cropArea.height + ) } recorder = try Recorder( - destination: URL(fileURLWithPath: destination), - fps: Int(fps)!, + destination: URL(fileURLWithPath: options.destination), + fps: options.fps, cropRect: cropRect, - showCursor: showCursor == "true", - highlightClicks: highlightClicks == "true", - displayId: displayId == "main" ? CGMainDisplayID() : CGDirectDisplayID(displayId)!, - audioDevice: audioDeviceId == "none" ? nil : .default(for: .audio) + showCursor: options.showCursor, + highlightClicks: options.highlightClicks, + displayId: options.displayId == "main" ? CGMainDisplayID() : CGDirectDisplayID(options.displayId)!, + audioDevice: options.audioDeviceId != nil ? AVCaptureDevice(uniqueID: options.audioDeviceId!) : .default(for: .audio) ) recorder.onStart = { @@ -70,16 +84,14 @@ func usage() { ) } -let numberOfArgs = CommandLine.arguments.count - -if numberOfArgs == 8 { - try record() +if arguments.first == "list-audio-devices" { + // Use stderr because of unrelated stuff being outputted on stdout + printErr(try toJson(DeviceList.audio())) exit(0) } -if numberOfArgs == 2 && CommandLine.arguments[1] == "list-audio-devices" { - // Use stderr because of unrelated stuff being outputted on stdout - printErr(try toJson(DeviceList.audio())) +if arguments.first != nil { + try record() exit(0) }