-
Notifications
You must be signed in to change notification settings - Fork 5
Antoine/swift6 #11
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
Antoine/swift6 #11
Changes from 5 commits
8bfa6a0
a4b6e84
63ea77f
20cc39a
5cfcec1
d65a673
cc79e72
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| import AVFoundation | ||
| import Foundation | ||
|
|
||
| public actor CaptureBody { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's illegal to perform start/stop running in between session configurations. Session is also non sendable. Ensure all access is done sequentially. |
||
|
|
||
| // Can't be easily made into an actor do to the deinit. Maybe if the min framework is 18.4 we can move to an actor | ||
| public final class CaptureBody: @unchecked Sendable { | ||
| private let backgroundExecutionQueue = DispatchQueue(label: "Capturer.CaptureBody.backgroundExecutionQueue", qos: .userInitiated) | ||
|
|
||
| public struct Configuration: Sendable { | ||
|
|
||
|
|
@@ -41,22 +44,28 @@ public actor CaptureBody { | |
|
|
||
| public var handlers: Handlers = .init() | ||
|
|
||
| public let session: AVCaptureSession | ||
| private lazy var session: AVCaptureSession = { | ||
| backgroundExecutionQueue.sync { | ||
| .init() | ||
| } | ||
| }() | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it should be let, not lazy? |
||
|
|
||
| private var inputNode: InputNodeType? | ||
| private var outputNodes: [OutputNodeType] = [] | ||
|
|
||
| public init( | ||
| configuration: Configuration | ||
| ) { | ||
| session = .init() | ||
| guard ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] != "1" else { return } | ||
| _ = self.session | ||
|
|
||
| assert(Utils.checkIfCanUseCameraAccordingToPrivacySensitiveData() == true) | ||
| backgroundExecutionQueue.async { | ||
|
|
||
| session.performConfiguration { | ||
| $0.sessionPreset = configuration.sessionPreset | ||
| $0.automaticallyConfiguresCaptureDeviceForWideColor = true | ||
| self.session.performConfiguration { | ||
| $0.sessionPreset = configuration.sessionPreset | ||
| $0.automaticallyConfiguresCaptureDeviceForWideColor = true | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
@@ -65,36 +74,42 @@ public actor CaptureBody { | |
|
|
||
| Log.debug(.capture, "Session started") | ||
|
|
||
| session.startRunning() | ||
| backgroundExecutionQueue.async { | ||
| self.session.startRunning() | ||
| } | ||
| } | ||
|
|
||
| public func stop() { | ||
|
|
||
| Log.debug(.capture, "Session stopped") | ||
|
|
||
| session.stopRunning() | ||
| backgroundExecutionQueue.async { | ||
| self.session.stopRunning() | ||
| } | ||
| } | ||
|
|
||
| public func batchAttaching( | ||
| input newInputNode: InputNodeType, | ||
| outputs newOutputNodes: [OutputNodeType] | ||
| ) { | ||
|
|
||
| session.performConfiguration { session in | ||
| backgroundExecutionQueue.async { | ||
|
|
||
| if let currentInputNode = inputNode { | ||
| currentInputNode.tearDown(sessionInConfiguring: session) | ||
| } | ||
| self.session.performConfiguration { session in | ||
|
|
||
| if let currentInputNode = self.inputNode { | ||
| currentInputNode.tearDown(sessionInConfiguring: session) | ||
| } | ||
|
|
||
| inputNode = newInputNode | ||
| self.inputNode = newInputNode | ||
|
|
||
| newInputNode.setUp(sessionInConfiguring: session) | ||
| newInputNode.setUp(sessionInConfiguring: session) | ||
|
|
||
| outputNodes.append(contentsOf: newOutputNodes) | ||
| self.outputNodes.append(contentsOf: newOutputNodes) | ||
|
|
||
| session.performConfiguration { session in | ||
| newOutputNodes.forEach { | ||
| $0.setUp(sessionInConfiguring: session) | ||
| session.performConfiguration { session in | ||
| newOutputNodes.forEach { | ||
| $0.setUp(sessionInConfiguring: session) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -107,18 +122,19 @@ public actor CaptureBody { | |
| public func attach(input newInputNode: some DeviceInputNodeType) { | ||
|
|
||
| Log.debug(.capture, "Attach input \(newInputNode)") | ||
| backgroundExecutionQueue.async { | ||
|
|
||
| session.performConfiguration { session in | ||
| self.session.performConfiguration { session in | ||
|
|
||
| if let currentNode = inputNode { | ||
| currentNode.tearDown(sessionInConfiguring: session) | ||
| } | ||
| if let currentNode = self.inputNode { | ||
| currentNode.tearDown(sessionInConfiguring: session) | ||
| } | ||
|
|
||
| inputNode = newInputNode | ||
| self.inputNode = newInputNode | ||
|
|
||
| newInputNode.setUp(sessionInConfiguring: session) | ||
| newInputNode.setUp(sessionInConfiguring: session) | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
||
| public func attach(output component: some OutputNodeType) { | ||
|
|
@@ -127,10 +143,12 @@ public actor CaptureBody { | |
|
|
||
| outputNodes.append(component) | ||
|
|
||
| session.performConfiguration { | ||
| component.setUp(sessionInConfiguring: $0) | ||
| } | ||
| backgroundExecutionQueue.async { | ||
|
|
||
| self.session.performConfiguration { | ||
| component.setUp(sessionInConfiguring: $0) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public func removeCurrentInput() { | ||
|
|
@@ -141,22 +159,29 @@ public actor CaptureBody { | |
|
|
||
| inputNode = nil | ||
|
|
||
| session.performConfiguration { | ||
| currentInput.tearDown(sessionInConfiguring: $0) | ||
| backgroundExecutionQueue.async { | ||
|
|
||
| self.session.performConfiguration { | ||
| currentInput.tearDown(sessionInConfiguring: $0) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| deinit { | ||
|
|
||
| Log.debug(.capture, "\(self) deinitializes") | ||
|
|
||
| session.performConfiguration { [inputNode] in | ||
| inputNode?.tearDown(sessionInConfiguring: $0) | ||
| } | ||
|
|
||
| session.performConfiguration { [outputNodes] session in | ||
| outputNodes.forEach { output in | ||
| output.tearDown(sessionInConfiguring: session) | ||
| backgroundExecutionQueue.async { [inputNode, outputNodes, session] in | ||
|
|
||
| session.performConfiguration { [inputNode] in | ||
| inputNode?.tearDown(sessionInConfiguring: $0) | ||
| } | ||
|
|
||
| session.performConfiguration { [outputNodes] session in | ||
| outputNodes.forEach { output in | ||
| output.tearDown(sessionInConfiguring: session) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
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.
Basically just apply recommended changes and swift 6