-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Require macOS 10.13 and add support for pause/resume #14
Conversation
Package.swift
Outdated
@@ -1,4 +1,4 @@ | |||
// swift-tools-version:5.2 | |||
// swift-tools-version:5.1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on Mojave, so I can't run 5.2. Had to set to 5.1 for development. We can bump again before merging
Package.swift
Outdated
@@ -15,13 +15,15 @@ let package = Package( | |||
) | |||
], | |||
dependencies: [ | |||
.package(url: "https://github.com/wulkano/Aperture", from: "0.2.0") | |||
.package(url: "https://github.com/wulkano/Aperture", from: "0.2.0"), | |||
.package(url: "https://github.com/apple/swift-argument-parser", from: "0.1.0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, used 0.1.0
because I can only run on Swift 5.1, but it had everything I needed for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TODO comment about upgrading this dependency?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After I'm done with the rest of the comments if you want to pull down and migrate, that'd work too. I don't know if any breaking changes happened. I just can't even fetch 0.2.0 without using Swift tools 5.2, so I couldn't test it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can keep it 5.1 until you can upgrade.
@sindresorhus I'm sure my swift code needs cleanup, feel free to push any updates needed on the branch if you don't want to comment on everything 😄 Also if you can test it locally as well that'd be great |
I haven't added the 1 sec delay we discussed in the other PR. I didn't test it here. I'll test it locally in a bit, and update with the results |
Looks like there's still that 1s delay. Both after just resolving However, from the moment before you call So, if we add the 1s delay on both promises, we could call |
👍 |
Added the 1s delay to both the resume and startRecording calls |
index.js
Outdated
@@ -43,7 +44,7 @@ class Aperture { | |||
videoCodec = undefined | |||
} = {}) { | |||
this.processId = getRandomId(); | |||
return new Promise((resolve, reject) => { | |||
return new Promise(async (resolve, reject) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an anti-pattern to use async
in new Promise
as if the async function rejects, it causes an unhandled rejection. It's better then to use an async-IIFE and try/catch inside it.
Package.swift
Outdated
@@ -15,13 +15,15 @@ let package = Package( | |||
) | |||
], | |||
dependencies: [ | |||
.package(url: "https://github.com/wulkano/Aperture", from: "0.2.0") | |||
.package(url: "https://github.com/wulkano/Aperture", from: "0.2.0"), | |||
.package(url: "https://github.com/apple/swift-argument-parser", from: "0.1.0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TODO comment about upgrading this dependency?
return notification.userInfo?[name] as? T | ||
} | ||
|
||
func getData() -> String? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func getData() -> String? { | |
var data: String? { |
answer(nil) | ||
} | ||
|
||
func answer(_ data: Any?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func answer(_ data: Any?) { | |
func answer(_ data: Any? = nil) { |
and you can drop func answer()
var payload = [AnyHashable: Any]() | ||
|
||
if data != nil { | ||
payload["data"] = "\(data!)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't force-unwrap. Use guard or if-let. Applies in other places too.
data: Any?, | ||
using callback: @escaping (ApertureNotification) -> Void | ||
) { | ||
let responseName = "aperture.\(processId).\(event).response.\(UUID().uuidString)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
responseIdentifier
would be more correct, I think.
} | ||
|
||
DistributedNotificationCenter.default().postNotificationName( | ||
.Name("aperture.\(processId).\(event)"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"aperture.\(processId).\(event)
is used in three places. I think it could benefit from being moved into a function.
sendEvent(processId: processId, event: event, data: nil) { _ in } | ||
} | ||
|
||
func sendEvent(processId: String, event: String, data: Any?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func sendEvent(processId: String, event: String, data: Any?) { | |
func sendEvent(processId: String, event: String, data: Any? = nil) { |
and you can drop the above method.
payload["data"] = "\(data!)" | ||
} | ||
|
||
var observer: Any? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var observer: Any? | |
var observer: AnyObject? |
} | ||
} | ||
|
||
func sendEvent( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you namespace these methods? (enum with static members)
) | ||
} | ||
|
||
func sendEvent(processId: String, event: String, using callback: @escaping (ApertureNotification) -> Void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
processId
should be a Int
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we default it to "main"
Should it be a required arg? Or should it default to some kind of random Int?
Bump |
Will be working on this next, when I have some downtime |
@karaggeorge Bump :) |
+1, this would be amazing to have for users. Thank you 🙏🏽 |
Sorry for all the delay 😅 I also updated the js code a bit to match the PR that went in since this was opened, so now the startRecording resolves with nothing, but isFileReady resolves with the file path. Also, bumped the minimum version to 10.13 since new Aperture is also 10.13 Because of the above two, we probably need a major version bump when publishing. I'll also work on adding some typings in a separate PR when I get some time |
@karaggeorge Thank you so much for doing this. I'm a Product Manager, and so many of our users asked us for the ability to pause/stop their recordings. We were able to build it on Windows, but we were waiting for Aperture-Node to support it. So thank you on behalf of our users. 🙏🏽 |
@YoucefHQ no problem. If you don't mind me asking, what are you using as a windows alternative for aperture-node? |
@karaggeorge We use a native library on Windows called ScreenRecorderLib https://github.com/sskodje/ScreenRecorderLib |
Closes #2
Closes #5
Closes #1
Also replaces #12 (re-implemented those changes here)
So, this has a bunch of changes:
Aperture sends events like
onStart
,onPause
etc that we can listen to, and we can send events to Aperture likepause
,resume
to access functionality.The communication happens using
DistributedNotificationCenter
and specifically mapped event names, inspired by howelectron-better-ipc
works.This is sandboxed to a single aperture process using a randomly generated
processId
which is included in the events.Also, the events can answer back using another unique id that is generated on the spot for each event. This way two parallel events of the same type won't get their responses confused.
I've tested the regular flow, including
pause
,resume
andisPaused
to ensure it works.A weird observation. This code:
Outputs:
And in the output the first frame is after the
resume
call (no time-skip). So, we could theoretically pause right after start, then play a countdown timer or do whatever and then resume, to ensure we start at a convenient time for us.